以下是个人理解,错误的地方请指出。。
题目网址
http://ctf5.shiyanbar.com/web/more.php
思路
题目就是思路,其实只要知道什么是ereg()截断漏洞,这题就简单了,关键是题目告诉我了,但我也不知道怎么去使用!!!
截断漏洞
这到底是什么鬼?
按漏洞的名称来看,既然是截断漏洞,就肯定有个东西在某个地方把他给截了,是用什么东西呢?在什么地方呢?具体怎么操作呢?
看以下介绍
题目代码
<?php
if (isset ($_GET['password'])) {
if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
{
echo '<p>You password must be alphanumeric</p>';
}
else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999)
{
if (strpos ($_GET['password'], '*-*') !== FALSE)
{
die('Flag: ' . $flag);
}
else
{
echo('<p>*-* have not been found</p>');
}
}
else
{
echo '<p>Invalid password</p>';
}
}
?>
知识点:
ereg(string pattern, string originalstring, [array regs]); 就是一个正则匹配,匹配不到返回 false.
strpos(string,find,start),string是整个字符串,find是你想要找到的,start是定义开始的位置。这个函数的作用就是找find在string中的第一次出现的位置,如果有就返回位置,如果没有就返回False.
password满足的要求
if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
1,password必须是a-zA-Z0-9的字符
if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999)
2,password的长度小于8并且password要大于9999999
if (strpos ($_GET['password'], '*-*') !== FALSE)
3,password中必须要包含 *-*
漏洞利用
ereg()存在2个漏洞:
1,当password为数组时返回的是null
2,当遇到%00是会被截断
第一种方法
长度小于8并且password要大于9999999可以使用科学计数法表示 1e8
password = 1e8%00-
%00是一个空字节,占用字节为1
ereg()在匹配字符串的时候遇到%00就只认前面的后面的就会被过滤,进而完成了绕过。
第二种方法
既然password为数组时返回null,那我就传入一个数组试试呢
http://ctf5.shiyanbar.com/web/more.php?password=[5]
提示这样做不对
我又想了下,用下面的形式试试呢(原来就是以这样的形式传数组的)
http://ctf5.shiyanbar.com/web/more.php?password[]=8 没想到flag直接就出来的,哈哈哈
但原理呢?
ereg ("^[a-zA-Z0-9]+$", $_GET['password'])
password为数组,ereg()返回的就是null,
null === false 肯定是false。
三等于号是数值,类型一起做比较的,都匹配对的话为true
所以上面的这句代码就被绕过了
但下面的代码为什么被执行了呢????
strlen($_GET['password']) < 8
不用说了,肯定是满足条件的
$_GET['password'] > 9999999
password是array,在php中array和其他类型比较,总是更大,所以这也满足条件了。
strpos ($_GET['password'], '*-*') !== FALSE)
strpos()官网介绍
password是数组,官网里说strpos()传入数组时会出现意料之外的情况,呵呵,难道说的就是这种情况?这就代码居然也被绕过了。。。。。