写在前头一些与本文无关的话
好久好久没有写博客了,上次写的那篇离现在也有大半年了。这大半年去了公司实习,公司事情比较多也没时间整理。
好吧!主要还是因为懒,在这期间也想恢复想blog的,但又被心中那个黑天使给按下了一直堕落到现在,最近才幡然
醒悟。决定之后大概每周整理更新一篇关于自己最近一周学到的新知识或工作中遇到的问题及解决办法。前路很长,希
望我能带着坚持做下去,努力成长。
正文内容
脚本编写初衷
前几个星期吧,都在做某个运营商的项目主要的任务是对运营商的资产服务识别,以及弱口令等常规漏洞的检查。由于
IP数量巨大,客户自己都不知道有哪些资产服务且有些端口服务开关不定,给工作带来了极大的干扰,导致一些服务上
的弱口令及常规未授权访问漏洞在第一轮没有清扫干净,例如海康、ftp、ssh弱口令等。因此在第一轮排查后想写个脚
本来监测客户的IP资产,当有新的服务端口开放时用邮件进行通知,再进行排查。根据实际漏洞情况及时间安排进行三
轮监控:
第一阶段针对团体名、telnet、海康摄像后台弱口令,redis、Memcached未授权访问漏洞对下面端口服务进行监控:
telnet 23,snmp 161,Redis 6379,Memcached 11211,Rtsp 554
第二阶段主要是对数据库的一些弱口令及未授权登陆的排查,对下面端口服务进行监测:
MongoDB 27017,Oracle 1521 ,SQLServer 1433,MySQL 3306,Pointbase 9092,DB2 5000,Sybase 4100
第三阶段是对主机系统可能存在的弱口令进行监测:
ftp 21,ssh 22,RDP 3389
脚本编写过程
大体思路
1.使用python调用nmap对指定资产以及端口服务进行扫描并将扫描结果导出为xml文本。
2.使用python下的xml模块解析上一步导出的xml文本,将开放了指定监测服务端口的IP存入数据库。
3.第一次排查完成后开始后续检测当有新的IP出现监测服务时,将该IP存入数据库,并把IP及开放端口邮件发送至我邮箱。
4.上述完成后程序休眠3小时后开始下一次检测。
脚本模块
扫描模块
调用nmap对资产进行扫描,我所采用的nmap命令如下:1
nmap -sS -p ports -Pn -iL filename -oX result.xml
扫描模块代码如下:1
2
3
4
5
6
7def scanner(filename,ports,i):
strTime = time.strftime("%Y-%m-%d-%H%M%S", time.localtime(time.time()))
print strTime + ' 资产开始第%d次端口扫描\n' % i
os.system("nmap -sS -p "+ports+" -Pn -iL "+filename+" -oX "+str(i)+".xml")
print time.strftime("%Y-%m-%d-%H%M%S", time.localtime(time.time())) + " 资产完成第%d次扫描,开始解析" % i
file='{x}.xml'.format(x=i)
analysis(file,i)
解析模块
使用python的xml模块来对扫描模块的xml文本进行解析,关于xml模块的教程可参考该网址
解析模块如下所示:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29def analysis(file,i):
tree = ET.parse(file)
root = tree.getroot()
list=[]
for temp in root.findall('host'):
ports = ''
ip = temp.find('address').get('addr')
try:
xml_ports = temp.find('ports').findall('port')
except:
print ip + "没有检测出"
continue
for temp1 in xml_ports:
if temp1.find('state').get('state') == 'open':
port = temp1.get('portid')
ports = ports + ' ' + port
cursor.execute('select count(*) from host where ip=?',(ip,))
result=cursor.fetchall()
if len(ports)>0 and str(result)=='[(0,)]':
store(ip,ports)
list.append((ip+':'+ports))
cursor.close()
conn.commit()
conn.close()
if len(list)!=0 and i!=1:
send_email(list)
elif i!=1 and len(list)==0:
print "本次没有新地址出现"
print "本次解析完成!休息一小时候继续工作。\n"
存储模块
该脚本采用的是python自带的sqlite3模块进行数据库的创建,由于SQLite本身是C写的,而且体积很小,实现简单所以
,经常被集成到各种应用程序中,甚至在iOS和Android的App中都可以集成。具体教程参见菜鸟教程
创建数据、获取游标、执行sql语句1
2
3conn=sqlite3.connect('host.db')
cursor=conn.cursor()
cursor.execute(r"insert into host (ip,ports) values ('{ip}', '{ports}')".format(ip=ip,ports=ports))
邮件发送模块
采用了python下的smtp模块进行了邮件的发送,具体教程参考该网址
邮件模块代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18def send_email(list):
sender="你的163邮箱"
receiver=["yangtao5@nsfocus.com","dingwenchao2@nsfocus.com","panwenxiang@nsfocus.com","wangguangteng@nsfocus.com"]
str=""
for ip in list:
str=str+ip+"\n"
text=MIMEText("the new open address and ports:\n"+str,'plain','utf-8')
message=MIMEMultipart('mixed')
message['From']='你的163邮箱'
message['To']=';'.join(receiver)
message['Subject']='new address!!!!!!'
message.attach(text)
smtp=smtplib.SMTP()
smtp.connect('smtp.163.com')
smtp.login('你的163邮箱','你的163邮箱密码')
smtp.sendmail(sender,receiver,message.as_string())
smtp.quit()
print "已发现新地址,邮件已发送完成\n"
整个脚本内容
1 | #coding:gbk |
实现效果:
将该脚本部署到了客户提供的服务器上进行资产检测,以下是运行截图
当有新地址出现时邮件截图
最后一点打算
想把这个脚本用改成网页形式,放在服务端可随时使用。但放在服务端和web形式需要考虑一些可能会存在的安全问题,有空了把它实现一下。