Injections

Discover Pynt's documentation on security tests for injections! Learn how Pynt fortifies your APIs against injection vulnerabilities.

Intro

Injection flaws, such as SQL, NoSQL, Command Injection, etc., occur when untrusted data is sent to an interpreter as part of a command or query. The attacker’s malicious data can trick the interpreter into executing unintended commands or accessing data without proper authorization

Source: OWASP

What are the common mistakes done by developers ?

Injection attacks happen when input from API request is used directly in an operation such as DB query, system call or a template without validating whether the input includes unwanted characters.

How can I fix Injections issues ?

SQL Injection:

To prevent SQL injection attacks, consider the following measures:

  1. Use parameterized queries: Parameterized queries allow you to separate the SQL query logic from the user-supplied data. Instead of concatenating user input directly into the SQL statement, you use placeholders in the SQL statement and pass the user input as parameters to the query. This prevents attackers from injecting malicious code into the SQL statement.

Example of parameterized query in Python:

cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s", (username, password))
  1. Sanitize user input: Even with parameterized queries, it's important to sanitize user input to ensure that it conforms to expected values. This can include validating input format, data type, and length, as well as removing potentially harmful characters.

NoSQL Injection:

here's an example of a NoSQL injection vulnerability in a Node.js API that uses MongoDB as the database:

const express = require('express');
const bodyParser = require('body-parser');
const mongodb = require('mongodb');

const app = express();
const mongoClient = mongodb.MongoClient;
const mongoUrl = 'mongodb://localhost:27017/mydb';

app.use(bodyParser.json());

app.post('/login', (req, res) => {
  const username = req.body.username;
  const password = req.body.password;

  mongoClient.connect(mongoUrl, (err, db) => {
    if (err) throw err;

    const users = db.collection('users');
    users.findOne({ username: username, password: password }, (err, user) => {
      if (err) throw err;

      if (user) {
        res.status(200).json({ message: 'Login successful' });
      } else {
        res.status(401).json({ message: 'Invalid username or password' });
      }

      db.close();
    });
  });
});

app.listen(3000, () => {
  console.log('API server started on port 3000');
});

In this example, the POST /login route accepts a JSON request body with a username and password field. The route queries the users collection in MongoDB to find a user with the specified credentials. If a matching user is found, the route returns a 200 OK response with a success message. If no matching user is found, the route returns a 401 Unauthorized response with an error message.

However, this API has a NoSQL injection vulnerability because it does not properly sanitize or validate the user input. An attacker can craft a specially-crafted JSON request body that bypasses the username and password check and allows them to log in as any user in the database.

For example, an attacker can send the following request body:

{
  "username": { "$ne": "" },
  "password": { "$ne": "" }
}

This request body contains MongoDB operators ($ne) that instruct MongoDB to return any user document that has a non-empty username and password field. By doing so, the attacker can bypass the username and password check and log in as any user in the database.

To prevent NoSQL injection vulnerabilities, you should always sanitize and validate user input before using it in database queries.

Command Injection:

Here is an example of a command injection vulnerability in a Python Flask API:

import subprocess
from flask import Flask, request

app = Flask(__name__)

@app.route('/ping')
def ping():
    host = request.args.get('host')
    result = subprocess.check_output(['ping', '-c', '1', host])
    return result

if __name__ == '__main__':
    app.run(debug=True)

In this example, the GET /ping route accepts a query parameter host and uses the subprocess.check_output() method to run the ping command on the specified host. However, this API has a command injection vulnerability because it does not properly validate or sanitize the user input. An attacker can craft a specially-crafted query parameter that injects arbitrary commands into the ping command and executes them on the server.

For example, an attacker can send the following request:

GET /ping?host=127.0.0.1; ls -la

This request injects the ls -la command into the ping command and lists the contents of the current directory on the server.

To prevent command injection vulnerabilities, you should always sanitize and validate user input before using it in command-line or shell operations.

Template Injection:

Here's an example of how template injection vulnerability can occur in an API:

Let's say you have an API that takes user input to generate a report. The report is generated using a template engine that allows users to inject their own variables into the template.

An attacker could exploit this vulnerability by injecting malicious code into the template engine. For example, suppose the attacker injects the following code into the template:

{{7*'7'}}

If the template engine doesn't properly sanitize the input, it will execute the expression and return the result, which is 49. However, if the attacker injects something more malicious, such as:

{{config.items()}}

This could allow the attacker to access and retrieve sensitive information about the server's configuration.

To prevent template injection vulnerabilities, it's important to always sanitize and validate user input before using it to generate templates. Additionally, it's important to limit the privileges of any code that executes within the context of the template engine to prevent attackers from executing arbitrary code on the server-side.

Test cases in this category:

Test caseOWASPCWE

[INJ001] SQL Injection (Generic)

[INJ002] MS-SQL Injection

[INJ003] MySQL Injection

[INJ004] SQLite Injection

[INJ005] PostgreSQL Injection

[INJ006] NoSQL Injection

[INJ007] Command Injection

[INJ008] Server-side template injection

Last updated