Sitemap
Ahmed Rabeaa Mosaa (SadC0d3r)

Ahmed Rabeaa Mosaa (SadC0d3r)

Sr. Cyber Security Engineer | CRTO | CRTE | eCPTXv2 | eWPTXv2 | eCPPTv2 | eMAPT | CAP | Red Teamer Wannabe | 7xCVE | Bug Bounty Hunter

SuiteCRM SQL Injection: Breaking an XSS-Oriented Input Sanitization Layer

6 min readSep 21, 2026
Press enter or click to view image in full size

A Code Review and Vulnerability Research Journey

As part of my security code-review practice, I wanted to analyze a real-world application with a relatively large attack surface, multiple user roles, and a history of publicly disclosed vulnerabilities.

I chose SuiteCRM because it is a mature, open-source CRM platform with a large PHP codebase and multiple modules, controllers, and user-controlled input paths.

During the review, I focused initially on SQL injection and, more specifically, on how SuiteCRM sanitizes user-controlled input before it reaches database queries.

What started as a straightforward review of SQL query construction eventually led me to an interesting input-validation issue involving an XSS-oriented sanitization layer.

SuiteCRM follows an MVC-oriented architecture. For the initial review, I focused on controllers and model/database interactions because these components provide useful entry points for tracing user-controlled input into SQL queries.

At first glance, several SQL query construction points appeared potentially interesting because user-controlled parameters seemed to reach query-building code.

But actually not. I found the application passes any user input firstly into a utils file,

user input → utils → antiXSS → SQL

So this file contains multiple layers of filtration and sanitization, so I found the SQLi preventing using two main functions.At this stage, I did not identify an obvious bypass through the first validation layer, and the second one is interesting for me because in this function, it uses an XSS prevention library called antiXSS (https://github.com/voku/anti-xss).

So how does an XSS prevention library prevent SQLi?

I’m digging into this function because it’s very interesting to me then i found the function it’s seems be secure

From this point i started the test

I first established a baseline by submitting a benign value (sad) and observing how it propagated through the application and into the generated query.

I then introduced a single quote (') as a minimal SQL metacharacter test. The application transformed or rejected the character, indicating that the input was being processed by the sanitization layer before reaching the query construction logic.

Press enter or click to view image in full size

I then introduced a single quote (') as a minimal SQL metacharacter test.

Press enter or click to view image in full size
Press enter or click to view image in full size

The same behavior was observed with other quote characters.

At this point, the initial filtering mechanism appeared to be working as expected.

Get Ahmed Rabeaa Mosaa (SadC0d3r)’s stories in your inbox

Join Medium for free to get updates from this writer.

However, this did not prove that the complete input-handling mechanism was safe.

Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size

I extracted the validation code into sperated file to test it

<?php
define('sugarEntry', true);
if (!defined('sugarEntry') || !sugarEntry) {
die('Not A Valid Entry Point');
}
require_once __DIR__ . '/../php_version.php';
require_once __DIR__ . '/../include/SugarObjects/SugarConfig.php';
require_once __DIR__ . '/../include/utils/security_utils.php';
require_once __DIR__ . '/../vendor/autoload.php';
use voku\helper\AntiXSS;
function securexss($uncleanString)
{
if (is_array($uncleanString)) {
$new = [];
foreach ($uncleanString as $key => $val) {
$new[$key] = securexss($val);
}

return $new;
}

static $xss_cleanup = [
'&quot;' => '&#38;',
'"' => '&quot;',
"'" => '&#039;',
'<' => '&lt;',
'>' => '&gt;',
'`' => '&#96;'
];

$uncleanString = preg_replace(array('/javascript:/i', '/\0/', '/javascript:/i'),
array('java script:', '', 'java script:'), (string) $uncleanString);

$partialString = str_replace(array_keys($xss_cleanup), $xss_cleanup, $uncleanString);

$antiXss = new AntiXSS();
$antiXss->removeEvilAttributes(['style', 'onerror']);

return $antiXss->xss_clean($partialString);
}
echo securexss("sad") . '
';

And i read the library code from github so i noted that

One behavior caught my attention when the input contained the < character.

The input was being processed according to HTML/XSS-oriented sanitization rules. As a result, the < character could be transformed while other parts of the input remained unchanged.

I then tested whether an SQL expression could survive this transformation while incorporating a character sequence that triggered the HTML-oriented processing.

So if i put a regular SQLi payload and tied with “ — < — “ the payload will bypass normally and the “< “ will be encoded only.

Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size

When the SQLi payload contain — < — the antixss lib decod all html encoded then encode < only

Press enter or click to view image in full size

The root cause was not simply insufficient character filtering. The deeper issue was the use of an XSS-oriented sanitization routine as part of an SQL input protection mechanism.

XSS and SQL injection are different classes of vulnerabilities and require context-specific defenses. Transformations that are useful for HTML output cannot be treated as a substitute for parameterized SQL queries or context-aware database escaping.

Press enter or click to view image in full size

By this bypass i greped all functions use this prevention techniques and i got more than 9 SQLi and there are the CVEs and waiting 5 to assign a CVE number

And the funny things this function is secure without using antiXSS library

Press enter or click to view image in full size

Sometimes, adding more security layers does not make an application more secure. When those layers are used outside their intended context, they can create new attack paths instead.

وفي الاخر حابب اقول

سُبْحَانَكَ لَا عِلْمَ لَنَا إِلَّا مَا عَلَّمْتَنَا إِنَّكَ أَنْتَ الْعَلِيمُ الْحَكِيمُ

--

--

Ahmed Rabeaa Mosaa (SadC0d3r)
Ahmed Rabeaa Mosaa (SadC0d3r)

Written by Ahmed Rabeaa Mosaa (SadC0d3r)

Sr. Cyber Security Engineer | CRTO | CRTE | eCPTXv2 | eWPTXv2 | eCPPTv2 | eMAPT | CAP | Red Teamer Wannabe | 7xCVE | Bug Bounty Hunter