SQL injection is one of the most accessible ways of hacking a website. The injections work by introducing an arbitrary SQL code into the site data (transmitted via GET & POST requests, or cookie values). If the site is vulnerable and carries out the injections, then there is an opportunity for anything to happen with the database (usually MySQL).
How do I identify the vulnerabilities that allow an SQL injection?
It’s quite easy. Take the test site test.com. The site has a news panel and a detailed view option. The address of the page with the detailed view looks like this: test.com/?detail=1. So, the detail variable transmits the value 1 (the identifier of the record in the news panel) through a GET request.
Let’s change the GET request to ?detail=1′ or ?detail=1“. Next, try to send those requests to the server, i.e., go to test.com/?detail=1′ or test.com/?detail=1″.
If an error appears when trying to enter those sites, then the website is vulnerable to SQL injections.
Possible SQL Injections (SQL deployments)
- The simplest way is to shorten the WHERE clause to the true result for any value of the parameters.
- Connecting the results request to another request. This is done through the UNION operator.
- Commenting on part of the request.
Practice. Options for hacking a site that is vulnerable to SQL deployments.
So, we have our site test.com. The database contains 4 news articles, 3 of which are displayed. The permission to publish news depends on the public parameter (if the parameter has a value of 1, then the news is published).
When attempting to access the page test.com/?detail=4, which should contain the fourth news article, an error appears—the article is not found.
In our case, the article does exist, yet it is forbidden from publication.
Seeing as how we have already checked the site for vulnerabilities and it has given us a database error, let’s try to sort through the possible options for requests.
In the URL, the plus (+) serves as a space, so don’t be afraid
Test the following options:
As a result, luck was on our side, and two requests (the first and third) returned a detailed description of the fourth article.
Here’s an analysis of the example from the inside
The block of code responsible for obtaining detailed descriptions of the articles is:
$zapros=”SELECT * FROM `$table_news` WHERE `public`=’1′ AND `id`=$detail_id ORDER BY `position` DESC”;
Not only does $detail_id get the value without any processing, but the construction of `id`=$detail_id is written unevenly, it’s better to stick to `id`=’$detail_id’ (i.e. the compared value is written in straight apostrophes).
Looking at the query that we get when accessing the page via test.com/?detail=4+OR+1
SELECT * FROM `news` WHERE `public`=’1′ AND `id`=4 OR 1 ORDER BY `position` DESC
it does not become all that clear why the fourth news result was displayed. The query returned all four articles from the news panel in reverse chronological order. That is why the fourth article was the very first result, and it was also detailed. It was just a coincidence.
Let’s analyze the query that is generated when accessing the page via test.com/?detail=4+UNION+SELECT+*+FROM+news+WHERE+id=4.
Here, the name of the news panel (in our case, it’s “news”), was obtained by a logical search.
So, the query SELECT * FROM `news` WHERE `public`=’1′ AND `id`=4 UNION SELECT * FROM news WHERE id=4 ORDER BY `position` DESC was executed. The second part of the query (after UNION) connected to the zero result of the first part of the query (before UNION), which returned a detailed description of the 4th article.
Protection Against SQL Injections (SQL deployments)
Protection against hacking comes down to the basic rule of “trust, but verify.” You must verify everything—numbers, strings, dates, and specially formatted data.
To check the variable for a numeric value, use the function is_numeric(n);, which will come back as true if the parameter n is a number, and false if it is not.
You can also manually override the type instead of checking the value for a number. Here’s an example, $_GET[‘id_news’] overrides the value $id into an integer value:
Most hacks through SQL occur because of “raw” quotes, apostrophes, and other special characters. To clean up those problems, use the addslashes($str); function, which returns an $str string with an added slash (\) before every special character. This process is called screening.
$a=”an example of apostrophized text ‘ “;
echo addslashes($a); //example of apostrophized text will be displayed \’
There are also two functions used in SQL statements that have been explicitly created to screen strings.
They are mysql_escape_string($str); and mysql_real_escape_string($str);.
The first option does not take into account the encryption of the database connection and can be bypassed, but the second option does and is completely safe. mysql_real_escape_string($str); returns the string $str with an added backslash to the following characters: \x00, \n, \r, \, ‘, ” и \x1a.
Magic quotes automatically replace quotes with a backslash (\), including the quotes in I/O operations. In some PHP configurations, this option is enabled, and in others, it is not. To avoid double screening characters and to screen data normally through mysql_real_escape_string($str);, you must remove the automatic placement of backslashes (if magic quotes are enabled).
To check whether magic quotes are enabled for data obtained from GET, POST, or cookies, use the function get_magic_quotes_gpc(); (it will return 1 if magic quotes are enabled, 0 if not).
If magic quotes are enabled (i.e., backslashes are added) and you see them often, then you need to remove them. This is done through the function stripslashes($str); (this will return the string $str without any backslashes in the quotes and straight apostrophes).
In conclusion, we present a code with full string screening for entries in the database.