├── config.pyc ├── lib ├── db.pyc ├── QQWry.pyc ├── __init__.py ├── util.pyc ├── yamsg.pyc ├── __init__.pyc ├── option.pyc ├── ipaddress.pyc ├── db.py └── util.py ├── modules ├── __init__.py ├── finger.pyc ├── __init__.pyc └── finger.py ├── data └── log │ └── 2017-11-17.log ├── config.py ├── README.md ├── yafinger.py └── pw_finger_db.sql /config.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaseng/yafinger/HEAD/config.pyc -------------------------------------------------------------------------------- /lib/db.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaseng/yafinger/HEAD/lib/db.pyc -------------------------------------------------------------------------------- /lib/QQWry.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaseng/yafinger/HEAD/lib/QQWry.pyc -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- 1 | __import__('pkg_resources').declare_namespace(__name__) 2 | -------------------------------------------------------------------------------- /lib/util.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaseng/yafinger/HEAD/lib/util.pyc -------------------------------------------------------------------------------- /lib/yamsg.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaseng/yafinger/HEAD/lib/yamsg.pyc -------------------------------------------------------------------------------- /lib/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaseng/yafinger/HEAD/lib/__init__.pyc -------------------------------------------------------------------------------- /lib/option.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaseng/yafinger/HEAD/lib/option.pyc -------------------------------------------------------------------------------- /modules/__init__.py: -------------------------------------------------------------------------------- 1 | __import__('pkg_resources').declare_namespace(__name__) 2 | -------------------------------------------------------------------------------- /lib/ipaddress.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaseng/yafinger/HEAD/lib/ipaddress.pyc -------------------------------------------------------------------------------- /modules/finger.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaseng/yafinger/HEAD/modules/finger.pyc -------------------------------------------------------------------------------- /modules/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaseng/yafinger/HEAD/modules/__init__.pyc -------------------------------------------------------------------------------- /data/log/2017-11-17.log: -------------------------------------------------------------------------------- 1 | 2017-11-17 23:17:57 [!][mysql]SELECT * from pw_finger_db where `enable`=1 2 | 2017-11-17 23:17:57 [+][finger]load fingers count 41 3 | 2017-11-17 23:17:58 [+]url:http://127.0.0.1/phpmyadmin/index.php app:phpmyadmin 4 | 2017-11-17 23:18:18 [!][mysql]SELECT * from pw_finger_db where `enable`=1 5 | 2017-11-17 23:18:18 [+][finger]load fingers count 41 6 | 2017-11-17 23:19:00 [+]url:http://www.discuz.net app:discuz 7 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | """ 3 | *@Projet Yafinger 4 | *@Author yaseng@uauc.net 5 | *@Desc global config 6 | """ 7 | import os 8 | from lib.db import * 9 | 10 | #init project 11 | def init(): 12 | pass 13 | 14 | #debug model on: show info alert error succeed message 15 | # off: error & alert succeed message log file & database 16 | debug=1 17 | #log_type 0:log to screen 1:log to file 18 | log_type=1 19 | 20 | #db_config 21 | log_sql=1 22 | db_config={"host":"127.0.0.1","port":3306, "user":"root", "passwd":"", "db":"playweb","charset":'utf8'} 23 | 24 | 25 | #path config 26 | pw_path='./' 27 | path={'log':pw_path+"/data/log/",'data':pw_path+'data/'} 28 | 29 | 30 | #global option 31 | o={} 32 | 33 | def set(key,value): 34 | global o 35 | o[key]=value 36 | 37 | def get(key): 38 | global o 39 | return o[key] 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # yafinger 2 | yet another web fingerprinter 3 | 4 | 5 | __ __ ___ 6 | /\ \ /\ \ /'___\ __ 7 | \ `\`\\/'/ __ /\ \__/ /\_\ ___ __ __ _ __ 8 | `\ `\ /' /'__`\ \ \ ,__\\/\ \ /' _ `\ /'_ `\ /'__`\/\`'__\ 9 | `\ \ \ /\ \L\.\_\ \ \_/ \ \ \ /\ \/\ \ /\ \L\ \ /\ __/\ \ \/ 10 | \ \_\\ \__/.\_\\ \_\ \ \_\\ \_\ \_\\ \____ \\ \____\\ \_\ 11 | \/_/ \/__/\/_/ \/_/ \/_/ \/_/\/_/ \/___L\ \\/____/ \/_/ 12 | /\____/ 13 | \_/__/ 14 | 15 | 16 | ## 安装 17 | 导入数据库,修改配置config.py即可。 18 | 19 | ## 使用 20 | 21 | ``` 22 | ➜ yafinger python yafinger.py 23 | Usage: yafinger.py --host host --port port --finger 24 | Example:yafinger.py --url http://127.0.0.1 --finger phpmyadmin 25 | 26 | Options: 27 | -h, --help show this help message and exit 28 | -u URL, --url=URL target url 29 | -f FINGER, --finger=FINGER 30 | finger_db app_name,default all 31 | ➜ yafinger python yafinger.py --url http://www.discuz.net 32 | [!][mysql]SELECT * from pw_finger_db where `enable`=1 33 | [+][finger]load fingers count 41 34 | [+]url:http://www.discuz.net app:discuz 35 | ``` 36 | 37 | ## 整合 38 | 本项目可以快速作为模块集成到扫描器或者其他项目中。输入url ,线程池识别指纹,结果输出到数据库。 39 | 40 | ## 文章 41 | 《浅谈现代化指纹识别及工具编写》 42 | 43 | 44 | -------------------------------------------------------------------------------- /modules/finger.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | """ 3 | *@Projet Yafinger 4 | *@Author yaseng@uauc.net 5 | *@Desc playweb finger modules 6 | """ 7 | import ast,time 8 | import config 9 | from lib import util 10 | 11 | def get_web_app(url): 12 | rsp_index = util.http_get(url) 13 | str_index = "" 14 | if rsp_index == None : 15 | return None 16 | list_app=[] 17 | fingers=config.get('fingers'); 18 | for finger in fingers : 19 | rule = ast.literal_eval(finger['finger']) 20 | if finger['type'] == 'web_index_contain': 21 | # limit header and body and code exp : {'header':'jsessionid=','code': 200, 'grep': '.action'} 22 | if rule.has_key('header') and rule['header'] not in str(rsp_index['headers']).lower() : 23 | continue 24 | if rsp_index['code'] == rule['code'] and rule['grep'] in rsp_index['data'] : 25 | list_app.append({'app_id':finger['id'], 'url':url}) 26 | util.log("url:%s app:%s" % (url, finger['app_name'])) 27 | 28 | elif finger['type'] == 'web_url_contain' : 29 | rsp_tmp = util.http_get(url + rule['url']) 30 | if rsp_tmp == None : 31 | continue 32 | if rsp_tmp['code'] == rule['code'] and rule['grep'] in rsp_tmp['data'] : 33 | list_app.append({'app_id':finger['id'], 'url':url}) 34 | util.log("url:%s app:%s" % (url + rule['url'], finger['app_name'])) 35 | elif finger['type'] == 'web_header_contain' : 36 | 37 | if rule['grep'] in str(rsp_index['headers']).lower() : 38 | list_app.append({'app_id':finger['id'], 'url':url}) 39 | util.log("url:%s app:%s" % (url , finger['app_name'])) 40 | 41 | 42 | time.sleep(0.01) 43 | return list_app -------------------------------------------------------------------------------- /yafinger.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | """ 3 | *@Projet Yafinger 4 | *@Author yaseng@uauc.net 5 | *@Desc yafinger test 6 | __ __ ___ 7 | /\ \ /\ \ /'___\ __ 8 | \ `\`\\/'/ __ /\ \__/ /\_\ ___ __ __ _ __ 9 | `\ `\ /' /'__`\ \ \ ,__\\/\ \ /' _ `\ /'_ `\ /'__`\/\`'__\ 10 | `\ \ \ /\ \L\.\_\ \ \_/ \ \ \ /\ \/\ \ /\ \L\ \ /\ __/\ \ \/ 11 | \ \_\\ \__/.\_\\ \_\ \ \_\\ \_\ \_\\ \____ \\ \____\\ \_\ 12 | \/_/ \/__/\/_/ \/_/ \/_/ \/_/\/_/ \/___L\ \\/____/ \/_/ 13 | /\____/ 14 | \_/__/ 15 | """ 16 | import os, time, sys, Queue, threading, ast 17 | import config 18 | from lib import util 19 | from lib.db import * 20 | from optparse import OptionParser 21 | from modules import finger 22 | 23 | if __name__ == "__main__": 24 | usage= '''%prog --host host --port port --finger \r\nExample:%prog --url http://127.0.0.1 --finger phpmyadmin ''' 25 | parser = OptionParser(usage=usage) 26 | parser.add_option("-u", "--url", dest="url", help="target url") 27 | parser.add_option("-f", "--finger", dest="finger", help="finger_db app_name,default all ", default="all") 28 | options, arguments = parser.parse_args() 29 | if options.url == None : 30 | parser.print_help() 31 | exit(0) 32 | db = MySQL(config.db_config) 33 | sql_finger_where=' ' if options.finger == 'all' else " and app_name='%s' " % options.finger 34 | db.query("SELECT * from pw_finger_db where `enable`=1 %s " % sql_finger_where) 35 | fingers = db.fetch_all() 36 | if len(fingers) == 0 : 37 | util.log('finger app_name %s not found' % options.finger ,3,'finger') 38 | config.set("fingers",fingers) 39 | util.log("load fingers count %d" % len(fingers),1,'finger') 40 | finger.get_web_app(options.url) 41 | -------------------------------------------------------------------------------- /lib/db.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | """ 3 | *@Projet Yafinger 4 | *@Author yaseng@uauc.net 5 | *@Desc mysql class 6 | """ 7 | 8 | import MySQLdb 9 | import time 10 | import config 11 | from lib import util 12 | 13 | 14 | # mysql 15 | class MySQL: 16 | error_code = '' 17 | 18 | _instance = None 19 | _conn = None 20 | _cur = None 21 | 22 | _TIMEOUT = 30 23 | _timecount = 0 24 | 25 | def __init__(self, dbconfig): 26 | try: 27 | self._conn = MySQLdb.connect(host=dbconfig['host'], 28 | port=dbconfig['port'], 29 | user=dbconfig['user'], 30 | passwd=dbconfig['passwd'], 31 | db=dbconfig['db'], 32 | charset=dbconfig['charset']) 33 | except MySQLdb.Error, e: 34 | self.error_code = e.args[0] 35 | util.log("MySQL error:%d %s" % (e.args[0], e.args[1]), 3, "mysql") 36 | return 37 | 38 | 39 | self._cur = self._conn.cursor(MySQLdb.cursors.DictCursor) 40 | self._instance = MySQLdb 41 | 42 | def execute(self, sql): 43 | if config.log_sql == 1 : 44 | util.log(sql, 2, 'mysql') 45 | return self._cur.execute(sql) 46 | 47 | def query(self, sql): 48 | try: 49 | self._cur.execute("SET NAMES utf8") 50 | result = self.execute(sql) 51 | except MySQLdb.Error, e: 52 | self.error_code = e.args[0] 53 | util.log("Query sql error:%d %s" % (e.args[0], e.args[1]), 3, "mysql") 54 | result = False 55 | return result 56 | 57 | def update(self, sql): 58 | try: 59 | self._cur.execute("SET NAMES utf8") 60 | result=self.execute(sql) 61 | self._conn.commit() 62 | except MySQLdb.Error, e: 63 | self.error_code = e.args[0] 64 | util.log("[MySQL]Update sql error:%d %s" % (e.args[0], e.args[1]), 3, "mysql") 65 | result = False 66 | return result 67 | 68 | def insert(self, sql): 69 | try: 70 | self._cur.execute("SET NAMES utf8") 71 | self.execute(sql) 72 | self._conn.commit() 73 | return int(self._cur.lastrowid) 74 | except MySQLdb.Error, e: 75 | self.error_code = e.args[0] 76 | util.log("[MySQL]Insert sql error:%d %s" % (e.args[0], e.args[1]), 3, "mysql") 77 | return False 78 | 79 | def fetch_all(self): 80 | return self._cur.fetchall() 81 | 82 | def fetch_one(self): 83 | return self._cur.fetchone() 84 | 85 | def getRowCount(self): 86 | return self._cur.rowcount 87 | 88 | def commit(self): 89 | self._conn.commit() 90 | 91 | def rollback(self): 92 | self._conn.rollback() 93 | 94 | def __del__(self): 95 | try: 96 | self._cur.close() 97 | self._conn.close() 98 | except: 99 | pass 100 | 101 | def close(self): 102 | self.__del__() 103 | -------------------------------------------------------------------------------- /lib/util.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | """ 3 | *@Projet Yafinger 4 | *@Author yaseng@uauc.net 5 | *@Desc util library 6 | """ 7 | 8 | 9 | import time, re 10 | import config 11 | import urllib2,cookielib,itertools,os 12 | 13 | import socket 14 | socket.setdefaulttimeout(10) 15 | 16 | 17 | """ 18 | *@desc log function 19 | *@param text: log text 20 | *@param type: log type 0=info([*]) 1=succeed [+] 2=alert [!] 3=error [x] 8=yamsg [y] 21 | *@param module : log module exp:mysql redis 22 | """ 23 | def log(text, type=1, module=""): 24 | str_time = time.strftime('%Y-%m-%d %X', time.localtime()) 25 | str_pre = '[*]' 26 | if type == 1 : 27 | str_pre = '[+]' 28 | elif type == 2: 29 | str_pre = '[!]' 30 | elif type == 3: 31 | str_pre = '[x]' 32 | if len(module) > 0: 33 | module = "[%s]" % module 34 | str_log = str_pre + module + text 35 | if config.debug == 1 : 36 | print str_log 37 | 38 | else : 39 | if type == 0: 40 | return 41 | else : 42 | file_path = config.path['log'] + time.strftime('%Y-%m-%d', time.localtime()) + ".log" 43 | file_log = open(file_path, "a") 44 | file_log.writelines(str_time + " " + str_log + "\n") 45 | file_log.close() 46 | 47 | def msg(text, type=0): 48 | str_pre = "" 49 | if type > 0 : 50 | for i in range(0, type) : 51 | str_pre = str_pre + " " 52 | print str_pre + text 53 | return 54 | 55 | 56 | def find_text(text, start, end): 57 | regex = '%s([\s\S]*)%s' % (start, end) 58 | text_re = re.search(regex, text) 59 | if text_re is None : 60 | return None 61 | return text_re.group(1) 62 | 63 | def addslashes(s): 64 | return s.replace("'", "") 65 | 66 | 67 | def get_http_headers(): 68 | headers = { 'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0', 69 | 'Referer' : 'http://www.baidu.com', 70 | 'X-FORWARDED-FOR' : '216.239.53.53' 71 | 72 | } 73 | return headers 74 | 75 | 76 | def http_get(url, headers=None, time=5): 77 | if headers == None : 78 | headers=get_http_headers() 79 | ret = {} 80 | req = urllib2.Request(url, None, headers) 81 | 82 | try: 83 | r = urllib2.urlopen(req,timeout=time) 84 | ret = {"data":r.read(), "code":200, "headers":r.headers} 85 | except urllib2.HTTPError, e: 86 | ret = {"data":e.read(), "code":e.code, "headers":e.headers} 87 | except urllib2.URLError, e: 88 | return None 89 | except : 90 | return None 91 | return ret 92 | 93 | 94 | def http_post(url, data, headers=None, time=10): 95 | ret = {} 96 | try: 97 | opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookielib.LWPCookieJar())) 98 | req = urllib2.Request(url, data, get_http_headers()) 99 | r = opener.open(req,None,time) 100 | ret = {"data":r.read(), "code":200, "headers":r.headers} 101 | except urllib2.HTTPError, e: 102 | ret = {"data":e.read(), "code":e.code, "headers":e.headers} 103 | except urllib2.URLError, e: 104 | return None 105 | except : 106 | return None 107 | return ret 108 | 109 | def process_exit(name): 110 | return len(os.popen('ps aux | grep %s | grep -v grep' % name ).readlines()) 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /pw_finger_db.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO `pw_finger_db` (`id`, `app_name`, `app_version`, `type`, `enable`, `finger`) VALUES 2 | (3, 'joomla', '', 'web_index_contain ', 1, '{\"code\": 200, \"grep\":\"/media/system/js/caption.js\"}'), 3 | (2, 'HttpFileServer', '', 'web_index_contain', 1, '{\"code\": 200, \"grep\": \"hfs_sid\"}'), 4 | (1, 'mikrotik', '', 'web_index_contain', 1, '{\"code\": 200, \"grep\": \"mikrotik\"}'), 5 | (265, 'AirLive_Camera', '', 'web_header_contain', 1, '{\'grep\':\'airlive\'}'), 6 | (264, 'Cisco_PVC2300_Camera', '', 'web_url_header', 1, '{\'url\':\'/oamp/System.xml?action=login&user=L1_admin&password=L1_51\',\'code\':\'200\',\'grep\':\'sessionid\'}'), 7 | (261, 'D-Link_DCS_Series', '', 'web_header_contain', 1, '{\'grep\':\'dcs-lig-httpd\'}'), 8 | (259, 'TP-Link_Device', '', 'web_header_contain', 1, '{\'grep\': \'tp-link\'}'), 9 | (260, 'IQeye_Camera', '', 'web_header_contain', 1, '{\'grep\':\'iqhttpd\'}'), 10 | (258, 'RomPager_Service', '', 'web_url_header', 1, '{\'url\':\'/rom-0\',\'code\': 200, \'grep\': \'application/octet-stream\'}'), 11 | (257, 'TRENDnet_webcam', '', 'web_header_contain', 1, '{\'grep\': \'netcam\'}'), 12 | (254, 'NETGEAR_ReadyNAS', '', 'web_url_contain', 1, '{\'url\': \'/np_handler\', \'code\': 200, \'grep\': \'Empty\'}'), 13 | (255, 'NETGEAR_DGN_Series', '', 'web_header_contain', 1, '{\'grep\':\'netgear dgn\'}'), 14 | (253, 'Linksys_Device', '', 'web_url_contain', 1, '{\'url\': \'/HNAP1\', \'code\': 200, \'grep\': \'Linksys\'}'), 15 | (252, 'airos_web', '', 'web_header_contain', 1, '{\'grep\':\'ubnt\'}'), 16 | (251, 'D-Link_DIR_Series', '', 'web_header_contain', 1, '{\'grep\':\'dir-\'}'), 17 | (244, 'ASUS_RT-N56U', '', 'web_header_contain', 1, '{\'grep\': \'rt-n56u\'}'), 18 | (243, 'phicomm_router', '', 'web_url_contain', 1, '{\'url\': \'/login.asp\', \'code\': 200, \'grep\': \'400-720-5677\'}'), 19 | (241, 'metinfo', '', 'web_index_contain', 1, '{\'code\': 200,\'grep\': \'metinfo.css\'}'), 20 | (245, 'airos', '', 'web_header_contain', 1, '{\'grep\': \'airos\'}'), 21 | (239, 'espcms', '', 'web_index_contain', 1, '{\'code\': 200,\'grep\': \'infolist_fff\'}'), 22 | (240, 'cmseasy', '', 'web_header_contain', 1, '{\'grep\': \'cmseasy\'}'), 23 | (238, 'ecshop', '', 'web_header_contain', 1, '{\'grep\': \'ecs_id\'}'), 24 | (237, 'WebLogic', '', 'web_url_contain', 1, '{\'url\': \'/console/login/LoginForm.jsp\', \'code\': 200, \'grep\': \'WebLogic Server\'}'), 25 | (236, 'Office Anywhere', '', 'web_index_contain', 1, '{\'code\': 200, \'grep\': \'/images/tongda.ico\'}'), 26 | (235, 'ThinkPHP', '', 'web_header_contain', 1, '{\'grep\': \'thinkphp\'}'), 27 | (234, 'gov_jsp_1', '', 'web_index_contain', 0, '{\'code\': 200, \'grep\': \'/deptWebsiteAction.do\'}'), 28 | (222, 'tomcat', '', 'web_url_contain', 1, '{\'url\': \'/manager/html\', \'code\': 401, \'grep\': \'tomcat\'}'), 29 | (223, 'phpmyadmin', '', 'web_url_contain', 1, '{\'url\': \'/phpmyadmin/index.php\', \'code\': 200, \'grep\': \'phpmyadmin\'}'), 30 | (263, 'Ruijie_GateWay', '', 'web_header_contain', 1, '{\'grep\':\'start http-server\'}'), 31 | (262, 'Network_Camera_LIVE_VIEW_asp', '', 'web_url_contain', 1, '{\'url\': \'/LIVE_VIEW.asp\', \'code\': 200, \'grep\': \'Network Camera\'}'), 32 | (246, 'AirLink101_SkyIPCam', '', 'web_header_contain', 1, '{\'grep\': \'skyipcam\'}'), 33 | (233, 'jboss', '', 'web_header_contain', 1, '{\'grep\': \'jboss\'}'), 34 | (224, 'wdcp', '', 'web_index_contain', 1, '{\'code\': 200, \'grep\': \'wdcp\'}'), 35 | (225, 'wordpress', '', 'web_index_contain', 1, '{\'code\': 200, \'grep\': \'wp-content\'}'), 36 | (226, 'dedecms', '', 'web_index_contain', 1, '{\'code\': 200, \'grep\': \'/plus/search.php\'}'), 37 | (227, 'discuz', '', 'web_header_contain', 1, '{\'grep\': \'_saltkey=\'}'), 38 | (228, 'Seagate Central', '', 'ftp_banner_contain', 1, '{\'banner\':\'Welcome to Seagate Central Shared Storage FTP service\'}'), 39 | (229, 'D-Link DSP-W215', '', 'web_url_contain', 1, '{\'url\':\'/HANP1/\',\'code\':\'200\',\'grep\':\'DSP-W215A1\'}'), 40 | (230, 'D-Link DSP-W110', '', 'web_url_contain', 1, '{\'url\':\'/HANP1/\',\'code\':\'200\',\'grep\':\'DSP-W110\'}'), 41 | (256, 'feiyuxing_router', '', 'web_index_contain', 1, '{\'code\': 200, \'grep\': \'R1Login.css\'}'), 42 | (231, 'struts2', '', 'web_index_contain', 1, '{\'header\':\'jsessionid=\',\'code\': 200, \'grep\': \'.action\'}'), 43 | (232, 'hikvision', '', 'web_url_contain', 1, '{\'url\': \'/doc/page/login.asp\', \'code\': 200, \'grep\': \'Hikvision Digital Technology\'}'), 44 | (268, 'grandstream', 'GXV3611_HD ', 'telnet', 0, '{\'grep\':\'Product of Grandstream\'}'), 45 | (4, 'h264_dvr', '', 'web_index_contain', 0, '{\"code\": 200, \"grep\": \"DVR Components\"}'); 46 | --------------------------------------------------------------------------------