SQL-Injection vulnerability in GET function resolved.
This commit is contained in:
@@ -4,6 +4,7 @@ namespace api\classes;
|
|||||||
class API
|
class API
|
||||||
{
|
{
|
||||||
public $conn;
|
public $conn;
|
||||||
|
public $pdo;
|
||||||
|
|
||||||
# The user uuid that requested the API
|
# The user uuid that requested the API
|
||||||
protected $user_uuid;
|
protected $user_uuid;
|
||||||
@@ -42,14 +43,21 @@ class API
|
|||||||
# Used for the query builder base
|
# Used for the query builder base
|
||||||
public $baseQuery = false;
|
public $baseQuery = false;
|
||||||
|
|
||||||
|
# Used for the general get function, this prevents SQL injecting by only allowing these columns instead of
|
||||||
|
# Whatever the user inputs straigt into the query.
|
||||||
|
public $allowedGetColumns = false;
|
||||||
|
|
||||||
|
# Cache the columns of the tables for some small performance improvements.
|
||||||
|
private static array $columnCache = [];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/bin/php/db_connect.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/bin/php/db_connect.php';
|
||||||
include_once $_SERVER['DOCUMENT_ROOT'] . '/bin/php/Functions/globalFunctions.php';
|
include_once $_SERVER['DOCUMENT_ROOT'] . '/bin/php/Functions/globalFunctions.php';
|
||||||
|
|
||||||
# Setup Database connection
|
# Setup Database connection
|
||||||
$this->conn = $GLOBALS['conn'];
|
$this->conn = $GLOBALS['conn'];
|
||||||
|
$this->pdo = $GLOBALS['pdo'];
|
||||||
|
|
||||||
if (!empty($_SESSION['user']['user_uuid'])) {
|
if (!empty($_SESSION['user']['user_uuid'])) {
|
||||||
$this->InitUserTypeFrontend();
|
$this->InitUserTypeFrontend();
|
||||||
@@ -694,6 +702,8 @@ class API
|
|||||||
|
|
||||||
protected function buildDynamicQuery(string $tableName): array
|
protected function buildDynamicQuery(string $tableName): array
|
||||||
{
|
{
|
||||||
|
$this->allowedGetColumns = $this->loadTableColumns($tableName);
|
||||||
|
|
||||||
if (!$this->baseQuery) {
|
if (!$this->baseQuery) {
|
||||||
$this->baseQuery = "SELECT * FROM " . $tableName;
|
$this->baseQuery = "SELECT * FROM " . $tableName;
|
||||||
}
|
}
|
||||||
@@ -714,6 +724,10 @@ class API
|
|||||||
$column = $builder['where'][0];
|
$column = $builder['where'][0];
|
||||||
$value = $builder['where'][1];
|
$value = $builder['where'][1];
|
||||||
|
|
||||||
|
if (!in_array($column, $this->allowedGetColumns, true)) {
|
||||||
|
$this->apiOutput(400, ['error' => 'The column ' . $column . ' is not allowed.']);
|
||||||
|
}
|
||||||
|
|
||||||
$whereClauses[] = "$column = ?";
|
$whereClauses[] = "$column = ?";
|
||||||
$types .= 's';
|
$types .= 's';
|
||||||
$values[] = $value;
|
$values[] = $value;
|
||||||
@@ -726,6 +740,20 @@ class API
|
|||||||
return [$this->baseQuery, $types, $values];
|
return [$this->baseQuery, $types, $values];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function loadTableColumns(string $tableName): array
|
||||||
|
{
|
||||||
|
if (isset(self::$columnCache[$tableName])) {
|
||||||
|
return self::$columnCache[$tableName];
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?";
|
||||||
|
|
||||||
|
$stmt = $this->pdo->prepare($sql);
|
||||||
|
$stmt->execute([$tableName]);
|
||||||
|
|
||||||
|
return self::$columnCache[$tableName] = $stmt->fetchAll(\PDO::FETCH_COLUMN);
|
||||||
|
}
|
||||||
|
|
||||||
protected function generalGetFunction($query, $types, $params, $returnBoolean, $itemName)
|
protected function generalGetFunction($query, $types, $params, $returnBoolean, $itemName)
|
||||||
{
|
{
|
||||||
$stmt = $this->prepareStatement($query);
|
$stmt = $this->prepareStatement($query);
|
||||||
|
|||||||
Reference in New Issue
Block a user