summaryrefslogtreecommitdiffstats
path: root/scripts/smb-vuln-ms10-061.nse
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/smb-vuln-ms10-061.nse')
-rw-r--r--scripts/smb-vuln-ms10-061.nse171
1 files changed, 171 insertions, 0 deletions
diff --git a/scripts/smb-vuln-ms10-061.nse b/scripts/smb-vuln-ms10-061.nse
new file mode 100644
index 0000000..a910ed9
--- /dev/null
+++ b/scripts/smb-vuln-ms10-061.nse
@@ -0,0 +1,171 @@
+local msrpc = require "msrpc"
+local smb = require "smb"
+local string = require "string"
+local vulns = require "vulns"
+local stdnse = require "stdnse"
+
+description = [[
+Tests whether target machines are vulnerable to ms10-061 Printer Spooler impersonation vulnerability.
+
+This vulnerability was used in Stuxnet worm. The script checks for
+the vuln in a safe way without a possibility of crashing the remote
+system as this is not a memory corruption vulnerability. In order for
+the check to work it needs access to at least one shared printer on
+the remote system. By default it tries to enumerate printers by using
+LANMAN API which on some systems is not available by default. In that
+case user should specify printer share name as printer script
+argument. To find a printer share, smb-enum-shares can be used.
+Also, on some systems, accessing shares requires valid credentials
+which can be specified with smb library arguments smbuser and
+smbpassword.
+
+References:
+ - http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-2729
+ - http://technet.microsoft.com/en-us/security/bulletin/MS10-061
+ - http://blogs.technet.com/b/srd/archive/2010/09/14/ms10-061-printer-spooler-vulnerability.aspx
+]]
+---
+-- @usage nmap -p 445 <target> --script=smb-vuln-ms10-061
+--
+-- @args printer Printer share name. Optional, by default script tries to enumerate available printer shares.
+--
+-- @output
+-- PORT STATE SERVICE REASON
+-- 445/tcp open microsoft-ds syn-ack
+
+-- Host script results:
+-- | smb-vuln-ms10-061:
+-- | VULNERABLE:
+-- | Print Spooler Service Impersonation Vulnerability
+-- | State: VULNERABLE
+-- | IDs: CVE:CVE-2010-2729
+-- | Risk factor: HIGH CVSSv2: 9.3 (HIGH) (AV:N/AC:M/Au:N/C:C/I:C/A:C)
+-- | Description:
+-- | The Print Spooler service in Microsoft Windows XP,Server 2003 SP2,Vista,Server 2008, and 7, when printer sharing is enabled,
+-- | does not properly validate spooler access permissions, which allows remote attackers to create files in a system directory,
+-- | and consequently execute arbitrary code, by sending a crafted print request over RPC, as exploited in the wild in September 2010,
+-- | aka "Print Spooler Service Impersonation Vulnerability."
+-- |
+-- | Disclosure date: 2010-09-5
+-- | References:
+-- | http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-2729
+-- | http://technet.microsoft.com/en-us/security/bulletin/MS10-061
+-- |_ http://blogs.technet.com/b/srd/archive/2010/09/14/ms10-061-printer-spooler-vulnerability.aspx
+--
+-- @see stuxnet-detect.nse
+
+author = "Aleksandar Nikolic"
+license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
+categories = {"vuln","intrusive"}
+
+hostrule = function(host)
+ return smb.get_port(host) ~= nil
+end
+
+action = function(host,port)
+
+ local ms10_061 = {
+ title = "Print Spooler Service Impersonation Vulnerability",
+ IDS = {CVE = 'CVE-2010-2729'},
+ risk_factor = "HIGH",
+ scores = {
+ CVSSv2 = "9.3 (HIGH) (AV:N/AC:M/Au:N/C:C/I:C/A:C)",
+ },
+ description = [[
+The Print Spooler service in Microsoft Windows XP,Server 2003 SP2,Vista,Server 2008, and 7, when printer sharing is enabled,
+does not properly validate spooler access permissions, which allows remote attackers to create files in a system directory,
+and consequently execute arbitrary code, by sending a crafted print request over RPC, as exploited in the wild in September 2010,
+aka "Print Spooler Service Impersonation Vulnerability."
+ ]],
+ references = {
+ 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-2729',
+ 'http://technet.microsoft.com/en-us/security/bulletin/MS10-061',
+ 'http://blogs.technet.com/b/srd/archive/2010/09/14/ms10-061-printer-spooler-vulnerability.aspx'
+ },
+ dates = {
+ disclosure = {year = '2010', month = '09', day = '5'},
+ },
+ exploit_results = {},
+ }
+ local report = vulns.Report:new(SCRIPT_NAME, host, port)
+ ms10_061.state = vulns.STATE.NOT_VULN
+ local status, smbstate
+ status, smbstate = msrpc.start_smb(host, msrpc.SPOOLSS_PATH,true)
+ if(status == false) then
+ stdnse.debug1("SMB: " .. smbstate)
+ return false, smbstate
+ end
+
+ local bind_result
+ status, bind_result = msrpc.bind(smbstate,msrpc.SPOOLSS_UUID, msrpc.SPOOLSS_VERSION, nil)
+ if(status == false) then
+ msrpc.stop_smb(smbstate)
+ stdnse.debug1("SMB: " .. bind_result)
+ return false, bind_result
+ end
+ local printer = stdnse.get_script_args(SCRIPT_NAME .. '.printer')
+ -- if printer not set find available printers
+ if not printer then
+ stdnse.debug1("No printer specified, trying to find one...")
+ local lanman_result
+ local REMSmb_NetShareEnum_P = "WrLeh"
+ local REMSmb_share_info_1 = "B13BWz"
+ status, lanman_result = msrpc.call_lanmanapi(
+ smbstate, 0, REMSmb_NetShareEnum_P, REMSmb_share_info_1, "\x01\x00\x7e\xff")
+ if status == false then
+ stdnse.debug1("SMB: " .. lanman_result)
+ stdnse.debug1("SMB: Looks like LANMAN API is not available. Try setting printer script arg.")
+ end
+
+ local parameters = lanman_result.parameters
+ local data = lanman_result.data
+ local status, convert, entry_count, available_entries = string.unpack("<I2 I2 I2 I2", parameters)
+ local pos = 1
+ for i = 1, entry_count, 1 do
+ local name, share_type = string.unpack(">c14 I2", data, pos)
+
+ if share_type == 1 then -- share is printer
+ name = string.unpack("z", name)
+ stdnse.debug1("Found printer share %s.", name)
+ printer = name
+ break
+ end
+ pos = pos + 20
+ end
+ end
+ if not printer then
+ stdnse.debug1("No printer found, system may be unpatched but it needs at least one printer shared to be vulnerable.")
+ return false
+ end
+ stdnse.debug1("Using %s as printer.",printer)
+ -- call RpcOpenPrinterEx - opnum 69
+ local status, result = msrpc.spoolss_open_printer(smbstate,"\\\\"..host.ip.."\\"..printer)
+ if not status then
+ return false
+ end
+ local printer_handle = string.sub(result.data,25,#result.data-4)
+ stdnse.debug1("Printer handle %s",stdnse.tohex(printer_handle))
+ -- call RpcStartDocPrinter - opnum 17
+ status,result = msrpc.spoolss_start_doc_printer(smbstate,printer_handle,",") -- patched version will allow this
+ if not status then
+ return false
+ end
+ local print_job_id = string.sub(result.data,25,#result.data-4)
+ stdnse.debug1("Start doc printer job id %s",stdnse.tohex(print_job_id))
+
+ -- call RpcWritePrinter - 19
+ status, result = msrpc.spoolss_write_printer(smbstate,printer_handle,"aaaa")
+ if not status then
+ return false
+ end
+ local write_result = string.sub(result.data,25,#result.data-4)
+ stdnse.debug1("Written %s bytes to a file.",stdnse.tohex(write_result))
+ if stdnse.tohex(write_result) == "00000000" then -- patched version would report 4 bytes written
+ ms10_061.state = vulns.STATE.VULN -- identified by diffing patched an unpatched version
+ end
+ -- call abort_printer to stop the actual printing in case the remote system is not vulnerable
+ -- we care about the environment and don't want to spend more paper then needed :)
+ status,result = msrpc.spoolss_abort_printer(smbstate,printer_handle)
+
+ return report:make_output(ms10_061)
+end