前言
在渗透测试的过程中,服务识别是一个很重要的环节。对于入侵者来说,发现这些运行在目标上的服务,就可以利用这些软件上的漏洞入侵目标;对于网络安全的维护者来说,也可以提前发现系统的漏洞,从而预防这些入侵行为。由于很多软件在连接之后都会提供一个表明自身信息的banner,在这里我们可以根据获取的banner信息对运行的服务类型进行判断,进而可以确定开放端口对应的服务类型及版本号。
文件共享服务端口
端口号 | 说明 | 作用 |
---|---|---|
21/22/69 | FTP/TFTP | 允许匿名上传、下载、破解和嗅探攻击 |
2049 | NFS服务 | 配置不当 |
139 | Samba服务 | 破解、未授权访问、远程代码执行 |
389 | LDAP(目录访问协议) | 注入、允许匿名访问、使用弱口令 |
远程连接服务端口
端口号 | 说明 | 作用 |
---|---|---|
22 | SSH远程连接 | 破解、SSH隧道及内网代理转发、文件传输 |
23 | Telnet远程连接 | 破解、嗅探、弱口令 |
3389 | Rdp远程桌面连接 | Shift后门(需要Windows Server 2003以下的系统)、破解 |
5900 | VNC | 弱口令破解 |
5632 | PyAnywhere服务 | 抓密码、代码执行 |
Web应用服务端口
端口号 | 说明 | 作用 |
---|---|---|
80/443/8080 | 常见Web服务端口 | Web攻击、破解、服务器版本漏洞 |
7001/7002 | WebLogic控制台 | Java反序列化、弱口令 |
8080/8089 | Jboss/Resin/Jetty/JenKins | 反序列化、控制台弱口令 |
9090 | WebSphere控制台 | Java反序列化、弱口令 |
4848 | GlassFish控制台 | 弱口令 |
1352 | Lotus Domino邮件服务 | 弱口令、信息泄露、破解 |
10000 | Webmin-Web控制面板 | 弱口令 |
数据库服务端口
端口号 | 说明 | 作用 |
---|---|---|
3306 | MySQL | 注入、提权、破解 |
1433 | MSSQL | 注入、提权、SA弱口令、破解 |
1521 | Oracle数据库 | TNS破解、注入、反弹shell |
5432 | PostgreSQL数据库 | 破解、注入、弱口令 |
27017/27018 | MongoDB | 破解、未授权访问 |
6379 | Redis数据库 | 可尝试未授权访问、弱口令破解 |
5000 | SysBase/DB2 | 破解、注入 |
邮件服务端口
端口号 | 说明 | 作用 |
---|---|---|
25 | SMTP邮件服务 | 邮件伪造 |
110 | POP3协议 | 破解、嗅探 |
143 | IMAP协议 | 破解 |
网络常见协议端口
端口号 | 说明 | 作用 |
---|---|---|
53 | DNS域名系统 | 允许区域传送、DNS劫持、缓存投毒、欺骗 |
67/68 | DHCP服务 | 劫持、欺骗 |
161 | SNMP协议 | 破解、搜集目标内网信息 |
特殊服务端口
端口号 | 说明 | 作用 |
---|---|---|
2181 | Zookeeper | 未授权访问 |
8069 | Zabbix服务 | 远程执行、SQL注入 |
9200/9300 | Elasticsearch | 远程执行 |
11211 | Memcache服务 | 未授权访问 |
512/513/514 | Linux Rexec服务 | 破解、Rlogin登录 |
873 | Rsync服务 | 匿名访问、文件上传 |
3690 | SVN服务 | SVN泄露、未授权访问 |
50000 | SAP Management Console | 远程执行 |
代码展示
导入程序所用到的模块和SIGNS指纹库
from optparse import OptionParser
import time
import socket
import re
SIGNS = (
# 协议 | 版本 | 关键字
#b" "前缀表示:后面字符串是bytes 类型
#用处:网络编程中,服务器和浏览器只认bytes 类型数据
b'FTP|FTP|^220.*FTP',
b'MySQL|MySQL|mysql_native_password',
b'oracle-https|^220- ora',
b'Telnet|Telnet|Telnet',
b'Telnet|Telnet|^\r\n%connection closed by remote host!\x00$',
b'VNC|VNC|^RFB',
b'IMAP|IMAP|^\* OK.*?IMAP',
b'POP|POP|^\+OK.*?',
b'SMTP|SMTP|^220.*?SMTP',
b'Kangle|Kangle|HTTP.*kangle',
b'SMTP|SMTP|^554 SMTP',
b'SSH|SSH|^SSH-',
b'HTTPS|HTTPS|Location: https',
b'HTTP|HTTP|HTTP/1.1',
b'HTTP|HTTP|HTTP/1.0',
)
time
模块主要用于产生延迟时间,optparse
模块用于生成命令行参数,socket
模块用于产生TCP请求,re
模块为正则表达式模块,与指纹信息进行有效匹配,进而确定服务类型。SIGNS
为指纹库,用于对目标主机返回的banner信息进行匹配。
然后利用optparse模块对输入的参数进行接收和批量处理
def main():
parser = OptionParser("Usage: %prog -i <target host>")
parser.add_option('-i',type='string',dest='IP',help='specify target host')
#获取IP地址参数
parser.add_option('-p',type='string',dest='PORT',help='specify target host')
options,args = parser.parse_args()
ip = options.IP
port = options.PORT
print("Scan report for " +ip+ "\n")
for line in port.split(','):
request(ip,line)
time.sleep(0.2)
print("\nScan finished!...\n")
我们在request
函数中首先调用sock.connect()
函数探测目标主机端口是否开放,如果端口开放,则利用sock.sendall()
函数将PROBE
探针发送给目标端口。sock.recv()
函数用于接收返回的指纹信息,并将指纹信息及端口发送到regex()函数。
def request(ip,port):
response = ''
PROBE = 'GET / HTTP/1.0\r\n\r\n'
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.settimeout(10)
result = sock.connect_ex((ip,int(port)))
if result == 0:
try:
sock.sendall(PROBE.encode())
response = sock.recv(256)
if response:
regex(response,port)
except(ConnectionResetError,socket.timeout):
pass
else:
pass
sock.close()
利用re.search()函数将返回的banner信息与SIGNS包含的指纹信息进行正则匹配,并将匹配到的结果输出。没有则输出Unrecongnized。
def regex(response,port):
text = ""
if re.search(b'<title>502 Bad Gateway',response):
proto = {"Service failed to access!!"}
for pattern in SIGNS:
pattern = pattern.split(b'|')
if re.search(pattern[-1], response, re.IGNORECASE):
proto = "["+port+"]" + " open " + pattern[1].decode()
break
else:
proto = "["+port+"]" + " open " + "Unrecongnized"
print(proto)
最后编写主函数
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print("interrupted by user, killing all threads...")
效果如下图所示
这个是Nmap版本的,nmap的扫描速度相对较快
import nmap
import optparse
def NmapScan(targetIP,targetPort):
#实例化PortScanner对象
nm = nmap.PortScanner()
try:
#host为目标IP地址,arguments为Nmap的扫描参数
#-sn:使用ping进行扫描
#-PE:使用ICMP的echo请求包(-PP:使用timestamp请求包 -PM:network请求包)
result = nm.scan(hosts=targetIP,arguments='-sV -p'+str(targetPort))
#对结果进行切片,提取主机状态信息
port_infor = result['scan'][targetIP]['tcp'][int(targetPort)]
print("[{}:{}] : [{}:{}]".format(targetPort,port_infor['state'],port_infor['name'],port_infor['product']))
except Exception as e:
pass
if __name__ == '__main__':
parser = optparse.OptionParser('usage: python %prog -i ip -p port\n\n'
'Example: python %prog -i 192.168.1.1 -p 80,3306\n')
# 添加目标IP参数-i
parser.add_option('-i','--ip',dest='targetIP',default='192.168.1.1',type='string',help='target ip address')
# 添加扫描端口参数-p
parser.add_option('-p','--port',dest='targetPort',default='80',type='string',help='target port')
options,args = parser.parse_args()
for i in range(0,len(options.targetPort.split(','))):
NmapScan(options.targetIP, options.targetPort.split(',')[i])