Search This Blog

Showing posts with label API Vulnerabilities. Show all posts
Showing posts with label API Vulnerabilities. Show all posts

Thursday, July 22, 2021

API Security Testing - How we can do/stop hacking to the APIs : Part-3

 

The first two parts in this series have set us well on our path to API security/intrusion nirvana; we first got to grips with current API technology basics, moved on to API Attack surface detection and then looked at a series of common and potent vulnerability attacks – all sharing the fact that they are pretty simple to perform using a little wit and available tools. Let’s dig a little more in our arsenal before concluding with some hands on tips on how to work with API Security Testing.

Cross Site Request Forgery (CSRF)

The last vulnerabilities we looked at in the previous installment were related to cross-site scripting attacks (XSS). Now, let’s have a look at another vulnerability / attack that plays with similar cards; cross-site request forgery. Just like XSS, this is an attack that originates from a web-browser – but since it often follows through with an API call it is definitely something you should be aware of:

HackYourAPI10

Let’s walk through this so to provide an understanding of how this type of attack works:

  • A user logs in to his/her bank account – which sets a session cookie on the client
  • The bank shows a (malicious) ad for the latest vitamin pills, which the user clicks on without first logging out of the bank
  • The page selling vitamin pills also contains a hidden form performing a bank-transfer, which is submitted automatically without the user noticing
  • Since the user is still logged in to the bank the “forged request” succeeds and makes the transfer without the user noticing.

While this example may seem somewhat contrived (what bank shows vitamin ads?), I’m sure you get the idea, and I’m also sure I’m not the only one that has navigated away from an authenticated site without logging out first.

A common way to attempt to prevent these attacks is to look for specific http headers related to request referral, but headers can easily be spoofed using various techniques described online. The much better way to guard for these attacks from a development point-of-view is therefore to require a unique request token to be added to each incoming request to an API – either as an HTTP header or as a query parameter. The value is generated by the server when preparing the underlying webpage using a secret algorithm - which the attacker presumably won’t know – and thus won’t be able to.

Testing this becomes straightforward; are tokens enforced and validated correctly? What if you use one of the previously discussed techniques for the token itself; fuzzing, injection, etc.? Is this all handled gracefully or does an error message give away a little too much about how things are being done on the server side?

Insufficient SSL Configuration

Let’s shift our focus a little and have a look at some common vulnerabilities and attack opportunities that relate to the security stack of your API itself.

Using a self-signed SSL certificate is an easy mistake to make – the convenience of generating your own certificate is high – but the dangers are lurking, especially when it comes to APIs; if your app is the only one consuming your API your developers might even have hard-coded the client to accept the certificate – and then forgot all about it. Unfortunately, using a self-signed certificate leaves your API wide open for man-in-the-middle attacks – where an attacker inserts him/herself between the API and its client by replacing the client-facing certificate – allowing them to listen in on (and modify) traffic that was meant to be encrypted.

Testing for insufficient SSL configurations is straightforward – make sure your tests accept only valid certificates. Taking an extra precaution for MITM attacks is also advisable – for example by adding signatures to a message, which makes it impossible (well, almost) for a eavesdropper to modify messages on the wire, even if they manage to insert themselves in the communication pipeline. Testing with signatures, that they are enforced, correctly validated, etc. – is equally possible.

Insecure Direct Object References (IDOR)

Including object references as arguments to an API call is common practice – and consequently a very common API vulnerability is that access rights are not enforced for objects a user does not have access to. Identifying id parameters and sequentially looping through possible values can be an easy way to access data that isn’t meant for a user – once again API metadata can be a natural source for more information in this regard, making it easy for both hackers and tester to find possible attack surfaces within an API topology.

As a tester you need to validate that security is correctly enforced for objects one should not have access to – which is easily done by automating requests to resource not accessible and validating that the correct error messages are shown. At a higher level – you should perhaps also question the usage of identifier values that can easily be guessed – especially if the data is sensitive. Perhaps using GUID identifiers could be a better solution as identifiers in applicable cases.

Bad Session / Authentication Handling

The previous vulnerability is a specific example of whole slew of vulnerabilities related to bad session, security and authentication handling. Consider some more examples:

  • Are session tokens re-used or sequential?
  • Do session tokens timeout correctly?
  • Are tokens exposed in unencrypted traffic?
  • Are tokens added to URLs when sending links?
  • Are login endpoints restricted?

All of these will be obvious attack points for a hacker – and should be as such for you as a Security Tester. Make sure that the described situations are correctly handled, do not give “bad” error messages if charged with invalid / unexpected input (using the arsenal of tests we have been looking at) – and do not provide an entry point for a hacker to start prying away at the walls of your APIs defense mechanisms!

Recap – and some tips to go!

Some hands-on tips to ensure that your APIs are fully security tested before we say our goodbyes:

  • Automate: Most of the testing approaches for security vulnerabilities that we have covered can be automated and should definitely be done so – preferably against your production environment in some way. A system upgrade or server reconfiguration could be just as much a cause for a security vulnerability as bad development in the code of your APIs – and you definitely want to find out if such changes open up for unexpected vulnerabilities before anyone else.
  • Stay on top: OWASP provides invaluable services and information on Internet related security vulnerabilities – and how to work against them. Make it a habit to check out their website and match their recommendations and findings against your APIs and infrastructure. Follow their guidelines – specifically those geared at APIs - and make sure you are doing what you can base on their resources.
  • Finally - It’s your problem: Security is probably not going to be fixed or worried by anyone else than you, – make sure you give it the same attention and focus as you do to functional, performance, usability, A/B testing, etc. The price to pay for leaked passwords or erased user data is too high to pay for you not to care (which I know you do).

And there you have it - that’s it for the last part of the series. Hopefully you have learned plenty; basic underpinnings of API security vulnerabilities, how easy it is too perform common API attacks and how equally easy it is in most cases to test for corresponding vulnerabilities. Now get out there and hack an API!

API Security Testing - How we can do/stop hacking to the APIs : Part-2

In our last post, we prepared our API hacking weaponry – we looked at the basics of Web-based APIs (HTTP, Message Formats, Security Standards) and how to discover the attack surface of an API. This time around we’re going to start with some basic attacks. Let’s see if we can get our API out of balance and joviality – welcome back!

The immediate purpose of an attack

Before we fire our trebuchets and spout our boiling canola oil, let’s take a quick step back and consider the actual immediate purpose of an attack. Although the high-level goal of an API hack might be to get access to credit card numbers or user passwords – a single attack is often just a step on the way. To get to those credit card numbers, we have to learn about a system’s underpinnings and its weaknesses. We have to pry around to find out how it works and what its vulnerabilities are.

A common approach is to provoke an API with unexpected content in the hope that its inability to handle it correctly will teach us about its inner workings. For example, getting the target API to return a database error for an unexpected input is of great value; we now know that there is a database behind the scenes (SQL Injection vulnerabilities?) and, if we’re “lucky”, we might even know a little about its vendor / version / schema / etc. – all pieces that help us put the vulnerability-puzzle. And the more verbose the error message, the better for us.  There is plenty of information online that will tell us of any known security vulnerabilities of any specific server/framework/OS setup.

As a Security Tester, you would most likely be doing the same; trying to get your target system to behave in a way that helps hackers get under its skin – but in your case you’ll tell your development team so they can fix the issues instead. Right?

Fuzzing

Fuzzing is a classic way of attacking (and testing!) a target system; the basic idea is to repeatedly generate randomized input for a target API until we stumble upon something that provokes an error message or system. With today’s tools, it’s easy to set up a script that runs millions of requests in the hope that some combination of input parameters will achieve our purpose.

As a tester, set up assertions that validate the response to be consistent and concise, use the correct HTTP error code, and do not expose any sensitive system information.

Invalid Input Attacks

Where fuzzing has little structure to it, invalid input attacks are slightly more intelligent as they aim to provoke a target system by sending input that it doesn’t expect. The better an API is described via metadata or documentation, the easier it is to do this efficiently. Examples would be sending strings when the API expects numbers, sending text when it expects dates, or for any field, send nothing or send something too long. Given our knowledge of HTTP this can be done at the protocol level also by sending invalid HTTP Headers and values – targeting both the APIs HTTP layer and its own logic.

Just as for fuzzing, a security tester can automate boundary/invalid-input tests and configure assertions that validate the error message. Be sure to take into account that, for usability reasons, your API might provide “friendly” error messages – make sure that these are “generic” and don’t give away any details of the underlying technologies.

Malicious input

While the above mentioned attacks generally hope to provoke unexpected system behavior and “bad” error messages, some input can be directly malicious and target both the API itself and its hosting infrastructure. Message parsers have been a common target for these attacks, with XML parsers being the prime example. Consider the following “XML Bomb” attack:

 When a misconfigured or vulnerable XML parser attempts to expand the lol9 entity in the actual document, the recursive nature of the “lol” entities will most likely result in out-of-memory errors. This could possibly bring down the entire server and leave it in a state where it might be vulnerable to attacks.

Another possibility for vulnerabilities and malicious input is where files are uploaded – does that target system process these files “safely”? What if the system expects a PDF but you upload a shell script instead – will that get executed on the server? Or get propagated to a 3rd party when they try to access the file (that they thought was a PDF) via another API call? Will corrupt files be handled gracefully or give away information about the underlying file system?

As a Security Tester, you can easily attempt to provoke your system by “playing the hacker” and sending malicious data as described. Obviously you need to be careful so you don’t bring down your system (unless that’s your goal) – but on the other hand going “full throttle” might be the only way of ensuring that your system isn’t vulnerable to these kinds of attacks. At least you’ll know what hit you.

Injection Attacks

According to OWASP, injection vulnerabilities are the most common types of security vulnerabilities out there. Many of the attacks that have gained media attention in recent times exploited related weaknesses. In OWASP-speak, an injection attack is one where an “Attacker sends simple text-based attacks that exploit the syntax of the targeted interpreter. Almost any source of data can be an injection vector, including internal sources.”

Let’s have a look at a simple SQL Injection example. Let’s say we have a REST API for a pet store (the one described in the Swagger document in the previous post of this series):

http://petstore.com/api/v1/pet/123

The actual implementation of the API uses the ID of the pet (“123” in the example URL) to look up the data in a database using the following SQL statement:

“SELECT * FROM pets WHERE petID=’” + petId +”‘”;

When the request is as above, this expands to

“SELECT * FROM pets WHERE petID = ‘123’”

Which is totally fine.

Now consider what happens if an attacker sends the following instead

http://petstore.com/api/v1/pet/’%20or%20’1’=’1

which with the above (admittedly naive) logic becomes

SELECT * FROM pets WHERE petID = ‘’ or ‘1’ = ‘1’

Whoa!! Suddenly we have a SQL statement that will give us all pets in the database, which could result in both a severely overloaded server (if the database of pets is large) and pet owners gaining access to other clients’ pet information – the horror! Although somewhat contrived, this simple example shows the danger; a more malicious SQL injection will attempt to augment SQL statements to delete data, change passwords, etc.

As hinted by the OWASP description above, injection attacks aren’t specific to SQL; any language interpreter used to process (API) input is at risk; Json, XPath, XSLT, JavaScript, etc. are all technologies that require parsers/processors which can be buggy and “compromisable” and should be seen as a risk (or an opportunity, depending on your point of view). As before, collections and examples of common injection attack vectors for common systems and technologies can easily be found online – use this to your advantage and make sure your API isn’t vulnerable to them.

As a Security Tester, injection attacks are a little bit more challenging than the invalid-input related attacks we looked at to start with. First of all, you need to know and understand a little about the inner workings of the target API to choose the “right” injection attacks (this is what a hacker would use other attacks to find out).  Then you have to decide on what a “successful” injection attack would look like. For the above example, you would probably want to validate that you either get a 404 (Not Found) or a 400 (Bad Request).

Cross-Site Scripting Attacks

Let’s finish this post with a look at another very common way to attack a system and its users – XSS (cross-site-scripting) attacks. The name of the attack is somewhat misleading; you might spontaneously think that this applies to web applications only, but since APIs are often driving the interface of a web application, it makes sense to test that the API keeps things as invulnerable as possible.

XSS attacks can be either “reflective” or “persistent” – the underlying “objective” of either being the insertion of a script that is executed in the browser/system of an unsuspecting user.

For reflective XSS, the script is often included in link in an email – when the user clicks the link the script is sent to a target server and returned to the client where it is executed:

So what is the API’s role here? Well, in today’s world, the actual request to the victim’s server that returns data is an API call that is formatted on the client – if your API “reflects” its input in any way (example: a search API might include the search-string in the returned result), you will need to decide if it’s up to the API or the client to handle input that is potentially malicious. Then test the API accordingly.

For persistent XSS – the malicious script is injected into a backend system. It is  then retrieved and executed by a separate client at a later time (this could also be seen as a client-injection attack):

Once again, it’s not obvious if an involved API should be handling this – or the client UI. For example, let’s say you have an issue tracker with an API where you can create issues. If someone inserts a script into the description of an issue, is it up to the API backend to remove/escape that script before it is returned to an API client? Or is it up to the client to perform this handling?

One way to look at it is that this XSS attacks are basically injection attacks – a script is injected into the system – and then either executed on the client, or somewhere during the processing on the backend, and in either case it’s a potential vulnerability and something you need to assess (before a hacker does it for you).

Whatever you decide, it is easy to set up the appropriate tests, Vectors of common cross-site scripting attacks are available online, allowing you to set up data-driven tests with these vectors using your favorite API testing tool to run and perhaps even automate corresponding tests.

Moving ahead

Thus concludes our lesson outlining the various weapons in your API hacking arsenal. But this is only a portion of the methods at your disposal – next part to look at some more common attacks and how to test for them. More importantly, I’ll provide advice on how to set up your API security tests and how to stay up-to-date with the latest security vulnerabilities so that the only person hacking your API is you.

API Security Testing - How we can do/stop hacking to the APIs : Part-1

 So, you’ve created an exhaustive regression test suite for your APIs that runs as part of your continuous build and deploy process. You’ve run and even automated (cool!) load-tests that simulate magnitudes more users than your API will probably ever (but maybe) have. You’ve set up monitors that will catch any bug that sneaks past all these lines of defense. Hey - you’ve even automated the validation of the metadata that gets generated for your API every time you commit some changes to your code (high five)! Your API is ready for Primetime! (…or not.)

You probably know where this is going – but it’s somebody else’s problem, right? Isn’t there a CSO (Chief Security Officer) at your company that has this covered, with a long list of API security tools? Aren’t you using the latest updates to your frameworks? How could there be any security flaws in them? They are surely written by super-smart developers that avoid SQL Injection attacks, just as they would avoid crossing the street on a green light. And your API management vendor uses the latest OAuth implementation with tokens and nonces flying through the ether like bats in the night. All this talk about API Security is just a scare by vendors that want to sell you more tools. Right?

But deep down you know that API Security is something you need to take seriously – just like Facebook, SnapChat, Twitter,  Bitly, Sony, Microsoft, Tinder, Apply, NBC, Evernote and many others decidedly did not. Nobody is going to bail you out if your customers’ credit card numbers are stolen, or your customers’ users’ personal dating data is published on a torrent website. And deep down you’re right.

So what to do? Just like you do when validating functionality and performance, try to break things – put your hacker cloak on and make the developers of your API (you?) shiver as you approach for the attack.  And since even hackers need a little structure to their dwellings – let’s attempt to break this down somewhat – you wouldn’t want to fail at hacking your API, would you?

1) Know Thy Target

If you’re going to attack an API, then you must understand its perimeters… because the gate is where you often sneak in the Trojan horse.

  • HTTP: Most APIs today are using the HTTP protocol, which goes for both REST and SOAP. HTTP is a text-based protocol which therefore is fortunately very easy to read. Take, for example, the following HTTP Request:

HackYourAPI1and the corresponding response:

HackYourAPI2

As you can see – the Request and Status lines, Request and Response Headers, and Request/Response messages are all plain text – easily readable, and easily customizable for performing a security attack.

  • Message Formats: Messages sent over the web are sent using some message format. JSON is predominant in the REST world, while XML is mandatory in the SOAP world. Understand these formats (they’re easy too!) and how their peculiarities can be used to form an attack (we’ll get back to that later). And of course most formats can open for vulnerabilities if used incorrectly – PDF, Image formats like JPG and PNG, etc.

2) There is api security, and there is API Security

Security is a vague term; claiming an API is secure because it uses SSL or OAuth is false – there is more to an API than its transport-layer (although admittedly SSL goes a far way);

  • Different Authorization/Authentication standards are at play for REST and SOAP; OAuth 1.X and 2.X, SAML, WS-Security, OpenID Connect, etc.
  • SSL is great for transport-level security – but what if ones message data needs to be encrypted (so no one can read it) or signed (so you can be sure it hasn’t been tampered with) after it has been sent over HTTP? Perhaps you should be encrypting credit card numbers or sensitive customer data in your NoSQL database so that it’s useless if it should come into the wrong hands? SOAP APIs have the possibility to shine in this regard; WS-Security is a mature and complex standard handling most of these requirements. REST APIs are referred to as “startup initiatives” like JWT (JSON Web Tokens) or homegrown solutions.

As a hacker, you will be looking for these standards to be used improperly – or not at all where they should be. Perhaps getting access to someone’s credit card numbers is as simple as reusing a session token to get an authenticated user’s account information that isn’t encrypted in the message itself (more on incorrect session logic in a later post).

3) API Attack Surface Detection

Now that you’ve mastered the basics of web APIs and you’ve decided on an API to attack (your own API - don’t lose focus), you need to know where launch the attack; what is the “Attack Surface” of your API?

This can be tricky. Finding an Attack Surface for a UI-based solution (for example a web or mobile app) is straightforward: you can actually see the different input fields, buttons, file-uploads, etc. all waiting to be targeted during an attack. For an API, things are different - there is no UI to look at, just an API endpoint. But to launch a “successful” attack on an API, we need to know as much as possible about the API’s endpoints, messages, parameters and behavior. The more we know, the merrier our attack will be.

Fortunately, there are a number of “helpful” API technologies out there to facilitate our malignancies:

  • API Metadata and documentation has a lot of momentum currently; API providers are putting strong efforts into providing API consumers with detailed technical descriptions of an API, including all we need for our attack - paths, parameters, message formats, etc. Several standards are at play:

    • Swagger, RAML, API-Blueprint, I/O Docs, etc for REST APIs
    • WSDL/XML-Schema for SOAP APIs
    • JSON-LD, Siren, Hydra, etc for Hypermedia APIs

Have a look at the following Swagger definition for example:

HackYourAPI3

As you can see, a helpful Swagger specification also tells us a lot about an API’s possible vulnerabilities, helping us target the attack.

  • API Discovery: what if you have no metadata for the API you want to compromise? An alternative to getting an initial attack surface is to record interactions with the API using an existing client. For example, you might have an API consumed by a mobile app; set up a local recording proxy (there are several free options available) and direct your mobile phone to use this proxy when accessing the API – all calls will be recorded and give you an understanding of the APIs usage (paths, parameters, etc). There are even tools out there that can take recorded traffic and generate a metadata specification for you. As a hacker, it’s just as useful to you as it is to developers or honest testers.
  • Brute Force: full disclosure: most developers aren’t famed for their creativity when deciding on API paths, arguments, etc. More often than not, you can guess at an API’s paths like /api, /api/v1, /apis.json, etc. – which might at least give you something to start with. And if the target API is a Hypermedia API, then you’re in luck; Hypermedia APIs strive to return possible links and parameters related to an API response with the response itself, which for a hacker means that it will nicely tell you about all its attack surfaces as you consume it.

So now you’re all set with core API technologies, security standards and your API’s Attack Surface. You know what API to strike and where to hit, but how do you make your attack?

Tuesday, June 22, 2021

API Security Testing - Cheat Sheet

REST evolved as Fielding wrote the HTTP/1.1 and URI specs and has been proven to be well-suited for developing distributed hypermedia applications. While REST is more widely applicable, it is most commonly used within the context of communicating with services via HTTP.

The key abstraction of information in REST is a resource. A REST API resource is identified by a URI, usually a HTTP URL. REST components use connectors to perform actions on a resource by using a representation to capture the current or intended state of the resource and transferring that representation.

The primary connector types are client and server, secondary connectors include cache, resolver and tunnel.

REST APIs are stateless. Stateful APIs do not adhere to the REST architectural style. State in the REST acronym refers to the state of the resource which the API accesses, not the state of a session within which the API is called. While there may be good reasons for building a stateful API, it is important to realize that managing sessions is complex and difficult to do securely.

Stateful services are out of scope of this Cheat Sheet: Passing state from client to backend, while making the service technically stateless, is an anti-pattern that should also be avoided as it is prone to replay and impersonation attacks.

In order to implement flows with REST APIs, resources are typically created, read, updated and deleted. For example, an ecommerce site may offer methods to create an empty shopping cart, to add items to the cart and to check out the cart. Each of these REST calls is stateless and the endpoint should check whether the caller is authorized to perform the requested operation.

Another key feature of REST applications is the use of standard HTTP verbs and error codes in the pursuit or removing unnecessary variation among different services.

Another key feature of REST applications is the use of HATEOAS or Hypermedia As The Engine of Application State. This provides REST applications a self-documenting nature making it easier for developers to interact with a REST service without prior knowledge.

HTTPS

Secure REST services must only provide HTTPS endpoints. This protects authentication credentials in transit, for example passwords, API keys or JSON Web Tokens. It also allows clients to authenticate the service and guarantees integrity of the transmitted data.

See the Transport Layer Protection Cheat Sheet for additional information.

Consider the use of mutually authenticated client-side certificates to provide additional protection for highly privileged web services.

Access Control

Non-public REST services must perform access control at each API endpoint. Web services in monolithic applications implement this by means of user authentication, authorisation logic and session management. This has several drawbacks for modern architectures which compose multiple microservices following the RESTful style.

  • in order to minimize latency and reduce coupling between services, the access control decision should be taken locally by REST endpoints
  • user authentication should be centralised in a Identity Provider (IdP), which issues access tokens

JWT

There seems to be a convergence towards using JSON Web Tokens (JWT) as the format for security tokens. JWTs are JSON data structures containing a set of claims that can be used for access control decisions. A cryptographic signature or message authentication code (MAC) can be used to protect the integrity of the JWT.

  • Ensure JWTs are integrity protected by either a signature or a MAC. Do not allow the unsecured JWTs: {"alg":"none"}.
  • In general, signatures should be preferred over MACs for integrity protection of JWTs.

If MACs are used for integrity protection, every service that is able to validate JWTs can also create new JWTs using the same key. This means that all services using the same key have to mutually trust each other. Another consequence of this is that a compromise of any service also compromises all other services sharing the same key. See here for additional information.

The relying party or token consumer validates a JWT by verifying its integrity and claims contained.

  • A relying party must verify the integrity of the JWT based on its own configuration or hard-coded logic. It must not rely on the information of the JWT header to select the verification algorithm. See here and here

Some claims have been standardised and should be present in JWT used for access controls. At least the following of the standard claims should be verified:

  • iss or issuer - is this a trusted issuer? Is it the expected owner of the signing key?
  • aud or audience - is the relying party in the target audience for this JWT?
  • exp or expiration time - is the current time before the end of the validity period of this token?
  • nbf or not before time - is the current time after the start of the validity period of this token?

As JWTs contain details of the authenticated entity (user etc.) a disconnect can occur between the JWT and the current state of the users session, for example, if the session is terminated earlier than the expiration time due to an explicit logout or an idle timeout. When an explicit session termination event occurs, a digest or hash of any associated JWTs should be submitted to a block list on the API which will invalidate that JWT for any requests until the expiration of the token. See the JSON_Web_Token_for_Java_Cheat_Sheet for further details.

API Keys

Public REST services without access control run the risk of being farmed leading to excessive bills for bandwidth or compute cycles. API keys can be used to mitigate this risk. They are also often used by organisation to monetize APIs; instead of blocking high-frequency calls, clients are given access in accordance to a purchased access plan.

API keys can reduce the impact of denial-of-service attacks. However, when they are issued to third-party clients, they are relatively easy to compromise.

  • Require API keys for every request to the protected endpoint.
  • Return 429 Too Many Requests HTTP response code if requests are coming in too quickly.
  • Revoke the API key if the client violates the usage agreement.
  • Do not rely exclusively on API keys to protect sensitive, critical or high-value resources.

Restrict HTTP methods

  • Apply an allow list of permitted HTTP Methods e.g. GETPOSTPUT.
  • Reject all requests not matching the allow list with HTTP response code 405 Method not allowed.
  • Make sure the caller is authorised to use the incoming HTTP method on the resource collection, action, and record

In Java EE in particular, this can be difficult to implement properly. See Bypassing Web Authentication and Authorization with HTTP Verb Tampering for an explanation of this common misconfiguration.

Input validation

  • Do not trust input parameters/objects.
  • Validate input: length / range / format and type.
  • Achieve an implicit input validation by using strong types like numbers, booleans, dates, times or fixed data ranges in API parameters.
  • Constrain string inputs with regexps.
  • Reject unexpected/illegal content.
  • Make use of validation/sanitation libraries or frameworks in your specific language.
  • Define an appropriate request size limit and reject requests exceeding the limit with HTTP response status 413 Request Entity Too Large.
  • Consider logging input validation failures. Assume that someone who is performing hundreds of failed input validations per second is up to no good.
  • Have a look at input validation cheat sheet for comprehensive explanation.
  • Use a secure parser for parsing the incoming messages. If you are using XML, make sure to use a parser that is not vulnerable to XXE and similar attacks.

Validate content types

A REST request or response body should match the intended content type in the header. Otherwise this could cause misinterpretation at the consumer/producer side and lead to code injection/execution.

  • Document all supported content types in your API.

Validate request content types

  • Reject requests containing unexpected or missing content type headers with HTTP response status 406 Unacceptable or 415 Unsupported Media Type.
  • For XML content types ensure appropriate XML parser hardening, see the XXE cheat sheet.
  • Avoid accidentally exposing unintended content types by explicitly defining content types e.g. Jersey (Java) @consumes("application/json"); @produces("application/json"). This avoids XXE-attack vectors for example.

Send safe response content types

It is common for REST services to allow multiple response types (e.g. application/xml or application/json, and the client specifies the preferred order of response types by the Accept header in the request.

  • Do NOT simply copy the Accept header to the Content-type header of the response.
  • Reject the request (ideally with a 406 Not Acceptable response) if the Accept header does not specifically contain one of the allowable types.

Services including script code (e.g. JavaScript) in their responses must be especially careful to defend against header injection attack.

  • Ensure sending intended content type headers in your response matching your body content e.g. application/json and not application/javascript.

Management endpoints

  • Avoid exposing management endpoints via Internet.
  • If management endpoints must be accessible via the Internet, make sure that users must use a strong authentication mechanism, e.g. multi-factor.
  • Expose management endpoints via different HTTP ports or hosts preferably on a different NIC and restricted subnet.
  • Restrict access to these endpoints by firewall rules or use of access control lists.

Error handling

  • Respond with generic error messages - avoid revealing details of the failure unnecessarily.
  • Do not pass technical details (e.g. call stacks or other internal hints) to the client.

Audit logs

  • Write audit logs before and after security related events.
  • Consider logging token validation errors in order to detect attacks.
  • Take care of log injection attacks by sanitising log data beforehand.

Security Headers

There are a number of security related headers that can be returned in the HTTP responses to instruct browsers to act in specific ways. However, some of these headers are intended to be used with HTML responses, and as such may provide little or no security benefits on an API that does not return HTML.

The following headers should be included in all API responses:

HeaderRationale
Cache-Control: no-storePrevent sensitive information from being cached.
Content-Security-Policy: frame-ancestors 'none'To protect against drag-and-drop style clickjacking attacks.
Content-TypeTo specify the content type of the response. This should be application/json for JSON responses.
Strict-Transport-SecurityTo require connections over HTTPS and to protect against spoofed certificates.
X-Content-Type-Options: nosniffTo prevent browsers from performing MIME sniffing, and inappropriately interpreting responses as HTML.
X-Frame-Options: DENYTo protect against drag-and-drop style clickjacking attacks.

The headers below are only intended to provide additional security when responses are rendered as HTML. As such, if the API will never return HTML in responses, then these headers may not be necessary. However, if there is any uncertainty about the function of the headers, or the types of information that the API returns (or may return in future), then it is recommended to include them as part of a defence-in-depth approach.

HeaderRationale
Content-Security-Policy: default-src 'none'The majority of CSP functionality only affects pages rendered as HTML.
Feature-Policy: 'none'Feature policies only affect pages rendered as HTML.
Referrer-Policy: no-referrerNon-HTML responses should not trigger additional requests.

CORS

Cross-Origin Resource Sharing (CORS) is a W3C standard to flexibly specify what cross-domain requests are permitted. By delivering appropriate CORS Headers your REST API signals to the browser which domains, AKA origins, are allowed to make JavaScript calls to the REST service.

  • Disable CORS headers if cross-domain calls are not supported/expected.
  • Be as specific as possible and as general as necessary when setting the origins of cross-domain calls.

Sensitive information in HTTP requests

RESTful web services should be careful to prevent leaking credentials. Passwords, security tokens, and API keys should not appear in the URL, as this can be captured in web server logs, which makes them intrinsically valuable.

  • In POST/PUT requests sensitive data should be transferred in the request body or request headers.
  • In GET requests sensitive data should be transferred in an HTTP Header.

OK:

https://example.com/resourceCollection/[ID]/action

https://twitter.com/vanderaj/lists

NOT OK:

https://example.com/controller/123/action?apiKey=a53f435643de32 because API Key is into the URL.

HTTP Return Code

HTTP defines status code. When designing REST API, don't just use 200 for success or 404 for error. Always use the semantically appropriate status code for the response.

Here is a non-exhaustive selection of security related REST API status codes. Use it to ensure you return the correct code.

CodeMessageDescription
200OKResponse to a successful REST API action. The HTTP method can be GET, POST, PUT, PATCH or DELETE.
201CreatedThe request has been fulfilled and resource created. A URI for the created resource is returned in the Location header.
202AcceptedThe request has been accepted for processing, but processing is not yet complete.
301Moved PermanentlyPermanent redirection.
304Not ModifiedCaching related response that returned when the client has the same copy of the resource as the server.
307Temporary RedirectTemporary redirection of resource.
400Bad RequestThe request is malformed, such as message body format error.
401UnauthorizedWrong or no authentication ID/password provided.
403ForbiddenIt's used when the authentication succeeded but authenticated user doesn't have permission to the request resource.
404Not FoundWhen a non-existent resource is requested.
405Method Not AcceptableThe error for an unexpected HTTP method. For example, the REST API is expecting HTTP GET, but HTTP PUT is used.
406UnacceptableThe client presented a content type in the Accept header which is not supported by the server API.
413Payload too largeUse it to signal that the request size exceeded the given limit e.g. regarding file uploads.
415Unsupported Media TypeThe requested content type is not supported by the REST service.
429Too Many RequestsThe error is used when there may be DOS attack detected or the request is rejected due to rate limiting.
500Internal Server ErrorAn unexpected condition prevented the server from fulfilling the request. Be aware that the response should not reveal internal information that helps an attacker, e.g. detailed error messages or stack traces.
501Not ImplementedThe REST service does not implement the requested operation yet.
503Service UnavailableThe REST service is temporarily unable to process the request. Used to inform the client it should retry at a later time.

My Profile

My photo
can be reached at 09916017317