各种神奇的姿势
LDAP注入
ldap注入详解
Web150-Injection
一个注入,其实不难。。。主要是不太熟悉罢了,LDAP注入
在乌云有这么一篇文章写得很详细:http://drops.wooyun.org/tips/967
根据LDAP的特性,我们可以利用特殊符“*”去替换过滤器中的一个或多个字符,经过测试:
admin *,进入search页面:
输入test后发现
再次发现通配符*,发现正确可以回显,不正确不能回显,并且输入有长度限制。
令uid=*,构造)(2=,以形成(|(uid=*)(2=*))
然后看了下cookie,有东西:
猜测description是一个参数,于是构造:test)(description=
随机输入字符,当test)(description=z时有正确回显,于是利用burp诸位爆破:
得到flag:zctf{303a61ace0204a2d5f352771d6f1bba2}
group by with rollup
题目:http://ctf5.shiyanbar.com/web/pcat/index.php
右键查看源码可以看到source.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| <?php error_reporting(0); if (!isset($_POST['uname']) || !isset($_POST['pwd'])) { echo '<form action="" method="post">'."<br/>"; echo '<input name="uname" type="text"/>'."<br/>"; echo '<input name="pwd" type="text"/>'."<br/>"; echo '<input type="submit" />'."<br/>"; echo '</form>'."<br/>"; echo '<!--source: source.txt-->'."<br/>"; die; } function AttackFilter($StrKey,$StrValue,$ArrReq){ if (is_array($StrValue)){ $StrValue=implode($StrValue); } if (preg_match("/".$ArrReq."/is",$StrValue)==1){ print "姘村彲杞借垷锛屼害鍙禌鑹囷紒"; exit(); } } $filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)"; foreach($_POST as $key=>$value){ AttackFilter($key,$value,$filter); } $con = mysql_connect("XXXXXX","XXXXXX","XXXXXX"); if (!$con){ die('Could not connect: ' . mysql_error()); } $db="XXXXXX"; mysql_select_db($db, $con); $sql="SELECT * FROM interest WHERE uname = '{$_POST['uname']}'"; $query = mysql_query($sql); if (mysql_num_rows($query) == 1) { $key = mysql_fetch_array($query); if($key['pwd'] == $_POST['pwd']) { print "CTF{XXXXXX}"; }else{ print "浜﹀彲璧涜墖锛�"; } }else{ print "涓€棰楄禌鑹囷紒"; } mysql_close($con); ?>
|
主要是这几行代码:
1 2 3 4 5 6 7 8 9 10 11 12
| $sql="SELECT * FROM interest WHERE uname = '{$_POST['uname']}'"; $query = mysql_query($sql); if (mysql_num_rows($query) == 1) { $key = mysql_fetch_array($query); if($key['pwd'] == $_POST['pwd']) { print "CTF{XXXXXX}"; }else{ print "浜﹀彲璧涜墖锛�"; } }else{ print "涓€棰楄禌鑹囷紒"; }
|
有两层限制,第一个限制是要查询结果为一行,可以用' or '1'='1' limit 1#
来绕过,而且如果不加limit的话就会绕不过,这就说明不止一个用户,用offset看了下有两个用户.
接下来第二层限制的话用一个神奇的东西group by with rollup
group by pwd 是按照pwd来分组,此处是为了搭配 with rollup
使用with rollup 统计pwd组的信息,这里没用任何统计函数(sum,avg…),多出的那一行的pwd列只能是NULL所以到目前取出的的数据类似这样:
+——-+——-+
| uname | pwd |
+——-+——-+
| usr1 | * |
| usr2 | * |
| usr2 | NULL |
+——-+——-+
然后是limit 1 offset 2 就是跳过两个,只用第三个数据。
那么最终取出的数据就是这样了
+——-+——-+
| uname | pwd |
+——-+——-+
| usr2 | NULL |
+——-+——-+
这样
OOB注入
因为这种注入挺常见的,而且东西还是挺多的,所以另外开了篇博客来记录https://err0rzz.github.io/2017/11/16/OOB%E6%B3%A8%E5%85%A5/
宽字节注入
主要造成的原因是数据库所使用的编码和前端的编码方式不一致。
比如说MYSQL中使用了GBK编码方式,则0Xbf27和0Xbf5c都会被认为是一个字符(双字节字符)。但是Web语言中并没有考虑到双字节字符这种情况,所以还是会把0Xbf27当成两个字节,即0Xbf和0X27。
而且开发者为了安全,会使用PHP的addslashes()函数,或者打开magic_quotes_gps。此时会对某些特定的字符进行转义,即在字符前加一个“\”。
1 2 3 4 5
| addslashes()函数会对以下字符进行转义: ('), (\), ("), NUL
|
此时如果我们注入的时候输入0Xbf27 or 1=1
,则在进入数据库前会被转义成0Xbf5c27 or 1=1
,即在单引号前面添加一个反斜杠。然后进入数据库之后,编码方式为GBK的数据库会把0Xbf5c
看成一个字符,从而使得单引号逃逸了出来,达成单引号绕过。
最好统一设置成UTF-8编码。