RESTFul APIs: Security Tips
July 20th, 2020
This is the fifth article in a five part series on RESTful APIs.
Basic security should be in the mind of every developer, even in start-ups. Strong security means protection against a dedicated attacker. This is a vast subject, but we will go over some of the most important tips a developer should know.
Keep the design as simple as possible. Simple is more secure. Remove unused stuff, refactor the code. A chain is as strong as its weakest link.
Always use HTTPS in production, that way you get a lot of security for free because every part of the request is encrypted, except the FQDN. Never expose information in the URLs, like passwords and sensitive data, because, even though they are encrypted, the link is visible to the browser, may appear in router logs, or might be shared by the user.
Always hash passwords in databases. That way, if somebody steals the database, it cannot have the password of the users. Users might reuse passwords and that is a major security risk.
Always validate requests server-side and never trust your users. Control your inputs and outputs and keep the software up to date. Filter input data properly (avoid NoSQL injection).
Only give the user enough privileges to do its job, no more, no less. This applies with trust, giving a user as much trust as necessary to do their jobs. A user might delete a resource by mistake.
Expect the unexpected. Identify, and deal with exceptions.
Give out the least amount of information as possible. This is called security through obscurity. Even though it is not that powerful on its own, it helps other methods used with it. Saying that an email is already taken or that the password is wrong gives information about your system to the attacker. Trying to access a banking account from my banking account technically would mean a 403 should be given because I am authenticated but forbidden to take that action, but that implies that the account exists and that is a security leak. Now the attacker knows for sure.
You have to carefully manage the information given to the user so that it can successfully do his job and deter the hacking process.
Configure the system so that you can hide information about the operating system, the programming language, the used framework, etc.
Presence and length. The text input should exist and should have some minimum and maximum values.
Check the type. If you are waiting for a pdf, or an image or a number check that the user is uploading/typing the proper type.
Check the formatting. If you are expecting an email, the input should look like a valid email. If you are expecting a number from 1-10, 11 is an invalid number.
After validation the data may still need some processing, we cannot trust the data fully yet. Some things like trimming needed to be that are harmless or the input contains a NO-SQL injection attack that needs to be mitigated.
Another vector might be submitting code (js/php) to and the characters need to be escaped or encoded, basically replacing the harmful characters with harmless equivalents (“>” with “& g t;”). Always sanitize user input before usage.
Use sanitization functions from the language or from a well tested-library.
What to log?
Usually, we log errors, sensitive actions(change permission), and, sometimes, suspicious activity. The information logged might also include date and time, source (IP/target), Action, URL, parameter, cookies. But you should not log sensitive information like passwords or emails. If you log a user password from the body of the request, then you have a plain text password stored in logs. Remember security is as strong as it's weakest link.