Author: Aaron Bishop
What is CSRF?
Cross-site request forgery, commonly referred to as CSRF (pronounced sea-surf), is an attack in which a user who is authenticated to an application is tricked into unintentionally performing a state-changing action. For example, if the vulnerable function is something like a bank transfer, the victim could unintentionally transfer a sum of money to the attacker. Similar to a sophisticated con, the con artist doesn't need to break into your account and take your money, instead they trick you into sending the money to them and it appears to be legitimate.
Is Cross-Site request forgery still an issue?
It's true that CSRF isn't talked about as frequently as it once was; CSRF was removed from the OWASP Top 10 and tagged 'Gone but not Forgotten', many frameworks now include some method of CSRF protection, and even browsers have implemented features to prevent or minimize CSRF attacks. It's less common than it once was, but still exists.
Example of CSRF from a penetration test
Our story begins in December 2019, a Castel NextGen DVR device appeared in a penetration test. The application associated with the device included the parameter __RequestVerificationToken with state-changing requests like
POST /Administration/Users/Create HTTP/1.1 ... __RequestVerificationToken=REDACTED&Username=test123&Email=test%40test.com &FirstName=test&LastName=test&LDAPUser=false&Roles%5B0%5D.RoleId=1 &Roles%5B0%5D.IsSelected=true&Roles%5B0%5D.IsSelected=false&Roles%5B1%5D.RoleId=3 &Roles%5B1%5D.IsSelected=true&Roles%5B1%5D.IsSelected=false&Roles%5B2%5D.RoleId=4 &Roles%5B2%5D.IsSelected=true&Roles%5B2%5D.IsSelected=false
A cursory glance implied the application has CSRF protection in place and the token appeared to be sufficiently long and random, however, a CSRF token is only beneficial if it is validated by the application. Merely including a token but not validating it is like installing a lock and never engaging it.
I noticed that when __RequestVerificationToken is removed from the request (shown below)...
POST /Administration/Users/Create HTTP/1.1 ... Username=test123&Email=test%40test.com&FirstName=test&LastName=test&LDAPUser=false &Roles%5B0%5D.RoleId=1&Roles%5B0%5D.IsSelected=true&Roles%5B0%5D.IsSelected=false &Roles%5B1%5D.RoleId=3&Roles%5B1%5D.IsSelected=true&Roles%5B1%5D.IsSelected=false &Roles%5B2%5D.RoleId=4&Roles%5B2%5D.IsSelected=true&Roles%5B2%5D.IsSelected=false
...the request was successful and the new user was created. This indicated the application may be vulnerable to CSRF as there was nothing to verify that this request had been intentional. To be sure, I verified there were no other tricks employed to prevent CSRF attacks and created a mock page to verify CSRF was possible. It was.
The CSRF was reported, resolved, and assigned CVE-2020-11682.
I checked other state-changing requests to discover the extent and exploitability of the issue. The following functionality was vulnerable:
POST /Administration/Archiving/Delete POST /Administration/FileStores/Create
POST /Administration/FileStores/Delete POST /Administration/LDAP POST /Administration/Roles/Edit/:RoleId
POST /Administration/Users/Edit/:UserId POST /Administration/Users/ResetPassword
Combined with the authentication bypass issue reported in CVE-2020-11680, and discussed in Authorization Bypass: A cautionary tale, an admin user would unintentionally be created if any user visits a malicious page that submits a request similar to the /Administration/Users/Create request shown above. Armed with an admin user, an attacker could retrieve the credentials for the SMTP host and compromise other accounts.
Many modern frameworks provide some method of CSRF prevention, however, numerous legacy applications exist that are often inherited or passed on to new developers. While not as common as it once was, CSRF should remain a topic of discussion and developers should know how their application is protected from CSRF.