def insertData(self, tablename, data): retu = 0 try: result, conn, cursor = self._connect() if result: columns = [] values = [] valuesTuple = [] for key in data: columns.append('`' + key + '`') values.append('%s') valuesTuple.append(data[key]) sql = "insert into %s (%s) values (%s)" % ( tablename, ",".join(columns), ",".join(values)) resultExec = cursor.execute(sql, tuple(valuesTuple)) conn.commit() sql = "select LAST_INSERT_ID() as id" resultExec = cursor.execute(sql) conn.commit() res = cursor.fetchone() if res and len(res) > 0 and res['id'] > 0: retu = res['id'] self._close(conn, cursor) return retu except Exception, e: self._close(conn, cursor) logger.exception(e) return retu
def run_domain(http, config): #重新组织请求的参数 scanInfo = {} scanInfo['siteId'] = config['siteId'] scanInfo['ip'] = config['ip'] scanInfo['scheme'] = config['scheme'] scanInfo['domain'] = config['domain'] scanInfo['level'] = config['level'] scanInfo['vulId'] = config['vulId'] headers = headerDictDefault headers['cookie'] = config['cookie'] headers['Host'] = config['domain'] source_ip = config.get('source_ip') responseList = [] try: #使用单引号测试是否存在SQL报错,有则存在漏洞 if source_ip: url = scanInfo['scheme'] + "://" + source_ip else: url = scanInfo['scheme'] + "://" + scanInfo['domain'] response = request(url=url, headers=headers, method="GET") if response['httpcode'] == 200: if response['response_body'].find('foosun') != -1: injectInfo = returnInjectResult(url=url, confirm=1, detail="检测到风讯CMS", response=response) responseList.append(getRecord2(scanInfo, injectInfo)) return responseList except Exception, e: logger.exception(e)
def getDataCount(self, tablename, where): retu = 0 try: result, conn, cursor = self._connect() if result: whereSql = '' for k in where: if whereSql == '': whereSql = "`%s` = '%s'" % (k, where[k]) else: whereSql = "%s and `%s` = '%s'" % (whereSql, k, where[k]) sql = "select count(id) as c from %s where %s" % (tablename, whereSql) returnExec = cursor.execute(sql) res = cursor.fetchone() if res and len(res): retu = res['c'] self._close(conn, cursor) return retu except Exception, e: self._close(conn, cursor) logger.exception(e) return retu
def run_url(http, config, item): # 重新组织请求的参数 scanInfo = {} scanInfo['siteId'] = config['siteId'] scanInfo['ip'] = config['ip'] scanInfo['scheme'] = config['scheme'] scanInfo['domain'] = config['domain'] scanInfo['level'] = config['level'] scanInfo['vulId'] = config['vulId'] headers = headerDictDefault headers['cookie'] = config['cookie'] responseList = [] try: # 使用单引号测试是否存在SQL报错,有则存在漏洞 url = item['url'] path = urlparse.urlparse(url)[2] pathList = path.split('/') if path[-9:] == '.svn-base' or '.svn' in pathList: level = 'LOW' detail = '网址中包含SVN信息' request = '' response = '' responseList.append( getRecord(scanInfo, url, 'LOW', detail, request, response)) return responseList except Exception, e: logger.exception("File:CheckSvnScript_yd.py:")
def run_url(http, config, item): # 重新组织请求的参数 scanInfo = {} scanInfo['siteId'] = config['siteId'] scanInfo['ip'] = config['ip'] scanInfo['scheme'] = config['scheme'] scanInfo['domain'] = config['domain'] scanInfo['level'] = config['level'] scanInfo['vulId'] = config['vulId'] headers = headerDictDefault headers['cookie'] = config['cookie'] responseList = [] try: # 使用单引号测试是否存在SQL报错,有则存在漏洞 url = item['url'] path = urlparse.urlparse(url)[2].lower() if path.find('sitefiles/bairong'): level = 'HIGH' detail = '检测到 SiteServer CMS' request = '' response = '' responseList.append(getRecord(scanInfo, url, 'HIGH', detail, request, response)) return responseList except Exception, e: logger.exception(e)
def deleteData(self, tablename, where): retu = False try: result, conn, cursor = self._connect() if result: values = [] whereSql = '' for k in where: if whereSql == '': whereSql = "`%s` = %s" % (k, '%s') else: whereSql = "%s and `%s` = %s" % (whereSql, k, '%s') values.append(where[k]) sql = "delete from %s where %s" % (tablename, whereSql) resultExec = cursor.execute(sql, tuple(values)) conn.commit() retu = True self._close(conn, cursor) return retu except Exception, e: self._close(conn, cursor) logger.exception(e) return retu
def _close(self, conn, cursor): try: cursor.close() conn.close() except Exception, e: logger.exception(e) return False
def run_domain(http, config): ''' 重写run_url函数,实现检测SQL注入的功能 有异常时,直接输出异常 无异常时,以list类型返回检测结果记录 ''' # 重新组织请求的参数 scanInfo = {} scanInfo['siteId'] = config['siteId'] scanInfo['ip'] = config['ip'] scanInfo['scheme'] = config['scheme'] scanInfo['domain'] = config['domain'] scanInfo['level'] = config['level'] scanInfo['vulId'] = config['vulId'] headers = headerDictDefault headers['cookie'] = config['cookie'] headers['Host'] = config['domain'] source_ip = config.get('source_ip') responseList = [] try: # 使用单引号测试是否存在SQL报错,有则存在漏洞 payload = "'" if source_ip: scanInfo['domain'] = source_ip urlBase = scanInfo['scheme'] + "://" + scanInfo['domain'] # 第一种方式,header头检测 url = urlBase response = request(url=url, headers=headers, method="GET") if response['httpcode'] == 200: if response['response_headers'].has_key('Server') and response[ 'response_headers']["Server"].lower().find('waf'): injectInfo = returnInjectResult( url=url, confirm=1, detail="Web应用防火墙被检测到,扫描被保护的系统,会导致不准确的报告", response=response) responseList.append(getRecord2(scanInfo, injectInfo)) return responseList # 第二种方式,不合法的参数请求,返回403则表示被保护 url = urlBase + '?param=-1+UNION+SELECT+GROUP_CONCAT(table_name)+FROM+information_schema.tables' response = request(url=url, headers=headers, method="GET") if response['httpcode'] == 403 or response['httpcode'] == 461: injectInfo = returnInjectResult( url=url, confirm=1, detail="Web应用防火墙被检测到,扫描被保护的系统,会导致不准确的报告", response=response) responseList.append(getRecord2(scanInfo, injectInfo)) return responseList except Exception, e: logger.exception(e)
def _connect(self): try: conn = MySQLdb.connect(self.host, self.user, self.passwd, db=self.database, charset="utf8") cursor = conn.cursor(MySQLdb.cursors.DictCursor) except Exception, e: logger.exception(e) return (False, None, None)
def cleanWebScan(self, taskId, assetTaskId): retu = False try: result, conn, cursor = self._connect() if result: #清空扫描任务字段 sql = "update `task` set `web_scan_state` = '0', `web_search_site_state` = '0' where `id` = '%s' " % ( taskId) resultExec = cursor.execute(sql) #清空扫描域名记录 if assetTaskId > 0: sql = "delete from `sites` where `task_id` = '%s' and `asset_task_id` = '%s'" % ( taskId, assetTaskId) else: sql = "delete from `sites` where `task_id` = '%s'" % ( taskId) resultExec = cursor.execute(sql) #清空Web扫描结果 if assetTaskId > 0: sql = "delete from `web_result` where `task_id` = '%s' and `asset_task_id` = '%s'" % ( taskId, assetTaskId) else: sql = "delete from `web_result` where `task_id` = '%s'" % ( taskId) resultExec = cursor.execute(sql) #清空Web扫描报文记录 if assetTaskId > 0: sql = "delete from `web_result_data` where `task_id` = '%s' and `asset_task_id` = '%s'" % ( taskId, assetTaskId) else: sql = "delete from `web_result_data` where `task_id` = '%s'" % ( taskId) resultExec = cursor.execute(sql) # #清空扫描的URL记录结果 # if assetTaskId > 0: # sql = "delete from `spider_url` where `task_id` = '%s' and `asset_scan_id` = '%s'" % (taskId, assetTaskId) # else: # sql = "delete from `spider_url` where `task_id` = '%s'" % (taskId) # resultExec = cursor.execute(sql) conn.commit() retu = True self._close(conn, cursor) return retu except Exception, e: self._close(conn, cursor) logger.exception(e) return False
def __init__(self, host='', database='', user='', passwd=''): try: if host == '' or database == '' or user == '' or passwd == '': self.host = SCANER_DB_HOST self.database = SCANER_DB_DATABASE self.user = SCANER_DB_USER self.passwd = SCANER_DB_PASSWORD else: self.host = host self.database = database self.user = user self.passwd = passwd self.module = self.__class__.__name__ except Exception, e: logger.exception(e)
def getRowDataBySql(self, sql): retu = None try: result, conn, cursor = self._connect() if result: resultExec = cursor.execute(sql) res = cursor.fetchone() if res and len(res) > 0: retu = res self._close(conn, cursor) return retu except Exception, e: self._close(conn, cursor) logger.exception(e) return retu
def updateHostWebScanState(self, taskId, assetTaskId, ip): retu = False try: result, conn, cursor = self._connect() if result: sql = "update host_infos set `web_scan_state` = '1' where (select count(id) from sites where `state` <> '1' and `ip` = '%s' and task_id = '%s' and `asset_task_id` = '%s') = 0 and `ip` = '%s' and task_id = '%s' and `asset_task_id` = '%s'" % ( ip, taskId, assetTaskId, ip, taskId, assetTaskId) resultExec = cursor.execute(sql) conn.commit() retu = True self._close(conn, cursor) return retu except Exception, e: self._close(conn, cursor) logger.exception(e) return retu
def getTaskData(self, taskId, columns='*'): retu = None try: result, conn, cursor = self._connect() if result: sql = "select %s from task where id = %s" % (columns, taskId) resultExec = cursor.execute(sql) res = cursor.fetchone() if res and len(res) > 0: retu = res self._close(conn, cursor) return retu except Exception, e: self._close(conn, cursor) logger.exception(e) return retu
def getSiteData(self, siteId, columns='*'): retu = None try: result, conn, cursor = self._connect() if result: sql = "select * from sites where id = '%s'" % (siteId) resultExec = cursor.execute(sql) res = cursor.fetchone() if res and len(res) > 0: retu = res self._close(conn, cursor) return retu except Exception, e: self._close(conn, cursor) logger.exception(e) return retu
def getSpiderUrlOtherCount(self, siteId=0, url='', params='', method=''): retu = 0 try: result, conn, cursor = self._connect() if result: sql = "select count(id) as c from spider_url_other where `site_id`=%s and `url`=%s and `params`=%s and `method`=%s" sequence = (siteId, url, params, method) resultExec = cursor.execute(sql, sequence) res = cursor.fetchone() if res and len(res): retu = res['c'] self._close(conn, cursor) return retu except Exception, e: self._close(conn, cursor) logger.exception(e) return retu
def getAssetTaskId(self, taskId): retu = False try: result, conn, cursor = self._connect() if result: sql = "select `asset_task_id` from `task` where `id` = '%s'" % ( taskId) resultExec = cursor.execute(sql) res = cursor.fetchone() if res and len(res) > 0: retu = res['asset_task_id'] self._close(conn, cursor) return retu except Exception, e: self._close(conn, cursor) logger.exception(e) return retu
def getSiteExceptionCount(self, siteId): retu = 0 try: result, conn, cursor = self._connect() if result: sql = "select `exception_count` from sites where id = '%s'" % ( siteId) resultExec = cursor.execute(sql) res = cursor.fetchone() if res and res.has_key('exception_count'): retu = res['exception_count'] self._close(conn, cursor) return retu except Exception, e: self._close(conn, cursor) logger.exception(e) return retu
def countSpiderUrlForPost(self, siteId, url, patternPost): retu = 0 try: result, conn, cursor = self._connect() if result: sql = "select count(1) as total from spider_url where `site_id`=%s and `url`=%s and `pattern_post`=%s and `method`=%s" sequence = (siteId, url, patternPost, "post") resultExec = cursor.execute(sql, sequence) res = cursor.fetchone() if res and len(res): retu = res['total'] self._close(conn, cursor) return retu except Exception, e: self._close(conn, cursor) logger.exception(e) return retu
def getUrlList(self, siteId): retu = [] try: result, conn, cursor = self._connect() if result: sql = "select * from spider_url where site_id = '%s'" % ( siteId) resultExec = cursor.execute(sql) res = cursor.fetchall() if res and len(res) > 0: retu = res self._close(conn, cursor) return retu except Exception, e: self._close(conn, cursor) logger.exception(e) return retu
def run_url(http, config, item): frame = config.get('siteType') if frame and frame in ['asp', 'aspx', 'jsp']: return [] # 重新组织请求的参数 scanInfo = {} scanInfo['siteId'] = config['siteId'] scanInfo['ip'] = config['ip'] scanInfo['scheme'] = config['scheme'] scanInfo['domain'] = config['domain'] scanInfo['level'] = config['level'] scanInfo['vulId'] = config['vulId'] headers = headerDictDefault headers['cookie'] = config['cookie'] headers['Host'] = config['domain'] source_ip = config.get('source_ip') responseList = [] try: # 使用单引号测试是否存在SQL报错,有则存在漏洞 url = item['url'] url_parse = urlparse.urlparse(url) scheme = url_parse.scheme domain = url_parse.netloc path = url_parse.path query = url_parse.query if source_ip: domain = source_ip if query: new_url = "%s://%s%s?%s" % (scheme, domain, path, query) else: new_url = "%s://%s%s" % (scheme, domain, path) response = request(url=new_url, headers=headers, method="GET") if response['httpcode'] == 200: if response['response_body'].find('phpvod') != -1: injectInfo = returnInjectResult( url=new_url, confirm=1, detail="检测到phpvod/vodcms 视频管理系统", response=response) responseList.append(getRecord2(scanInfo, injectInfo)) return responseList except Exception, e: logger.exception("CheckVodCmsScript_yd" + e.message)
def run_domain(http, config): # 重新组织请求的参数 server = config.get('server') if server in ['nginx', 'iis']: return [] scanInfo = {} scanInfo['siteId'] = config['siteId'] scanInfo['ip'] = config['ip'] scanInfo['scheme'] = config['scheme'] scanInfo['domain'] = config['domain'] scanInfo['level'] = config['level'] scanInfo['vulId'] = config['vulId'] headers = headerDictDefault headers['cookie'] = config['cookie'] headers['Host'] = config['domain'] source_ip = config.get('source_ip') responseList = [] try: # 使用单引号测试是否存在SQL报错,有则存在漏洞 payload = "'" if source_ip: url = scanInfo['scheme'] + "://" + source_ip else: url = scanInfo['scheme'] + "://" + scanInfo['domain'] response = request(url=url, headers=headers, method="GET") if response['httpcode'] == 200: server = '' if response['response_headers'].has_key('server'): server = response['response_headers']['server'] if response['response_headers'].has_key('Server'): server = response['response_headers']['Server'] server = server.lower() if server and server.find("apache") != -1: version = server.split(' ')[0].split('/')[1] if version > '2.2.0' and version < '2.3.0' and version != '2.2.15': injectInfo = returnInjectResult( url=url, confirm=1, detail="Apache mod_isapi模块悬挂指针漏洞", response=response) responseList.append(getRecord2(scanInfo, injectInfo)) return responseList except Exception, e: logger.exception(e)
def run_url(http, config, item): # 重新组织请求的参数 scanInfo = {} scanInfo['siteId'] = config['siteId'] scanInfo['ip'] = config['ip'] scanInfo['scheme'] = config['scheme'] scanInfo['domain'] = config['domain'] scanInfo['level'] = config['level'] scanInfo['vulId'] = config['vulId'] headers = headerDictDefault headers['cookie'] = config['cookie'] headers['Host'] = config['domain'] source_ip = config.get('source_ip') responseList = [] try: # 使用单引号测试是否存在SQL报错,有则存在漏洞 url = item['url'] url_parse = urlparse.urlparse(url) scheme = url_parse.scheme domain = url_parse.netloc path = url_parse.path query = url_parse.query if source_ip: domain = source_ip if query: url = "%s://%s%s?%s" % (scheme, domain, path, query) else: url = "%s://%s%s" % (scheme, domain, path) path = urlparse.urlparse(url)[2] if path[-3:] == '.js' or path[-4:] == '.css': response = request(url=url, headers=headers, method="GET") if response['httpcode'] == 200: if response['response_body'].find('eWebEditor') != -1: injectInfo = returnInjectResult( url=url, confirm=1, detail="检测到eWebEditor,此编辑器一般会有默认后台及默认密码", response=response) responseList.append(getRecord2(scanInfo, injectInfo)) return responseList except Exception, e: logger.exception("ScanEWebEditor_yd" + e.message)
def run_url(http, config, item): ''' 有异常时,直接输出异常 无异常时,以list类型返回检测结果记录 ''' # 重新组织请求的参数 scanInfo = {} scanInfo['siteId'] = config['siteId'] scanInfo['ip'] = config['ip'] scanInfo['scheme'] = config['scheme'] scanInfo['domain'] = config['domain'] scanInfo['level'] = config['level'] scanInfo['vulId'] = config['vulId'] headers = headerDictDefault headers['cookie'] = config['cookie'] headers['Host'] = config['domain'] source_ip = config.get('source_ip') responseList = [] try: url = item['url'] url_parse = urlparse.urlparse(url) scheme = url_parse.scheme domain = url_parse.netloc path = url_parse.path query = url_parse.query if source_ip: domain = source_ip if query: new_url = "%s://%s%s?%s" % (scheme, domain, path, query) else: new_url = "%s://%s%s" % (scheme, domain, path) # path = urlparse.urlparse(url)[2] if path[-3:] == '.js': response = request(url=new_url, headers=headers, method="GET") if response['httpcode'] == 200: if response['response_body'].find('hdwiki'): injectInfo = returnInjectResult(url=new_url, confirm=1, detail="检测到HDWiki建站系统", response=response) responseList.append(getRecord2(scanInfo, injectInfo)) return responseList except Exception, e: logger.exception(e)
def run_domain(http, config): ''' 重写 run_url 函数,实现检测 SQL 注入的功能 有异常时,直接输出异常 无异常时,以 list 类型返回检测结果记录 ''' # 重新组织请求的参数 scanInfo = {} scanInfo['siteId'] = config['siteId'] scanInfo['ip'] = config['ip'] scanInfo['scheme'] = config['scheme'] scanInfo['domain'] = config['domain'] scanInfo['level'] = config['level'] scanInfo['vulId'] = config['vulId'] headers = headerDictDefault headers['cookie'] = config['cookie'] headers['Host'] = config['domain'] source_ip = config.get('source_ip') responseList = [] try: if source_ip: url = scanInfo['scheme'] + "://" + source_ip else: url = scanInfo['scheme'] + "://" + scanInfo['domain'] response = request(url=url, headers=headers, method="GET") if response['httpcode'] == 200: try: jsonData = json.loads(response['response_body']) if jsonData['version']['number'] < '1.2.1': injectInfo = returnInjectResult( url=url, confirm=1, detail="Elasticsearch 1.2 及以下版本存在命令执行漏洞", response=response) responseList.append(getRecord2(scanInfo, injectInfo)) return responseList except Exception, e: logger.info(url + " cant return a valid json format string") return responseList except Exception, e: logger.exception(e)
def getWebVulByPolicy(self, policyId): vulList = [] try: result, conn, cursor = self._connect() if result: vulList = [] sql = "select `vul_id`,`level`,`vul_name`,`scan_type`,`script` from `web_vul_list` where web_vul_list.enable=1 and `vul_id` in (select `vul_id` from `web_vul_policy_ref` where `policy_id` = '%s') order by `priority` asc" % ( str(policyId)) resultExec = cursor.execute(sql) res = cursor.fetchall() if res and len(res) > 0: for row in res: vulList.append(row) self._close(conn, cursor) return vulList except Exception, e: self._close(conn, cursor) logger.exception(e) return vulList
def getUnscandSite(self, taskId, assetTaskId=0): siteIds = [] try: result, conn, cursor = self._connect() if result: sql = "select `id` from `sites` where `state` <> '1' and `task_id` = '%s' and `asset_task_id` = '%s'" % ( taskId, assetTaskId) resultExec = cursor.execute(sql) conn.commit() res = cursor.fetchall() if res and len(res) > 0: for row in res: siteIds.append(str(row['id'])) self._close(conn, cursor) return siteIds except Exception, e: self._close(conn, cursor) logger.exception(e) return siteIds
def getRowData(self, tablename, where, columns='*'): retu = None try: result, conn, cursor = self._connect() if result: whereSql = ' 1 = 1 ' values = [] for k in where: whereSql = "%s and `%s` = %s" % (whereSql, k, '%s') values.append(where[k]) sql = "select %s from %s where %s" % (columns, tablename, whereSql) resultExec = cursor.execute(sql, tuple(values)) res = cursor.fetchone() if res and len(res) > 0: retu = res self._close(conn, cursor) return retu except Exception, e: self._close(conn, cursor) logger.exception(e) return retu
def run_domain(http, config): # 重新组织请求的参数 scanInfo = {} scanInfo['siteId'] = config['siteId'] scanInfo['ip'] = config['ip'] scanInfo['scheme'] = config['scheme'] scanInfo['domain'] = config['domain'] scanInfo['level'] = config['level'] scanInfo['vulId'] = config['vulId'] headers = headerDictDefault headers['cookie'] = config['cookie'] headers['Host'] = config['domain'] source_ip = config.get('source_ip') responseList = [] try: # 使用单引号测试是否存在SQL报错,有则存在漏洞 payload = "'" if source_ip: url = scanInfo['scheme'] + "://" + source_ip else: url = scanInfo['scheme'] + "://" + scanInfo['domain'] response = request(url=url, headers=headers, method="GET") if response['httpcode'] == 200: xPoweredBy = '' for key, value in response['response_headers'].iteritems(): if key.lower() == 'x-powered-by': xPoweredBy = value.lower() if xPoweredBy and xPoweredBy.find("php") != -1: version = xPoweredBy.split(' ')[0].split('/')[1] if (version >= '5.3.0' and version <= '5.3.5') or (version >= '5.2.0' and version <= '5.2.17'): injectInfo = returnInjectResult(url=url, confirm=1, detail="PHP浮点数解析挂起漏洞", response=response) responseList.append(getRecord2(scanInfo, injectInfo)) return responseList except Exception, e: logger.exception(e)
def run_domain(http, config): ''' 重写run_url函数,实现检测SQL注入的功能 有异常时,直接输出异常 无异常时,以list类型返回检测结果记录 ''' #重新组织请求的参数 scanInfo = {} scanInfo['siteId'] = config['siteId'] scanInfo['ip'] = config['ip'] scanInfo['scheme'] = config['scheme'] scanInfo['domain'] = config['domain'] scanInfo['level'] = config['level'] scanInfo['vulId'] = config['vulId'] headers = headerDictDefault headers['cookie'] = config['cookie'] headers['Host'] = config['domain'] source_ip = config.get('source_ip') responseList = [] try: #使用单引号测试是否存在SQL报错,有则存在漏洞 payload = "'" if source_ip: urlBase = scanInfo['scheme'] + "://" + source_ip else: urlBase = scanInfo['scheme'] + "://" + scanInfo['domain'] url = urlBase + '/admin/index1.asp' response = request(url=url, headers=headers, method="GET") if response['httpcode'] == 200: injectInfo = returnInjectResult(url=urlBase, confirm=1, detail="仙游旅行社管理系统后台越权访问", response=response) responseList.append(getRecord2(scanInfo, injectInfo)) return responseList except Exception,e: logger.exception(e)