In-depth analysis of Cross-Site Request Forgery from the perspective of hackers
When testing Web applications, the automated tools we use sometimes miss some very serious security vulnerabilities. Cross-Site Request Forgery is one of them. Therefore, for Web application testing, it is very important to analyze code manually.
In the recent Web application testing process, I discovered several CSRF vulnerabilities manually. If I use them in tandem, they can become more serious security vulnerabilities. Next, this article describes how to discover these vulnerabilities and how to use them to control the victim's account. It should be noted that some content has been blurred to protect customer information.
0 × 01 difficult discovery journey
In order to carry out cross-site request forgery attacks, we must first conduct some investigation work. To this end, I log on to the Web application that needs to be tested based on the low-permission account provided by the customer. On this website, most pages require you to know the account name, product serial number, and other information in advance. I had no idea about this, so I had to look into the account overview page. This page allows users to update their account information, such as name, email address, city, province, and so on.
For browsers, I usually select Firefox, because the TamperData plug-in can be used to conveniently operate form fields to see if interesting things happen. For example, I often insert some strange data between quotes or asterisks to explore various injection attacks. In this example, I found a hidden form field that will be transmitted along with other account information. The field name is _ RequestVerificationToken. I kept playing with this field, but I did not find the injection vulnerability. However, I noticed an important thing, that is, the site does not seem to care about all the modifications I have made to this field.
This is very strange to me. Based on the field name, it seems to be a security measure used to verify whether each submitted request comes from the actual user of the website. This is usually used to prevent cross-site Request Forgery (CSRF) attacks. However, this page does not seem to verify this token, which means that this information update form is vulnerable to CSRF attacks.
After remembering this, I began to test other parts of the website. I think if one page has this vulnerability, other pages may also have this vulnerability. Unfortunately, this is not the case. For all other pages, modification of this token will cause a server error and the form cannot be processed. That is to say, in addition to personal information pages, the doors of other places are blocked. Next, we need to find a way to use it for more evil.
0 × 02 forgot password
Like some websites, this website also provides a "forgot password" function. The original intention of this function is of course to help users who forget their passwords. This automation system is very simple. You can enter the user name to the corresponding form field and click Submit. If the user name is valid, the system generates a new random password for the user's account and sends it to the email address bound to the user account. This function is not only very simple for users, but also provides great convenience for hackers.
I realized that if I could use the CSRF vulnerability to update a user's email address to my own email address, I could use the forgot password function to send the user's password to me, instead of users. Unfortunately, I quickly encountered a problem.
The email address that the customer (here referred to as example.com) provides to my test account contains the customer's domain name, such as a bob@example.com. Although the system allows me to change this email address to the address I want, there is a problem. When the system sends a new password to my email address, what we actually receive is a server error. I don't know why, it seems like only mailbox like bob@example.com.
After further manual testing, I found that it can accept any user name, as long as it ends with example.com. I don't know why this happens, because other accounts in the system contain email addresses from different domains. I think there must be some additional security verification, such as comparing the email address domain name based on the whitelist. However, my personal email address or domain name must not be in this table. Therefore, we need to use the techniques described below.
0 × 03 Gmail
I have a hunch that the white list matching process of the email address can be cracked. Later, it turns out that I still feel very accurate: I found that, any email address can bypass the White List, as long as the email name of this address contains the word "example.com. For example, example.com@otherdomain.com can fully achieve our purpose. Therefore, we only need to create an email account with example.com in the mailbox name.
Now, Gmail is playing. Gmail is selected because it allows the plus sign to be used after the Gmail user name and @ symbol. This feature is very useful for us. For example, if your email address is a rick@gmail.com, you can also use rick + test@gmail.com to receive the mail, in fact the mail will still be sent to the rick@gmail.com mailbox, because Gmail ignores all content between the plus sign and the @ symbol.
With this in mind, I again logged on to the Web application for testing and updated the account's email address to "rick + example.com@gmail.com ". Sure enough, this method is indeed feasible. The password reset function sent me a new password. In this case, we should verify the availability of the CSRF vulnerability from the poc.
0 × 04 a simple Web form
Because this vulnerable application uses the POST method to submit data, I have to build my own forms to achieve my goal. This is just a poc, so it is not too refined. The Form I created contains some hidden text fields. When my profile is updated, all the form fields will be transferred to this Web application. This includes a CSRF token, but the value of this token is actually irrelevant because the application fails to validate it. The most important part here is the EmailAddress field, which is hidden but contains an important default value, rick + example.com@gmail.com.
In this form, the only visible part is a submit button. For poc, I loaded the new webpage to my local computer. For actual attackers, they can host a Web server on the Internet, and probably the server built on the system they have successfully intruded. Once loaded, the victim will see the following page:
Of course, this page looks a little simple, but it is enough for poc. Next, we must act as victims ourselves. To this end, I first opened the browser and used a normal account to log on to the Web application. This is no different from normal users. Then, I uploaded the previous malicious form page to another tag. Attackers may use an email to send this link to me. Then, I clicked this button, as expected, and the attack was successful.
This malicious webpage will send all the information to the target site and update the email address field as required. It should be noted that, even if the target page is already closed in the victim's browser, this attack will still be successful, as long as the user's session is still open, that's enough. In many cases, a session can be opened for a long time, even after the web page is closed. Now, the only thing Attackers need to do is to use the password reset function to obtain the new password of the victim (here we are ourselves) via email.
In this way, the victim's account is under our control.
0 × 05 further improved attack methods
It should be noted that this attack method has two disadvantages: first, the victim is required to participate, because the victim must access at least one malicious page so that the method can succeed. In this example, the victim must also press a button. However, Javascript can automatically complete form submission during page loading.
Another problem is that you must know the user name of the victim. To use the forgot password function, we must know the user name of the victim. Fortunately, I found another way to bypass this problem.
0 × 06 hidden form fields
I noticed that the Update page of my profile also submits a field for UsersName. This aroused my interest because the User Name field cannot be modified on the page itself. This is a static entry, that is, it always remains unchanged. Out of curiosity, I decided to try again to modify this variable through Tamper Data. To my surprise, it actually worked. In fact, this website not only accepts the user name I have changed, but also the user name of this account. Of course, we cannot update the user name to existing ones, but we can update it to a randomly selected and infrequently used user name, which is easy to succeed.
To use this feature, we only need to update the form on the malicious page so that the username field contains a new value that is not currently in use. Now, when the victim clicks the submit button, not only will their email address be updated, but even their username be changed to the value we set previously. This means that the link can be sent to anyone who has logged on to the website, and their accounts may be stolen. Further, we can even script this process so that we can send different forms to different people in batches. As long as they click it, all the tricks will be done.
0 × 07 how to protect yourself
So how can we protect ourselves from the threat of such attacks? In fact, this attack occurs mainly because of two core vulnerabilities. Next we will introduce how to solve this problem.
Here, the most serious problem is the CSRF attack. Without it, nothing will happen later. To defend against CSRF attacks, OWASP has provided a variety of methods, but the most secure method is to use a unique token in hidden fields. This is what we are trying to do with this example website. If it can be fully implemented, the chances of winning CSRF attacks will be greatly reduced. However, as long as a page does not thoroughly check the token, attackers can still take advantage of it. This is because, for them, it is enough to have a vulnerability, and don't forget that people with bad intentions can have time.
Another issue is related to user input verification. Although the system looks to use a whitelist to check email addresses, this method is not valid. It only checks whether the email address contains a domain name in the whitelist. If yes, no matter where it appears. In fact, it should focus on the last part of the email address, or perform more rigorous checks on the entire email address. In addition, it is safer to ask users to re-enter their current password when updating their profile information. Of course, you can also add CAPTCHA verification when re-entering the password, Because malicious Web forms cannot automatically recognize CAPTCHA.
The final vulnerability also involves user input verification. According to the design of the Personal Information Update page, this page does not seem to have users update their usernames. In the original form, the User Name field cannot be edited. If so, the form should not submit the user name as a field. Even if this field must be submitted for some reason, the page should be rewritten to prohibit user name editing.
0 × 08 Summary
CSRF attacks are one of the methods that attackers can use to access your data. However, scanning only website vulnerabilities is far from enough. This requires careful review of how the website operates to detect more subtle flaws. This article illustrates through examples that we can not only identify such defects, but also help customers defend against such attacks to avoid catastrophic data damages.