Designing secure APIs in 2019 (and why cloud services don't)
Application Programming Interfaces (APIs) are key to any product that will involve sharing data nowadays. With phones and tablets running Android or iOS, laptops running ChromeOS, Windows, or macOS, plus a whole host of Internet of Things coming online, you could soon be designing an app for at least 5 separate systems at any one time. How do you do that efficiently?
The answer is an API, and with any sense you'll develop one adhering to REpresenting State Transfer (REST) principles. You're already using one RESTful API right now, albeit as a client - the World Wide Web. Various principles go into designing a REST API, such as the ability to cache responses, layers, and communication statelessness, and whole articles can be written on that, but LTPCGO is a security company and you're reading this thinking how do you do this securely. Good - security should be a central pillar to any company in the 21st century!
There are some principles that go into designing any system securely - least privilege, defence in depth, do not trust, minimisation of attack surface area, and encryption. There are some principles to avoid too - security by obscurity is not security! Usability also must be factored in - the most secure system is air-gapped and no data is allowed in or out, but that isn't very useful for an API sitting in the cloud serving request all over the world. From a security aspect for an API then the important aspects are the client-server relationship and data storage.
Focusing firstly on the relationship between the client and server, all data should be transmitted securely. If you aren't forcing visitors to your website onto HTTPS (HyperText Transfer Protocol Secure) and haven't submitted your domain to HSTS (HTTP Strict Transport Security) preload lists then you're allowing your users to send data in an insecure format so that any man in the middle can read it. A Virtual Private Network (VPN) alleviates this, as does a proxy over Secure SHell (SSH), but standard networks are insecure, even when they utilise encryption (looking at you, mobile phone networks with intentionally easy-to-break encryption built-in). You can't put the onus on the user to secure their transmission, and if you do your API is not going to be RESTful. All the hard work has been done for you as every framework or library you use in your program will include an ability to communicate over a secure socket layer. Make sure you use at least Transport Layer Security (TLS) 1.2, and ideally TLS 1.3, along with Elliptic Curve Diffie–Hellman Ephemeral (ECDHE) key exchange algorithms for perfect forward secrecy and authentication via the Elliptic Curve Digital Signature Algorithm (ECDSA).
Next, make sure the user can only access what they are allowed. A moderator should be able to add and delete any user data, but not admin tables, although they might have to read them - a standard user should not be able to do this, a standard user shouldn't even be able to see another user's data! In terms of sending data, a user shouldn't be able to send a string in place of an integer, and rarely should they be able to send data that can be executable either at the time or afterwards. Don't blacklist data entries, because you will miss something - instead check them against a whitelist.
What about a more malicious user, who utilises a vulnerability in your underlying infrastructure to get a shell on your server? Well, since you never use your root account and the keys are locked down far away (right?!), the attacker doesn't have unlimited access, but it may just be a matter of time. By running your application with the least privileges and access it requires to the rest of your server you limit the vulnerabilities an attacker may be able to exploit. This is also where regular credential rotation, service separation, and administrator alarms are invaluable - limit the time an attacker has, limit the services available to an attacker, and find out the attacker is there so you can prevent and patch.
Secondly, regarding storage, it should be a given that any identifying data stored on your server should be encrypted as much as possible, to AES256 processed with an initialisation vector and a key utilising the full 256-bit key space for a total key space requirement of a little over a hundred thousand trillion trillion trillion trillion trillion...or around ten times less than the number of atoms in the observable universe. Passwords are not to be encrypted - they should be hashed (which means they can't be decrypted) ideally with an Argon2 algorithm or bcrypt, and compared using some method which operates over a random time so an attacker can't perform a timing attack and gain information by looking for a response that is quicker or slower than others. Utilise your language's techniques to perform password verification, hashing, and encryption, if you can make your own unbreakable encryption you would not be reading this!
You might not be able to keep a username unencrypted as it is likely a primary key for other data stores, but that isn't so important since it is often public knowledge. That means too then that it should not make up any of your encryption keys. Ideally, even an administrator should not be able to decrypt this data, and by making an individual user responsible for their key the potential for leaked information affecting multiple users is minimised.
Simple Object Access Protocol (SOAP) is often touted as a more secure protocol for exchanging information (partly because people seem to misinterpret the 'S' as 'Secure'). It isn't. It uses eXtensible Markup Language to transfer information, whereas a REST API can use whatever language you like. SOAP does have an official protocol developed by W3C, and so has features such as Atomicity, Consistency, Isolation, Durability (ACID) and authorisation built-in, but you can utilise the principles in it for your REST API to help guide your development.
But what about cloud Services (AWS, GCP, Azure, ...)?
So...why can any application or user on your server type an insecure URL like these to get server information about that instance?
Well the first point to observe is that if you click one of the above addresses you shouldn't be able to open it. They all point (clearly in the case of Azure) to a link-local IP address. These are reserved addresses in the space 169.254.0.0/16 that are not forwarded by routers, and crucially are only accessible from a given instance.
The second point to note is the data that the URL contains. User data can be stored via these APIs, but it shouldn't be as it isn't protected by cryptographic methods. Identity and Access Management (IAM) data can also be stored, and that is one of their strengths. But wait! Doesn't that mean any user with access can see data that allows them to do things they really shouldn't? Well...yes. However, that data is rotated on a relatively short time frame (~1 hour by default) meaning any reveal is limited, and the data can be rotated on demand.
Why is the URL unencrypted though? There is still network communication taking place, even if it was hosted on a local network interface. Well, as it's only accessible from your instance, and any attacker looking to sniff network packets requires root access (for any reasonably normal scenario at least), it can't be intercepted by anybody except root - and if a user has root access to your machine, then it doesn't matter what data is stored in the credentials! That doesn't quite explain it all, and the real answer is speed. Any additional handshake takes time, and if there is no practical need to having the data encrypted then why do it? Securing it here offers no additional protection, and only serves to delay the many requests to the API.
Why then is it not a big worry that IAM credentials can be gained in an insecure model, especially when LTPCGO services run via GCP and AWS? The answer lies in the very first two principles. First, the IAM roles assigned to the instances assigned in our case offer no capability to write or create new data or interfaces. Second, the data that they can read only offers SELECT and INSERT access to two databases. To be able to read or write to a database ordinarily requires credentials to be stored somewhere on the server, normally in a fixed state out of public view, which is a worse situation than having access to them available to anyone who gains access to a server and can read the file.
Before you write a single line of code have a high-level meeting with your team on what your product roll-out, deployment, and data strategy will look like. Knowing what data looks like now and in the future will help in having a strong pillar however your application develops. Do not forget about speed though or the actual application design - if you can find a more efficient way to store and access data for your seven-figure user base which doesn't require the same stringent and load-heavy security considerations as other parts of your system, then don't pass it through security!
If you need help figuring out how to put together your data structure in order to comply with ISO/IEC 27001:2013, examining data transmission, storage, backup, encryption and retrieval, get in touch. If you're moving your infrastructure to the cloud and have more questions, feel free to reach out too. Finally, if you are in development stage of a central API for your big idea and want to work with a lateral-thinking team who puts protecting computing at the centre of development, we would love to work with you.
Currently we are not able to disclose details of a vulnerability we have found, but this post will be updated once the system in question has been fixed and secured.
Responsible disclosure is an important part of cybersecurity, and if a vulnerability is reported to you it is up to you and your business to fix it. Some companies ignore issues raised until late, with the financial and reputational damage hitting large.LTPCGO can help verify issues, perform a risk assessment, repair the vulnerability, and check for any exploits.
Get in touch today.
How to protect yourself from exploits in other's software
Good code is secure code. It also takes time to write and test, and needs specialisation. We rely on other people and companies taking the time to audit their code properly every day, whenever we step on a plane, make a bank transaction, or use the Internet. Apple have recently failed gravely in releasing good, secure code however; in a series of posts, Ian Beer from Project Zero has detailed to an excruciating level a series of exploits which offered root access to iPhones just by browsing a website. Root access means having full control and access to the device, meaning any other security measures such as encryption or sandboxing are meaningless.
The technical details do not need reproducing here, but the program installed onto the device allowed an attacker full access to pictures, What's App conversations, e-mails, Telegram, and anything else stored on the phone. Obviously, you can't write your own code for an iPhone and secure it that way, and iOS differs from Android in that it is not open source, so you can't even audit it yourself.
Ordinarily, you might start by ensuring any files on the phone are encrypted. If it's impractical to store the key on the device, you could send a key using a secure socket. Either way, because these exploits offered root access, the root user would be able to capture this information and decrypt files too.
Essentially, there's nothing you can do on the device except treat it as compromised - don't put information on there which you would not be comfortable with others seeing such as bank details, private photos, or passwords. Of course, that isn't very good on the triangle between security, functionality, and usability; if you can't store anything on your device, it becomes a lot less useful.
It is also possible to combat some of the information leakage by regularly updating passwords and other details which could be used to compromise other areas. Systems which rely on remembering your device, or two-factor authentication, could have been compromised by this exploit. If you have a system which requires users to login, you can ensure users regularly update login information by having a password expiration policy - LTPCGO can help with this. For devices such as routers, which often do not have administration options like this, we can create custom login portals, including two-factor authentication, which can enforce best practices.
One way of combating rogue programs is often to restart the device - often, they will be running in memory or through a temporary directory which is empty when the device boots. Again, it falls foul of the triangle though. The same goes for keeping your device in 'aeroplane mode' so that it can't send data externally.
The easiest mitigation to this exploit would have been to avoid Safari as a browser. Although Chrome for iOS was vulnerable, this attack only targeted Safari users. Avoiding unknown websites that might contain scrupulous content also decreases your likelihood of being exploited, but of course many websites get compromised and could be used to push unexpected things to your device. And of course, as Natalie Silvanovich also of project zero writes, there are several remote interaction-less attack surfaces on mobile devices that can be exploited.
For corporate users, BYOD ('Bring Your Own Device') policies are getting increasing acceptance, but often this can increase potential attack surfaces into your company. Any device you let onto your company network or which you allow company information to reside on must have a secure configuration profile. LTPCGO can create one which helps secure your company - get in touch! In this example, you could enforce all traffic on company devices to go via your VPN, and do packet analysis on outgoing unencrypted communications, then block potential combinations of keywords. This would however come at a heavy performance penalty.
You should however monitor your web traffic - if possible, you can keep a whitelist of addresses which are allowed through your firewall. There are signatures from the program's communication with a command & control server sending data every 60 seconds which would appear above any noise in your normal traffic logs.
All of the above is incomparable to one last bit of advice - KEEP YOUR DEVICES UPDATED! Apple released fixes for all these exploits in iOS 12.1.4 back on the 7th February.
LTPCGO has officially launched
We are ready to provide services to secure and protect your business and stakeholders immediately.
With a globally-connected world, and the benefits that can bring, a variety of people, businesses, and even countries are taking steps to steal funds, information, and techniques from others. Make sure your company isn't vulnerable.
We are currently completing a project using Sitecore for a large international bank, and look forward to helping more businesses into a secure future.