CVE-2015-10019: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: A vulnerability, which was classified as problematic, has been found in foxoverflow MySimplifiedSQL. This issue affects some unknown processing of the file MySimplifiedSQL_Examples.php. The manipulation of the argument FirstName/LastName leads to cross site scripting. The attack may be initiated remotely. The patch is named 3b7481c72786f88041b7c2d83bb4f219f77f1293. It is recommended to apply a patch to fix this issue. The associated identifier of this vulnerability is VDB-217595.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2023-01-07T09:15Z
Repository: https://github.com/foxoverflow/MySimplifiedSQL
Language: PHP
Files changed: LICENSE, MySimplifiedSQL.php, MySimplifiedSQL_Examples.php, README.md
Commit date: 2015-01-18 01:22:55 +0000
Commit message: Added XSS protection in MySimplifiedSQL_Examples.php

Added XSS protection to make sure people don't forget about it.

Diff: diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7d6d330
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 foxoverflow
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/MySimplifiedSQL.php b/MySimplifiedSQL.php
new file mode 100644
index 0000000..b7181a5
--- /dev/null
+++ b/MySimplifiedSQL.php
@@ -0,0 +1,151 @@
+<?php
+/*
+GitHub: https://github.com/foxoverflow/MySimplifiedSQL
+
+Copyright (c) 2015 foxoverflow
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+class MySimplifiedSQL
+{
+    public $mysqli;
+    public $num_rows = 0;
+    public $rowArray = array();
+    public $testMode = 0;
+
+    function __construct($db_user, $db_password, $db_host, $db_name, $testModeParameter = 0)
+    {
+        if($testModeParameter == 0)
+        {
+            $this->mysqli = @mysqli_connect($db_host, $db_user, $db_password, $db_name);
+            if(!$this->mysqli) 
+            {
+                throw new Exception("MySimplifiedSQL: Error connecting to MySQL database, MySQLi connect error: " . mysqli_connect_error());
+            }
+            if (!$this->mysqli->set_charset("utf8")) 
+            {
+                throw new Exception("MySimplifiedSQL: Error setting charset to UTF-8, do not continue as sanitization will not work properly.");
+            }
+        }
+        else 
+        {
+            $this->testMode = 1;
+            echo "MySimplifiedSQL: Test mode is active, no queries will be executed.<br>";
+        }
+    }
+
+    function __destruct()
+    {
+        if($this->testMode == 0) mysqli_close($this->mysqli);
+    }
+
+    public function testMode($testModeParameter)
+    {
+        $this->testMode = $testModeParameter;
+    }
+
+    public function sanitize($variable)
+    {
+        if($this->testMode == 0)
+        {
+            return mysqli_real_escape_string($this->mysqli, $variable);
+        }
+        else return $variable;
+    }
+
+    public function query($query, $selectQuery = 0)
+    {
+        if($selectQuery == 0 && strpos($query, "SELECT") !== false) $selectQuery = 1; 
+        if($this->testMode == 0)
+        {
+            $queryResult = mysqli_query($this->mysqli, $query);
+            if(!$queryResult)
+            {
+                throw new Exception("MySimplifiedSQL: Error executing your query, it was: {$query} - MySQL Error: " . mysqli_error($this->mysqli));
+            }
+            if($selectQuery == 1) 
+            {
+                $this->rowArray = array();
+                while($row = $queryResult->fetch_assoc())
+                {
+                    $this->rowArray[] = $row;
+                }
+            }
+            @$this->num_rows = $queryResult->num_rows;
+        }
+        else echo htmlentities($query) . "<br>";
+    }
+
+    public function insert($table, array $elements)
+    {
+        $queryStatement = "INSERT INTO {$table} (";
+        $totalFieldCount = count($elements);
+        $fieldCount = 0;
+        foreach ($elements as $field => $value) 
+        {
+            $fieldCount++;
+            $queryStatement .= $field;
+            if($fieldCount < $totalFieldCount) $queryStatement .= ", "; else $queryStatement .= ") VALUES (";
+        }
+        $fieldCount = 0;
+        foreach ($elements as $field => $value) 
+        {
+            $fieldCount++;
+            $value = $this->sanitize($value);
+            $queryStatement .= "'" . $value . "'";
+            if($fieldCount < $totalFieldCount) $queryStatement .= ", "; else $queryStatement .= ")";
+        }
+        $this->query($queryStatement);
+    }
+    
+    public function select($table, array $where, $condition = "AND", $extra = "") // In $extra you can use "ORDER BY" for example
+    {
+        if($condition != "AND" && $condition != "OR") throw new Exception("MySimplifiedSQL: Select condition is not \"AND\" nor \"OR\"");
+        $queryStatement = "SELECT * FROM {$table} WHERE ";
+        $totalWhereCount = count($where);
+        $whereCount = 0;
+        foreach($where as $whereField => $whereValue)
+        {
+            $whereCount++;
+            $whereValue = $this->sanitize($whereValue);
+            $queryStatement .= $whereField . "='" . $whereValue . "'";
+            if($whereCount < $totalWhereCount) $queryStatement .= " " . $condition . " ";
+        }
+        $this->query($queryStatement . " {$extra}", 1);
+    }
+
+    public function delete($table, array $where, $condition = "AND")
+    {
+        if($condition != "AND" && $condition != "OR") throw new Exception("MySimplifiedSQL: Select condition is not \"AND\" nor \"OR\"");
+        $queryStatement = "DELETE FROM {$table} WHERE ";
+        $totalWhereCount = count($where);
+        $whereCount = 0;
+        foreach($where as $whereField => $whereValue)
+        {
+            $whereCount++;
+            $whereValue = $this->sanitize($whereValue);
+            $queryStatement .= $whereField . "='" . $whereValue . "'";
+            if($whereCount < $totalWhereCount) $queryStatement .= " " . $condition . " ";
+        }
+        $this->query($queryStatement, 1);
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/MySimplifiedSQL_Examples.php b/MySimplifiedSQL_Examples.php
new file mode 100644
index 0000000..2a7afe2
--- /dev/null
+++ b/MySimplifiedSQL_Examples.php
@@ -0,0 +1,37 @@
+<?php
+/*
+MySimplifiedSQL is an easy-to-use PHP class to interact with an SQL database. Currently this makes use of the MySQLi extension and therefore only supports MySQL/MariaDB.
+All field values are properly sanitized , this means that you don't have to worry about security (Unless your perform direct queries, example: $database->query("SELECT * FROM users WHERE FirstName='John'"))
+This .php file shows you some examples on how you can use MySimplifiedSQL.
+GitHub: https://github.com/foxoverflow/MySimplifiedSQL
+*/
+require_once 'MySimplifiedSQL.php';
+//$database = New MySimplifiedSQL($db_user, $db_password, $db_host, $db_name); // Connect to MySQL and build class object
+$database = New MySimplifiedSQL("example_user", "example_password", "example_host", "example_name", 1); // Test mode activated, set the last parameter to 0 or omit it to perform queries instead of viewing them
+//$database->testMode(1); // (Optional) Set test mode to 1 if you want to see querys instead of executing them
+$database->insert("users", array("FirstName" => "John")); // "INSERT INTO users (FirstName) VALUES ('John')"
+$database->insert("users", array("FirstName" => "John", "LastName" => "Smith")); // "INSERT INTO users (FirstName, LastName) VALUES ('John', 'Smith')"
+$database->select("users", array("FirstName" => "John")); // "SELECT * FROM users WHERE FirstName='John'"
+$database->select("users", array("FirstName" => "John", "LastName" => "Smith")); // "SELECT * FROM users WHERE FirstName='John' AND LastName='Smith'"
+$database->select("users", array("FirstName" => "John", "LastName" => "Smith"), "OR"); // "SELECT * FROM users WHERE FirstName='John' OR LastName='Smith'"
+$database->select("users", array("FirstName" => "John", "LastName" => "Smith", "MiddleName" => "Bill"), "OR"); // "SELECT * FROM users WHERE FirstName='John' OR LastName='Smith' OR MiddleName='Bill'"
+/*
+The following $database->select is correctly written, however, there is a bug with the current MySimplifiedSQL version when we execute it:
+$database->select("users", array("FirstName" => "John", "LastName" => "Smith", "LastName" => "Bill"), "OR"); 
+The query that should have been producted is: "SELECT * FROM users WHERE FirstName='John' OR LastName='Smith' OR LastName='Bill'"
+However, in the current version, the produced query is: "SELECT * FROM users WHERE FirstName='John' OR LastName='Smith'"
+There is currently no ETA for a fix for this since you can easily solve it by performing a direct query, see at the end of this file examples.
+*/
+foreach($database->rowArray as $row) // Only to be used after a SELECT query ($database->select). If test mode is enabled, the array will be empty.
+{
+	echo "First name:" . htmlentities($row['FirstName']) . "<br>"; // htmlentities is used here to combat XSS attack attempts
+	echo "Last name:" . htmlentities($row['LastName']) . "<br>";
+}
+$database->delete("users", array("FirstName" => "John", "LastName" => "Smith")); // "DELETE FROM users WHERE FirstName='John' AND LastName='Smith'" - Works like $database->select
+// If you want more control over your queries, you can manually build an SQL Query, also known as direct query.
+$userInputDemo = "John' Smith"; // The ' could cause an SQL error, allowing to know SQL Injection is possible.
+$userInputDemo = $database->sanitize($userInputDemo); // Field sanitization, escaping "malicious" characters like '
+$database->query("SELECT * FROM users WHERE Name='" . $userInputDemo . "'"); // "SELECT * WHERE FirstName='John\' Smith'" - The ' was successfully escaped
+// You can also use MySQLi functions directly if you want, the connection handle/link is $database->mysqli
+// mysqli_query($database->mysqli, $query);  
+?> 
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d932588
--- /dev/null
+++ b/README.md
@@ -0,0 +1,8 @@
+# MySimplifiedSQL
+An easy-to-use PHP class to interact with a SQL database.
+
+I have developed this initially for private use, but later I though it would be worth to share it. I believe it's not coded in the best way possible, but it works pretty well.
+
+Currently the script uses the MySQLi extension (Supports MySQL/MariaDB), support for PDO is one of the main ideas. Unfortunately, I lack the time to do it. Anyway, it is safe and ready for production use. 
+
+See the examples to get started. If you want to handle errors properly make sure to use try/catch statements (Not included in examples).
\ No newline at end of file

Fixed code: The MIT License (MIT)

Copyright (c) 2015 foxoverflow

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

<?php
/*
GitHub: https://github.com/foxoverflow/MySimplifiedSQL

Copyright (c) 2015 foxoverflow

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
class MySimplifiedSQL
{
    public $mysqli;
    public $num_rows = 0;
    public $rowArray = array();
    public $testMode = 0;

    function __construct($db_user, $db_password, $db_host, $db_name, $testModeParameter = 0)
    {
        if($testModeParameter == 0)
        {
            $this->mysqli = @mysqli_connect($db_host, $db_user, $db_password, $db_name);
            if(!$this->mysqli) 
            {
                throw new Exception("MySimplifiedSQL: Error connecting to MySQL database, MySQLi connect error: " . mysqli_connect_error());
            }
            if (!$this->mysqli->set_charset("utf8")) 
            {
                throw new Exception("MySimplifiedSQL: Error setting charset to UTF-8, do not continue as sanitization will not work properly.");
            }
        }
        else 
        {
            $this->testMode = 1;
            echo "MySimplifiedSQL: Test mode is active, no queries will be executed.<br>";
        }
    }

    function __destruct()
    {
        if($this->testMode == 0) mysqli_close($this->mysqli);
    }

    public function testMode($testModeParameter)
    {
        $this->testMode = $testModeParameter;
    }

    public function sanitize($variable)
    {
        if($this->testMode == 0)
        {
            return mysqli_real_escape_string($this->mysqli, $variable);
        }
        else return $variable;
    }

    public function query($query, $selectQuery = 0)
    {
        if($selectQuery == 0 && strpos($query, "SELECT") !== false) $selectQuery = 1; 
        if($this->testMode == 0)
        {
            $queryResult = mysqli_query($this->mysqli, $query);
            if(!$queryResult)
            {
                throw new Exception("MySimplifiedSQL: Error executing your query, it was: {$query} - MySQL Error: " . mysqli_error($this->mysqli));
            }
            if($selectQuery == 1) 
            {
                $this->rowArray = array();
                while($row = $queryResult->fetch_assoc())
                {
                    $this->rowArray[] = $row;
                }
            }
            @$this->num_rows = $queryResult->num_rows;
        }
        else echo htmlentities($query) . "<br>";
    }

    public function insert($table, array $elements)
    {
        $queryStatement = "INSERT INTO {$table} (";
        $totalFieldCount = count($elements);
        $fieldCount = 0;
        foreach ($elements as $field => $value) 
        {
            $fieldCount++;
            $queryStatement .= $field;
            if($fieldCount < $totalFieldCount) $queryStatement .= ", "; else $queryStatement .= ") VALUES (";
        }
        $fieldCount = 0;
        foreach ($elements as $field => $value) 
        {
            $fieldCount++;
            $value = $this->sanitize($value);
            $queryStatement .= "'" . $value . "'";
            if($fieldCount < $totalFieldCount) $queryStatement .= ", "; else $queryStatement .= ")";
        }
        $this->query($queryStatement);
    }
    
    public function select($table, array $where, $condition = "AND", $extra = "") // In $extra you can use "ORDER BY" for example
    {
        if($condition != "AND" && $condition != "OR") throw new Exception("MySimplifiedSQL: Select condition is not \"AND\" nor \"OR\"");
        $queryStatement = "SELECT * FROM {$table} WHERE ";
        $totalWhereCount = count($where);
        $whereCount = 0;
        foreach($where as $whereField => $whereValue)
        {
            $whereCount++;
            $whereValue = $this->sanitize($whereValue);
            $queryStatement .= $whereField . "='" . $whereValue . "'";
            if($whereCount < $totalWhereCount) $queryStatement .= " " . $condition . " ";
        }
        $this->query($queryStatement . " {$extra}", 1);
    }

    public function delete($table, array $where, $condition = "AND")
    {
        if($condition != "AND" && $condition != "OR") throw new Exception("MySimplifiedSQL: Select condition is not \"AND\" nor \"OR\"");
        $queryStatement = "DELETE FROM {$table} WHERE ";
        $totalWhereCount = count($where);
        $whereCount = 0;
        foreach($where as $whereField => $whereValue)
        {
            $whereCount++;
            $whereValue = $this->sanitize($whereValue);
            $queryStatement .= $whereField . "='" . $whereValue . "'";
            if($whereCount < $totalWhereCount) $queryStatement .= " " . $condition . " ";
        }
        $this->query($queryStatement, 1);
    }

}

?>
<?php
/*
MySimplifiedSQL is an easy-to-use PHP class to interact with an SQL database. Currently this makes use of the MySQLi extension and therefore only supports MySQL/MariaDB.
All field values are properly sanitized , this means that you don't have to worry about security (Unless your perform direct queries, example: $database->query("SELECT * FROM users WHERE FirstName='John'"))
This .php file shows you some examples on how you can use MySimplifiedSQL.
GitHub: https://github.com/foxoverflow/MySimplifiedSQL
*/
require_once 'MySimplifiedSQL.php';
//$database = New MySimplifiedSQL($db_user, $db_password, $db_host, $db_name); // Connect to MySQL and build class object
$database = New MySimplifiedSQL("example_user", "example_password", "example_host", "example_name", 1); // Test mode activated, set the last parameter to 0 or omit it to perform queries instead of viewing them
//$database->testMode(1); // (Optional) Set test mode to 1 if you want to see querys instead of executing them
$database->insert("users", array("FirstName" => "John")); // "INSERT INTO users (FirstName) VALUES ('John')"
$database->insert("users", array("FirstName" => "John", "LastName" => "Smith")); // "INSERT INTO users (FirstName, LastName) VALUES ('John', 'Smith')"
$database->select("users", array("FirstName" => "John")); // "SELECT * FROM users WHERE FirstName='John'"
$database->select("users", array("FirstName" => "John", "LastName" => "Smith")); // "SELECT * FROM users WHERE FirstName='John' AND LastName='Smith'"
$database->select("users", array("FirstName" => "John", "LastName" => "Smith"), "OR"); // "SELECT * FROM users WHERE FirstName='John' OR LastName='Smith'"
$database->select("users", array("FirstName" => "John", "LastName" => "Smith", "MiddleName" => "Bill"), "OR"); // "SELECT * FROM users WHERE FirstName='John' OR LastName='Smith' OR MiddleName='Bill'"
/*
The following $database->select is correctly written, however, there is a bug with the current MySimplifiedSQL version when we execute it:
$database->select("users", array("FirstName" => "John", "LastName" => "Smith", "LastName" => "Bill"), "OR"); 
The query that should have been producted is: "SELECT * FROM users WHERE FirstName='John' OR LastName='Smith' OR LastName='Bill'"
However, in the current version, the produced query is: "SELECT * FROM users WHERE FirstName='John' OR LastName='Smith'"
There is currently no ETA for a fix for this since you can easily solve it by performing a direct query, see at the end of this file examples.
*/
foreach($database->rowArray as $row) // Only to be used after a SELECT query ($database->select). If test mode is enabled, the array will be empty.
{
	echo "First name:" . htmlentities($row['FirstName']) . "<br>"; // htmlentities is used here to combat XSS attack attempts
	echo "Last name:" . htmlentities($row['LastName']) . "<br>";
}
$database->delete("users", array("FirstName" => "John", "LastName" => "Smith")); // "DELETE FROM users WHERE FirstName='John' AND LastName='Smith'" - Works like $database->select
// If you want more control over your queries, you can manually build an SQL Query, also known as direct query.
$userInputDemo = "John' Smith"; // The ' could cause an SQL error, allowing to know SQL Injection is possible.
$userInputDemo = $database->sanitize($userInputDemo); // Field sanitization, escaping "malicious" characters like '
$database->query("SELECT * FROM users WHERE Name='" . $userInputDemo . "'"); // "SELECT * WHERE FirstName='John\' Smith'" - The ' was successfully escaped
// You can also use MySQLi functions directly if you want, the connection handle/link is $database->mysqli
// mysqli_query($database->mysqli, $query);  
?> 
# MySimplifiedSQL
An easy-to-use PHP class to interact with a SQL database.

I have developed this initially for private use, but later I though it would be worth to share it. I believe it's not coded in the best way possible, but it works pretty well.

Currently the script uses the MySQLi extension (Supports MySQL/MariaDB), support for PDO is one of the main ideas. Unfortunately, I lack the time to do it. Anyway, it is safe and ready for production use. 

See the examples to get started. If you want to handle errors properly make sure to use try/catch statements (Not included in examples).