實戰:Mailivery 模擬登入

顾平安發表於2024-11-13

問題情景

混淆群內的小夥伴遇到這麼個問題,Mailivery 這個網站登入後,明明提交的表單(郵箱和密碼也正確)、請求頭等等都沒問題,為啥一直重定向到登入頁面呢?唉,該出手時就出手啊,我也看看咋回事吧!

  • url: https://app.mailivery.io/login

截圖_20241113133726

登入引數分析

顯而易見,需要:郵箱(有郵箱校驗)、密碼

開啟開發者工具,隨意輸入郵箱和密碼登入,檢視登入介面的請求和方法:

截圖_20241113133929

請求網址:https://app.mailivery.io/login
請求方法:POST
狀態程式碼:302 Found

302?!重定向嗎?在登入不成功後重定向到了登入網站,要求重新登入。目測前後端不分離專案(阿巴阿巴),如果登入成功,肯定會攜帶登入成功時設定的 Cookie 重定向到主頁或者相關主皮膚。

檢視一下登入介面提交頭:

POST /login HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 341
Content-Type: application/x-www-form-urlencoded
Cookie: XSRF-TOKEN=省略; mailivery_session=省略; ......
DNT: 1
Host: app.mailivery.io
Origin: https://app.mailivery.io
Pragma: no-cache
Referer: https://app.mailivery.io/login
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36
sec-ch-ua: "Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"

沒有啥加密引數,emm……,很簡單,的確是看著很簡單,注意 Content-Typeapplication/x-www-form-urlencoded

再看看提交的引數:

_token=lCsu2Ruuw33uHlHkRlKwZG3C2tw7TQBjUoTo1yjz&paid_user_Khe2xqZLA4Tkq3py=&submitted_in_seconds=eyJpdiI6IjJ4OXdFK3ZPZklKUnNadXVtRTk0L3c9PSIsInZhbHVlIjoiNHg5NzJmUjM3UnlDOU1tanlnUHpWdz09IiwibWFjIjoiMDYxYmRkODU0YmY1ZjY0MDk4OWMzNmM5YWU5MjNmZDM4NTg5NzQ1MmM3MzBjNzQ3YjYxNTg0MjliYjFjYzM3OCIsInRhZyI6IiJ9&email=xxx%40foxmail.com&password=123

格式化看一下:

_token: lCsu2Ruuw33uHlHkRlKwZG3C2tw7TQBjUoTo1yjz
paid_user_Khe2xqZLA4Tkq3py: 
submitted_in_seconds: eyJpdiI6IjJ4OXdFK3ZPZklKUnNadXVtRTk0L3c9PSIsInZhbHVlIjoiNHg5NzJmUjM3UnlDOU1tanlnUHpWdz09IiwibWFjIjoiMDYxYmRkODU0YmY1ZjY0MDk4OWMzNmM5YWU5MjNmZDM4NTg5NzQ1MmM3MzBjNzQ3YjYxNTg0MjliYjFjYzM3OCIsInRhZyI6IiJ9
email: xxx%40foxmail.com
password: 123

表單提交嘛,多多少少也是帶點驗證引數,比如這裡的:_tokenpaid_user_Khe2xqZLA4Tkq3pysubmitted_in_seconds

經過多次登入提交,發現 _tokensubmitted_in_seconds 的值是變動的,而 paid_user_Khe2xqZLA4Tkq3py 變動的是 paid_user_ 之後的部分。並且這些引數與視窗的 Cookie 相關,如果不一致,將發生 416 錯誤,提示頁面過期。看來這就是個反爬點了,還記得我說的嗎,這個網站是前後端不分離,那麼這些引數肯定也隱藏於表單,在元素中搜尋特色濃重的 submitted_in_seconds

截圖_20241113135213

非常的好,可以看到我們這三個引數的來源了,捋一捋:

訪問 login 網站(GET) 得到三個引數,此時響應頭所設定的 Cookie 無登入效力
對 login 網站(POST) 攜帶三個引數,根據結果重定向:
	如果登入失敗,此時響應頭所設定的 Cookie 也是無登入效力的,攜帶 Cookie 要求咱們繼續登入
	如果登入成功,此時響應頭所設定的 Cookie 就是具備登入效力的,攜帶 Cookie 直接上主頁

接下來在 Python 中實現一下,建立 login.pydashboard.py

login.py 實現登入的介面:

import requests

url = "https://app.mailivery.io/login"

_token = ''
paid_user = ''
submitted_in_seconds = ''
email = 'xxx%40163.com'
password = 'xxxxxxx'

payload=f'_token={_token}&{paid_user}=&submitted_in_seconds={submitted_in_seconds}&email={email}&password={password}'

headers = {
   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
   'Accept-Language': 'zh-CN,zh;q=0.9',
   'Host': 'app.mailivery.io',
   'Origin': 'https://app.mailivery.io',
   'Referer': 'https://app.mailivery.io/login',
   'Sec-Fetch-Dest': 'document',
   'Sec-Fetch-Mode': 'navigate',
   'Sec-Fetch-Site': 'same-origin',
   'Sec-Fetch-User': '?1',
   'Upgrade-Insecure-Requests': '1',
   'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
   'sec-ch-ua': '"Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"',
   'sec-ch-ua-mobile': '?0',
   'sec-ch-ua-platform': '"Windows"',
   'Cookie': 'XSRF-TOKEN=eyJpdiI6Ikk1WjFjMFRsdVhKdzBuMjBWamNVVEE9PSIsInZhbHVlIjoiblAzS0ZBOEUyK1lXWGV0ZXhuT1Y5MldLc290d2ZzL0E3dTQxT3BDMmNGR3d6aG0vamhUekozeVFCUVVVczRJSWxxQTM1ZGpvOU5KTm11bFp4NEsvWGlObUJ6V1A3WWc1WFJXcUlPYWYzYTgrSGNMZ2VtM0s1R0tGUlJ4Z0ZMSy8iLCJtYWMiOiI2NGUxYmNhMjEwMmE3ZDNmOTc4OTcxMWVlZGY3ODIyNDZhODBiYzUxZjVhMWE2YWZkMWVhOGM2YjA4MmQzYmY0IiwidGFnIjoiIn0%3D; mailivery_session=eyJpdiI6IjVwL1QwUHNhMTlTdGUyZ0ozUzY3aGc9PSIsInZhbHVlIjoiYlNuSXI2d2tKWjMrYjFpVmx1Ym5uTEVOUGhXZjFKRGhVV1VMeXRHQ1BpRWFsV0ZnYVFkNDd4Vm9wdXY1ZElqVWpVL2xhSytNdnBDYS9NNHRBWmNzRDF4ZjJtWFhPTHFJRFBLVnNYSmFPMW9HSkEweVVpQTZZVjhJU2k5WSswR0oiLCJtYWMiOiJkYzg0ZmY2ODEwZmEyMzczNzU5NGU4YzMwYjA2MDRlZTc0ZWJiNDc4ZDBhMDU4OTgyM2E3NDMzZDM3NmRmNTcxIiwidGFnIjoiIn0%3D',
   'Content-Type': 'application/x-www-form-urlencoded',
   'Connection': 'keep-alive'
}

response = requests.request("POST", url, headers=headers, data=payload, allow_redirects=False, proxies={
    'http': None,
    'https': None
})

print(response.headers)
print(response.status_code)

注意,我說過,Cookie 和三個引數是有緊密聯絡的,上述 Cookie 是透過對登入頁面 GET 時得到的,三個引數同理。

三個引數的值我已省略,特別特別要注意的是:請求時,allow_redirects這個值最好設定為 False,因為重定向底層和瀏覽器不同,如果為 True,你會發現你的 Cookie 一直都是失效的。因為產生了如下的重定向過程:

郵箱密碼正確的情況:
login -> dashboard -> login
郵箱密碼錯誤的情況:
login -> login
引數未校驗的情況:
login -> 頁面過期

為什麼最終又到 login 了???

我猜測可能是反爬點,動態載入未載入好,太快了,Cookie 或者三個引數在後端都還是未準備好的狀況。

我們只需要取得跳轉到 dashboard 前響應頭中的 Set-Cookie 的值,也就是 XSRF-TOKENmailivery_session

因此我們停止使用 requests 的重定向。

接下來看一下 dashboard.py 這個檔案,主要測試一下取得 Cookie 是否有效:

import requests

url = "https://app.mailivery.io/campaign/dashboard"

payload={}
xsrf_token = 'xxx'
mailivery_session = 'xxx'

headers = {
   'Cookie': f'XSRF-TOKEN={xsrf_token}; mailivery_session={mailivery_session}',
   'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
   'Accept': '*/*',
   'Host': 'app.mailivery.io',
   'Connection': 'keep-alive'
}

response = requests.request("GET", url, headers=headers, data=payload, proxies={
    'http': None,
    'https': None
})

print(response.text)

全套模擬

我們最終的效果是:自動獲取三個引數和初始的 Cookie,然後根據郵箱和密碼登入,再攜帶 Cookie 訪問 Dashboard。

  1. 自動獲取這個很簡單,透過 lxml 中的 etree 解析,Cookie 透過 requests 響應頭得到。

  2. 然後去登入,也很簡單,攜帶好引數和上一級得到的 Cookie,如果登入密碼這些沒錯,將得到有效的 Cookie。

  3. 最後攜帶上一級得到的有效 Cookie 進行登入。

如果說你覺得到此結束了,那很抱歉,你再進行上述的實現後,將發現 Cookie 無效!!!

略帶一筆,自動獲取的表單引數和初始 Cookie 如果有問題,請求時將響應 416。如果沒問題,你在取到後立馬進行登入,請求將響應 200。200 就一定是好事嗎?我已經說過了,要重定向到 dashboard 頁面,那麼應該是 302 才對!所以我們在取引數到登入這個請求中進行延時,等待後端緩過神,比如 3 秒?4秒?都是可以的。或者你根據響應狀態碼增加重試機制,嘗試到出現 302 的情況。

完整程式碼就不提供啦,自行琢磨吧~

相關文章