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.
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.
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.
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 /Administration/Users/Create
:
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/Alerts/Create POST /Administration/SMTP
POST /Administration/Alerts/Delete POST /EventLogPOST /Administration/Archiving/ GET /Recordings/DeleteAnnotation
POST /Administration/Roles/Delete POST /Administration/Archiving/Create
POST /Administration/Archiving/Delete POST /Administration/FileStores/Create
POST /Administration/FileStores/Delete POST /Administration/LDAP
POST /Administration/Roles/Edit/:RoleId POST /Administration/Users/DeletePOST /Administration/Users/Create GET /Recordings/SaveAnnotation
POST /Administration/Users/Edit/:UserId POST /Administration/Users/ResetPassword
POST /Administration/Archiving/Edit/:ArchiveRuleId
POST /Administration/FileStores/Edit/:FileStoreId
POST /Administration/Alerts/Edit/:EventAlertId
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.