[题目信息]:
题目名称 | 题目难度 |
---|---|
PHP-ereg | 1 |
[题目考点]:
ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字母的字符是大小写敏感的。可选的输入参数规则包含一个数组的所有匹配表达式,他们被正则表达式的括号分组。
ereg()函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配.
ereg()函数只能处理字符串的,遇到数组做参数返回NULL.
[Flag格式]:
Sangfor{EM0ji_VF8nQz}
[环境部署]:
docker-compose.yml文件或者docker tar原始文件。
http://分配ip:2019
[题目writeup]:
右键源代码发现存在提示文件,index.php.txt
<?php
header ( 'Content-Type: text/html; charset=utf-8' ); // 网页编码
error_reporting ( 0 );
$flag = "*******************";
//echo $_POST['num'];
if (isset ( $_POST ['num'] )) {
if (@ereg ( "^[1-9]+$", $_POST['num'] ) === FALSE)
echo '说好的数字呢?';
else if (strpos ( $_POST['num'], '#tag' ) !== FALSE)
die ( 'Flag: ' . $flag );
else
echo '你的数字不太符合我的心意哦!';
}
?>
<html>
<head>
<title>猜密码</title>
</head>
<body style="text-align: center">
<center>
<img src="num.png"/>
<form action="index.php" method="post">
<input type="text" name="num" /> <input type="submit" value="提交" />
</form>
</center>
<!-- index.php.txt -->
</body>
</html>
分析代码,首先参数以post方式传入,再看条件,第一个if,ereg函数的作用是正则匹配,此处是要求传入的参数只能为单个或多个数字,结果才能为true,接下来与FALSE进行强比较,结果为FALSE,所以跳过执行下一个判断条件。再看else if,strpos函数的作用是查找后一个字符串在前一个字符串中第一次出现的位置,没有找到的话返回false,找到了话返回true,如果子字符串位于字符串的第一位则会返回0,为了区分0和false,所以需要用强等,=或者!。
所以综上要想得到flag,首先输入的必须为数字,其次里面必须要有#tag,最终才能输出flag,但是明显两个条件不可能同时满足,因此寻找两个处理函数的漏洞才有可能得到flag。
经过查找资料,得到了两个函数的特性:
①ereg和strpos两个函数均是处理字符串的,如果传入的参数为数组,则会返回NULL,而NULL和FALSE、TRUE的类型不同(强等需要类型也相同),因此可以用数组绕过。
②ereg函数存在NULL截断漏洞,导致正则过滤被绕过,可以用%00–截断,而strpos函数不存在,因此可以读取到后面的字符串,所以既可以用%00绕过。
方法一:数组绕过
POST:
num[]=1
方法二:%00截断
POST:
num=1%00#tag
[题目信息]:
题目名称 | 题目难度 |
---|---|
PHP-ereg | 1 |
[题目考点]:
ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字母的字符是大小写敏感的。可选的输入参数规则包含一个数组的所有匹配表达式,他们被正则表达式的括号分组。
ereg()函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配.
ereg()函数只能处理字符串的,遇到数组做参数返回NULL.
[Flag格式]:
SangFor{EJfnq9pZPXW38ZXJ}
[环境部署]:
docker-compose.yml文件或者docker tar原始文件。
http://分配ip:2011
[题目writeup]:
1、实验主页
2、源码分析
<?php
error_reporting(0);
include('flag.php');
if (isset ($_GET['password']))
{
if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
{
echo '<p>数字或者字母</p>';
}
else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999)
{
if (strpos ($_GET['password'], '*-*') !== FALSE)
{
$flag;
}
else
{
'<p>再想想呢</p>';
}
}
else
{
'<p>password不正确!</p>';
}
}
highlight_file(__FILE__);
?>
分析代码首先判断如果有定义通过GET方式传递的变量password,则进入if内的语句。用正则表达式"^[a-zA-Z0-9]+$"匹配password,如果不匹配,返回“数字或者字母”;否则,如果password的长度小于8 或者password大于9999999,并且password中有“*-*”字符串则返回flag。
因为ereg函数存在%00截断漏洞,就是说ereg会把%00当成是字符串的结尾,%00之后的字符串就不进行匹配了。但是strpos并不存在此漏洞。至于长度限制可以使用科学计数法进行绕过。
http://localhost/?password=9e9%00*-*