滲透基礎-利用IMAP協議讀取郵件
0x00 前言
在滲透測試中,當我們獲得了用戶的郵箱憑據,需要對郵箱內容進行分析時,可以選擇通過IMAP協議實現自動化來提高效率。
本文以Exchange為例,介紹通過IMAP協議下載郵件和附件的方法,開源代碼,分享腳本編寫細節。
0x01 簡介
本文將要介紹以下內容:
- 基礎知識
- Exchange開啟IMAP功能和登錄日志
- Python3實現細節
- 開源代碼
0x02 基礎知識
1.IMAP
- 全稱是Internet Mail Access Protocol,即交互式郵件存取協議
- 是一種郵件獲取協議,可以從郵件服務器上獲取郵件的信息
- 使用端口143
2.IMAP4_SSL
- 全稱是IMAP over SSL,是IMAP協議基于SSL安全協議之上的一種變種協議
- 繼承了SSL安全協議的非對稱加密的高度安全可靠性,可防止郵件泄露,也是用來接收郵件的
- 使用端口993
3.Python3 imaplib庫
官方文檔:
https://docs.python.org/3/library/imaplib.html
- 該模塊定義了三個類,IMAP4,IMAP4_SSL和 IMAP4_stream
- 為了提高安全性,我們通常使用用于安全連接的子類IMAP4_SSL
4.Python3 email庫
官方文檔:
https://docs.python.org/3/library/email.html
- 當我們使用imaplib庫讀取郵件時,需要使用email庫將接收的消息轉換為EmailMessage對象,可以更加方便的對郵件內容進行處理
0x03 Exchange開啟IMAP功能和登錄日志
默認情況下,Exchange中未啟用IMAP4客戶端連接
參考資料:
https://docs.microsoft.com/en-us/exchange/clients/pop3-and-imap4/configure-imap4?view=exchserver-2019
開啟方法如下:
1.啟動IMAP4服務,并將服務配置為自動啟動
Powershell命令如下:
- Start-Service MSExchangeIMAP4; Start-Service MSExchangeIMAP4BESet-Service MSExchangeIMAP4 -StartupType Automatic; Set-Service MSExchangeIMAP4BE -StartupType Automatic
2.配置IMAP4設置
格式如下:
- Set-ImapSettings -ExternalConnectionSettings "::", "::"... -X509CertificateName [-SSLBindings ":",":"...] [-UnencryptedOrTLSBindings ":",":"...]
Powershell命令實例:
- Set-ImapSettings -ExternalConnectionSettings "mail.test.com:993:SSL","mail.test.com:143:TLS" -X509CertificateName mail.test.com
3.重新啟動IMAP4服務
Powershell命令如下:
- Restart-Service MSExchangeIMAP4; Restart-Service MSExchangeIMAP4BE
4.查看配置:
Powershell命令如下:
- Get-Service MSExchangeIMAP4; Get-Service MSExchangeIMAP4BEGet-ImapSettings | Format-List *ConnectionSettings,*Bindings,X509CertificateName
使用郵箱用戶登錄OWA,選擇Settings->Options,能夠看到IMAP配置,如下圖:

默認情況下,Exchange中未啟用日志功能
參考資料:
https://docs.microsoft.com/en-us/exchange/configure-protocol-logging-for-pop3-and-imap4-exchange-2013-help
開啟方法如下:
1.開啟日志功能
Powershell命令如下:
- Set-ImapSettings -Server "CAS01" -ProtocolLogEnabled $true
2.重啟服務
重新啟動IMAP4服務,Powershell命令如下:
- Restart-Service MSExchangeIMAP4; Restart-Service MSExchangeIMAP4BE
3.查看配置信息:
Powershell命令如下:
- Get-ImapSettings | Format-List ProtocolLogEnabled,LogFileLocation,LogPerFileSizeQuota,LogFileRollOverSettings
默認的日志保存路徑為:C:\Program Files\Microsoft\Exchange Server\V15\Logging\Imap4
0x04 Python3實現細節
測試代碼1
- import imaplibM = imaplib.IMAP4_SSL('192.168.1.1','993')M.login('User1', 'Password')data = M.list()print(data)M.logout()
以上代碼用來獲得所有郵箱文件夾對應的名稱
(1)M.list()用來列出郵箱文件夾的名稱
注:
不同的郵件系統只有收件箱名稱統一默認為INBOX,發件箱的名稱一般不同,例如Exchange的發件箱名稱為"Sent Items"。
測試代碼2
- import imaplibM = imaplib.IMAP4_SSL('192.168.1.1','993')M.login('User1', 'Password')M.select('INBOX')typ, data = M.search(None, 'ALL')for num in data[0].split():typ, data = M.fetch(num, '(RFC822)')print('Message %s\n%s\n' % (num, data[0][1]))M.close()M.logout()
以上代碼用來讀取收件箱所有郵件的內容。
(1)M.select('INBOX')表示選擇收件箱
- 如果換成讀取Exchange的發件箱,對應的代碼為M.select('"Sent Items"')
- 如果添加參數2為False,表示設置了只讀標志,不允許修改郵箱,示例:M.select('"Sent Items"',False)
(2)typ, data = M.search(None, 'ALL')中,None表示使用默認的ASCII編碼,ALL表示搜索條件為所有郵件
- 如果想要篩選出發件人為user2的郵件,對應語句為typ, msgnums = M.search(None, '(FROM "user2")')
M.search()返回的結果為郵件的序列號,例如我的測試環境下,收件箱有9個郵件,此時返回的結果為:
- [b'1 2 3 4 5 6 7 8 9']
注:
- 這里需要區分郵件序列號和UID
- 郵件序列號為從1開始累加的數列,UID是區分郵件的唯一標識
獲得郵件序列號同UID對應關系可使用以下代碼:
- import imaplibM = imaplib.IMAP4_SSL('192.168.1.1','993')M.login('User1', 'Password')M.select('INBOX')typ, data = M.search(None, 'ALL')for num in data[0].split():typ, data = M.fetch(num, 'UID')print(data)M.close()M.logout()
(3)M.fetch(num, '(RFC822)')用來提取郵件消息
- 參數1num表示提取的郵件序列號
- 參數1支持同時提取多個連續郵件消息,例如同時提取郵件序列號為2-5的郵件命令為M.fetch('2:5', '(RFC822)')
- 參數2'(RFC822)'表示數據項名稱,這里’(RFC822)’等同于BODY[],只返回郵件體文本格式和大小的摘要信息
如果只想獲得郵件頭部的內容,可以使用以下代碼:
- M.fetch(num, 'BODY[HEADER]')
如果只想獲得郵件體的內容,可以使用以下代碼:
- M.fetch(num, 'BODY[TEXT]')
(4)M.close()用來關閉當前選擇的郵箱
在執行完M.select()后使用
測試代碼3
- import imaplibimport emailM = imaplib.IMAP4_SSL('192.168.1.1','993')M.login('User1', 'Password')M.select('INBOX')typ, data = M.search(None, 'ALL')for num in data[0].split():typ, data = M.fetch(num, '(RFC822)')msg = email.message_from_bytes(data[0][1])for part in msg.walk():if part.get('Content-Disposition'):fileName = part.get_filename()if bool(fileName):with open(fileName,'wb') as f:f.write(part.get_payload(decode=True))M.close()M.logout()
以上代碼用來保存收件箱所有郵件的附件
(1)msg = email.message_from_bytes(data[0][1])用來將數據轉換為email對象
(2)msg.walk()用來遍歷郵件對象的所有部分
(3)part.get('Content-Disposition')用來獲得對應字段名Content-Disposition的字段值
如果郵件包含附件,將會帶有字段Content-Disposition,通過這個判斷郵件是否包含附件
(4)part.get_filename()用來獲得信息頭當中Content-Disposition字段當中名為filename的參數值,對應附件的名稱
(5)part.get_payload(decode=True)用來獲得附件內容
由于附件內容是以Base64編碼的形式存儲,所以在讀取時需要加入參數decode=True作Base64解碼。
測試代碼4
- import imaplibimport emailM = imaplib.IMAP4_SSL('192.168.1.1','993')M.login('User1', 'Password')M.select('INBOX')typ, data = M.search(None, 'ALL')for num in data[0].split():typ, data = M.fetch(num, '(RFC822)')msg = email.message_from_bytes(data[0][1])with open(num.decode('utf8') + '.eml','wb') as f:f.write(bytes(msg))M.close()M.logout()
以上代碼用來逐個保存收件箱的所有郵件,以郵件序列號為名稱,后綴名為eml,可以使用Outlook打開。
0x05 開源代碼
我已經將完整的代碼上傳至github,地址如下:
https://github.com/3gstudent/Homework-of-Python/blob/master/imapManage.py
代碼支持以下功能:
- 查看文件夾配置
- 從收件箱下載所有附件
- 從發件箱下載所有附件
- 從收件箱下載所有郵件
- 從發件箱下載所有郵件
在下載文件時,首先以郵箱用戶名創建文件夾,保存對應用戶下載的文件。
默認支持通過IMAP4_SSL訪問Exchange郵件,對于不同的郵件系統,收件箱沒有區別,發件箱的名稱有所不同。發件箱的名稱可以通過。CheckConfig命令查詢文件夾對應的名稱進行修改。
代碼修復了附件名稱因為編碼問題無法識別的bug。
為了便于記錄郵件訪問過程,加入了日志記錄功能。
0x06 小結
本文以Exchange為例,介紹通過IMAP協議下載郵件和附件的方法,開源代碼imapManage.py,分享腳本編寫細節。對于其他郵件系統,可以參照此代碼只需要修改發件箱的名稱即可。
本文為 3gstudent 原創稿件,授權嘶吼獨家發布,如若轉載,請注明原文地址。