CVE監控之Python代碼實現


前幾天在先知上看到偽全棧式安全研發:CVE監控這篇文章,就想着也實現一下代碼進行最新CVE的監控。語言采用了Python,數據庫也為Mongodb數據庫。代碼和實現的什么不重要,重要的是過程。

主要包括以下幾個方面。

  1. 獲取最新的CVE列表和詳情
    主要采用了python的requests模塊和BeautifulSoup模塊。
  2. 將最新的CVE信息存入數據庫
    數據庫使用了Mongodb,采用了pymongo模塊。
  3. 通過郵件發送最新的CVE信息
    發送郵件采用了smtplib模塊。
  4. 定時執行任務
    使用了linux的crontab來實現。

0x02 實現過程

1. 獲取最新的CVE列表和詳情

訪問https://cassandra.cerias.purdue.edu/CVE_changes/today.html ,可以獲取每天新增的CVE信息。

接口1

接口源代碼
通過查看源代碼,發現沒html沒什么規律可言,都是些超鏈接。要想獲取最新的列表,可以通過取文本中間的方法來獲取。
這里需要獲取New entries:Graduations之間的內容。然后通過BeautifulSoup來解析其中的超鏈接。
主要代碼如下:

def getCVES():# 獲取最新到CVE列表
try:
url = 'https://cassandra.cerias.purdue.edu/CVE_changes/today.html'
res = requests.get(url, headers=headers, timeout=60)
CVEList_html = getMiddleStr(res.text, 'New entries:', 'Graduations')
soup = BeautifulSoup(CVEList_html, 'html.parser')
for a in soup.find_all('a'):
print(a['href'])
print(a.string)
except Exception as e:
print(e)

 

獲取文本中間內容的代碼:

def getMiddleStr(content, startStr, endStr): # 獲取文本中間內容
startIndex = content.index(startStr)
if startIndex >= 0:
startIndex += len(startStr)
endIndex = content.index(endStr)
return content[startIndex:endIndex]

 

運行效果:
獲取cve列表
超鏈接的地址是CVE的詳情。隨便進入一個查看效果。
例如:http://cve.mitre.org/cgi-bin/cvename.cgi?name=2017-0874
CVE詳細信息
這里需要記錄的信息有:CVE-ID、Description、Assigning CNA和Date Entry Created。

CVE詳情網頁源代碼
通過查看網頁源碼發現,所有需要記錄的信息在一個表格里面。但該頁面有很多table,而且沒有明顯的標識來區分。而該table在div中,可以通過id來獲取。
CVE-ID可以直接通過soup.find(nowrap='nowrap').find('h2').string獲取。其他的幾個信息可以通過獲取相應tr中的td中的內容獲得。
獲取CVE詳情
這樣就可以獲取最新的CVE列表和詳情。

2. 將最新的CVE信息存入數據庫

數據庫采用了Mongodb。安裝方法apt-get install mongodb
然后啟動數據庫

mkdir /var/data/ #創建數據存儲位置
mongod --port 65521 --dbpath /var/data/ --bind_ip 127.0.0.1 #啟動mongodb,指定端口和路徑,且僅本機可連
mongo 127.0.0.1:65521/mydb
db.createUser({user:'tass',pwd:'liehu',roles:[{role:'dbOwner',db:'mydb'}]}) #添加認證

 

Mongodb數據庫插入一條數據,一般使用的是insert。

db.test.insert({"title":"test1", "blog_cont":"test1"})

 

如果我們想實現一個如果title存在,就對數據進行更新,不存在,就插入。可以這樣來實現。

db.test.update({"title":"test2"}, {$set:{"title":"test2", "blog_cont":"test2"}}, {upsert:true})
db.test.update({"title":"test1"}, {$set:{"title":"test1", "blog_cont":"test3"}}, {upsert:true})
db.test.find()

 

執行完成后最終有兩條數據,title分別為test1和test2,對應的內容為test3和test2.

存在更新,不存在插入
因此在插入數據的時候,我們可以直接使用db.test.update({"title":"test2"}, {$set:{"title":"test2", "blog_cont":"test2"}}, {upsert:true})這種方式來實現。

插入測試
更新只需更改data內容即可。
更新測試

為了數據庫的安全性,使用--bind_ip 127.0.0.1來設置數據庫僅本地可以連接。更多mongodb數據庫的配置可以參考MongoDB Mongodb.conf 配置 Auth

3. 通過郵件發送最新的CVE信息

發送郵件這里用到了smtplib。
發送郵件比較簡單,就直接貼代碼了。

def sendEmail(mail_msg): # 發送郵件
sender = 'from@163.com' # 發件人
password = 'password' # 發件人密碼
receiver = 'receiver@163.com' # 收件人
message = MIMEText(mail_msg, 'plain', 'utf-8') #以文本發送
message['From'] = sender
message['To'] = receiver

subject = '最新CVE列表'
message['Subject'] = Header(subject, 'utf-8')

try:
smtpObj = smtplib.SMTP('smtp.163.com')
smtpObj.login(sender, password)
smtpObj.sendmail(sender, receiver, message.as_string())
print('郵件發送成功')
except smtplib.SMTPException:
print('Error: 無法發送郵件')

 

4. 定時執行任務

直接使用linux下的crontab來完成。
例如設置每天早上7點執行,可以這樣設置:

0 7 * * * python /myJob/CVE-Monitor.py >> /log/CVE-Monitor.log

 

根據https://cassandra.cerias.purdue.edu/CVE_changes/ 看到today.html更新的時間是明天的06:53,對應北京時間是19:53。若想及時獲取,可以更換時間為20:00.

5.完善和優化

到這里監控腳本完成的差不多了,剩下就是如何來融合一起並改善了。
為了方便發送郵件內容和插入數據庫,我們新建類CVEInfo。主要代碼如下:

class CVEInfo:
def __init__(self,url, cveid, description, company, createdate):
self.url = url
self.cveid = cveid
self.description = description
self.company = company
self.createdate = createdate

def show(self):
return '<p><b>漏洞編號:</b><a href="'+self.url+'">'+self.cveid+'</a></p><b>相關廠商:</b>'\
+self.company +'<br><b>披露日期:</b>'\
+self.createdate+'<br><b>漏洞描述:</b>'\
+self.description + '<br><br><hr/>'

def add(self):
data = {
'cveid': self.cveid,
'description': self.description,
'company': self.company,
'createdate': datetime.strptime(self.createdate, "%Y%m%d"),
'addDate': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())),

}
return data

為了美觀,將郵件以html方式發送

message = MIMEText(mail_msg, 'html', 'utf-8')

郵箱收到的效果:
郵件內容
查看數據庫數據:
數據庫內容

從上面兩張圖片可以看到有三十多個,但我們有時候並不是都需要看。我們可以根據Description中關鍵信息來進行過濾,僅僅將我們需要關注的CVE信息發送到郵箱或進行入庫操作。
如下圖為獲取CVE-2017-8295的信息。
添加關鍵字匹配
然后修改main方法,根據是否有關注的CVE信息來決定郵件的內容。
這里先用本地服務器為例,新建today.html文件,其中包含CVE-2017-9805CVE-2017-16241
關鍵字匹配
運行代碼結果打印了一條包含了我們的關鍵字的數據。
郵件中的內容如下所示:
關鍵字匹配郵件內容
這樣就能過濾其他CVE信息,僅僅記錄我們關注的內容了。

0x03 總結

本文主要用到了BeautifulSoup解析網頁和mongodb數據庫的使用,然后就可以將想要的內容保存到數據庫中。腳本並不限於在此處使用,也可以修改一下抓取其他網站內容。
代碼地址:https://github.com/fupinglee/MyPython/blob/master/work/CVE-Monitor.py
查詢的功能就不做了,若想實現其他功能,可以自行增加和修改。

0x03 參考

[1]https://xianzhi.aliyun.com/forum/topic/1694/
[2]http://blog.csdn.net/guoxingege/article/details/47339885


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM