function QueryTest::testConditionOperatorArgumentsSQLInjection

Same name and namespace in other branches
  1. 9 core/tests/Drupal/KernelTests/Core/Database/QueryTest.php \Drupal\KernelTests\Core\Database\QueryTest::testConditionOperatorArgumentsSQLInjection()
  2. 8.9.x core/tests/Drupal/KernelTests/Core/Database/QueryTest.php \Drupal\KernelTests\Core\Database\QueryTest::testConditionOperatorArgumentsSQLInjection()
  3. 10 core/tests/Drupal/KernelTests/Core/Database/QueryTest.php \Drupal\KernelTests\Core\Database\QueryTest::testConditionOperatorArgumentsSQLInjection()

Tests SQL injection via condition operator.

File

core/tests/Drupal/KernelTests/Core/Database/QueryTest.php, line 72

Class

QueryTest
Tests Drupal's extended prepared statement syntax.

Namespace

Drupal\KernelTests\Core\Database

Code

public function testConditionOperatorArgumentsSQLInjection() : void {
    $injection = "IS NOT NULL) ;INSERT INTO {test} (name) VALUES ('test12345678'); -- ";
    try {
        $result = $this->connection
            ->select('test', 't')
            ->fields('t')
            ->condition('name', 1, $injection)
            ->execute();
        $this->fail('Should not be able to attempt SQL injection via condition operator.');
    } catch (InvalidQueryException $e) {
        $this->assertSame("Invalid characters in query operator: {$injection}", $e->getMessage());
        // Expected exception; just continue testing.
    }
    // Test that the insert query that was used in the SQL injection attempt did
    // not result in a row being inserted in the database.
    $result = $this->connection
        ->select('test')
        ->condition('name', 'test12345678')
        ->countQuery()
        ->execute()
        ->fetchField();
    $this->assertEquals(0, $result, 'SQL injection attempt did not result in a row being inserted in the database table.');
    // Attempt SQLi via union query with no unsafe characters.
    $this->enableModules([
        'user',
    ]);
    $this->installEntitySchema('user');
    $this->connection
        ->insert('test')
        ->fields([
        'name' => '123456',
    ])
        ->execute();
    $injection = "= 1 UNION ALL SELECT password FROM user WHERE uid =";
    try {
        $result = $this->connection
            ->select('test', 't')
            ->fields('t', [
            'name',
            'name',
        ])
            ->condition('name', 1, $injection)
            ->execute();
        $this->fail('Should not be able to attempt SQL injection via operator.');
    } catch (InvalidQueryException $e) {
        $this->assertSame("Invalid characters in query operator: {$injection}", $e->getMessage());
        // Expected exception; just continue testing.
    }
    // Attempt SQLi via union query - uppercase tablename.
    $this->connection
        ->insert('TEST_UPPERCASE')
        ->fields([
        'name' => 'secrets',
    ])
        ->execute();
    $injection = "IS NOT NULL) UNION ALL SELECT name FROM {TEST_UPPERCASE} -- ";
    try {
        $result = $this->connection
            ->select('test', 't')
            ->fields('t', [
            'name',
        ])
            ->condition('name', 1, $injection)
            ->execute();
        $this->fail('Should not be able to attempt SQL injection via operator.');
    } catch (InvalidQueryException $e) {
        $this->assertSame("Invalid characters in query operator: {$injection}", $e->getMessage());
        // Expected exception; just continue testing.
    }
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.