[red sun Day12 CTF] SQL injection caused by htmlentities

Exercise notes

Recurrence Code:

index.php

<?php
require 'config.php';

if(isset($_REQUEST['username'])){
    if(preg_match("/(?:\w*)\W*?[a-z].*(R|ELECT|OIN|NTO|HERE|NION)/i", $_REQUEST['username'])){
        die("Attack detected!!!");
    }
}

if(isset($_REQUEST['password'])){
    if(preg_match("/(?:\w*)\W*?[a-z].*(R|ELECT|OIN|NTO|HERE|NION)/i", $_REQUEST['password'])){
        die("Attack detected!!!");
    }
}

function clean($str){
    if(get_magic_quotes_gpc()){
        $str=stripslashes($str);
    }
    return htmlentities($str, ENT_QUOTES);
}

$username = @clean((string)$_GET['username']);
$password = @clean((string)$_GET['password']);


$query='SELECT * FROM ctf.users WHERE name=\''.$username.'\' AND pass=\''.$password.'\';';

#echo $query;

$result=mysql_query($query);
while($row = mysql_fetch_array($result))
{
    echo "<tr>";
    echo "<td>" . $row['name'] . "</td>";
    echo "</tr>";
}

?>

config.php

<?php
$mysql_server_name="localhost";
$mysql_database="day12";    /** Name of the database */
$mysql_username="root";  /** MySQL Database user name */
$mysql_password="root";  /** MySQL Database password */
$conn = mysql_connect($mysql_server_name, $mysql_username,$mysql_password,'utf-8');
?>
Building sql statements for CTF environment
#
# Structure for table "users"
#
CREATE database day12;
use day12;
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `pass` varchar(255) DEFAULT NULL,
  `flag` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

#
# Data for table "users"
#

/*!40000 ALTER TABLE `users` DISABLE KEYS */;
INSERT INTO `users` VALUES (1,'admin','qwer!@#zxca','hrctf{sql_Inject1on_Is_1nterEst1ng}');
/*!40000 ALTER TABLE `users` ENABLE KEYS */;

Vulnerability analysis:

To access the website:

http://10.211.55.2:100/day12/index.php

From line 27 of the index.php code

$query='SELECT * FROM ctf.users WHERE name=\''.$username.'\' AND pass=\''.$password.'\';';

Obviously, this question examines sql injection, but here are two investigation points. Let's take a look at them separately.

The first part

Lines 23 and 24 deal with the username and password obtained by GET,

$username = @clean((string)$_GET['username']);
$password = @clean((string)$_GET['password']);

The processing function is clean. This function is defined on lines 16-20

function clean($str){
    if(get_magic_quotes_gpc()){
        $str=stripslashes($str);
    }
    return htmlentities($str, ENT_QUOTES);
}

The main function of the function is to use the htmlentities function to process the special characters in the variables. The optional parameter ENT_QUOTES of the htmlentities function is added here. Therefore, the single quotation mark, double quotation mark and other special characters will be escaped here. Since the injection here is character type, you need to close or escape the single quotation mark, so you need to bypass this function. We can use the following example to observe the processing effect of clean function:

Select this row to enter the database query and return the value of the name column field. The sql statement here is as follows:

$query='SELECT * FROM ctf.users WHERE name=\''.$username.'\' AND pass=\''.$password.'\';';

If the username is admin and the password is admin, the normal sql statement will be formed.

The problem with this question is that you can introduce a backslash, which is an escape character. The official Escape character That's the explanation.

For example, if you want to match a "*" character, you need to write * in the pattern. This applies when a character has a special meaning without escaping.

Let's take a simple example to understand this escape symbol.

The escape symbol will make the current special symbol lose its function. In this problem, we can introduce the backslash, which is the escape symbol, to make

$query='SELECT * FROM ctf.users WHERE name=\''.$username.'\' AND pass=\''.$password.'\';';

The 'fail' after username, as long as the 'fail', can close the 'pass = after'. The last combination of payload s is shown in the figure below

So in fact, the current value of name is admin \ 'and pass =. At this time, the value of password is a controllable input point. We can use this value to construct sql joint query and comment out the last single quotation mark.

Finally, let's look at the results of the execution in mysql.

The second part

OK, in the first part, we have successfully constructed the payload, but look back at the title. There are two regular expressions in lines 5 and 6 and lines 11 and 12 of the title, which are used to exit and output Attack detected if there are or, and, union and other data in the parameter!!!

Here, of course, we can face this regular expression. But here we talk about a more interesting solution.
We see that the data is passed in by REQUEST, while the REQUEST variable in PHP contains arrays of GET, POST and COOKIE by default. In the php.ini configuration file, there is a parameter "variables" order, which has the following optional items

; variables_order
; Default Value: "EGPCS"
; Development Value: "GPCS"
; Production Value: "GPCS"

These letters correspond to E: Environment, G:Get, P:Post, C:Cookie, S:Server. The order in which these letters appear indicates the order in which the data is loaded. The default configuration of this parameter in php.ini is GPCS. That is to say, if the same variable is passed in POST or GET mode, the value of the variable obtained by REQUEST will be the value of POST.

Let's give you a simple example to understand:


We can see that the data in the post mode covers the data in the get mode, so the last payload here is as follows:

http://10.211.55.2:100/day12/index.php?username=\&password= union select 1,flag ,3,4 from day12.users%23

POST:

username=0&password=1

Published 25 original articles, won praise 17, visited 4542
Private letter follow

Tags: PHP Database SQL MySQL

Posted on Sun, 19 Jan 2020 09:50:36 -0500 by Kingskin