Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE REQUEST] Server Filesystem Enumeration using SQL injection #2908

Closed
edgarolijar opened this issue Feb 2, 2018 · 14 comments
Closed

Comments

@edgarolijar
Copy link

edgarolijar commented Feb 2, 2018

Tools

SQLMAP is a powerful tool (with overwhelming amount of features), but there is currently no real functionality to perform servers's file system enumeration via SQL injection (e.g. MySQL's load_file(...)). If you want to scan web folder, then tools like DirBuster already exist and do their job very well, but if you want to enumerate server's internal structure by using SQL injection, then ... there is currently only such a tool which is called SqlNuke and is written in ruby (and not python =( ) and isn't far so mature tool as sqlmap is (ok there is also a Metasploit tool, but it's still not cool enough: https://digi.ninja/metasploit/mysql_file_enum.php).

meme

Why SQLMAP?

Why is sqlmap so perfect to solve this task? Because it has already all the necessary functionality to make an SQL injection in very different ways (cookies & headers, POST & GET requests, payload suffix, prefix, time based, blind, union based, stacked, SQL injection type recognition and payload generation and and and ... - you know how much it is ;)). So why not just add another cool option to contribute to the glory of this great tool!

There are several possible scenarios, where it might be useful

1. File privilege is on, but it's impossible to write file to any world-viewable folder

  1. All world-viewable folders are protected -> still possible to write to "non-public" folders (we can also check if the file exists if we are able to write to some non-public folder from the outside, but if we try to create file with specific name we'll fail because MySQL's into outfile can't overwrite files)
  2. MySQL's into outfile requires quotes or doublequotes (load_file(...) can still work with HEX), which are e.g. blocked.

2. File priv is on: We can read and write files, but we just don't know DocumentRoot's location and need to bruteforce it. Quotes aren't blocked.

  1. "Spammer 4ever"-style: try to write a file with special payload (easier detection in the next step, if it's a right file) (MySQL: into outfile) and then try to read it back (MySQL: load_file(...)). Problem: Some folders might be still protected, or there might be a rare case with file collision (MySQL's into outfile can't overwrite existing files)(file names must be carefully chosen to avoid possible collisions).
    After such "attack" we definitely will need to clean up the server xD so a list with tested paths would be useful...
  2. We know how our script in the DocumentRoot is called (e.g. index.pl), so we will try to bruteforce DocumentRoot (maybe we have some minimal information leak found, where we see relative path like use lib qw(../../../service/lib); and then later in the code use Foo::Engine; (e.g. leaked perl code)) by using bugs (read below) or dictionary-based or pure bruteforce. (consider the case where we can't find DocumentRoot via php bugs (or similar) or google search or in log files or in database itself - we just d-o-n't have it =()

Note

  1. MySQL's load_file() works with HEX-encoded or quoted string and works also with relative paths, e.g.: load_file("../../../../Apache/htdocs/path/file.php") (current working directory on MySQL is @@datadir (default path is /var/lib/mysql))
    (https://websec.wordpress.com/2007/11/17/mysql-table-and-column-names/)
  2. Stacked queries ";" are disabled by default, so I'm considering here the most common case where we can use subqueries (nested queries) only
  3. I use MySQL only as example here

Suggestions

  1. Fixed list with default/common file paths of config files
    /etc/passwd
    /etc/init.d/apache/httpd.conf
    /etc/init.d/apache2/httpd.conf
    ...
    -> https://wiki.apache.org/httpd/DistrosDefaultLayout
    -> nginx, Apache, lighttpd, Apache Tomcat, Jetty, ...
    -> possibility to use own lists
  2. Dictionary based search or pure bruteforce
    {variable_path}{fixed_filename} OR {fixed}{variable}{fixed}
    Example: /var/www/{variable}/htdocs/index.php
    Where {variable} might be from a wordlist or be just bruteforced (only lower-case chars OR only upper-case chars OR only numbers OR upper-case + lower case OR ... etc)
    And don't forget about "ugly" file or folder names. Example /var/www/java_1.6/file.txt, so we need to bruteforce only the java version in this folder name: {fixed}{java_{0..9}[1].{0...9}[1]}{fixed}
  3. Using cool bugs on specific MySQL versions:
    https://securityweekly.com/2013/01/18/mysql-file-system-enumeration/
    -> Instead of enumerating file names we can use this bug to enumerate directories
    -> Windows MySQL 4.1.7, 5.5.29, Linux MySQL 5.5.25, ... (and maybe other versions?)(maybe there are similar bugs on other DBMSs?) - btw is there a CVE for this bug?!

Not so important question

Does SQLMAP use any of known *SQL's bugs which you can find in the CVE-list?
And again, just for example MySQL: https://www.cvedetails.com/vulnerability-list.php?vendor_id=185

@Ekultek
Copy link
Contributor

Ekultek commented Feb 2, 2018 via email

@shadowzoom
Copy link

Im suggesing something like this: --file-enumerate -f list.txt
where list.txt contains
/etc/passwd
/etc/init.d/apache/httpd.conf and etc

@wandoelmo
Copy link

I made a perl script to enumerate and download all the files, automating the sqlmap.

@edgarolijar
Copy link
Author

edgarolijar commented Feb 13, 2018

At moment there are following possibilities to scan/download (within response) files from server:
--sql-query=QUERY SQL statement to be executed
--sql-shell Prompt for an interactive SQL shell
--sql-file=SQLFILE Execute SQL statements from given file(s)

btw not only enumeration, but also download option would be really cool. Just extract file contents from response & save to file in sqlmap's extra folder server-files. For example this might look like this:
.sqlmap/output/example.com/server-files/etc/passwd, where server-files is just a placeholder for root "/".

@devcoinfet
Copy link

devcoinfet commented Jul 19, 2018

I needed this small script for an engagement to show a customer How you can read files from the server.
https://github.com/devcoinfet/Sqlmap_file_reader/blob/master/file_read.py

@edgarolijar
Copy link
Author

yes, but it is stupid to write own scripts. just let others write them. xD

no. now seriously. sqlmap has everything, but not this feature and i'm tired of writing own dumper scripts. I mean it's not a big deal to write it once or twice for differrent cases. But that's why people started to create more or less generic tools. Just to avoid repetitive work.

@devcoinfet
Copy link

Well the script I gave U does exactly what your asking for just tweak it and change the domain to come from sys.argv[1] or such

I literally code all day everyday, So I highly disagree about letting others write our code for us.

2 reasons

1.)Its a learning experience
2.)it helps You understand the vulnerability in better detail

@edgarolijar
Copy link
Author

edgarolijar commented Oct 10, 2018

Well the script I gave U does exactly what your asking for just tweak it and change the domain to come from sys.argv[1] or such

I literally code all day everyday, So I highly disagree about letting others write our code for us.

2 reasons

1.)Its a learning experience
2.)it helps You understand the vulnerability in better detail

you missed the point. this is not a thread for philosophical discussions. here is a feature request for a popular tool, that i personally miss, that's it. you wonna write your scripts & tools i won't stop you from doing it.

stamparm added a commit that referenced this issue Jun 27, 2019
@stamparm
Copy link
Member

--common-files      Check existence of common files

p.s. checks for these files

@edgarolijar
Copy link
Author

edgarolijar commented Jun 28, 2019

@stamparm awesome, thank you so much!

does this flag support also Windows paths? Windows accepts paths like:

  • C:\\boot.ini
  • C:/boot.ini
  • C:\Users\Foo\.conda\environments.txt
  • C:/Users/Foo/.conda/environments.txt

@edgarolijar
Copy link
Author

It works indeed on windows by using paths like "\windows\system32\drivers\etc\hosts" (without "C:\" or "C:/" or any other drive prefix)

@stamparm
Copy link
Member

@edgarolijar

A) well, I left the issue deliberately opened for further discussion (like your comment). Currently paths are sent in unmodified form as put inside the common-files.txt. I'll also introduce the additional question whether user wants to provide its own filepaths (via his local file).
B) from my own experience, DBMSes on Windows should accept both / and \ formats. If anybody will notice different, they are free to "nag" and I'll do additional logic :)

@edgarolijar
Copy link
Author

edgarolijar commented Jun 28, 2019

currently it is possible just to edit the file "sqlmap/data/txt/common-files.txt" and just to add own stuff there. maybe it would be cleaner just to add another flag like "--custom-files "?
(but what should then happen if both flags are being selected?)

another question is - if the backend escapes quotes, then load_file(...) will not be able to read any files (e.g. load_file("/etc/passwd")) - will the flag --hex turn the file path string "/etc/passwd" into hex?
load_file(0x2f6574632f706173737764) can still work with hex encoded paths (... into outfile can't ...).

stamparm added a commit that referenced this issue Jun 28, 2019
@stamparm
Copy link
Member

@edgarolijar

A) with the latest revision you'll be asked (like in other --common-... switches) whether you want to use default common files file or you want to provide your own
B) checked common filepaths are now automatically converted to slash format (e.g. C:\foobar -> C:/foobar)
C) --hex doesn't convert file paths to hexadecimal format, only the retrieved value
D) there won't be any more changes to the current switch/option command line logic regarding the --common-files. It is perfectly inline with the rest of similar --common-.. switches

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants