Security Cribs: REST

REST is an extremely popular web application architecture. To call functions on the server, ordinary HTTP requests with specified parameters are used (JSON or XML is usually used to structure parameters), and there is no strict standard for the REST architecture, which adds flexibility (and, of course, a bit of chaos).
REST allows you to flexibly approach the issue of security or, than many sin, not to approach the question at all. Based on OWASP , we have prepared a list of tips to help you improve the security of your REST application.
As a starting point in those rare cases when it is needed here, we use python and Django.
Rule 0
Https
Just set it up. You are welcome. The protection of the transmitted data has not harmed anyone. Even if you think that there is nothing to protect at the moment, this will not always be the case and you still have to configure HTTPS. So configure it better right away, and everyone will be fine.
Rule 1
Authentication
It would seem obvious advice, which, however, many prefer to neglect. The application should always have authentication, even if you now think that you will use it only within the company and there is no difference which of the employees does it. And if you add more with magazines, then investigating incidents and analyzing activity will become incomparably simpler.
As access tokens at the moment it is considered good form to use JWT(JSON web tokens). Do not use tokens with the value {"alg": "none"} for integrity control, tokens should always contain a signature or MAC! A signature is preferable due to the fact that the generation and verification keys of the MAC match (or can be easily calculated from each other), that is, if the server is able to check the MAC value, then it can also generate its values. The signature also confirms not only the integrity of the message, but also the identity of the sender.
Rule 2
Deny HTTP methods that you don’t use
Configure the server to whitelist those methods that you work with (GET, POST, PUT, etc.) and reject anything that does not fit into this list. It’s unlikely that your server needs to process TRACE requests at production (this method is part of the XST attack (Cross-Site Tracing), which consists of an XSS attack and the TRACE or TRACK method. This attack allows, for example, to steal a user's cookie, even if they are marked as HttpOnly). The less information about your infrastructure available from the outside, the better.
Rule 3
Differentiate access
Do all your users need all methods, for example, DELETE? If you do not want some users to be able to carry out certain operations - configure access control in your application. For example, an ordinary user can access only the GET method for some functions, the manager can use GET and POST, etc. For this, it is worth setting roles in the database that can be assigned to users for convenient access control.
As a result, each function will have a check block of approximately this type:
if request.POST and user.is_manager:
do_stuff()
Rule 4
Think about limiting the number of queries
If you think that your users should not send you one hundred thousand requests per second, then you should limit this number. Use API keys or any other mechanism convenient for you to track and limit the number of requests that will be processed in a certain period of time from one user. For Django, for example, django-ratelimit provides this functionality, where you can set various parameters as an identifier for the restriction, not necessarily API keys, but an IP address.
Rule 5
Be sure to validate / sanitize the input
Never trust the transmitted input parameters, always carry out validation / sanitation:
- If possible (and where possible), set a limit on the length / type / format of the input and the request itself. Reject all requests / transmitted data that exceed the length specified by you or that do not match the type / format.
- When processing strings, always escape all special characters.
- If you use the framework, most of them contain their own built-in validation and sanitation tools (offhand from the popular ones - Django (python) and Yii2 (php)), so it’s important to study their capabilities and if some aspect you need is not covered - find a library that closes this, or write such functionality yourself.
- Keep track of validation errors. If the requests of some users constantly fail validation - think about automatically blocking such users.
- Make sure your input parser (or its current version) is not susceptible to any attacks by itself.
Rule 6
Do not give out more information than necessary
If any request caused an error in the application, or it is simply unavailable for some reason, do not provide details in the response, return the most abstract error message. Some servers return stacktrace after an error by default, so be sure to reconfigure this logic.
Rule 7
Always keep logs
Let each event (authentication, error, request, etc.) be logged as detailed as possible. Log them logically for more convenient search in them if necessary. Just in case, before recording in the logs, sanitize the recorded data.
Rule 8
Indicate Content-Type correctly - this is important!
In order for the browser (or client) to correctly read the provided data, the correctly specified Content-Type corresponding to the provided data is important. In the case of browsers, it is also worth setting the X-Content-Type-Options: nosniff header to prevent the browser from trying to detect other Content-Type besides the one that was actually sent (a measure against XSS attacks).
Rule 9
Validate Content-Type
- It is worth setting up rejection of requests if their Content-Type differs from their contents. This will reduce the risk of incorrect data processing, which can lead to injection or code execution at the server / client.
- It is also worth rejecting requests whose Content-Type you do not support, or for which this header is generally absent. Also avoid direct answers about which Content-Type function accepts / issues, if this is not necessary (this will help to avoid XXE attacks).
- In REST services, it is commonplace to support several types of responses (for example, json and xml), and the client indicates the preferred type of response in the Accept header when requesting. Avoid copying the contents of the Accept header into the Content-Type of the response as a mechanism for setting this header. Also reject requests for which the Accept header does not directly contain at least one of the supported types.
Rule 10
Don't forget to set up Cross-Origin Resource Sharing (CORS)
CORS is a standard that describes working with cross-domain queries. If your application does not support CORS, disable the work with this type of headers. If you need to use it, the access policy should be as specific and strict as possible.
Rule 11
Do not expand parameters in URL
All critical data (passwords, keys, tokens and logins, preferably also) should be inside the request body or in the headers, but in no case should appear in the URL. If you need to pass sensitive data through the GET method, put it in the header.
It is impossible:
example .com / controller / 123 / action? ApiKey = a53f435643de32
It is possible:
example .com / controller / 123 / action
Headers:
Host: example.com
User-Agent: Mozilla ...
X-APIkey: a53f435643de32
Rule 12
Think about protection against CSRF attacks
You can read more about all types of protection here , and so, the use of CSRF tokens is considered the most popular way to reduce the risk of attacks of this type.
Rule 13
Explore your framework
If you use any framework to implement REST in your application, then you should study it and not blindly use it, as is often done. Read the documentation carefully, especially the security part. Do not leave it working on the default settings! Each framework has its own nuances, especially when it comes to security, so knowing them is very important.