Location>code7788 >text

Practical: Mailivery simulation login

Popularity:68 ℃/2024-11-13 17:44:28

Problem scenarios

A friend in the obfuscation group encountered this problem, Mailivery After logging in to this website, obviously the submitted form (email and password are correct), request headers, etc. are all fine, why does it keep redirecting to the login page? I'll take a look at what's going on!

  • url: /login

截图_20241113133726

Login Parameter Analysis

Obviously, it requires: email (with email verification), password

Open the developer tools and log in with a random email and password to see the requests and methods of the login interface:

截图_20241113133929

Request URL:/login
Request Method:POST
Status Code:302 Found

302? Redirection? After an unsuccessful login redirected to the login site and asked to log in again. Eyeballing the non-separation of front-end and back-end projects (aba aba aba), if the login is successful, it will definitely redirect to the homepage or the relevant main panel carrying the cookie set at the time of the successful login.

Check out the login interface submission header:

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=an omission; mailivery_session=an omission; ......
DNT: 1
Host:
Origin:
Pragma: no-cache
Referer: /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"

There are no cryptographic parameters, emm ......, it's very simple, indeed it looks simple, pay attention toContent-Type beapplication/x-www-form-urlencoded

Take a look at the submission parameters again:

_token=lCsu2Ruuw33uHlHkRlKwZG3C2tw7TQBjUoTo1yjz&paid_user_Khe2xqZLA4Tkq3py=&submitted_in_seconds=eyJpdiI6IjJ4OXdFK3ZPZklKUnNadXVtRTk0L3c9PSIsInZhbHVlIjoiNHg5NzJmUjM3UnlDOU1tanlnUHpWdz09IiwibWFjIjoiMDYxYmRkODU0YmY1ZjY0MDk4OWMzNmM5YWU5MjNmZDM4NTg5NzQ1MmM3MzBjNzQ3YjYxNTg0MjliYjFjYzM3OCIsInRhZyI6IiJ9&email=xxx%&password=123

Format it and see:

_token: lCsu2Ruuw33uHlHkRlKwZG3C2tw7TQBjUoTo1yjz
paid_user_Khe2xqZLA4Tkq3py: 
submitted_in_seconds: eyJpdiI6IjJ4OXdFK3ZPZklKUnNadXVtRTk0L3c9PSIsInZhbHVlIjoiNHg5NzJmUjM3UnlDOU1tanlnUHpWdz09IiwibWFjIjoiMDYxYmRkODU0YmY1ZjY0MDk4OWMzNmM5YWU5MjNmZDM4NTg5NzQ1MmM3MzBjNzQ3YjYxNTg0MjliYjFjYzM3OCIsInRhZyI6IiJ9
email: xxx%
password: 123

Form submission, more or less with some validation parameters, such as here:_tokenpaid_user_Khe2xqZLA4Tkq3pysubmitted_in_seconds

After logging in several times to submit_token together withsubmitted_in_seconds The value of thepaid_user_Khe2xqZLA4Tkq3py The changes arepaid_user_ section after that. And these parameters are the same as the window'sCookie Related, if it doesn't match, a 416 error will occur indicating that the page is out of date. It looks like this is an anti-crawl point, remember what I said, this site is not separated from the front and back end, so these parameters must be hidden in the form as well, searching for the elements featured heavily in thesubmitted_in_seconds

截图_20241113135213

Very good to see where our three parameters came from, run through them:

Access to login website (GET) with three parameters, the cookie set in the response header has no effect on login
To login website (POST) with three parameters, according to the result redirection.
If login fails, the cookie set in the response header also has no login effect, and carry the cookie to ask us to continue to login.
If the login succeeds, the cookie set in the response header is valid for login, carry the cookie to the homepage directly.

The next step is to implement it in Python, creating the together with

The interface that implements the login:

import requests

url = "/login"

_token = ''
paid_user = ''
submitted_in_seconds = ''
email = 'xxx%'
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': '',
   'Origin': '',
   'Referer': '/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 = ("POST", url, headers=headers, data=payload, allow_redirects=False, proxies={
    'http': None,
    'https': None
})

print()
print(response.status_code)

Note that, as I said, the cookie and the three parameters are closely related. The above cookie is obtained through a GET of the login page, and the same applies to the three parameters.

I have omitted the values of the three parameters, with a special, special note that the request for theallow_redirectsThis value is best set to False because the redirection underpinnings are different from the browser, and if it's True, you'll find that your cookie is always disabled. If True, you'll find that your cookie will always be invalidated because of the redirection process that occurs as follows:

The case where the e-mail password is correct:
login -> dashboard -> login
In case the mailbox password is wrong:
login -> login
If the parameter is not validated:
login -> Page expired

Why did it end up in login again?

My guess is that it could be a counter-crawl point, where dynamic loading is not loaded properly, too quickly, and the cookie or all three parameters are still in an unprepared condition on the back end.

All we need to do is get the value of the Set-Cookie in the response header before jumping to the dashboard, that is, theXSRF-TOKEN together withmailivery_session

So we stopped using redirects from requests.

The next step is to take a look at this file, which is a test to see if getting a cookie works:

import requests

url = "/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': '',
   'Connection': 'keep-alive'
}

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

print()

full set of simulations

What we end up with is: automatically get the three parameters and the initial cookie, then log in based on the email and password, then carry the cookie to access the Dashboard.

  1. It's easy to get this automatically, by parsing through the etree in lxml, and the cookie is available in the requests response header.

  2. Then go to login, also very simple, carry the parameters and the cookie you got from the previous level, if the login password and these are correct, you will get a valid cookie.

  3. Finally, log in with a valid cookie from the previous level.

If that's the end of it for you, I'm sorry to say that you will find the cookie invalid after doing the above implementation again!!!!

As a side note, if there's a problem with the auto-fetch form parameters and the initial cookie, the request will respond with a 416. If there's no problem, and you log in immediately after fetching it, the request will respond with a 200. Is 200 necessarily a good thing? I've already said that to redirect to the dashboard page, it should be a 302! So we delay the request from fetching the parameter to logging in and wait for the backend to catch its breath, say 3 seconds, 4 seconds? That's fine. Or you can add a retry mechanism based on the response status code to try to get to a 302.

I won't provide the full code, you can figure it out on your own.