📜 ⬆️ ⬇️

"Calendar tester" for March. Test security

We continue the cycle of articles “Calendar of the tester” , this month we will talk about security testing. Many do not know where to start and are afraid of difficulties. Ivan Rumak, a web application security tester in Contour, shared the basics of finding vulnerabilities. Beginners will find basic knowledge in the article, and a section on circumventing CSRF protection will be useful for experienced testers.

Last year, Ivan took 4th place in the vulnerability search program Mail.ru and entered the prize top 100 competition Hack The World 2017 .

In February, I decided to teach fellow testers to look for vulnerabilities and check releases for security bugs. From the training plan, I brought to my article the very basics: where to start, what HTTP is, and also made a complete analysis of one vulnerability - how to find, protect and bypass protection.




Where to begin?


This problem is faced by many newbies. Someone first goes to OWASP - a community for web application security. The most useful thing that I learned from OWASP is a list of the most dangerous and common vulnerabilities in web applications . Meaningful learning began when I began to study each of them in detail and google all unfamiliar words. It became clear that it is extremely difficult to study even the most common client vulnerabilities (CSRF, XSS) without knowledge of the HTTP protocol device.


Therefore, I began to teach other testers with the device of this protocol, the data transfer formats for it and the setting of Burp. This is a debugging proxy through which the browser passes all HTTP requests. There you can edit, analyze, scan, send again.


Another excellent source of information is reading and playing public reports of other hackers.


There are sites that aggregate disclosed messages about security bugs, for example, http://h1.nobbd.de/ . There you will learn what vulnerabilities are, how they are found and repaired. It is important to try to reproduce the bugs yourself in order to gain practical experience. To do this, you can use the site to work out the search for vulnerabilities, for example, DVWA .


About HTTP


It is super important to know how user interaction with the web application is arranged. Therefore, I will tell about the HTTP protocol through which the client interacts with the web server. In it we are interested in:


Methods For a start, it is enough to distinguish between GET and POST. Indicated in the first line of the request.


GET - get content from the site.


GET / HTTP/1.1 Host: example.com 

POST - what to send there.


 POST /endpoint HTTP/1.1 Host: example.com User-Agent: Apache-HttpClient/4.5.5 (Java/1.8.0_161) Content-Type: application/x-www-form-urlencoded param1=value1&param2=value2 

URI : path to the file or endpoint, indicated after the slash in the first line of the query.


Headers - headers : User-Agent, Content-Type, Host, etc. There are standard (Accept, User-Agent, etc.) and custom with arbitrary names and values ​​(for example X-Auth-Token: 123).


About Content-Type


Content-Type must be specified for requests where parameters are passed in the body. This header tells the web server the format in which the content of the request is sent in the body. Basic 3 Content-Type:


- application / json


 Content-Type: application/json {"param1":"value1","param2":"value2"} 

- application / x-www-form-urlencoded


 Content-Type: application/x-www-form-urlencoded param1=value1&param2=value2 

- text / plain


 Content-Type: text/plain anytext{"param":123}><<>><xml> 

Parameters transmitted to the server. Contain name and value. They are recorded either after the URI as? Param = value & param2 = value2 & param3 = value3, or in the body in the format specified in the Content-Type.


Cookie. The most common way to authorize a user. When a user logs into a service, he is given a unique key, which is stored in the browser and with which he sends all further HTTP requests to this service. Used to authenticate users so that client A does not gain access to client B.


When a user clicks buttons on a UI, for example, “Save”, he sends such HTTP requests to the web server, containing the method, URI, parameters, and his cookies. You can catch the requests you sent for research in the browser (in Chrome F12 -> Network), and send via some API clients, for example, Restlet Client . Or use a debugging proxy ( Burp , Fiddler).


Knowing the device HTTP-protocol, you can begin to study the specific vulnerabilities. As an example, I will cite the CSRF vulnerability — it is useful for beginners to start with.


Pro CSRF vulnerability


CSRF (Cross site request forgery) - the ability to force the user to send an arbitrary HTTP request to a vulnerable resource. The CSRF vulnerability is "client" - it can only attack other users, but not the server and the internal infrastructure.


Under the threat of services that do not check where the request came from: from their website or from an outside domain. Such a request is sent using the form tag via the onload attribute - i.e. will go immediately when any element on the page is loaded.

<form> . This tag in the html-page sends GET or POST requests to any resource.


Example:


 <form name=form1 action=”https://example.com/sendmoney” method=”POST”> <input type=hidden name=”amount” value=”9999”> </form> 

Attributes:
name=”form1” - the name of the form
action=”https://example.com/test” - where to send the request
method=”POST”, method=”GET” - which method to use
enctype=”application/x-www-form-urlencoded” - with which Content-Type to send a request. If you do not specify this attribute, the default is sent as application / x-www-form-urlencoded.


To specify the parameters use the tag <input> .


His attributes are:
type=”hidden” - type, it is almost always better to use hidden. If you need to upload a file, use type=”file” , if you need a button that will send a request in the form: type=”submit” .
name=”sendmoney” - the name of the parameter
value=”9999” - parameter value


Sample page:


 <html><body> <form name=form1 action=”https://example.com/changepassword” method=”POST”> <input type=hidden name=”newpassword” value=”123456”></form> <body onload=”document.form1.submit()”> <!--  form1 --> </body></html> 

When visiting such a page, a user without his knowledge will send something like this request:


 POST /changepassword HTTP/1.1 Host: example.com Content-Length: 18 Origin: https://evil.com Content-Type: application/x-www-form-urlencoded Accept: text/html, */* Cookie: auth.cookie.from.example.com=verysecret User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36 Referer: https://evil.com newpassword=123456 

If there is no verification on the server where the HTTP request came from, then it will process it as normal. Those. The evil.com user will send an HTTP request with the auth.cookie.from.example.com = verysecret, which the browser will substitute, and in the context of the current session on example.com his password will change to 123456.


There are subtleties of sending a request from the HTML page:


1) Sending a request via the form tag is limited to standard headers only. CSRF cannot be used if the session token in the application is not transmitted via a cookie, but through an authorization header in each request, for example, Authorization.


 GET /userdata HTTP/1.1 Host: example.com Accept: text/html, */* Authorization: APIKEY123123123123123123 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36 Referer: https://evil.com 

2) Content-Type fake POST request can only be application / x-www-form-urlencoded, multipart / form-data or text / plain. Again, due to the limitations of the form tag.


3) The form tag allows you to send only GET / POST requests. PUT / PATCH / DELETE / MKCOL and others are not skipped.


How to search for CSRF


Monitor requests that go to the server when working in your application. Select requests to change something and try to send them through the form tag from some csrftest.html file.
')




If the server accepted such a request from csrftest.html as usual and changed something, then you can start a bug.


The sequence of work:


  1. Click through the application and catch requests in the browser console or debug proxy.
  2. If something has changed through a GET request, try to repeat it from the html page as <img src = ”all path with parameters”>.
  3. If the changes occurred through a POST request and there is no protection from CSRF, repeat it in the form tag.
  4. If there is protection, try to circumvent it.


CSRF Protection


To protect yourself from involuntary sending by the user of cross-domain requests through the form tag, make sure that such a request does not come from an external site.

How to verify that the request from the form came from your site?


1) Each request made on the site transfers a unique token in cookies and in the custom CSRFToken header. When a request is received, before changing something with this request, check that the header value matches what is stored in cookies.


 POST /changepassword HTTP/1.1 Host: example.com CSRFToken: dadfaae9-c625-4bdf-8804-c7977d96954f Cookie: session=123123123123; CSRFToken=dadfaae9-c625-4bdf-8804-c7977d96954f Content-Type: application/x-www-form-urlencoded Content-Length: 61 newpass=123456 

The disadvantage of such protection - for GET requests, this heder is almost always optional. If the application has some endpoint that changes something (for example / changepass), you can transfer the parameters from the POST body to the URL and make the request as GET (HEAD and OPTIONS, by the way, can work as well), while the request will work as a full POST, such protection can be circumvented like this:


<img src=”https://example.com/changepass?newpassword=123456”>




2) The same as the last item, only the token in cookies is compared with the token in the parameter.


 POST /changepassword HTTP/1.1 Host: example.com Cookie: session=123123123123; CSRFToken=dadfaae9-c625-4bdf-8804-c7977d96954f Content-Type: application/x-www-form-urlencoded Content-Length: 61 newpass=123456&CSRFToken=dadfaae9-c625-4bdf-8804-c7977d96954f 

Even if the request to this endpoint can be made as a GET with parameters in the URL, then the csrftoken parameter of other users is unknown to the attacker, and it is mandatory that it stops this attack.


You can try to get around if the token is generated from two parts: static (for example, the hash from the user’s ID) and dynamic (the hash from the date the token was received). Then you can send a token with only a static part. Or send a request without tokens in general, Facebook had such a bug ( https://amolnaik4.blogspot.ru/2012/08/facebook-csrf-worth-usd-5000.html ).


3) Content-Type of each request must be different from those supported by the form tag (urlencoded, text / plain, multipart / form-data).


This is a good way to protect the API from the CSRF, if user authentication is possible both by cookie, by the custom header, and by the parameter in the URL.


If at the root of the site there is a poorly configured crossdomain.xml, then through Flash you can force the user to send a request with any Content-Type. Here is a detailed article about Flash .


4) Same Site Cookie. The flag on cookies, which is placed during authentication along with httponly and does not allow the browser to send your cookies from the left sites, to which these cookies do not relate. Cool, but not all browsers support this flag. The same thing about checking Origin is cool, it works, but not all browsers correctly send Origin for cross-domain queries.


Check right now:


- In your application, POST requests have protection against CSRF.


- Sensitive actions (changing the password, creating an additional user in the organization, sending money) that are sent as POST, in case the protection is based on the token in the custom header and the token in cookies, cannot be redone to GET with parameters in the URL from body and change something in the system (200 OK, 201 CREATED ...). Similarly, with the translation of PUT / PATCH to POST or GET.


- If sensitive actions are sent with “Content-Type: application / json” and protection against CSRF is built only on this, then try sending a request with the body in the formats application / x-www-form-urlencoded, multipart / form-data, text / plain. If successful, repeat from the left site on the Internet through <form> .


- In the root of the site there is a badly configured crossdomain.xml file for cross-domain queries using Flash. (example.com/crossdomain.xml). “Bad” is when any cross-domain requests can be sent from any site to yours, in crossdomain.xml it is explicitly described from which domain and which requests can be made.


Total


Now you know about some basics of security testing and where you can take information to go into the topic, you can check your projects on the CSRF and understand HTTP.


What's next? Learn new types of vulnerabilities, look for them in your project, fix them. Together we will make the Internet more secure!


useful links



List of calendar articles:
Try a different approach
Reasonable pair testing
Feedback: as it happens
Optimize tests
Read the book
Analytics testing
The tester must catch the bug, read Kaner and organize a move.
Load service
Metrics in QA service
Test security
Know your customer
Disassemble backlog

Source: https://habr.com/ru/post/351806/


All Articles