def POST(self): params = web.input() kw = { k: params[k].strip() for k in ("title", "url", "ip", "port", "protocol", "level", "os", "server_info", "middleware", "description", "project_id") } Host.insert(**kw) return jsonSuccess()
def POST(self): params = web.input() kw = { k: params[k].strip() for k in ("title", "url", "ip", "port", "protocol", "level", "os", "server_info", "middleware", "description") } Host.where(id=params.id.strip()).update(**kw) return jsonSuccess()
def GET(self): params = web.input() try: projectid = int(params.id) except (ValueError, AttributeError): raise web.internalerror("parameter error.") project = Project.getraw(projectid) if project: hosts = Host.where(project_id=projectid,tmp=0).getsraw() for host in hosts: host['vuls'] = Vul.where(host_id=host['id']).getsraw('name','url','info','type','level','description') host['comments'] = Comment.where(host_id=host['id']).getsraw('name','url','info','level','description') del host['id'] del host['tmp'] del host['project_id'] project['hosts'] = hosts del project['id'] projectName = "_".join(project['name'].split(" ")) projectFile = os.path.join("static","tmp",projectName+".proj") try: with open(projectFile,'w') as fd: json.dump(project, fd) except IOError: raise web.internalerror("save imported project failed")
def GET(self): params = web.input() result = Host.where(project_id=params.projectid.strip(), tmp=0).orderby(params.orderby.strip()).getsraw( 'id', 'title', 'url', 'ip', 'level', 'protocol') return json.dumps(result)
def GET(self): params = web.input() try: projectid = int(params.id) except (ValueError, AttributeError): raise web.internalerror("parameter error.") project = Project.getraw(projectid) if project: hosts = Host.where(project_id=projectid, tmp=0).getsraw() for host in hosts: host['vuls'] = Vul.where(host_id=host['id']).getsraw( 'name', 'url', 'info', 'type', 'level', 'description') host['comments'] = Comment.where(host_id=host['id']).getsraw( 'name', 'url', 'info', 'level', 'description') del host['id'] del host['tmp'] del host['project_id'] project['hosts'] = hosts del project['id'] projectName = "_".join(project['name'].split(" ")) projectFile = os.path.join("static", "tmp", projectName + ".proj") try: with open(projectFile, 'w') as fd: json.dump(project, fd) except IOError: raise web.internalerror("save imported project failed")
def GET(self): web.header('Content-Type', 'application/json') params = web.input() try: hid = str(int(params.id)) except AttributeError as error: RTD.log.error(error) raise web.internalerror(error) try: Host.delete(hid) except (KeyError, AttributeError, FieldError, ModelError, DBError) as error: RTD.log.error(error) raise web.internalerror(error) return jsonSuccess()
def POST(self): web.header('Content-Type', 'application/json') params = web.input(projectfile={}) try: fileName = params.projectfile.filename fileStr = params.projectfile.value except AttributeError: raise web.internalerror("Missing parameter.") projectDict = json.loads(fileStr) hosts = projectDict.get("hosts", []) try: del projectDict['hosts'] except KeyError: pass try: Project(**projectDict).save() except DBError as error: raise web.internalerror("failed to insert project " + str(error)) projectid = Project.where( name=projectDict.get('name')).getsraw('id')[0]['id'] for host in hosts: vuls = host.get("vuls", []) comments = host.get("comments", []) try: del host['vuls'] del host['comments'] except KeyError: pass host['project_id'] = projectid Host(**host).save() kwargs = { key: host[key] for key in ['url', 'ip', 'port'] if key in host } hostid = Host.where(**kwargs).getsraw('id')[0]['id'] for vul in vuls: vul['host_id'] = hostid Vul(**vul).save() for comment in comments: comment['host_id'] = hostid Comment(**comment).save() return jsonSuccess()
def handle(self, data): if not isinstance(data, Host): self.put(data) else: dnsresolver = DnsResolver(data.url) records = dnsresolver.getZoneRecords() for line in records: if line[2] == "A": self.put( Host(url=line[0], ip=line[1], description="Generated by zonetrans plugin.")) elif line[2] == "CNAME": self.put( Host(url=line[0], description= "Generated by zonetrans plugin. Domain alias " + line[1]))
def handle(self, data): if not isinstance(data, Host): self.put(data) else: for host in ServiceIdentify(self.ptype, **data): if 'description' in data: host.description = data.description if 'level' in data: host.level = data.level if host.get('protocol', None) in ['http', 'https']: if 'url' in data: host.url = data.url if 'title' in data: host.title = data.title self.put(Host(**host))
def handle(self, data): if not isinstance(data, Host): self.put(data) return try: dataDomain = self.urlPattern.match(data.url).groups()[0].lower() except AttributeError: raise PluginError("dns brute plugin, domain format error") for item in DnsBrute(dataDomain, self.dictlist, self.bruteTopDomain): self.put(Host(**item))
def POST(self): web.header('Content-Type', 'application/json') originParams = web.input() options = (("domain", "string", "1-200"), ("type", "integer", "0-3"), ("project_id", "integer", "")) try: params = formatParam(originParams, options) except ParamError as error: raise web.internalerror("Parameter error, {0}.".format(error)) domain = params.domain.lower() protocol = "" port = None #resolve protocol if domain.startswith("http://"): protocol = "http" domain = domain[7:] port = 80 elif domain.startswith("https://"): protocol = "https" domain = domain[8:] port = 443 elif "://" in domain: raise web.internalerror( "unrecognized protocol, should be 'http' or 'https'.") #resolve port try: pos = domain.rindex(":") except ValueError: pass else: try: port = int(domain[pos + 1:]) except ValueError: pass domain = domain[:pos] if not protocol: protocol = "http" if not port: port = 80 task = ServiceIdentifyPlugin(ptype=int(params.type)) | DataSavePlugin( projectid=params.project_id) host = Host(url=domain, protocol=protocol, port=port) task.dostart([host]) return jsonSuccess()
def GET(self): web.header('Content-Type', 'application/json') params = web.input() try: projectid = int(params.project_id) except AttributeError as error: RTD.log.error(error) raise web.internalerror(error) iplist = self.getIPList(projectid) hosts = Host.where(project_id=projectid, tmp=1).orderby("ip").getsraw('id','title','ip','port','protocol') result = {'iplist':iplist, 'hosts':hosts} return json.dumps(result)
def handle(self, data): if not isinstance(data, Host): self.put(data) else: try: hostStr = data.ip + "/24" except AttributeError: raise PluginError( "SubnetScanPlugin plugin got an invalid model") portStr = ",".join([str(x) for x in self.portList]) cmd = "nmap -n -PS{ports} -p{ports} {host} -oX -".format( ports=portStr, host=hostStr) result = Nmap.scan(cmd) for host in result: self.put(Host(**host))
def GET(self): params = web.input() if not params.id.strip().isdigit(): raise web.internalerror("Parameter type error.") host = Host.get(params.id.strip()) vuls = Vul.where(host_id=host.id).gets("id") for vul in vuls: vul.remove() comments = Comment.where(host_id=host.id).gets("id") for comment in comments: comment.remove() host.remove() return jsonSuccess()
def GET(self): web.header('Content-Type', 'application/json') params = web.input() try: projectid = int(params.project_id) except AttributeError as error: RTD.log.error(error) raise web.internalerror(error) iplist = self.getIPList(projectid) hosts = Host.where(project_id=projectid, tmp=1).orderby("ip").getsraw( 'id', 'title', 'ip', 'port', 'protocol') result = {'iplist': iplist, 'hosts': hosts} return json.dumps(result)
def POST(self): web.header('Content-Type', 'application/json') params = web.input(projectfile={}) try: fileName = params.projectfile.filename fileStr = params.projectfile.value except AttributeError: raise web.internalerror("Missing parameter.") projectDict = json.loads(fileStr) hosts = projectDict.get("hosts",[]) try: del projectDict['hosts'] except KeyError: pass try: Project(**projectDict).save() except DBError as error: raise web.internalerror("failed to insert project "+str(error)) projectid = Project.where(name=projectDict.get('name')).getsraw('id')[0]['id'] for host in hosts: vuls = host.get("vuls",[]) comments = host.get("comments",[]) try: del host['vuls'] del host['comments'] except KeyError: pass host['project_id'] = projectid Host(**host).save() kwargs = {key:host[key] for key in ['url','ip','port'] if key in host} hostid = Host.where(**kwargs).getsraw('id')[0]['id'] for vul in vuls: vul['host_id'] = hostid Vul(**vul).save() for comment in comments: comment['host_id'] = hostid Comment(**comment).save() return jsonSuccess()
def POST(self): web.header('Content-Type', 'application/json') params = web.input() rawParam = web.data() try: projectid = int(params.project_id) except AttributeError as error: RTD.log.error(error) raise web.internalerror(error) rawParamList = [x.split("=") for x in rawParam.split("&")] ipList = [x[1] for x in rawParamList if x[0] == "iplist"] hosts = [Host(ip=x) for x in ipList] defaultValue = {"tmp": 1} task = SubnetScanPlugin() | ServiceIdentifyPlugin( ptype=1) | DataSavePlugin(defaultValue=defaultValue, projectid=projectid) task.dostart(hosts) return jsonSuccess()
def getIPList(self, projectid): try: hosts = Host.where(project_id=projectid).getsraw("ip") except (KeyError, AttributeError, FieldError, ModelError, DBError) as error: RTD.log.error(error) raise web.internalerror(error) result = list() for host in hosts: try: pos = host['ip'].rindex(".") ip = host['ip'][:pos] + ".1" except (KeyError, ValueError, AttributeError): continue for key in result: if ip == key[0]: key[1] += 1 break else: result.append([ip,1]) return result
def POST(self): web.header('Content-Type', 'application/json') params = web.input() rawParam = web.data() try: projectid = int(params.project_id) except AttributeError as error: RTD.log.error(error) raise web.internalerror(error) rawParamList = [x.split("=") for x in rawParam.split("&")] dictList = [x[1] for x in rawParamList if x[0] == "dictlist"] options = (("domain", "url", ""), ) try: domainParams = formatParam(params, options) except ParamError as error: raise web.internalerror("Parameter error, {0}.".format(error)) task = None if "dnsbrute" in params.keys(): task = DnsBrutePlugin(dictList) if "googlehacking" in params.keys(): task = (task + GoogleHackingPlugin()) if task else GoogleHackingPlugin() if "zonetrans" in params.keys(): task = (task + ZoneTransPlugin()) if task else ZoneTransPlugin() if task is None: task = GoogleHackingPlugin() task = task | ServiceIdentifyPlugin() | DataSavePlugin( projectid=projectid) host = Host(url=domainParams.domain) task.dostart([host]) return jsonSuccess()
def getIPList(self, projectid): try: hosts = Host.where(project_id=projectid).getsraw("ip") except (KeyError, AttributeError, FieldError, ModelError, DBError) as error: RTD.log.error(error) raise web.internalerror(error) result = list() for host in hosts: try: pos = host['ip'].rindex(".") ip = host['ip'][:pos] + ".1" except (KeyError, ValueError, AttributeError): continue for key in result: if ip == key[0]: key[1] += 1 break else: result.append([ip, 1]) return result
def handle(self, data): if not isinstance(data, Host): self.put(data) else: try: domain = data.url[4:] if data.url.startswith("www.") else data.url except AttributeError: raise PluginError("GoogleHackingPlugin plugin got an invalid model") query = Query(site=domain) | -Query(site="www."+domain) resultBaidu = query.doSearch(engine="baidu", size=10) resultBing = query.doSearch(engine="bing", size=10) urlSet = set() for line in itertools.chain(resultBaidu,resultBing): try: url = self.urlPattern.match(line.url).groups()[0] except AttributeError: continue else: if url not in urlSet: urlSet.add(url) description = "Generated by googlehacking plugin.\r\n" + "href: " + line.url + "\r\n" + "description: " + line.brief host = Host(title=line.title,url=url,description=description) self.put(host)
def GET(self): params = web.input() result = Host.where(project_id=params.projectid.strip(),tmp=0).orderby(params.orderby.strip()).getsraw('id','title','url','ip','level','protocol') return json.dumps(result)
def POST(self): params = web.input() kw = {k:params[k].strip() for k in ("title","url","ip","port","protocol","level","os","server_info","middleware","description","project_id")} Host.insert(**kw) return jsonSuccess()
def GET(self): params = web.input() result = Host.getraw(params.id) return json.dumps(result)
def POST(self): params = web.input() kw = {k:params[k].strip() for k in ("title","url","ip","port","protocol","level","os","server_info","middleware","description")} Host.where(id=params.id.strip()).update(**kw) return jsonSuccess()
def __parse_options(): parser = argparse.ArgumentParser(description="配置下发/获取工具") parser.add_argument("-a", "--account", type=str, help=""" 登录时的用户名密码,可指定多对。用户名和密码之间用空格分隔;每对之间用空格分隔。 如: user1 pass1 user2 pass2 user3 pass3 如果同时指定了--account-from-file, 则以--account-from-file为准 """) parser.add_argument( "--account-from-file", help="以文件的形式指定用户名密码。格式为: user1 pass1<换行>user2 pass2<换行>user3 pass3" ) # get or set parser.add_argument("--opmode", choices=[consts.OP_MODE_GET, consts.OP_MODE_SET], required=True, help="操作模式(设置:get, 还是读取: set)") parser.add_argument("--one-command-timeout", type=int, default=600, help="get模式下每条命令超时时间(一条命令最长执行多久). 单位为秒. 默认为600") # 采用手动登录的形式, 不借助库来登录; 只依赖于prompt # # 这个device-type选项只在ssh中有用, 如果写了auto, 会自动探测 # parser.add_argument( # "-t", "--device-type", # choices=[ # consts.MF_CISCO, consts.MF_HUAWEI, consts.MF_H3C, # consts.MF_JUNIPER, consts.MF_LINUX, consts.MF_AUTODETECT # ], # default=consts.MF_AUTODETECT, # help="设备类型, 只针对ssh登录(opmode=set). h3c的自动检测不出来, 可以指定一下. 默认自动检测, 支持: cisco|h3c|juniper|huawei|linux|autodetect") parser.add_argument("--host", default='', required=False, help=""" 对哪个host的设备操作,多个用英文逗号分隔, 每一个的格式为 ip[ device_type], 如 "192.168.3.3 cisco" 或者"192.168.3.3", 其中device_type可选, 无默认值, 不指定的话将会自动探测. 如果同时指定了--host-from-file, 以--host-from-file为准 """) parser.add_argument("--host-from-file", required=False, help=""" 如果host太多,可用文件指定, 一行一个, 每行的格式为: ip[ device_type]. 如 "192.168.3.3 cisco" 或者"192.168.3.3", 其中device_type可选, 无默认值, 不指定的话将会自动探测. """) parser.add_argument("--conn-timeout", required=False, default=5, type=int, help=""" 每个设备通过ssh/telnet建立TCP连接的超时时间(秒). 如果指定时间内未连接成功, 认为连接失败. """) parser.add_argument("--empty-command-interval", required=False, default=30, type=int, help=""" 一个命令执行时间过长时, 可能会导致连接会话断开, 需要下发空命令(如空格)来实现"保活" 此选项即为 下发空命令的时间间隔, 单位为秒 """) parser.add_argument( "--command", default='', required=False, help= "要执行的命令,多个用英文分号分隔. 如果同时指定了command-from-file, 以--command-from-file为准" ) parser.add_argument("--command-from-file", required=False, help="如果命令太多,可用文件指定,一行一条命令. 会忽略空白行") parser.add_argument("--protocol", default='', choices=["ssh", "telnet"], help="登录时使用的协议,目前支持ssh, telnet. 不指定的话取所有支持的挨个试。") parser.add_argument("--ssh-port", default=22, type=int, help="ssh协议端口,默认22") parser.add_argument("--telnet-port", default=23, type=int, help="telnet协议端口,默认23") parser.add_argument("--command-interval", default=0.5, type=float, help="两条命令之间执行的间隔,单位为秒。默认0.5") # parser.add_argument( # "--cmd-exec-until-prompt", # default=False, # action="store_true", # help=""" # get模式时, 每条命令执行直到出现提示符(一般为主机名), 默认为true # 如果这个选项为true, 则会忽略--cmd-interval # """ # ) parser.add_argument("--debug", default=False, help="开启debug模式,默认为false", action="store_true") # parser.add_argument("--parallel", default=False, help="多个host并发执行,默认为false", action="store_true") parser.add_argument("--concurrency", default=1, type=int, help="并发执行时, 同时最多的协程数(默认为1). 为1时表示表示串行, 大于1表示并发") # 对某设备在执行命令时, 发现有报错的(如: Error: Unrecognized command), 跳过此设备 # 如在ssh中执行发现有命令报错的, telnet的也不要再执行了 parser.add_argument( "--ignore-on-command-error", default=False, help="如果命令执行过程出错,是否直接跳过当前设备? 默认为false, 即:命令执行出错就跳过当前设备", action="store_true") parser.add_argument("--output", default='stdout', choices=["stdout", "file"], help="结果输出位置, 默认为标准输出。 如果要输出到文件, 传file") parser.add_argument("--output-dir", default=".", help="如果是输出到文件, 文件放到哪个目录? 默认为当前目录") parser.add_argument( "--output-filename-format", default= "{protocol}-{host}-{username}-{connect_ok}-{login_ok}-{time}", help=""" 如果选择输出到文件, 文件名的格式。time为生成结果时的时间,格式(年月日时分秒)如:20200723_153029. 默认为: {protocol}-{host}-{username}-{connect_ok}-{login_ok}-{time} 其中的{host}, {protocol}等为占位符, 中间的连字符可换成其他的字符。 {login_ok}表示是否登录成功, 具体的会以login_ok, login_err来作为实际的值 如: {host}@{protocol}-{time} """) parser.add_argument( "--ttl", type=int, default=1800, help=""" 脚本执行总时长(秒), 不管多少个主机, 默认1800秒(30分钟). 如果过了这个时间, 脚本会立刻退出 """, ) parser.add_argument( "--output-password", default=False, help=""" 输出结果时要不要打印密码, 默认为false """, action="store_true", ) args = parser.parse_args() args_map = vars(args) # debug模式 global DEBUG_MODE DEBUG_MODE = args_map.get("debug") args_map2 = copy.deepcopy(args_map) if not args_map.get("output_password"): args_map2.pop("account") debug_print("options passed from cli: {}".format(args_map2)) # 命令行参数校验 host = args_map.get("host") host_from_file = args_map.get("host_from_file") host_list = None # split host to list if host: host_list = host.split(",") if host_from_file: # 未指定host,则从文件读取 host_list = utils.get_file_as_lines(host_from_file, ignore_empty_line=True) if not host_list: utils.exit_err(msg="host is empty") # host去重复, 如果重复给出提示 tmp_host_list = [] host_obj_list = [] # Host object slice for host in host_list: if not host: continue host = host.strip() host_pair = host.split(" ") # format: ip[ device_type] host_addr = host_pair[0] host_device_type = consts.MF_AUTODETECT if len(host_pair) > 2: utils.exit_err("host format error: " + host) if len(host_pair) == 2: host_device_type = host_pair[1] host_obj_list.append( Host(addr=host_addr, device_type=host_device_type)) # 重复判断 if host not in tmp_host_list: tmp_host_list.append(host) else: utils.exit_err(msg="duplicated host: " + host) # 每个host都要合法(暂时按ipv4来判断) for host_obj in host_obj_list: host_obj.addr = host_obj.addr.strip() if not utils.valid_ipv4(host_obj.addr): utils.exit_err(msg="invalid ipv4 " + host_obj.addr) args_map["host_list"] = host_obj_list # 处理command command = args_map.get("command") command_from_file = args_map.get("command_from_file") command_list = None if command: command_list = command.split(";") if command_from_file: command_list = utils.get_file_as_lines(command_from_file, ignore_empty_line=True) if not command_list: utils.exit_err(msg="command is empty") # 针对特殊前缀的命令做处理(转ascii码) # 如C^-32 => ' ' for i, _ in enumerate(command_list): if command_list[i].startswith(consts.EMPTY_CMD_PREFIX): command_list[i] = chr( int(command_list[i][len(consts.EMPTY_CMD_PREFIX):])) args_map["command_list"] = command_list # 处理用户名密码 account = args_map.get("account") account_from_file = args_map.get("account_from_file") account_list = [] accounts = [] # [u1, p1, u2, p2, ..., un, pn] if account: accounts = account.split(" ") if account_from_file: tmp_accounts = utils.get_file_as_lines(account_from_file) for a in tmp_accounts: pair = a.split(" ") if len(pair) != 2: utils.exit_err( "username password: {} format error".format(pair)) u = pair[0].strip() p = pair[1].strip() accounts.append(u) accounts.append(p) if len(accounts) % 2 != 0: utils.exit_err("username and password count not match") i = 0 while i < len(accounts): account_list.append( Account( username=accounts[i + 0], password=accounts[i + 1], string_show_password=args_map.get("output_password"), )) i += 2 if not account_list: utils.exit_err(msg="account is empty") cos = CliOptions() cos.account_list = account_list cos.host_list = host_list cos.command_list = command_list fields = vars(cos) for k in args_map: if k in fields: cos.__setattr__(k, args_map[k]) # print(vars(cos)) return cos