PHP代码审计基础(四)

弱类型比较

1.md5()函数和sha1()绕过

无论是在实际代码审计中,还是在CTF比赛中,这些我们都是碰到过的函数。那么当我们遇到用这两个函数来判断的时候,如果绕过呢?

PHP 在处理哈希字符串的时候,会使用!=或者==来对哈希值进行比较,它会把每一个0E开头的哈希值都解释为0,那么这个时候问题就来了,如果两个不同的值,经过哈希以后它们都变成了0E开头的哈希值,那么 PHP 就会将它们视作相等处理。那么0E开头的哈希值有哪些呢?

s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s1885207154a
0e509367213418206700842008763514
s1502113478a
0e861580163291561247404381396064
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s155964671a
0e342768416822451524974117254469
s1184209335a
0e072485820392773389523109082030
s1665632922a
0e731198061491163073197128363787
s1502113478a
0e861580163291561247404381396064
s1836677006a
0e481036490867661113260034900752
s1091221200a
0e940624217856561557816327384675
s155964671a
0e342768416822451524974117254469
s1502113478a
0e861580163291561247404381396064
s155964671a
0e342768416822451524974117254469
s1665632922a
0e731198061491163073197128363787
s155964671a
0e342768416822451524974117254469
s1091221200a
0e940624217856561557816327384675
s1836677006a
0e481036490867661113260034900752
s1885207154a
0e509367213418206700842008763514
s532378020a
0e220463095855511507588041205815
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s214587387a
0e848240448830537924465865611904
s1502113478a
0e861580163291561247404381396064
s1091221200a
0e940624217856561557816327384675
s1665632922a
0e731198061491163073197128363787
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s1665632922a
0e731198061491163073197128363787
s878926199a
0e545993274517709034328855841020

来个简单的例子吧

代码示例:

<?php
    $a = $_GET['a'];
	$b = $_GET['b'];
	if($a != $b && md5($a) == md5($b)){
    
    
        echo 'aaaaa';  //这就是弱类型绕过
    }
	else{
    
    
        echo 'bbb';
    }
?>

结果
在这里插入图片描述在这里插入图片描述
从上面我给出的哪些值中,挑两个不同的值传入参数,就能看到相应的结果

上面是md5()函数的绕过姿势,那么sha1()如何绕过呢?再来看一个简单的例子

<?php
    $a = $_GET['a'];
	$b = $_GET['b'];
	if(isset($a,$b)){
    
    
		if(sha1($a) === sha1($b)){
    
    
			echo 'nice!!!';
		}
		else{
    
    
			echo 'Try again!';
		}
	}
?>

当我们传入a[]=1&b[]=2的时候,虽然它会给出警告,说我们应该传入字符串而不应该是数组,但是它还是输出了nice!!!,所以我们完全可以用数字来绕过sha1()函数的比较。
在这里插入图片描述

2. is_numeric()绕过

我们先来了解一下这个函数。此函数是检测变量是否为数字或者数字字符串

is_numeric( mixed $var) : bool

如果var是数字或者数字字符串那么就返回TRUE,否则就返回FALSE。那么这里说的绕过是什么姿势呢?是十六进制。我们先来看一个简单的例子。

<?php
    $a = is_numeric('0x31206f722031');
	if($a){
    
    
        echo 'It meets my requirement';
    }
	else{
    
    
        echo 'Try again';
    }
?>
执行结果——>
It meets my requirement

这里说一下0x31206f722031这个是什么?这个是or 1=1的十六进制,从这里可以看出,如果某处使用了此函数,并将修饰后的变量带入数据库查询语句中,那么我们就能利用此漏洞实现sql注入。同样的,这个漏洞再CTF比赛中也是很常见的。

3. in_array()绕过

此函数用来检测数组中是否存在某个值。

in_array( mixed $needle, array $haystack[, bool $strict = FALSE] ) : bool

参数

  • needle:带搜索的值(区分大小写)。
  • haystack:带搜索的数组。
  • strict:若此参数的值为TRUE,那么in_array()函数将会检查needle的类型是否和haystack中的类型相同。

有时候我们再传入一个数组的时候,代码可能会过滤某些敏感字符串,但是我们又需要传入这样的字符串,那么我们应该如何绕过它的检测呢?

<?php
    $myarr = array('Alice');
	$needle = 0;
	if(in_array($needle,$myarr)){
    
    
        echo "It's in array";
    }
	else{
    
    
        echo "not in array";
    }
?>

上面代码示例执行的结果会是什么呢?从简单的逻辑上分析。0是不存在要搜索的数组中的,所以理论上,应该是输出not in array,但是实际却输出了It's in array。这是为什么呢?原因就在于PHP的默认类型转换。这里我们第三个参数并没有设置为true那么默认就是非严格比较,所以在数字与字符串进行比较时,字符串先被强制转换成数字,然后再进行比较。并且因为某些类型转换正在发生,就会导致发生数据丢失,并且都被视为相同。所以归根到底还是非严格比较导致的问题。所以再遇到这个函数用来变量检测的时候,我们可以看看第三个参数是否开启,若未开启,则存在数组绕过。


XSS漏洞

首先要对XSS的基本原理要知道。PHP中一下这些函数之所以会出现XSS的漏洞情况,主要还是没有对输出的变量进行过滤。

1.print()

代码示例:

<?php
	$str = $_GET['x'];
	print($str);
?>

在这里插入图片描述

2.print_r()

代码示例:

<?php
	$str = $_GET['x'];
	print_r($str);
?>

在这里插入图片描述

3.echo()

代码示例:

<?php
	$str = $_GET['x'];
	echo "$str";
?>

结果同上

4. printf()

代码示例:

<?php
	$str = $_GET['x'];
	printf($str);
?>

执行结果和上面相同,我就不再贴图片了

5.sprintf()

代码示例:

<?php
	$str = $_GET['x'];
	$a = sprintf($str);
	echo "$a";
?>

6.die()

此函数输出一条信息,并退出当前脚本。

代码示例:

<?php
	$str = $_GET['x'];
	die($str);
?>

7.var_dump()

此函数打印变量的相关信息,用来显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开之,通过缩进显示其结构。

代码示例:

<?php
	$str = $_GET['x'];
	$a = array($str);
	var_dump($a);
?>

8. var_export()

此函数输出或者返回一个变量的字符串表示。它返回关于传递给该函数的变量的结构信息,和var_dump类似,不同的是其返回的表示是合法的 PHP 代码。

代码示例:

<?php
	$str = $_GET['x'];
	$a = array($str);
	var_export($a);
?>

猜你喜欢

转载自blog.csdn.net/pggril/article/details/123830195