Skip to content

Instantly share code, notes, and snippets.

@groucho75
Last active December 17, 2015 00:29
Show Gist options
  • Save groucho75/5521608 to your computer and use it in GitHub Desktop.
Save groucho75/5521608 to your computer and use it in GitHub Desktop.
Minimal security for Database Queries and Results: MySQLi Prepared Statement & XSS Mitigation functions. Based on: https://www.owasp.org/index.php/PHP_Security_Cheat_Sheet
<?php
/**
* DB Configuration
*/
$Host ='localhost';
$Username = 'root';
$Password = 'root';
$DatabaseName = 'test';
/**
* SQL function
*
* usage: $res = SQL("query...");
*
* see: https://www.owasp.org/index.php/PHP_Security_Cheat_Sheet
*/
function SQL($Query) {
global $DB;
$args = func_get_args();
if (count($args) == 1) {
$result = $DB->query($Query);
if ($result->num_rows) {
$out = array();
while (null != ($r = $result->fetch_array(MYSQLI_ASSOC)))
$out [] = $r;
return $out;
}
return null;
} else {
if (!$stmt = $DB->prepare($Query))
trigger_error("Unable to prepare statement: {$Query}, reason: " . $DB->error . "");
array_shift($args); //remove $Query from args
//the following three lines are the only way to copy an array values in PHP
$a = array();
foreach ($args as $k => &$v)
$a[$k] = &$v;
$types = str_repeat("s", count($args)); //all params are strings, works well on MySQL and SQLite
array_unshift($a, $types);
call_user_func_array(array($stmt, 'bind_param'), $a);
$executed = $stmt->execute();
//fetching all results in a 2D array
$metadata = $stmt->result_metadata();
$out = array();
$fields = array();
if (!$metadata)
return ( $stmt->affected_rows > -1 ) ? $stmt->affected_rows : (int)$executed;
$length = 0;
while (null != ($field = mysqli_fetch_field($metadata))) {
$fields [] = &$out [$field->name];
$length+=$field->length;
}
call_user_func_array(array(
$stmt, "bind_result"
), $fields);
$output = array();
$count = 0;
while ($stmt->fetch()) {
foreach ($out as $k => $v)
$output [$count] [$k] = $v;
$count++;
}
$stmt->free_result();
return ($count == 0) ? false : $output;
}
}
/**
* XSS mitigation functions
*
* usage: xecho( "text to be cleaned and printed" );
*
* see: https://www.owasp.org/index.php/PHP_Security_Cheat_Sheet
*/
function xssafe ( $data, $encoding='UTF-8' )
{
return htmlspecialchars( $data, ENT_QUOTES | ENT_HTML401, $encoding );
}
function xecho ( $data )
{
echo xssafe( $data );
}
<?php
require_once 'db_escape.php';
/**
* DB Connection
*/
$DB = new mysqli($Host, $Username, $Password, $DatabaseName);
if (mysqli_connect_errno())
trigger_error("Unable to connect to MySQLi database.");
$DB->set_charset('UTF-8');
/**
* SAMPLES OF SQL USES
*/
// INSERT: return 1 (success) or 0 (failure)
$res = SQL("INSERT INTO posts ( title ) VALUES ( ? )" , "Nuovo post ". rand( 1, 999 ) );
if ( $res ) echo 'INSERT ID='.$DB->insert_id; else 'NO INSERT';
?><br /><?php
// INSERT: return number of updated rows (success) or 0 (no update or failure)
$res2 = SQL("UPDATE posts SET title= ? WHERE ID = ? OR ID = ?", "Aggiornato post!!!" , 10, 11);
if ( $res2 ) echo 'UPDATE ('.$res2.')' ; else 'NO UPDATE';
?><br /><?php
// DELETE: return number of deleted rows (success) or 0 (no delete or failure)
$res3 = SQL("DELETE FROM posts WHERE ID = ? OR ID = ?", 10, 11);
if ( $res3 ) echo 'DELETE ('.$res3.')' ; else 'NO DELETE';
?><br /><?php
// SELECT: return a 2D array or records (success) or 0 (no records or failure)
$res4 = SQL("SELECT * FROM posts WHERE ID > ? ORDER BY ? ASC LIMIT ?" , 0 , "title" , 100);
if( is_array($res4) )
{
foreach( $res4 as $index => $row )
{
xecho ( $row['ID'] . " " . $row['title'] );
echo '<br />';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment