Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Basic SQL Injection Vulnerability Analysis in PHP

Tech Jul 4 1

Basic Injection

SQL parameters are concatenated without any filtering.

<?php

$con = mysql_connect("localhost","root","root");

if (!$con){die('Could not connect: ' . mysql_error());}

mysql_select_db("test", $con);

$id = stripcslashes($_REQUEST[ 'id' ]);

$query = "SELECT * FROM users WHERE id = $id ";

$result = mysql_query($query)or die(''.mysql_error().'');

while($row = mysql_fetch_array($result))
{
echo $row['0'] . " " . $row['1'];
echo "<br />";
}

echo "<br/>";

echo $query;

mysql_close($con);
?>

Test statement: id=1 UNION SELECT user(),2,3,4 from users

Wide Byte Injection

A. MySQL Wide Character Injection

Example code:

<?php

$con = mysql_connect("localhost","root","root");

mysql_query("SET NAMES 'gbk'");

mysql_select_db("test", $con);

$id = isset($_GET['id']) ? addslashes($_GET['id']) : 1;

$query = "SELECT * FROM users WHERE id ='{$id}' ";

$result = mysql_query($query)or die(''.mysql_error().'');

while($row = mysql_fetch_array($result))
{
echo $row['0'] . " " . $row['1'];
echo "<br />";
}

echo "<br/>";

echo $query;

mysql_close($con);
?>

Test statement: %df%27

MySQL's characteristic is that gbk is a multi-byte encoding, two bytes represent a Chinese character, so %df and the following \ which is %5c becomes a Chinese character "運", which escapes the single quote.

According to the gbk encoding, the first byte's ASCII code is greater than 128, which is basical sufficient. For example, instead of using %df, we can use %a1.

The range of gb2312 encoding. Its high byte range is 0xA10xF7, the low byte range is 0xA10xFE, and \ is 0x5c, which is not in the low byte range.

Therefore, 0x5c is not part of the gb2312 encoding, so it does not cause wide byte injection. Expanding to all multi-byte encodings in the world, as long as the low byte range contains 0x5c, it can be used for wide character injection.

Fixing Wide Character Injection:

Option 1: Specify the character set for PHP connecting to MySQL

mysql_set_charset('gbk',$conn);

$id = mysql_real_escape_string($_GET['id']);

Option 2: Set character_set_client to binary (binary)

mysql_query("SET character_set_connection=gbk, character_set_results=gbk, character_set_client=binary",$conn);

Setting character_set_client to binary eliminates the issue of wide or multi-byte characters, and all data is transmitted in binary form, effectively preventing wide character injection.

B. PHP Encoding Conversion

Example code:

<?php

$con = mysql_connect("localhost","root","root");

mysql_query("SET NAMES 'gbk'");

mysql_select_db("test", $con);

mysql_query("SET character_set_connection=gbk,
character_set_results=gbk,character_set_client=binary", $con);

$id = isset($_GET['id']) ? addslashes($_GET['id']) : 1;

$id=iconv('utf-8','gbk',$id);

$query = "SELECT * FROM users WHERE id ='{$id}' ";

$result = mysql_query($query)or die(''.mysql_error().'');

while($row = mysql_fetch_array($result))
{
echo $row['0'] . " " . $row['1'];
echo "<br />";
}

echo "<br/>";

echo $query;

mysql_close($con);
?>

Test statement: 錦'

The character 錦 has a UTF-8 encoding of %e9%8c%a6, and a GBK encoding of %e5%5c.

After converting with iconv from UTF-8 to GBK, it becomes %e5%5c, and the subsequent ' is added by addslashes to become %5c%27, resulting in %e5%5c%5c%27, where two %5c are , which properly escape the backslash, allowing the ' to escape the single quote, causing an injection.

id=iconv('gbk','utf-8',id); // Test with %df%27

A GBK Chinese character is two bytes, while a UTF-8 Chinese charactre is three bytes. If we convert GBK to UTF-8, PHP will process two bytes at a time. Therefore, if the character before \ is odd, it will swallow the , allowing the ' to escape the restriction.

Other functions:

mb_convert_encoding(id,'utf-8','gbk')//GBKToUTF-8 is the same as iconv('gbk','utf-8',id)

Encoding and Decoding

Finding some encoding and decoding functions to bypass protection, such as urldecode(), rawurldecode(), base64_decode()

<?php

$con = mysql_connect("localhost","root","root");

mysql_select_db("test", $con);

$id = addslashes($_REQUEST['id']);

$id = urldecode($id);//$id = base64_decode($id);

$query = "SELECT * FROM users WHERE id = '{$id}'";

$result = mysql_query($query)or die(''.mysql_error().'');

while($row = mysql_fetch_array($result))
{
echo $row['0'] . " " . $row['1'];
echo "<br />";
}

echo "<br/>";

echo $query;

mysql_close($con);
?>

Test statement:

1'union select 1,2,3,4%23 Encode single quote as 1%2527union select 1,2,3,4%23

1'union select 1,2,3,4# Base64 encode MSd1bmlvbiBzZWxlY3QgMSwyLDMsNCM=

Second Injection

When stored, the escape characters disappear, making it 'hack', and when retrieved, it becomes 'hack', which can be used to close the single quote and cause injection.

Test:

CREATE TABLE test (user VARCHAR(20) NOT NULL);

INSERT INTO test values('hack'');

Example code:

// Test data create table test(

id INT NOT NULL,

user VARCHAR(100) NOT NULL,

pass VARCHAR(100) NOT NULL

)

INSERT INTO test values(1,'hack','hack');

// Test code

Global Protection Blind Spots

  1. The str_replace function filters single quotes, possibly leading to injection;
  2. The stripslashes() function deletes the backslashes added by addslashes(). Improper use of stripslashes() may lead to injection;

① Parameters like id=1, which are numeric, completely ignore GPC filtering; ② Key-value pairs where only the value is checked but not the key; ③ Sometimes global filtering only filters GET, POST, and COOKIE, but not SERVER.

② FILES injection, where global filtering only handles GET, POST, etc., but ignores FILES; ② Variable overwriting, dangerous functions: extract(), parse_str(), $$.

Vulnerability Protection

Basic idea: Input (to resolve numeric injection) - Escape processing (to resolve character injection) - Output (to resolve database error messages)

  1. Check whether input data matches the expected format. PHP has many functions for checking input, from simple variable functions and character type functions (like is_numeric(), ctype_digit()) to complex Perl-compatible regular expression functions. If the program expects a number, consider using is_numeric() to check, or directly use settype() to convert its type, or use sprintf() to format it as a number.

  2. Built-in PHP escape functions

Addslashes() http://php.net/manual/zh/function.addslashes.php magic_quotes_gpc http://php.net/manual/zh/info.configuration.php#ini.magic-quotes-gpc mysql_real_escape_string() http://php.net/manual/zh/function.mysql-real-escape-string.php mysql_escape_string() http://php.net/manual/zh/function.mysql-escape-string.php

  1. Preventing database error message leakage:

Set php.ini file display_errors = Off

Add a @ character before the database query function

The most effective way to prevent SQL injection attacks is to use prepared statements for database queries:

<?php

$mysqli = new MySQLi("localhost","root","root","test");

if(!$mysqli){
die($mysqli->error);
}

$sql = "select id,username,password from users where id=?";////Create a predefined object ? placeholder

$mysqli_stmt = $mysqli->prepare($sql);

$id=$_REQUEST['id'];

$mysqli_stmt->bind_param("i",$id);////Bind parameter

$mysqli_stmt->bind_result($id,$username,$password);////Bind result set

$mysqli_stmt->execute();//Execute

while($mysqli_stmt->fetch()){ //Fetch the bound result set

echo $id." " . $username . " " . $password;

}

echo "<br/>";

echo $sql;

$mysqli_stmt->free_result(); ////Close result set

$mysqli_stmt->close();

$mysqli->close();
?>
Tags: PHP

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.