快捷搜索:  汽车  科技

ctf赛常见题型(对一道n1ctf赛题的详细分析)

ctf赛常见题型(对一道n1ctf赛题的详细分析)整个过程如下:$time=(isset($_GET['time'])) ? urldecode(date(file_get_contents('php://input'))) : date("Y/m/d H:i:s"); ​ $name="/var/www/tmp/".time().rand().'.txt'; ​ if(file_put_contents($name $time)){ echo "<pre class='language-html'><code class='language-html'>logpath:$name</code></pre>";而$time的内容会被写入$name所在的文件中。if

最近做了一道N1CTF2021的题目,学到了不少,分享给大家共同学习。

0x01 题目详情

题目如下:

ctf赛常见题型(对一道n1ctf赛题的详细分析)(1)

源码如下:

<?php //flag is /flag ​ $path=$_POST['path']; ​ $time=(isset($_GET['time'])) ? urldecode(date(file_get_contents('php://input'))) : date("Y/m/d H:i:s"); ​ $name="/var/www/tmp/".time().rand().'.txt'; ​ $black="f|ht|ba|z|ro|;| |=|c|g|da|_"; $blist=explode("|" $black); ​ foreach($blist as $b){ ​ if(strpos($path $b) !== false){ ​ • die(); ​ } ​ } ​ if(file_put_contents($name $time)){ ​ • echo "<pre class='language-html'><code class='language-html'>logpath:$name</code></pre>"; ​ } ​ $check=preg_replace('/((\s)*(\n) (\s)*)/i' '' file_get_contents($path)); ​ if(is_file($check)){ ​ • echo "<pre class='language-html'><code class='language-html'>".file_get_contents($check)."</code></pre>"; ​ }

页面下方输出的是日志文件。要拿到flag,我首先关注到下方的两个if语句,先看最下面这个:

if(is_file($check)){ ​ echo "<pre class='language-html'><code class='language-html'>".file_get_contents($check)."</code></pre>"; ​ }

如果$check是一个文件,那么读取他的内容,并输出。如果$check的值刚好是/flag,那这道题就解出来了。而$check是由这行代码来的:

$check=preg_replace('/((\s)*(\n) (\s)*)/i' '' file_get_contents($path));

此处使用了preg_replace函数,将$path文件内容里的换行空格等内容删除。而$path最初是通过POST请求提交的,之后进行了过滤,不能包含一些字符:

$black="f|ht|ba|z|ro|;| |=|c|g|da|_"; ​ $blist=explode("|" $black); ​ foreach($blist as $b){ ​ if(strpos($path $b) !== false){ ​ die(); ​ }

除了POST请求提交path参数我们可以控制,另外一个参数time通过GET方式和伪协议的方式我们也可以控制:

$time=(isset($_GET['time'])) ? urldecode(date(file_get_contents('php://input'))) : date("Y/m/d H:i:s"); ​ $name="/var/www/tmp/".time().rand().'.txt'; ​ if(file_put_contents($name $time)){ echo "<pre class='language-html'><code class='language-html'>logpath:$name</code></pre>";

而$time的内容会被写入$name所在的文件中。

0x02 利用思路

整个过程如下:

ctf赛常见题型(对一道n1ctf赛题的详细分析)(2)

我们可控的地方有path参数和time参数,time参数的内容最终会写入到name文件中。name文件会在每次请求的时候输出,我们不可控,但能够得知name文件的路径。path参数对应的文件名可控,但其文件内容不可控,而check文件名来源于path文件的内容,最终会读取并输出check文件的内容。

所以,我们要想读取/flag的内容,我们就要使check文件内容等于/flag,即可直接在网页中显示出/flag的内容。check文件名可通过path参数进行控制,而name文件内容我们可以通过time参数控制,所以,我们要想方法把/flag这个字符串写入name文件内容中,然后将check文件名设置为name文件即可。

0x03 利用过程

第一步,我们首先将/flag字符串写入time文件。

程序通过如下代码获得time的值:

$time=(isset($_GET['time'])) ? urldecode(date(file_get_contents('php://input'))) : date("Y/m/d H:i:s");

其中涉及到php的伪协议php://input,它可以读取我们POST请求的内容,time参数如果被设置,同时有POST数据,POST数据将会赋值给$time,我在本机进行调试如下:

ctf赛常见题型(对一道n1ctf赛题的详细分析)(3)

内容写入到time对应的txt文件中:

ctf赛常见题型(对一道n1ctf赛题的详细分析)(4)

为什么写入的内容不是/flag?因为有date函数并结果urldecode,所以,改成如下即可:

ctf赛常见题型(对一道n1ctf赛题的详细分析)(5)

查看对应的文件即为/flag:

ctf赛常见题型(对一道n1ctf赛题的详细分析)(6)

而我们将path参数设置为time对应的txt文件名,那么check文件名就会被设置为/flag,最终读取输出flag。

按照本地测试的效果,首先传递time参数,将/flag写入文件,然后记下页面输出的txt文件路径:

ctf赛常见题型(对一道n1ctf赛题的详细分析)(7)

然后再次请求时,指定path为txt文件路径/var/www/tmp/16375737971145120615.txt,得到flag内容:

ctf赛常见题型(对一道n1ctf赛题的详细分析)(8)

猜您喜欢: