pop3&smtp
pop3
Post Office Protocol - Version 3
pop3協議是離線郵件協議,是客戶端取郵件用的。
默認監聽在TCP:110端口.
POP3會話有3個狀態AUTHORIZATION、TRANSACTION和UPDATE不同狀態能用的命令不同。
等待連接 身份確認 quit命令
—— |AUTHORIZATION|————— |TRANSACTION|——————|UPDATE|
|________________________________________________________|
重返認可狀態
POP3命令碼如下:
命令(ascII字符) | 參數 | 狀態 | 描述 |
---|---|---|---|
USER | username | AUTHORIZATION | 用戶名 |
PASS | password | AUTHORIZATION | 密碼,若成功,將導致狀態轉換 |
APOP | username Digest(加密后密碼) | AUTHORIZATION | Digest是MD5消息摘要 |
STAT | none | TRANSACTION | 請求服務器發回關於郵箱的統計資料,如郵件總數和總字節數 |
UIDL(unique-id listing) | [message] | TRANSACTION | 返回郵件的唯一標識符,POP3會話的每個標識符都將是唯一的 |
LIST | [message] | TRANSACTION | 返回郵件數量和每個郵件的大小 |
RETR(retrieve) | [message] | TRANSACTION | 返回由參數標識的郵件的全部文本 |
DELE | [message] | TRANSACTION | 服務器將由參數標識的郵件標記為刪除,會話進入UPDATE后刪除 |
RSET | [message] | TRANSACTION | 服務器將重置所有標記為刪除的郵件,用於撤消DELE命令 |
TOP | [message] | TRANSACTION | 服務器將返回由參數標識的郵件前n行內容,n必須是正整數 |
NOOP | [message] | TRANSACTION | 服務器返回一個肯定的響應 |
QUIT | none | UPDATE | pop3服務器刪除標記為deleted的郵件,無論錯誤與否,釋放獨占鎖、關閉TCP連接 |
wireshark抓包:第一張為開始,第二章為結束
SMTP
SMTP工作在兩種情況下
- 發件人客戶端傳輸到服務器
- 郵件服務器向另一個郵件服務器傳輸郵件
smtp是個請求/響應協議,命令和響應都是基於ascii文本,並以cr和lf符結束。響應包括一個表示返回狀態的三位數字代碼。
網圖,來自https://blog.csdn.net/bripengandre/article/details/2191048
模型
-------------------------------------------------------------
+----------+ +----------+
+------+ | | | |
| User |<-->| | SMTP | |
+------+ | Sender- |Commands/Replies| Receiver-|
+------+ | SMTP |<-------------->| SMTP | +------+
| File |<-->| | and Mail | |<-->| File |
|System| | | | | |System|
+------+ +----------+ +----------+ +------+
Sender-SMTP Receiver-SMTP
-------------------------------------------------------------
命令格式
COMMAND [Parameter]
XXX Readable Illustration。XXX是三位十進制數;Readable Illustration是可讀的解釋說明,用來表明命令是否成功等。XXX具有如下的規律:以2開頭的表示成功,以4和5開頭的表示失敗,以3開頭的表示未完成(進行中)。
命令
命令 | 描述 |
---|---|
HELO
|
向服務器標識用戶身份 |
MAIL FROM:
|
|
RCPT TO:
|
|
DATA
|
將之后的數據作為數據發送,以
|
REST
|
重置會話,當前傳輸被取消 |
NOOP
|
要求服務器返回OK應答,一般用作測試 |
QUIT
|
結束會話 |
VRFY
|
驗證指定的郵箱是否存在,由於安全方面的原因,服務器大多禁止此命令 |
EXPN
|
驗證給定的郵箱列表是否存在,由於安全方面的原因,服務器大多禁止此命令 |
HELP
|
查詢服務器支持什么命令 |
AUTH LOGIN | 認證請求 |
EHLO | 除了HELO所具有的功能外,EHLO主要用來查詢服務器支持的擴充功能 |
編碼
250 8BITMIME /* 最后一個響應數字應答碼之后跟的是一個空格,而不是'-' */
用戶名、密碼需采用base64編碼(Base64就是一種基於64個可打印字符來表示二進制數據的表示方法。)
以“X”開頭的關鍵字都是指服務器自定義的擴充(還沒納入RFC標准)
還有一些重要字段
Received: from DM6NAM11HT080.eop-nam11.prod.protection.outlook.com
(2603:1096:201:20::24) by HK0PR06MB3714.apcprd06.prod.outlook.com with HTTPS
via HK2PR02CA0212.APCPRD02.PROD.OUTLOOK.COM; Sat, 12 Oct 2019 02:04:31 +0000
Received: from DM6NAM11FT041.eop-nam11.prod.protection.outlook.com
(10.13.172.57) by DM6NAM11HT080.eop-nam11.prod.protection.outlook.com
(10.13.172.248) with Microsoft SMTP Server (version=TLS1_2,
cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.2347.16; Sat, 12 Oct
2019 02:04:30 +0000
Authentication-Results: spf=pass (sender IP is 120.26.244.201)
smtp.mailfrom=smail.kzedu.cc; hotmail.com; dkim=none (message not signed)
header.d=none;hotmail.com; dmarc=bestguesspass action=none
header.from=smail.kzedu.cc;
Received-SPF: Pass (protection.outlook.com: domain of smail.kzedu.cc
designates 120.26.244.201 as permitted sender)
receiver=protection.outlook.com; client-ip=120.26.244.201;
helo=smtp552.submail.cn;
Received: from smtp552.submail.cn (120.26.244.201) by
DM6NAM11FT041.mail.protection.outlook.com (10.13.172.98) with Microsoft SMTP
Server id 15.20.2347.16 via Frontend Transport; Sat, 12 Oct 2019 02:04:29
+0000
X-IncomingTopHeaderMarker:
OriginalChecksum:24B3073D37E1488647AB6D33914E56311671421DA99AC9F3ACCE5038C61D9AED;UpperCasedChecksum:4E628F444082EA3506FF7B7B728D6469D42940820A842E95A6AF817CE7359561;SizeAsReceived:633;Count:10
Date: Sat, 12 Oct 2019 2:4:28 +0000
Received是smtp服務器記錄的從哪里收到的郵件。從上往下就是SMTP中繼的各個節點。最下面的是發件服務器IP。
Received-SPF是防止假郵件的mail from可以偽造from更不用說,但是SPF記錄該域名的郵件服務器的發件IP地址,可以驗證真偽(要發假的垃圾郵件要模仿的是SMTP服務器行為,除非黑客控制了一個域名的郵件服務器)。
MIME消息由消息頭和消息體兩大部分組成,郵件頭與郵件體之間以空行進行分隔
郵件頭包含了發件人、收件人、主題、時間、MIME版本、郵件內容的類型等重要信息。每條信息稱為一個域,由域名后加“: ”和信息內容構成,可以是一行,較長的也可以占用多行。域的首行必須“頂頭”寫,即左邊不能有空白字符(空格和制表符);續行則必須以空白字符打頭,且第一個空白字符不是信息本身固有的,解碼時要過濾掉。
郵件體包含郵件的內容,它的類型由郵件頭的“Content-Type”域指出。常見的簡單類型有text/plain(純文本)和text/html(超文本),multipart/mixed, multipart/related和multipart/alternative。
multipart類型,是MIME郵件的精髓。郵件體被分為多個段,每個段又包含段頭和段體兩部分,這兩部分之間也以空行分隔。常見的multipart類型有三種:multipart/mixed, multipart/related和multipart/alternative。
+------------------------- multipart/mixed ----------------------------+
| |
| +----------------- multipart/related ------------------+ |
| | | |
| | +----- multipart/alternative ------+ +----------+ | +------+ |
| | | | | 內嵌資源 | | | 附件 | |
| | | +------------+ +------------+ | +----------+ | +------+ |
| | | | 純文本正文 | | 超文本正文 | | | |
| | | +------------+ +------------+ | +----------+ | +------+ |
| | | | | 內嵌資源 | | | 附件 | |
| | +----------------------------------+ +----------+ | +------+ |
| | | |
| +------------------------------------------------------+ |
| |
+----------------------------------------------------------------------+
可以看出,如果在郵件中要添加附件,必須定義multipart/mixed段;如果存在內嵌資源,至少要定義multipart/related段;如果純文本與超文本共存,至少要定義multipart/alternative段。什么是“至少”?舉個例子說,如果只有純文本與超文本正文,那么在郵件頭中將類型擴大化,定義為multipart/related,甚至multipart/mixed,都是允許的。
multipart諸類型的共同特征是,在段頭指定“boundary”參數字符串,段體內的每個子段以此串定界。所有的子段都以“--”+boundary行開始,父段則以“--”+boundary+“--”行結束。段與段之間也以空行分隔。在郵件體是multipart類型的情況下,郵件體的開始部分(第一個“--”+boundary行之前)可以有一些附加的文本行,相當於注釋,解碼時應忽略。
可以觀察一下邊界001、002、003等
提取pcapng中流量可以從wireshark中直接將郵件正文部分復制出來保存到文件中后綴改為.eml拿客戶端打開。反正我覺得自己解析郵件中的文件太難了,取個巧。
base64
Base64的索引表,字符選用了"A-Z、a-z、0-9、+、/"
64個可打印字符。數值代表字符的索引,這個是標准Base64協議規定的,不能更改。64個字符用6個bit位就可以全部表示,一個字節有8個bit位,剩下兩個bit就浪費掉了,這樣就不得不犧牲一部分空間了。這里需要弄明白的就是一個Base64字符是8個bit,但是有效部分只有右邊的6個bit,左邊兩個永遠是0。
那么怎么用6個有效bit來表示傳統字符的8個bit呢?8和6的最小公倍數是24,也就是說3個傳統字節可以由4個Base64字符來表示,保證有效位數是一樣的,這樣就多了1/3的字節數來彌補Base64只有6個有效bit的不足。
我的郵件當中有那么一段
先用base64解碼,然后用GB2312解碼
需要注意的是根據RFC 822規定,每76個字符,還需要加上一個回車換行。所以字符串要手動去除回車換行。
參考:
https://zh.wikipedia.org/wiki/Base64