Products

Solutions

Resources

REST API Security Testing Guide
REST API Security Testing Guide
REST API Security Testing Guide

Security testing

REST API Security Testing Guide

If you are a developer, security engineer or devsecops team member working with applications utilizing REST APIs, this REST API Security Testing guide is specifically tailored for you. It provides detailed, step-by-step instructions to effectively test REST APIs for potential security vulnerabilities, ensuring the highest level of application security.

What is REST API?

A REST API (Representational State Transfer Application Programming Interface) is a set of rules and conventions for building and interacting with web services. It allows systems to communicate with each other by exchanging data over HTTP.

Let’s take an Example of REST API:

A social media app like Twitter uses a REST API. When a user posts a tweet through the app, it sends an HTTP request to Twitter's server to create a new post. This request is formulated according to the rules defined by Twitter's REST API.

Example of Rest API

Why should you test REST API for Security flaws?

Imagine an e-commerce company developing with a mobile application that manages customer data. This company's application is powered by a REST API that handles various functionalities such as user authentication, data storage, and retrieval, among other things. The API must be secure to protect the sensitive customer data that it handles.

If the company's REST API lacks proper security measures, it may invite a host of problems.

For example, unauthorized access might lead to exposure of sensitive customer data, such as a customer's credit card information getting leaked. This could lead to instances of data breaches and identity theft. In a worst-case scenario, the company's reputation could suffer significantly.

Another examples, a DDoS attack could overwhelm the server, making it inaccessible to users. Non-compliance with data security regulations could also result in legal repercussions such as substantial fines or penalties.

Well, these are some of the important reasons why you should test your REST APIs.

  1. Ensures Data Safety: For example, an e-commerce website could use security testing to protect customer credit card information.

  2. Prevents Unauthorized Access: You should prevent unauthorized usage of the API. This could include, for instance, ensuring only admins can access certain sensitive endpoints in a web application.

  3. Protects Against Attacks: Security testing helps to identify and mitigate potential attack vectors like SQL injection and Cross-Site Scripting (XSS). For instance, an online form could be tested to ensure it isn't vulnerable to SQL injection attacks.

  4. Confirms Compliance: It ensures that the API meets the necessary regulatory compliance requirements for data security, such as HIPAA for healthcare applications.

  5. Builds User Trust: By ensuring a secure environment, it builds trust among users about the safety of their data. For example, a banking app that conducts regular security testing can ensure users that their financial data is safe.

Importance of API Security

Scenario

Imagine you're working as a security engineer for an online shopping platform. Your platform's REST API is responsible for handling various operations such as user authentication, processing payments, and managing user's personal and credit card information. Recently, your company has experienced a surge in user base which has drawn the attention of hackers. To ensure the security of your API and protect sensitive user data, you've decided to conduct a comprehensive security testing. You're about to test various aspects of your REST API security, from session management to server security and configuration.

Let’s check the step by step guide you will use for testing.

Step by Step REST API Security Testing Guide

Step 1: Ensure Prerequisites for REST API Security Testing

Before beginning security testing of REST APIs, ensure the following prerequisites are in place:

  1. API Documentation: Detailed documentation of the API you are testing, including endpoint descriptions, request/response formats, and error codes.

  2. Authorized API Access: Appropriate access credentials, such as API keys or tokens, to test different levels of authorization.

  3. Testing Environment: A separate and controlled environment for testing, which is an exact replica of the production environment but doesn't affect real users or data.

  4. Security Testing Tools: Tools like Postman or Akto for sending requests, and others as per your testing requirements.

  5. Test Cases: Well-defined test cases outlining different scenarios to be tested, including edge cases and potential security vulnerabilities.

  6. Knowledge of Security Threats: Understanding of potential security threats like injection attacks, broken authentication, and data exposure to create targeted test cases.

  7. Confirm Assets storage for your application -

  8. Is data stored in SQL/NoSQL db?

  9. Is data being sent to S3?

Once, all the above pre-requisites are in place, you are ready to go to step 2.

Step 2: Prioritize REST APIs for Testing

Before starting to test process, prioritize which parts of your REST API require the most immediate attention. This step is known as risk assessment. The goal is to identify the areas with the highest risk and start testing there.

Risk Factors

When prioritizing, consider these common risk factors:

  1. Functionality: APIs that are critical to your application's functionality should take precedence. If these APIs fail, your application may become unusable. Here are some examples of critical endpoints:

    1. Login Endpoint: POST /api/users/login

    2. Logout Endpoint: POST /api/users/logout

    3. User Registration Endpoint: POST /api/users/register

    4. User Profile Endpoint: GET /api/users/{user_id}/profile

    5. Password Reset Endpoint: POST /api/users/reset_password

    6. Update User Details Endpoint: PUT /api/users/{user_id}

    7. Delete User Account Endpoint: DELETE /api/users/{user_id}

  1. Complexity: Complex APIs like a POST /api/users/{user_id}/transactions endpoint, which might handle multiple data entries and transactions at once.

  2. Data Sensitivity: APIs that handle sensitive data like a GET /api/users/{user_id}/credit_card endpoint, which might handle credit card information.

  3. Change Frequency: APIs that are frequently updated like a PUT /api/posts/{post_id} endpoint, which might be frequently updated with new post content.

Prioritization Strategy

Once you've assessed the risk factors, assign a risk score to each API based on its importance, complexity, sensitivity, and volatility. Prioritize testing the APIs with the highest scores first. This way, you'll catch the most significant issues as early as possible, saving time and resources.

Let’s take an example below of the shopping application above:

Prioritize APIs example

Step 3: Conduct Security Testing of your REST APIs

Authentication

  1. Test all endpoints for unauthenticated requests: For example, an unauthorized request to GET /api/payments should return a 401 Unauthorized status, without revealing any payment information.

  2. Ensure password changes require authentication: For instance, an unverified request to POST /api/users/change_password should return a 401 Unauthorized status and not allow the password change.

  3. Check for secure transmission of credentials: For example, the login request POST /api/users/login should use HTTPS, not HTTP.

  4. Verify password strength requirements: For example, a request to POST /api/users/change_password with a weak password should return a 400 Bad Request status.

  5. Ensure token expiry: Tokens used for authentication should have an expiry time and any request with an expired token should return a 401 Unauthorized status.

  6. Test for brute force protection: Multiple failed login attempts should lock the account or increase the delay in response.

  7. Ensure secure storage of passwords: Passwords should be hashed and salted in the database. Verify this indirectly by checking if the password recovery mechanism sends the original password or resets it.

  8. Validate email confirmation process: A new account or email change should require email confirmation before becoming active.

Security testing example

Let’s take an example of an unauthenticated request to an endpoint. This example uses JavaScript and the Axios library to send an HTTP GET request:

const axios = require('axios');
axios.get('<http://example.com/api/payments>', {
  headers: {
    'Authorization': 'Bearer ' // no token provided
  }
})
.then(response => {
  console.log(response.data);
})
.catch(error => {
  console.log(error.response.status); // should return 401 Unauthorized
});

In this example, an attempt is made to access the /api/payments endpoint without providing any authentication token. According to the security test, this should return a 401 Unauthorized status.

Authorization

Authorization testing example
  1. Verify role-specific access controls: For example, a POST request to api/sales/update by a non-admin user should return 403 Forbidden.

  2. Ensure new features comply with existing security protocols: For instance, a request to GET /api/new_feature without proper authorization should return a 401 Unauthorized status and not show any sensitive content.

  3. Check that private user information remains private: For example, a request to GET /api/users/{user_id} from a non-friend user should return a 403 Forbidden status and not reveal any private user information.

  4. Test for Cross-Site Request Forgery (CSRF): An unauthorized action should not be performed on behalf of an authenticated user.

  5. Guard against Insecure Direct Object References (IDOR): Users should not be able to access resources directly by modifying the value of a parameter used to directly point to a resource.

  6. Prevent privilege escalation: Ensure that users are not able to elevate their privileges by manipulating request parameters or URLs.

  7. Check for exposed internal interfaces: Internal API endpoints should not be exposed to external users.

  8. Enforce strict content-type checking: APIs should only accept requests with a correctly set Content-Type header.

Let’s take an example of verifying role-specific access controls:

const axios = require('axios');
// Consider an API endpoint 'api/sales/update' which should only be accessible by admin users.
// Here, we're trying to access it with a non-admin user token.
axios.post('<http://example.com/api/sales/update>', {
  headers: {
    'Authorization': 'Bearer non_admin_user_token' // Token of non-admin user
  }
})
.then(response => {
  console.log(response.data);
})
.catch(error => {
  console.log(error.response.status); // should return 403 Forbidden
});

In this example, a POST request is sent to api/sales/update with the token of a non-admin user. According to the security test, this should return a 403 Forbidden status.

Data Validation

Data validation examle
  1. Test for injection attacks: For instance, sending GET /api/products?name=' OR '1'='1 should not alter database queries or return unexpected data.

  2. Ensure endpoints protect sensitive user data: For example, an unauthorized request to GET /api/users/emails should return a 403 Forbidden status and not reveal any user emails.

  3. Test for insecure data exposure: Sensitive user data should not be exposed in API responses, such as credit card numbers or passwords.

  4. Validate input data: Check for proper validation of all input data to prevent attacks involving malicious input.

  5. Test for buffer overflow vulnerabilities: Send excessively long input values to test how the API handles them.

  6. Check for proper encoding: Ensure the API encodes data properly to prevent attacks involving special characters.

  7. Test for proper handling of null values: The API should handle null values correctly without causing errors or unexpected behavior.

  8. Check for consistency of data: The same request should return the same response unless the data has been changed.

  9. Test for proper error handling: The API should handle errors gracefully without revealing sensitive information.

  10. Check for proper handling of data types: Sending the wrong data type should not cause the API to crash or behave unexpectedly.

  11. Test for proper parsing of JSON/XML: The API should correctly parse JSON/XML data and handle parsing errors gracefully.

Let's take an example of testing for injection attacks:

const axios = require('axios');
// Consider an API endpoint 'api/products' which should not alter database queries or return unexpected data.
// Here, we're trying to access it with a payload that could potentially lead to an injection attack.
axios.get('<http://example.com/api/products?name=\\\\' OR \\\\'1\\\\'=\\\\'1>', {
  headers: {
    'Authorization': 'Bearer your_auth_token' // Your valid token
  }
})
.then(response => {
  console.log(response.data);
})
.catch(error => {
  console.log(error.response.status); // Should not return unexpected data
});

In this example, a GET request is sent to api/products?name=' OR '1'='1 with a valid token. According to the security test, this should not alter database queries or return unexpected data.

Session Management

Session Management testing example
  1. Ensure sessions are invalidated upon logout: For instance, after a POST to /api/logout, a subsequent request with the same token should result in 401 Unauthorized.

  2. Implement automatic session timeouts: If a user is inactive for a certain period of time, the session should automatically end.

  3. Use secure session IDs: Session IDs should be long, complex, and unpredictable to prevent session prediction attacks.

  4. Regenerate session IDs after login: To prevent session fixation attacks, a new session ID should be issued once the user logs in.

  5. Restrict concurrent sessions: The system should not allow a user to be logged in from multiple devices or locations at the same time.

  6. Protect session data: Any data stored in the session should be encrypted to protect it from interception.

  7. Implement session logging: All session activities should be logged for future analysis and incident response.

  8. Validate session termination: After logout, check if cookies, tokens, and other session identifiers are still valid. They should be invalidated to prevent reuse.

Let's take the first point, "Ensure sessions are invalidated upon logout", as an example. Here's how you could test it using JavaScript and the Axios library:

const axios = require('axios');
// Log in and store the token
axios.post('<http://example.com/api/login>', {
  username: 'user',
  password: 'password'
})
.then(response => {
  const token = response.data.token;
  // Log out
  axios.post('<http://example.com/api/logout>', {}, {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  })
  .then(() => {
    // Try to access a protected resource using the old token
    axios.get('<http://example.com/api/protected>', {
      headers: {
        'Authorization': `Bearer ${token}`
      }
    })
    .then(response => {
      console.log(response.data); // This shouldn't be reached
    })
    .catch(error => {
      console.log(error.response.status); // Should return 401 Unauthorized
    });
  });
});

In this example, we first log in to the API and store the received token. Then we log out of the API using the token. Finally, we try to access a protected resource using the same token which, according to the security test, should return a 401 Unauthorized status since the session should be invalidated upon logout.

Cryptography

Cryptography testing example
  1. Verify that all data is encrypted during transit: For example, inspect traffic to ensure that a POST request to /api/user/update is using HTTPS and not HTTP.

  2. Ensure secure key management: Keys used for cryptographic functions should be securely managed and rotated regularly.

  3. Check for usage of strong algorithms: Cryptographic algorithms used should be strong and up-to-date to prevent decryption.

  4. Ensure secure storage of cryptographic keys: Keys should be stored securely and should not be hard-coded in the application.

  5. Validate secure random number generation: Cryptographic functions requiring random numbers should use secure random number generators.

  6. Ensure encryption at rest: Sensitive data stored should be encrypted at rest in addition to being encrypted during transit.

  7. Check for secure handling of cryptographic errors: Errors in cryptographic operations should be handled securely without revealing sensitive information.

Let's take the first point, "Verify that all data is encrypted during transit", as an example. Here's how you could test it using JavaScript and the Axios library:

const axios = require('axios');
// Log in and store the token
axios.post('<http://example.com/api/login>', { // This should be 'https://'
  username: 'user',
  password: 'password'
})
.then(response => {
  console.log(response.data);
})
.catch(error => {
  console.log(error); // Should show error indicating non-secure connection
});

In this example, we're trying to log in to the API using an insecure HTTP connection. According to the security test, this should fail and return an error indicating a non-secure connection.

Error Handling

error handing checklist
  1. Ensure error responses contain no sensitive details: For instance, triggering an error by sending malformed JSON should return a generic [500 Internal Server Error](<https://www.akto.io/academy/500>) without detailed system information.

  2. Prevent leakage of system-specific information: Error messages should not reveal system-specific details such as database structure, server configuration, or third-party libraries used, which could be exploited by an attacker.

  3. Implement consistent error responses: Regardless of the error type, all errors should return a consistent structure in the response. This aids in error parsing and handling on the client side.

  4. Ensure that failed login attempts are logged: Multiple failed login attempts could indicate a brute force attack. Make sure these attempts are logged and reviewed regularly.

  5. Verify proper handling of server-side exceptions: Unhandled exceptions could cause system instability and potential security risks, ensure they are properly handled and logged.

  6. Validate proper handling of HTTP status codes: The API should return the correct HTTP status codes to accurately represent the state of the request.

  7. Test for proper handling of edge cases: The API should handle edge cases correctly, returning the appropriate error messages and status codes.

  8. Check for proper rate limiting of error messages: The API should limit the number of errors returned in a given time period to prevent an attacker from gleaning information through repeated requests.

Let's take the first point, "Ensure error responses contain no sensitive details", as an example. Here's how you could test it using JavaScript and the Axios library:

const axios = require('axios');
// Send a malformed JSON payload to trigger an error
axios.post('<http://example.com/api/endpoint>', {
  invalid: "{json"
}, {
  headers: {
    'Content-Type': 'application/json'
  }
})
.then(response => {
  console.log(response.data); // This shouldn't be reached
})
.catch(error => {
  console.log(error.response.status); // Should return 500 Internal Server Error
  console.log(error.response.data); // Should not contain sensitive system information
});

In this example, we're sending a malformed JSON payload to an API endpoint. According to the security test, this should return a 500 Internal Server Error status and the error response should not contain any sensitive system information.

Server Security & Configuration

  1. Check that only necessary HTTP methods are enabled: For example, a DELETE request to /api/users/123 should return 405 Method Not Allowed if not applicable.

  2. Ensure secure server configuration: Server settings should be configured according to security best practices, such as disabling directory listing and keeping software updated.

  3. Verify secure SSL/TLS settings: Use up-to-date and secure cipher suites and protocols for HTTPS connections. Deprecated or insecure versions should be disabled.

  4. Check for secure error handling: Server errors should not expose any sensitive information or detailed system information.

  5. Confirm secure deployment practices: Sensitive information such as API keys or database credentials should not be included in the code or version control system.

  6. Check for proper security headers: Security headers like Content Security Policy (CSP), HTTP Strict Transport Security (HSTS) should be properly set.

  7. Enforce strict transport security: The server should enforce secure (HTTPS) connections where applicable.

  8. Check for proper logging: The server should maintain detailed logs for requests, responses, and server operations for auditing and debugging purposes.

  9. Validate server-side input: All user inputs should be validated server-side to prevent injection attacks or malformed data processing.

  10. Ensure server-side rate limiting: The server should implement rate limiting to prevent abuse and potential denial-of-service (DoS) attacks.

Server Security testing example

Here's an example of checking for secure server-side input validation using JavaScript and the Axios library:

const axios = require('axios');
// Attempting to send malicious input to the server
axios.post('<http://example.com/api/users/create>', {
  username: 'user',
  password: "' OR '1'='1" // Attempted SQL Injection
}, {
  headers: {
    'Content-Type': 'application/json'
  }
})
.then(response => {
  console.log(response.data); // This shouldn't be reached if input validation is in place
})
.catch(error => {
  console.log(error.response.status); // Should return 400 Bad Request or similar
  console.log(error.response.data); // Should not reveal any sensitive system information
});


In this example, we're trying to send a malicious input (an SQL Injection attempt) to the api/users/create endpoint. If the server-side input validation is secure, this should return an error like 400 Bad Request and not process the malicious input. The error response should not reveal any sensitive system information.

Rate Limiting and Throttling

  1. Implement rate limiting to mitigate risk of DDoS attacks: For instance, exceeding 100 requests per minute to /api/login should result in a 429 Too Many Requests response.

  2. Prevent spam account creation: For example, multiple requests to POST /api/users/create from the same IP in a short time period should return a 429 Too Many Requests status.

  3. Validate request rate limiting: Make sure that rate limiting is in place to prevent abuse and denial-of-service attacks.

  4. Limit API usage per user or token: To prevent abuse, each user or token should have a maximum number of API calls they can make in a given time period.

  5. Implement progressive throttling: As the user continues to exceed request limits, the time until they can make another request should increase.

  6. Apply different limits for different user types: For example, premium users could have a higher rate limit compared to free users.

  7. Include rate limit information in headers: Each response should include headers that indicate the user's current rate limit status.

  8. Ensure rate limiting works on a per-route basis: Different routes or endpoints may require different rate limits based on their functionality and demand.

  9. Test rate limits with automated scripts: Use scripts to simulate high-volume traffic and confirm that rate limits are functioning as expected.

  10. Monitor and adjust rate limits: Regularly review rate limit settings to ensure they're still appropriate for the current usage patterns and adjust as necessary.

Rate limiting example

Here's an example of how you might test rate limiting using JavaScript and the Axios library:

const axios = require('axios');
// Set a count for the number of requests
let requestCount = 0;
// Set an interval to send a request every second
let interval = setInterval(() => {
  axios.post('<http://example.com/api/login>', {
    username: 'user',
    password: 'password'
  })
  .then(response => {
    console.log(response.data);
    requestCount++;
    console.log('Request count:', requestCount);
  })
  .catch(error => {
    console.log(error.response.status); // Should eventually return 429 Too Many Requests
    clearInterval(interval); // Stop the interval
  });
}, 1000);

In this example, the script sends a login request to the API every second. After a certain number of requests, if rate limiting is in place, the API should start returning a 429 Too Many Requests status. At this point, the script stops sending requests.

Now that you have understood how to conduct testing, let’s learn about the how to implement this at scale in your organization.

Implementing REST API Security Testing at Scale

Planning

  • Define Scope: Identify the API endpoints that need to be tested. For example, if you're testing a blogging platform's API, this might include endpoints like POST /api/posts (to create a new blog post), GET /api/posts/{id} (to retrieve a specific post), and [DELETE](<https://www.akto.io/academy/delete>) /api/posts/{id} (to delete a post).

  • Assign Roles: Assign roles to each team member. For example, one team member might be responsible for testing all GET requests, while another tests all POST requests.

  • Define Success Criteria: Establish what constitutes a successful test. For instance, a successful test might mean that all endpoints return the correct status codes and data.

Execution:

  • Use Tools: Use tools like Akto to automate security testing of REST APIs. Akto has 200+ tests covering the cases mentioned above and more which you can plug and play for all your API Security Testing needs.

  • Document Findings: As you run your tests, document any issues or unexpected behavior. For example, if a GET request to /api/posts/{id} returns a 404 Not Found status when it should return a [200 OK](<https://www.akto.io/academy/200-ok>) status, you would note this down.

Frequency:

  • Implement automated, continuous testing as part of a CI/CD pipeline. This provides consistent, ongoing security checks and reduces the risk of vulnerabilities going unnoticed.

Analysis:

  • Review Findings: After the testing phase, review your findings with your team. For example, you might have a meeting where you discuss each issue, how serious it is, and how it should be addressed.

  • Prioritize Issues: Once you've reviewed your findings, prioritize them. For example, an issue that exposes sensitive user data would likely be a higher priority than one that merely causes a minor usability inconvenience.

Remediation:

  • Address Issues: Work with your development team to address each issue. For example, if you found that an endpoint is returning sensitive user data, a developer would need to update the endpoint to no longer return this data.

  • Retest: After an issue has been addressed, retest the relevant part of the API to ensure the issue has been successfully fixed. For instance, if an endpoint was fixed to no longer return sensitive user data, you would send a request to this endpoint and check the response to ensure this data is no longer present.

REST API Security testing

Akto for Rest API Security

You have now understood what it entails to conduct testing of your REST APIs. It can be a manual lengthy process if you don’t use automation tools. Using Akto will automate all the above for you.

  1. Akto will generate API Documentation in an automated way without you having to provide OpenAPI spec or postman collection.

  2. Akto has the largest test library for security testing. You can use the tests as is or customize them per your need.

  3. Akto can automate all your REST API Security testing needs in CI/CD.

  4. It is also Open Source for you to customize the platform as per your needs.

Best Practices for REST API Security

  • Keep your API documentation updated, as it can be a source of security loopholes if left outdated or incorrect.

  • Always remain proactive, don’t wait for a security breach to occur before taking action.

  • Automate security tests to run them continuously and catch vulnerabilities early.

  • Make use of API security tools and software to assist in identifying potential threats.

  • Engage in regular security training to keep your team's knowledge up to date.

  • Regularly audit your APIs for vulnerabilities and fix them promptly.

  • Consider implementing a bug bounty program to leverage the knowledge of the wider community in identifying security issues.

  • Regularly update your knowledge and skills in API security, as new threats and solutions are continually emerging.

Tools and Resources

Final Thoughts

Security testing for REST APIs is a critical step of any development process. It helps ensure data safety, prevents unauthorized access, protects against potential attacks, confirms regulatory compliance, and builds user trust. By following the guidelines and practices outlined in this guide, you can significantly enhance the security of your REST API and protect your valuable resources.

Explore your automated API Security Testing journey with Akto.

Frequently Asked Questions on REST API Security

  1. What is REST API Security?

REST API Security refers to the practices and guidelines employed to protect API resources from outside threats, unauthorized access, and data breaches. It involves various methods such as rate limiting, input validation, and secure communication protocols.

  1. Why is REST API Security important?

REST API Security is crucial for data privacy and integrity. It helps prevent unauthorized access to sensitive data, protects against potential attacks, ensures regulatory compliance, and builds user trust.

  1. How can I test the security of my REST API?

You can test the security of your REST API through various methods such as input validation, rate limiting, session management, and error handling. Automated API scanning tools can also be used to identify potential security threats.

  1. What tools can I use for REST API Security Testing?

You can use automated API scanning tools such as Akto, Postman, or ZAP for REST API Security Testing. These tools can help identify potential security threats and vulnerabilities in your API.

  1. What are some best practices for REST API Security?

Some best practices for REST API Security include keeping your API documentation updated, automating security tests, regularly auditing your APIs for vulnerabilities, and implementing a bug bounty program.

Continue reading

Continue reading

Gartner estimates that by 2025, less than 50% of enterprise APIs will be properly managed.

Gartner estimates that by 2025, less than 50% of enterprise APIs will be properly managed.

Protect your APIs from attacks now

Protect your APIs from attacks now

Protect your APIs from attacks now