DVWASqli filter #02-80sec

mac2026-05-24  1

0x01 WooYun-2014-51687

输入1',报错了。 后面跟#等注释符号,显示有waf。 尝试使用万能密码,1' or '1'='1,还是报错了,突然觉得这不会是整形的吧。。。用and测试了下,果然是整形注入。 使用联合查询1 union select 1,2的时候有新的报错。 由于有报错信息,依次删除字符,来判断,到底是哪个关键字引起的WAF。最后测试出,,没问题,单独使用select也没问题,看来问题出在union上了。 采用大小写,编码,内联注释等绕过,发现均不可绕过,于是改用盲注,但是每次到使用select的时候同样也会有WAF。。。纠结了一会就放弃了,直接来看源码吧。

0x02 源码分析

WooYun-2014-51687 Source <?php if(isset($_GET['Submit'])){ // Retrieve data $id = $_GET['id']; $id = CheckSql($id,'select'); $getid = "SELECT first_name, last_name FROM users WHERE user_id = $id"; $result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' ); $num = mysql_numrows($result); $i = 0; while ($i < $num) { $first = mysql_result($result,$i,"first_name"); $last = mysql_result($result,$i,"last_name"); echo '<pre>'; echo 'ID: ' . $id . '<br>First name: ' . $first . '<br>Surname: ' . $last; echo '</pre>'; $i++; } } //SQL语句过滤程序,由80sec提供,这里作了适当的修改 function CheckSql($db_string,$querytype='select') { $clean = ''; $error=''; $old_pos = 0; $pos = -1; $userIP = GetIP(); $getUrl = GetCurUrl(); //如果是普通查询语句,直接过滤一些特殊语法 if($querytype=='select') { $notallow1 = "[^0-9a-z@\._-]{1,}(union|sleep|benchmark|load_file|outfile)[^0-9a-z@\.-]{1,}"; //$notallow2 = "--|/\*"; if(eregi($notallow1,$db_string)) { exit("<font size='5' color='red'>Safe Alert: Request Error step 1 !</font>"); } } //完整的SQL检查 while (true) { $pos = strpos($db_string, '\'', $pos + 1); if ($pos === false) { break; } $clean .= substr($db_string, $old_pos, $pos - $old_pos); while (true) { $pos1 = strpos($db_string, '\'', $pos + 1); $pos2 = strpos($db_string, '\\', $pos + 1); if ($pos1 === false) { break; } elseif ($pos2 == false || $pos2 > $pos1) { $pos = $pos1; break; } $pos = $pos2 + 1; } $clean .= '$s$'; $old_pos = $pos + 1; } $clean .= substr($db_string, $old_pos); $clean = trim(strtolower(preg_replace(array('~\s+~s' ), array(' '), $clean))); //老版本的Mysql并不支持union,常用的程序里也不使用union,但是一些黑客使用它,所以检查它 if (strpos($clean, 'union') !== false && preg_match('~(^|[^a-z])union($|[^[a-z])~s', $clean) != 0) { $fail = true; $error="union detect"; } //发布版本的程序可能比较少包括--,#这样的注释,但是黑客经常使用它们 elseif (strpos($clean, '/*') > 2 || strpos($clean, '--') !== false || strpos($clean, '#') !== false) { $fail = true; $error="comment detect"; } //这些函数不会被使用,但是黑客会用它来操作文件,down掉数据库 elseif (strpos($clean, 'sleep') !== false && preg_match('~(^|[^a-z])sleep($|[^[a-z])~s', $clean) != 0) { $fail = true; $error="slown down detect"; } elseif (strpos($clean, 'benchmark') !== false && preg_match('~(^|[^a-z])benchmark($|[^[a-z])~s', $clean) != 0) { $fail = true; $error="slown down detect"; } elseif (strpos($clean, 'load_file') !== false && preg_match('~(^|[^a-z])load_file($|[^[a-z])~s', $clean) != 0) { $fail = true; $error="file fun detect"; } elseif (strpos($clean, 'into outfile') !== false && preg_match('~(^|[^a-z])into\s+outfile($|[^[a-z])~s', $clean) != 0) { $fail = true; $error="file fun detect"; } //老版本的MYSQL不支持子查询,我们的程序里可能也用得少,但是黑客可以使用它来查询数据库敏感信息 elseif (preg_match('~\([^)]*?select~s', $clean) != 0) { $fail = true; $error="sub select detect"; } if (!empty($fail)) { exit("<font size='5' color='red'>Safe Alert: Request Error step 2!</font>"); } else { return $db_string; } } //获得当前的脚本网址 function GetCurUrl() { if(!empty($_SERVER["REQUEST_URI"])) { $scriptName = $_SERVER["REQUEST_URI"]; $nowurl = $scriptName; } else { $scriptName = $_SERVER["PHP_SELF"]; if(empty($_SERVER["QUERY_STRING"])) { $nowurl = $scriptName; } else { $nowurl = $scriptName."?".$_SERVER["QUERY_STRING"]; } } return $nowurl; } function getIP() { return $_SERVER ["HTTP_X_FORWARDED_FOR"]; } ?>

这次的代码有点长。。。一点一点来看。 一开始对select语句做了检查 接着来看第一个检查语句 如果上列关键字不是以数字,字母,@,.,_,-开头和结尾都会被WAF检测出来,也就是说我只要满足其中一个条件就可以绕过此限制了,难怪之前使用/*!union*/报错的是step 1,而使用/*!12345union*/报错的是step 2。这里多说一下,/*!12345union*/里面的12345其实是mysql数据库的版本号,指的是大于此版本号的数据库可以正常使用。 这一大串其实就是说将两个'包含起来的字符串过滤掉,这个看了好久加上测试才看个大概,最后那个$s$没看懂,array()里面的好像是将空白字符换成空格,看点蒙,大佬看懂了指点一下阿,这到底要干啥。。。 如果有union的时候并且有以union开头或者不是[a-z]union开头或者结尾的时候就会报错,/*!12345union*/不满足条件。 如果有注释的话,就会报错,注意,这里是最难弄的地方,等会看payload再来说这个怎么绕过。 如果select前面有(则报错,这里就是为什么我之前盲注的时候select会报错的原因。

3.漏洞利用

好了,分析完了,开始讲漏洞利用了。 来简单分析下,为什么这样写就可以绕过去。 首先/*!12345union*/可以绕过去union的检查,关键的来了,使用两个`将单引号转义,在前面和后面各来一个,以此将中间的代码跳出上面所有的检查,所以这里就直接绕过了。接着我们去数据库里面看看这样的语句是如何执行成功的。 这里有#将后面都注释掉了,然后1 and @'就变成了0,因为@是用来定义用户变量的,这里的变量没有定义所以是Null,最后运算的结果就是0了。 不能不说,能搞出这样绕过的真的厉害,学习了。

最新回复(0)