# Dev Training ### Cross-site Request Forgery ## Overview ### What is it? * A dying vulnerability? * Exploits how browsers handle cookies * User is tricked or phished into submitting a request to a vulnerable website * The request is used to perform an action on behalf of the user * Change account email * Add API token * Transfer money * Attacker does not receive any data ### Types * CSRF is mostly performed with two HTTP verbs * GET * POST * PUT and DELETE requests can (currently) only be performed using JS * Protected by the browser's CORS policy * **But**, CSRF is still possible with lax CORS settings Note: cross origin resource sharing ### Why does it work? Traditionally when a request is made in a browser, relevant cookies are sent with the request, regardless of where the request originates from ### How does it work? * User is tricked into clicking a link * GET request * User is tricked into clicking a form submit button * POST request * If user is logged in, auth cookies follow with request * Action is performed by the authenticated user ## Same-origin policy (SOP) ### What is it? * Policy enforced by browsers * Only requests to same host with same protocol and port are allowed by SOP ### Example `http://some.example.com/index.php` | URL | Same origin | |-------------------------------------------|-------------| | `http://some.example.com/test.html` | Yes | | `http://other.example.com/test.html` | No | | `https://some.example.com/index.php` | No | | `http://some.example.com:5000/` | No | ### Cross-origin requests What if `example.com` needs to send requests to `api.example.com`? ### Cross-origin resource sharing (CORS) * Tells browsers SOP can be bypassed in certain ways * `Access-Control-Allow-Origin` * Allow cross-origin requests from these origins * `Access-Control-Allow-Credentials` * Allow cross-origin credentials * `Access-Control-Allow-Methods`
`Access-Control-Allow-Headers` * Allow specific HTTP methods and headers ### Request blocked by CORS
### Preflight requests * `OPTIONS` requests sent by browsers * Determine whether cross-origin request is allowed * Sent for all *non-simple* requests * Request is not `GET`, `POST` or `HEAD` * Content type is not text or URL encoded * Unusual headers ### Blocked preflighted request
Note: POST requests made using JS will be blocked by CORS policy ## CSRF with GET ### GET requests * HTTP GET requests are intended to retrieve data * If state is altered with GET requests, CSRF can be achieved simply by having the victim click a link * `bank.is/transfer?to=evil&amt=100000` * Same result can be achieved with JavaScript on any website the victim visits ### Protection * Don't alter application state in significant ways with GET requests * Log out is OK * Password change, updating account details, etc. is **not OK** ## CSRF with POST ### POST requests * Are intended for state change * Attack vectors * Trick victim to post form * JavaScript on website victim visits * Some JavaScript POST requests can be blocked by CORS policy ### Example ```html
``` ## Impact ### Impact * Depends on victim's privileges * Worst case * Data exfiltration * Account takeover * Remote code execution ## Protection ### CSRF tokens * Secret, random and unpredictable tokens generated to synchronize form submissions with the rendered form * Built into most modern web frameworks * User performs GET request to receive form * Server generates token * Injects it into response * User posts form * Token is included in request * Server validates that the token is valid for this user ### SameSite * `SameSite` attribute on session cookies should be set to `Lax` or `Strict` if possible * All popular browsers default to `Lax` for cross-site requests * Not always possible * If `example.com` sends authenticated requests to `api.example.com`, `SameSite` must be `None` Note: Strict, your cookie will only be sent in a first-party context. In user terms, the cookie will only be sent if the site for the cookie matches the site currently shown in the browser's URL bar. LAX:cookie would be allowed when following a regular link from an external website while blocking it in CSRF-prone request methods (e.g. POST) ## Rules of thumb ### General * Only allow requests from trusted sources with CORS headers * Don't make significant changes with `GET` requests * Use CSRF tokens for `POST`, `PUT` and `DELETE` requests * Use `SameSite` attribute on session cookies ## Epilogue ### Further reading * [OWASP - CSRF](https://owasp.org/www-community/attacks/csrf) * [OWASP - CSRF Prevention](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html) ### Hall of fame * [CSRF to RCE in Zabbix](https://www.horizon3.ai/cve-2021-27927-csrf-to-rce-chain-in-zabbix/) * [CSRF to RCE in WordPress plugin](https://blog.wpsec.com/csrf-to-rce-wordpress/) * [CSRF to RCE in Cisco Energy Management](https://medium.com/tenable-techblog/csrf-is-no-joke-e6f00594b21e)