Loading... <div class="tip share">请注意,本文编写于 1175 天前,最后修改于 710 天前,其中某些信息可能已经过时。</div> <div class="tip inlineBlock error"> 本项目已经停止线上预览,感谢您的支持 </div> # 任务 根据这项理论,实现整套蜜罐系统。 # 更新说明 2022年2月24日 更新了一条Bug解决方案 # 开源地址 https://github.com/zunmx/Threat-platform # 引言 我的毕业设计就是网络空间资产搜索引擎,主要灵感源于ZoomEye和shodan,但是后来发现fofa也挺强悍的,相对于更新频率来说,fofa频率仿佛更快一些,简单来说,网络空间资产就是对你的服务器进行扫描,检测端口,服务器应用和服务。一般来说,我们可以设置防火墙和IP白名单来限制这种行为,但是,对于这类扫描,我们可以通过迷惑行为,来让攻击者无从下手,或者更加提起攻击者的兴趣,我也是这么做的。 <div class="tip inlineBlock share"> 这里的数据库密码可不是我真正的数据库密码嗷,不要以身试法了,我也不会犯这种低级错误的。🤭 </div> # 我的扫描 前夕我对此理论进行实践,得到了很好的效果,并且可以发现,常见的攻击端口以及攻击者的IP,根据这些数据,也可以得到大概的一个结论,那些IP是危险IP,那些端口属于高危端口,比如我们使用常用的端口扫描工具nmap,看一下对我的测试服务器进行扫描的结果。 ![image.png](https://www.zunmx.top/usr/uploads/2021/07/2495080761.png) 由于开放端口太多,我这里仅对部分截图进行展示,对于端口号,我们可以打开所有,但是也有一些弊端。 # 并不是要占用所有端口 为什么说不能占用所有端口呢?比如FTP服务,不仅仅是21端口,其中还会打开其他端口进行传输文件,比如被动模式下,可能还会开启xxxxx号端口。也就是说,当你启动端口迷惑应用之后,其他程序若想再监听端口,就会启动失败,所以我们也要认真的排除可能需要的端口。 # 成果图 ![image.png](https://www.zunmx.top/usr/uploads/2021/07/4034527773.png) 这里是对于经常访问的IP和端口,根据发送的数据来分析可能进行的行为。 ![image.png](https://www.zunmx.top/usr/uploads/2021/07/1898478155.png) 以日记的访问量,这仅仅是暴露在公网上的IP,可想而知网络上的各种行为,真的是忽视了,万万没有想到,每分钟真的存在这么多行为。 # 代码 ```python import socket import threading import logging import os import time import pymysql import datetime import traceback js = """<script>setInterval(function(){var total="";for (var i=0;i<1000;i++){total= total+i.toString();history.pushState(0,0,total);}},1000)</script>""" sql = "insert into tp(sourceIP,targetPort,data,flag,intime) values(%s,%s,%s,%s,%s)" class Logger(object): def __init__(self, _filename=None): self.logger = logging.getLogger("") logFolder = os.path.join(os.getcwd(), 'logs') if not os.path.exists(logFolder): os.makedirs(logFolder) timestamp = time.strftime("%Y-%m-%d", time.localtime()) logfilename = '%s.txt' % ( timestamp) if _filename is None else '%s-%s.txt' % (_filename, timestamp) logFile = os.path.join(os.getcwd(), 'logs', logfilename) logging.basicConfig(filename=logFile, level=logging.DEBUG, format='> %(levelname)s - %(asctime)s - %(name)s\n%(message)s') def info(self, message): self.logger.info(message) print("\n" + message) def debug(self, message): self.logger.debug(message) print("\n" + message) def warning(self, message): self.logger.warning(message) print("\n" + message) def error(self, message): self.logger.error(message) print(message) _logger = Logger('FAKE PORT') def bindPort(port): global cursor, db def getFlag(data): flag = str() data = str(data) if data.find("b''") > -1 or (len(data) < 12 and len(data) > 0) or data.find("help") < 5 and data.find( "help") > 0: flag+="端口扫描 / " if data.find("login") > -1: flag+="登录检测 / " if data.find("mstshash") > -1: flag+="RDP扫描 / " if len(data.split("\\x")) > 1: flag+="漏洞exploit / " if data.find("HTTP/") > -1: flag+="Web应用检测 / " if data.find("EHLO ") > -1 or data.find("NOOP") > -1: flag+="邮件服务器检测 / " if data.find("RTSP/") > -1: flag+="RTSP应用检测 / " if data.find("libssh") > -1 or data.find("SSH-") > -1 or data.find("openssl") > -1: flag+="SSH检测 / " if data.find("help") > -1 or data.find("stats") > -1 or data.find("info") > -1: flag+="TELNET检测 / " if data.find("application/sdp") > -1 or data.find("sip:") > -1 > -1: flag+="SDP/SIP 检测 / " if data.find("fox a 1 -1 ") > -1: flag+="未知的检测源[fox a 1 -1] / " if flag == "": flag+="端口检测" return flag def inner(port): try: s = socket.socket() host = socket.gethostname() s.bind((host, port)) s.listen(10) # _logger.debug(str(port)+"启动成功") while True: try: conn, addr = s.accept() data = conn.recv(1024) _logger.info( "================================================================================================\n[Client]\n" + " IP:" + str(addr[0]) + '\n PORT:' + str(addr[1]) + '\n[Server]\n PORT:' + str(port) + "\n DATA:" + str(data)) db = pymysql.connect("localhost", "root", "abcDefg15732*", "CTEWP") # Threat platform cursor = db.cursor() cursor.execute(sql, (str(addr[0]), int(port), str(data), getFlag(data), datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) db.commit() if str(data).find("HTTP/") != -1: response_line = 'HTTP/1.1 403 forbidden\n' response_head = 'content-type: text/html,*/*;\n charset=UTF-8;\nServer: Apache_Smile_Lang\nSFW:Z-Security\n\n' response_body = '<title>Access denied</title><h1>Access denied</h1><br/>MSG--> Please close this page -->Z-SFW'+js conn.send( bytes(str(response_line+response_head+response_body).encode("utf8"))) else: conn.send( b">>-------------------------- \n [#] Access denied; \n [MSG]-->Connect close -->Z-SFW \n--------------------------<<") # conn.sendall(data) conn.close() except Exception as e: _logger.error("[ERROR] " + str(port) + "存在异常" + str(e)) db = pymysql.connect("localhost", "root", "abcDefg15732*", "CTEWP") # Threat platform cursor = db.cursor() traceback.print_exc() except Exception as e: _logger.error("[ERROR] " + str(port) + "启动失败" + str(e) ) threading.Thread(target=inner, args=(port,)).start() if __name__ == '__main__': global cursor, db db = pymysql.connect("localhost", "root", "abcDefg15732*", "CTEWP") # Threat platform cursor = db.cursor() for i in range(1, 10000): if (i in [80, 8080, 8000, 23]): continue bindPort(i) input() ``` # 备注 这里的行为分析也不是很准确,仅供参考。 # 配上可视化页面和数据库操作 引用一个前端模板,后端使用什么语言都可以,写数据库的就用python了,无非是查询,java,php都可以,当然对于开发难以程度来说,PHP是我的首选。但是一定要注意SQL注入嗷,所以最好把SQL语句写死,毕竟这只是个查询。前端页面的绑定可以选择Vue,但是任务量不大,原生JS和jQuery也是可以的,但是我为了复习原有的知识,使用了Angular,目前还有一些漏洞,有时间再维护一下吧,也属于疑难杂症,双向绑定偶尔失效,(lll¬ω¬)😓 # 稍加改造[TODO] 我在fofa中看到排除干扰项,可能也是为了排除迷惑吧,我当前上面的代码时支持telnet和http的连接的,如果我们写许多个模板,随机输出,这样就能真正的造成干扰,比如HTTP报头、远程桌面的、ftp的、ssh的,都可以伪造一下,让攻击者以为开放了这个端口,当我们把默认端口修改后,然后使用这个程序,效果最佳。 # 升级版 在微步云平台上分享了这个小玩意儿,感觉大家对这个东西还是蛮感兴趣的,故开放了目前我正在使用的版本。 ```python import datetime import logging import os import random import socket import threading import time import traceback import pymysql js = """<script>setInterval(function(){var total="";for (var i=0;i<1000;i++){total= total+i.toString();history.pushState(0,0,total);}},1000)</script>""" sql = "insert into tp(sourceIP,targetPort,data,flag,intime) values(%s,%s,%s,%s,%s)" tmp = random.sample('1230495867zyxwvutsrqponmlkjihgfedcba', random.randint(5, 10)) domainExample = "" for i in tmp: domainExample += i randomList = [ """HTTP/1.1 403 forbidden\ncontent-type: text/html,*/*;\ncharset=UTF-8;\nServer: Apache_Smile_Lang\nSFW:Z-Security\n\n<title>Access denied</title><h1>Access denied</h1><br/>MSG--> Please close this page -->Z-SFW """ + js, """Remote Desktop Protocol \x03\x00\x00\x13\x0e\xd0\x00\x00\x124\x00\x03\x00\x08\x00\x05\x00\x00\x00 Flag: PROTOCOL_SSL | PROTOCOL_RDSTLS Target_Name: {0} Product_Version: 10.0.19041 Ntlm 15 OS: Windows 10 NetBIOS_Domain_Name: {0} NetBIOS_Computer_Name: {0} DNS_Domain_Name: {0} DNS_Computer_Name: {0} System_Time: {1} +0000 UTC """.format(random.sample('1230495867zyxwvutsrqponmlkjihgfedcba', random.randint(5, 10)), time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())), """SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3""", """SSH-2.0-OpenSSH_7.4""", """SSH-2.0-OpenSSH_6.7p1 Debian-5""", """SSH-2.0-OpenSSH_8.1""", """220 Welcome to all FTP service. 530 Please login with USER and PASS.""", """220 (vsFTPd 3.0.3)""", """220 Microsoft FTP Service""", """220 (vsFTPd 3.0.2)""", """Login: Username:""", """G\x00\x00\x00\xffj\x04Host '*.*.*.*' is not allowed to connect to this MySQL server""", """Mysql Version: 8.0.19 J\x00\x00\x00 8.0.19\x00\xde#\x07\x00[~\x1a%-\x18 K\x00\xff\xff\xff\x02\x00\xff\xc7\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14yM5\x14 sJD\x0et1\x00caching_sha2_password\x00""", """I\x00\x00\x00\xffj\x04Host '*.*.*.*' is not allowed to connect to this MariaDB server""", """Mysql Version: 5.5.5-10.4.13-MariaDB-log ]\x00\x00\x00 5.5.5-10.4.13-MariaDB-log\x00\x93\x0f\x00\x00`9:V$N>,\x00\xfe\xff\x08\x02\x00\xff\xc1\x15\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00`"$-T@$1kHeE\x00mysql_native_password\x00""", """Mysql Version: 5.7.31-percona-sure1-log \\x00\x00\x00 5.7.31-percona-sure1-log\x00\x8aE\xdd\x00\x10\x1eq\\x13N_.\x00\xff\xff\x08\x02\x00\xff\xc1\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Gknrr~":Y\x19iK\x00mysql_native_password\x00""", """Version:9.2.0.8.0 \x016\x00\x01\x08\x00\x7f\xff\x01\x00\x00-\x00 \x08\x00\x00\x00\x00\x00\x00\x00\x00(DESCRIPTION=(TMP=)(VSNNUM=153094144)(ERR=0))""", """Version:11.2.0.1.0 "\x00\x00Y(DESCRIPTION=(TMP=)(VSNNUM=186646784)(ERR=1189)(ERROR_STACK=(ERROR=(CODE=1189)(EMFI=4))))""", """-ERR unknown command 'help' -NOAUTH Authentication required.""", """-ERR unknown command `help`, with args beginning with: -NOAUTH Authentication required.""", """Magic:ActiveMQ Version:12 \x00\x00\x01\x8e\x01ActiveMQ\x00\x00\x00\x01\x00\x00\x01|\x00\x00\x00\x00\x11TcpNoDelayEnabled\x01\x01\x00\x12SizePrefixDisabled\x01\x00\x00 CacheSize\x05\x00\x00\x04\x00\x00ProviderName \x00\x08ActiveMQ\x00\x11StackTraceEnabled\x01\x01\x00\x0fPlatformDetails \x00WJVM: 1.8.0_162, 25.162-b12, Oracle Corporation, OS: Linux, 2.6.32-642.el6.x86_64, amd64\x00CacheEnabled\x01\x01\x00\x14TightEncodingEnabled\x01\x01\x00MaxFrameSize\x06\x7f\xff\xff\xff\xff\xff\xff\xff\x00\x15MaxInactivityDuration\x06\x00\x00\x00\x00\x00\x00u0\x00 MaxInactivityDurationInitalDelay\x06\x00\x00\x00\x00\x00\x00'\x10\x00\x0fProviderVersion \x00\x065.14.4""", """Magic:ActiveMQ Version:9 \x00\x00\x00\xf0\x01ActiveMQ\x00\x00\x00 \x01\x00\x00\x00\xde\x00\x00\x00 \x00MaxFrameSize\x06\x7f\xff\xff\xff\xff\xff\xff\xff\x00 CacheSize\x05\x00\x00\x04\x00\x00CacheEnabled\x01\x01\x00\x12SizePrefixDisabled\x01\x00\x00 MaxInactivityDurationInitalDelay\x06\x00\x00\x00\x00\x00\x00'\x10\x00\x11TcpNoDelayEnabled\x01\x01\x00\x15MaxInactivityDuration\x06\x00\x00\x00\x00\x00\x00u0\x00\x14TightEncodingEnabled\x01\x01\x00\x11StackTraceEnabled\x01\x01""", """Zookeeper version: 3.4.6-1569965, built on 02/20/2014 09:09 GMT Clients: /*.*.*.*:41481[0](queued=0,recved=1,sent=0) /*.*.*.*:46152[1](queued=0,recved={0},sent={1}) /*.*.*.*:43109[1](queued=0,recved=0,sent=0) /*.*.*.*:52608[1](queued=0,recved={2},sent={3}) /*.*.*.*:54716[1](queued=0,recved={4},sent={4}) /*.*.*.*:56130[1](queued=0,recved={5},sent={7}) /*.*.*.*:36232[1](queued=0,recved={8},sent={6}) /*.*.*.*:37054[1](queued=0,recved={10},sent={9}) /*.*.*.*:48618[1](queued=0,recved={11},sent={13}) /*.*.*.*:56498[1](queued=0,recved={14},sent={16}) /*.*.*.*:35602[1](queued=0,recved={15},sent={12}) Latency min/avg/max: 0/0/101 Received: {17} Sent: {18} Connections: 11 Outstanding: 0 Zxid: 0x4000{19}fa Mode: follower Node count: 780""".format(random.randint(1, 10000), random.randint(1, 10000), random.randint(1, 10000), random.randint(1, 10000), random.randint( 1, 10000), random.randint(1, 10000), random.randint(1, 10000), random.randint( 1, 10000), random.randint(1, 10000), random.randint(1, 10000), random.randint( 1, 10000), random.randint(1, 10000), random.randint(1, 10000), random.randint(1, 10000), random.randint( 1, 10000), random.randint(1, 10000), random.randint(1, 10000), random.randint(1, 10000), random.randint(1, 10000), random.randint(1, 100)), """Unsupported command: GET dubbo>""", """RFB 003.008""", """220 z143.{0} ESMTP 250-z143.{0} 250-AUTH LOGIN CRAM-MD5 PLAIN 250-AUTH=LOGIN CRAM-MD5 PLAIN 250-PIPELINING 250 8BITMIME""".format(domainExample + ".org"), """+OK Dovecot ready. """, """+OK POP3""", """200 Kerio Connect 9.2.1 NNTP server ready""", """200 {0} Lyris ListManager NNTP Service ready (posting ok).""".format( domainExample + ".com"), """RTSP/1.0 404 Not Found CSeq: 1""", """RTSP/1.0 200 OK Server: Topsvision Server v2.1 CSeq: 1 Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, GET_PARAMETER, PLAY, PAUSE""", """RTSP/1.0 400 Bad Request""", """RTSP/1.0 200 OK CSeq: 1 Server: MgcServer Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, HEARTBEAT, GET_PARAMETER, SET_PARAMETER SupportAuth: AES BASE64""", """MSSQL Server Version: 184551476 (0xb000834) Sub-Build: 0 Encryption:Not available""", """MSSQL Server Version: 171050560 (0xa320640) Sub-Build: 0 Encryption:Not available""", """MSSQL Server Version: 134219767 (0x80007f7) Sub-Build: 0 Encryption:Not available""", """\x03`\xfb\xa3\xe1\x04\x05\x05\x01\x1cՃ\xeb-U\xd4\x00\x04S)z\xd195J\xaff2m\xfeָQ\xad\x1c\x88\xa4\xbcRWWe\xa6\x15,8\x12*\xcf/{\xd1=E\x9c=/\xe4m\x1aX\xdbKax$\xf6\xbe\x92\xe4(z\xa5\xcf\x05\xd2gPg?1>\xf4 \xc5\xf9\x01\xa2\x1a\x0f/k\xf2 K\xf0C \xa7_\x15p\xe8\xcbD\x94 \xc8\xe6 \xf2\x18[\xf4i\xd0\xd9:H\x90\x88\xc4y\x07\xd4\xfa\x9cLzR\xf3\x1a\xf0\x80\xd40\x8e\x7f\xbd\xe8\xccW\x85O\xbc\xf3\xe93\xed\xfe̠\xb4\x88\xfe\x93\xcd@ٓ\xc7M\x14\x96\xd9v\xac\xb9\xc3\x15\x15\x900\x1a=\xc8g\x1eD¦\xf9\xa3a,\x15\xeaP\xd2wCC\xb9\x11i R,\xa0Bz\x8a\xd4b\xc8:\xa5\x97_e\x8f\xd6\x8b:\xd5\xdd\x18\x9c\x8b\xce\xd7H\xa1\xbc\xea\x97Ğ\xd8\x06\x86\xad\xc3E\x82\xb0\x8a|k\x02\x97mI\x1eXt"g\x96F\x87\x08\x83U:\x9b\x18\xd72\xce\x031\x07\xef|\xd1{9Q\xb6\xa3\xe50u\x1e\x10\xb1\xe2\xe0E?6\x95\xa9\x04\xfdP\xb5\x06?l\x8b\xe2\xe7\x18\x10}\xb9=\x81sQ\xdcn\x85\x14\xd4\x126\xa9\x13\x17\xeb;\xbfj\x03,\xb8\xfb\x99\xa7\xf7\xcfH\xf2\xe2}\xa4b\xff_H\xb4G\xf7\xf6\xd7XH\xfa\x8cP正'\xcd\x1e^\xfe\xe1\x88<\xf1U\x15+-\xca\x04\xc1 в\xd3N\xe7Ъ\xaf\xc2F\xa7\xe2_."c\xe7\xcbp\xf1C\xa9\x885z\xb7\xfb.\xfc\xcaT ;G\x11U\x03y\xe1\x92\xf0B\xf2\x82\xe9h\xf1\x15\xbd\xca?c\x8filZ\x84\xa1>\x9a\x19\x08\x9f. d<z\x96\x92\xdb\xd2\xdc\xcbO \x812\xd8D\x1eU\x95a\xf2\x89\xdcE\xbe\x9c\xa3\x87\xf0\x9c\xc6G\x14\xc3\xd092\x17c\xbc)\x17,\x10\xfe"\xf5\xb8\xd9\x11\xf7Gk\xadSr\xcd]/gz\x13`A\x1d\x8d\xb6\xa9U\x005\x06\x08\x13d\xf7\xe7\x01{ }\x1d\x08\xd0\xff;\x98\xc0\xb4Rz?\xe9r\xd9\xdc\xf1\x9bY\xfa1\xf9\x035!\xde\xe0\xe3\xc5z\x9f\xe5>\x9e\x8f\xdb\xf7U\x90\x99\x1c\xac\x08H"\x19\xb4zș\xa4\x8boW*LQE\xd6f\xef\xc3f\xd2Kh\xaf)7\x86%_\xefu)\xc9\x1b\xea\x8c#\xa4 8;LPt\xe7\xb2\xc9>,&\xf03B\xb73\x8cľaȩ*\xe8\xfcS\x9c-0+\x9cD\x89H \x92\x9b\xa2\xe4\xb9َ\xed\x805\x12\x08\xd8\xe4\xf6\x96B$\xe8*ʠz\x12\xf2\x98\xa4\x99/|J?\x99\xd1<\x92*\x9eL\x13\x08\xef\x0e]6\xc2@\xd3\x05\xbdV\x82]\xa58\x11\xb2A\x96\xe9\xf6\xb2\xe4\xd9&\x9d]4\xb5\x14\xf1\x8e\xd3܋÷\x11\x19\xdd\xce\xce(\xb3\x83o\x1a\x04ܽ\xb79\x00\x9dyy\xb1)\x92a)\x9e\x84\xd4%J\xde\x01\xfb\xc0\xbc\x8f\xbf{\xa0%c\x073\xc3\x17\x99\x17b\x0fk};^\xf2\xd3\xd4H\x03\x9e]\xe8\xce\x1b\x1bk\x14(\xe4\xbd~\xab\x86\xa2\xa2\xee\xfc'T\xfd}\xc2~\x1e\xa3\x82\x98\xbe8ǜ\xf7\x8bQ\xcaI\xef2\xbf\xf9\xa7\x81\x1bY[\xc0\xe4\xfb\xa8\x98Y6u\xfc\x1d]\xba\xe8 U\x10U\xe1S\xefk\x8b\x12\xb2\xb3\x05oB\x8d?V\xefp\xfd]'\x9a\xc2\xee\xc0\xb3\x19\xc9"}\x96\x1a!\xa2\x1a\x9b\xa0\xf2\x17\x19a說\xe8\x81\xee\xd5\xc2U;\xa0\x90\xc2\x1cι\xb1\xf6\xe3)\x04\xda"\xc6)\x82l\x83\x14n\xa3\xdc\xd7`\xafE#䦿ȼ\xc4@:\xec\xb1\xdf{\xed\xdc\xf3\xecw]\xe6]a\xcf$\xd5&,\xd6AT6\x8b\xce'\xa3\xdc\x00/xE7\xd1\xefQ!p\xecSZ\xb1( \x85\xc28\xb2\xf8\xb6\xea\xfbWQX\xe4\xc9(\x07\x9c9\xeb\x11`$\xf1 \xf3Wj\xd6ƥ>\xfd\x11\xe8b/6\xc5$\xaf\xd4uh\x05ԑ\x18IHl\xd7u\x8f\xf0\xa7\xa3b\xc1(z\x15\x95l.e\xce\xfc\xd3\x17w\x04B\x92\xc9s\x00'IJs\x88\x9c\x00\xd7n\xc41o`\x8bG\x1e<a\xd4\xed\x8a\x1a!;\xfdo\x84\xf1\xdb\x1d\xb9\x89\x93\xba\x08\xe2\x9fM\x82\xaf\xa7k\x12\xb8ͦ\x8aQ!pv\xb8aT\x0e\xf8%\x08%ο\x00\xa1J\xe2\xbbS\xc2n\xb4\x01\x01\xfc\xdf\xee\x99\x16Coo}\xbd\xcd\x08?\xaf\x9euDA\x06t\xc7N+l\xe5!|\\xb6+-ZV$i\xe0\x03\xbeU\xf9\xf4\x888\xdc_\x13\x97\x8a\x85#\xf4:N\xa5\x1b#\xfb\xebUiH6y\xcb+&\xa7\xf0\xb7\x86`\x01\x19\xb9i\xab\x7fG̲b;:$*\xa2¹K\x00\xae\x08\x15\x1ct\xf5\x96G\x1f\xd7\xe5\x8f2\x1b\x92M\x8d\xe2\x87\xe4\x9f9\xa4\x8d{\xa9\xcc!\xed\x12\xbd\x96\xcb\xc3\x13\xd0,Mmz\xac\xb5<(4\x9dK"\xaa\xdb\xf1\xdaX6\x01\x8bΫ\xfcL\xe3\xfe\x13\xd0J\x8e\x82\xc0pr\x80I\xf5\xb4C<\x12\x05X\xe5&\xb0#\xd1\x02\xad\xbak\xb1\x1a\x81\xa0aR;\xb6\x8e\xbb\xaaU\xf1̗\xf0\xdfK1稬#\xb8%\xc8\xc4\xc0\x01j\xad\xb7Q\\xbcd\xa4[\x10}!\xbe\x85g<#*h\x06\x15'\x9e\x18\xc3oqD\xc8Z\x13\x90\xb6\xf5\xd5i\xfd\x16Zs\x02\x004\x15f\xf5fڍK\x14\xb1\xe3\xa8J\xed\x1ab\xbb\xb2\x10\xbc\x1a\x08\xee\xecܶ\xf8\xdc\xfc6z\xfa\xf4<\x18\xf6h\x93G^\xb7\xeeI\xfdy\xb8\xf9\xd4c\x10\xd3\xf6{쳤\xd0m\x90B\xf8\x89E\x13t\x83\xf4\xdcѹ}\xa5\xfd1\xf1&0\xa5/1\xbd\x8c\xc8\x02|\x1d\x02\xe0\xcd9k\xb0\xadjS\x84\x13\xdaL?P\xfbs\xdfn\x92\xb2\x98\xf6|G\xa3\xe4%\xad\x9b\x03승\x7f\x82\x1e\x85\xe5\x1e^\x8a\xc2e&\xc4\xc3\xded\xb0'\x92\xb6.\xc9c\xd3\xf9\x8bb\xfe\xc1\xa2I\xe0\x95\x14\x91\xfe.G\x07\xa8\xa2\x83\xf5\x82t+L\xa6\x84GyZ~\xecP\xef\xd9c O\x82\x13""", """Firmware: 1 Hostname: local Vendor: linux""", """Firmware: 1 Hostname: Vigor Vendor: DrayTek""", """Firmware: 1 Hostname: MikroTik Vendor: MikroTik""", """SuSE Meta pppd (smpppd), Version 5974385 """, """SuSE Meta pppd (smpppd), Version 20677753""", """Login Response Success(0x0000) Key/Value Pairs AuthMethod=None TargetAlias=LIO Target TargetPortalGroupTag=1""", """Login Response Success(0x0000) Key/Value Pairs AuthMethod=None""", """( success ( 2 2 ( ) ( edit-pipeline svndiff1 absent-entries commit-revprops depth log-revprops partial-replay ) ) )""", """( success ( 2 2 ( ) ( edit-pipeline svndiff1 absent-entries commit-revprops depth log-revprops atomic-revprops partial-replay inherited-props ephemeral-txnprops file-revs-reverse ) ) )""", """\x00\x16\x00\x00\x00\x06\x00No protocol specified \x00\x00""", """:{0} NOTICE AUTH :*** Looking up your hostname... ::{0} NOTICE AUTH :*** Looking up your hostname... :{0} NOTICE AUTH :*** Checking Ident :{0} NOTICE AUTH :*** Couldn't look up your hostname NOTICE AUTH :*** Checking Ident :{0} NOTICE AUTH :*** Couldn't look up your hostname""".format( domainExample + ".cn"), """{0} 020 * :Please wait while we process your connection.""".format( domainExample + ".cn"), """\x00'x\xae\x81\x05\x00\x01\x00\x00\x00\x00\x00\x01\x06google\x03com\x00\x00\x01\x00\x01\x00\x00)\x10\x00\x00\x00\x00\x00\x00\x00 \x00=\x00\x06\x85\x00\x00\x01\x00\x01\x00\x01\x00\x00\x07version\x04bind\x00\x00\x10\x00\x03\xc0\x00\x10\x00\x03\x00\x00\x00\x00\x00\x05\x04none\xc0\x00\x02\x00\x03\x00\x00\x00\x00\x00\x02\xc0""", """\x83\x00\x00\x01\x8f""", """Version: 6.1Build 7601 Target Name : ECS-S6-LARGE-2-""", """Version: 10.0Build 17763 Target Name : FPSERVERx""", ] class Logger(object): def __init__(self, _filename=None): self.logger = logging.getLogger("") logFolder = os.path.join(os.getcwd(), 'logs') if not os.path.exists(logFolder): os.makedirs(logFolder) timestamp = time.strftime("%Y-%m-%d", time.localtime()) logfilename = '%s.txt' % ( timestamp) if _filename is None else '%s-%s.txt' % (_filename, timestamp) logFile = os.path.join(os.getcwd(), 'logs', logfilename) logging.basicConfig(filename=logFile, level=logging.DEBUG, format='> %(levelname)s - %(asctime)s - %(name)s\n%(message)s') def info(self, message): self.logger.info(message) print("\n" + message) def debug(self, message): self.logger.debug(message) print("\n" + message) def warning(self, message): self.logger.warning(message) print("\n" + message) def error(self, message): self.logger.error(message) print(message) _logger = Logger('FAKE PORT') def bindPort(port): global cursor, db def getFlag(data): flag = str() data = str(data) if data.find("b''") > -1 or (len(data) < 12 and len(data) > 0) or data.find("help") < 5 and data.find( "help") > 0: flag += "端口扫描 / " if data.find("login") > -1: flag += "登录检测 / " if data.find("mstshash") > -1: flag += "RDP扫描 / " if len(data.split("\\x")) > 1: flag += "漏洞exploit / " if data.find("HTTP/") > -1: flag += "Web应用检测 / " if data.find("EHLO ") > -1 or data.find("NOOP") > -1: flag += "邮件服务器检测 / " if data.find("RTSP/") > -1: flag += "RTSP应用检测 / " if data.find("libssh") > -1 or data.find("SSH-") > -1 or data.find("openssl") > -1: flag += "SSH检测 / " if data.find("help") > -1 or data.find("stats") > -1 or data.find("info") > -1: flag += "TELNET检测 / " if data.find("application/sdp") > -1 or data.find("sip:") > -1 > -1: flag += "SDP/SIP 检测 / " if data.find("fox a 1 -1 ") > -1: flag += "未知的检测源[fox a 1 -1] / " if flag == "": flag += "端口检测" return flag def inner(port): try: s = socket.socket() host = socket.gethostname() s.bind((host, port)) s.listen(10) # _logger.debug(str(port)+"启动成功") while True: try: conn, addr = s.accept() data = conn.recv(1024) _logger.info( "================================================================================================\n[Client]\n" + " IP:" + str(addr[0]) + '\n PORT:' + str(addr[1]) + '\n[Server]\n PORT:' + str(port) + "\n DATA:" + str(data)) if str(data).find("HTTP/") != -1: if int(random.random()*1000) % 2 == 0: conn.send(bytes(randomList[random.randint( 0, len(randomList)-1)].encode("utf8"))) else: conn.send(bytes(str(randomList[0]).encode("utf8"))) else: conn.send(bytes(randomList[random.randint( 0, len(randomList)-1)].encode("utf8"))) # conn.sendall(data) conn.close() db = pymysql.connect("localhost", "YOUR_USERNAME", "YOUR_PASSWORD", "YOUR_DATABASE_NAME") # Threat platform cursor = db.cursor() cursor.execute(sql, (str(addr[0]), int(port), str(data), getFlag(data), datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) db.commit() except Exception as e: _logger.error("[ERROR] " + str(port) + "存在异常" + str(e)) db = pymysql.connect("localhost", "YOUR_USERNAME", "YOUR_PASSWORD", "YOUR_DATABASE_NAME") # Threat platform cursor = db.cursor() traceback.print_exc() except Exception as e: _logger.error("[ERROR] " + str(port) + "启动失败" + str(e)) threading.Thread(target=inner, args=(port,)).start() if __name__ == '__main__': global cursor, db db = pymysql.connect("localhost", "YOUR_USERNAME", "YOUR_PASSWORD", "YOUR_DATABASE_NAME") # Threat platform cursor = db.cursor() for i in range(1, 10000): if (i in [80, 81, 135, 139, 445, 3306, 3389, 900, 210, 7000, 443, 6379, 800, 33890, 8000, 900, 800, 890, 59000, 8023]): continue bindPort(i) input() ``` # 数据库模型 ```sql CREATE TABLE `tp` ( `id` mediumint(8) NOT NULL AUTO_INCREMENT, `sourceIP` varchar(16) DEFAULT NULL COMMENT '攻击者IP', `targetPort` int(5) DEFAULT NULL COMMENT '攻击目标端口', `data` varchar(4096) DEFAULT NULL COMMENT '请求数据', `flag` varchar(255) DEFAULT NULL, `intime` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 ``` # php后端 ```php <?php // error_reporting(0); // 隐藏PHP的日志信息 try { $conn = new Redis(); $conn->connect('REDIS_IP', REDIS_PORT); $conn->auth('REDIS_PASSWORD'); if ($conn->get(("report." . $_SERVER["REMOTE_ADDR"])) > 40) { $message = new message(); $message->fail('"请求过于频繁"'); echo $message->show(); return; } $conn->incr("report." . $_SERVER["REMOTE_ADDR"]); $conn->expireAt("report." . $_SERVER["REMOTE_ADDR"], intval(time()) + 20); } catch (Exception $e) { //echo $e; } class message { private $code = 0; private $msg = ""; public function ok($msg) { $this->code = 0; $this->msg = $msg; } public function fail($msg) { $this->code = 1; $this->msg = $msg; } public function custom($code, $msg) { $this->code = $code; $this->msg = $msg; } /** * @return int */ public function getCode() { return $this->code; } /** * @return string */ public function getMsg() { return $this->msg; } /** * @param int $code */ public function setCode($code) { $this->code = $code; } /** * @param string $msg */ public function setMsg($msg) { $this->msg = $msg; } public function show() { echo '{"code":"' . $this->getCode() . '","msg":' . $this->getMsg() . '}'; } } function doQuery($sql) { try { $message = new message(); $conn = mysqli_connect("127.0.0.1", "YOUR_USERNAME", "YOUR_PASSWORD", "YOUR_DATABASE_NAME", YOUR_PORT); mysqli_query($conn, "set names utf8"); $retval = mysqli_query($conn, $sql); if (!$retval) { $message->fail('无法读取数据: ' . mysqli_error($conn)); } $arr = array(); while ($row = mysqli_fetch_array($retval, MYSQLI_ASSOC)) { array_push($arr, $row); } $rst = json_encode($arr, JSON_UNESCAPED_UNICODE); $rst = trim($rst); $message->ok($rst); echo $message->show(); } catch (Exception $e) { $message->fail($e); } } $rst = (array)json_decode(file_get_contents('php://input'), true); if ($rst["method"] == "getv6") { doQuery("SELECT count(*) AS sec FROM ( SELECT id FROM tp WHERE date(intime) = date_sub(date(now()), INTERVAL 0 DAY) ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT id FROM tp WHERE date(intime) = date_sub(date(now()), INTERVAL 1 DAY) ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT id FROM tp WHERE date(intime) = date_sub(date(now()), INTERVAL 2 DAY) ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT id FROM tp WHERE date(intime) = date_sub(date(now()), INTERVAL 3 DAY) ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT id FROM tp WHERE date(intime) = date_sub(date(now()), INTERVAL 4 DAY) ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT id FROM tp WHERE date(intime) = date_sub(date(now()), INTERVAL 5 DAY) ) tt;"); } if ($rst["method"] == "getn6") { doQuery("SELECT count(*) AS sec FROM ( SELECT sourceIP, intime FROM tp WHERE date( intime )= date_sub( date( now()), INTERVAL 0 DAY ) GROUP BY sourceIP ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT sourceIP, intime FROM tp WHERE date( intime )= date_sub( date( now()), INTERVAL 1 DAY ) GROUP BY sourceIP ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT sourceIP, intime FROM tp WHERE date( intime )= date_sub( date( now()), INTERVAL 2 DAY ) GROUP BY sourceIP ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT sourceIP, intime FROM tp WHERE date( intime )= date_sub( date( now()), INTERVAL 3 DAY ) GROUP BY sourceIP ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT sourceIP, intime FROM tp WHERE date( intime )= date_sub( date( now()), INTERVAL 4 DAY ) GROUP BY sourceIP ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT sourceIP, intime FROM tp WHERE date( intime )= date_sub( date( now()), INTERVAL 5 DAY ) GROUP BY sourceIP ) tt;"); } if( $rst["method"]=="getp6"){ doQuery("SELECT count(*) AS sec FROM ( SELECT targetPort, intime FROM tp WHERE date( intime )= date_sub( date( now()), INTERVAL 0 DAY ) GROUP BY targetPort ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT targetPort, intime FROM tp WHERE date( intime )= date_sub( date( now()), INTERVAL 1 DAY ) GROUP BY targetPort ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT targetPort, intime FROM tp WHERE date( intime )= date_sub( date( now()), INTERVAL 2 DAY ) GROUP BY targetPort ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT targetPort, intime FROM tp WHERE date( intime )= date_sub( date( now()), INTERVAL 3 DAY ) GROUP BY targetPort ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT targetPort, intime FROM tp WHERE date( intime )= date_sub( date( now()), INTERVAL 4 DAY ) GROUP BY targetPort ) tt UNION ALL SELECT count(*) AS sec FROM ( SELECT targetPort, intime FROM tp WHERE date( intime )= date_sub( date( now()), INTERVAL 5 DAY ) GROUP BY targetPort ) tt;"); } if( $rst["method"]=="getbef10"){ doQuery("SELECT a.*,b.Description as service from (SELECT sourceIP,targetPort,flag,intime FROM TP order by intime desc limit 10) a left join `service-names-port-numbers` b on a.targetPort = b.`Port Number` order by intime desc"); } if( $rst["method"]=="gettopip10"){ doQuery("SELECT sourceIP ,count(1) as sec FROM TP GROUP BY sourceIP ORDER BY count( 1 ) DESC LIMIT 15"); } if( $rst["method"]=="gettopport10"){ doQuery("SELECT a.*,b.Description as service from (SELECT targetPort ,count(1) as sec FROM TP GROUP BY targetPort ORDER BY count( 1 ) DESC LIMIT 15) a left join `service-names-port-numbers` b on a.targetPort = b.`Port Number` and b.`Transport Protocol` = 'tcp' order by a.sec desc"); } if( $rst["method"]=="gettotal"){ doQuery("SELECT count(1) as sec FROM TP"); } if( $rst["method"]=="getwarn"){ doQuery("SELECT flag ,count(1) as sec FROM TP group by flag order by sec desc "); } if( $rst["method"]=="ipatttime"){ doQuery(<<<EOF SELECT concat( concat( YEAR ( intime ), concat( "-", concat( MONTH ( intime ), "-" ) ), concat(DAY ( intime )," ")), HOUR ( intime )) as dt, count( 1 ) AS sec FROM tp GROUP BY YEAR ( intime ), MONTH ( intime ), DAY ( intime ), HOUR ( intime ) ORDER BY intime DESC limit 100 EOF ); } ``` # 前端部分 可以查看网页源代码,在这里就不进行展示和附件了。 # BUG 今天有一位User在使用过程中,页面无法显示一些数据,调用api.php 接口返回数据是空数组。可以考虑将php升级到7版本,并且把api.php中sql语句中的大写TP改成小写tp,保证与数据库中的表名一致,根本原因是数据库的大小写敏感。 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 2 如果觉得我的文章对你有用,请随意赞赏