首页 > 安全资讯 >

Angular JS模板注入漏洞分析

16-05-28

周末挖掘漏洞的过程中,发现了一个有意思的XSS,是运用了Angular JS的模板进行注入,从而执行了恶意代码,思路和技术比较新颖。Angular JS是一款比较流行的前端MVC框架,很多前沿的网站都在用。

周末挖掘漏洞的过程中,发现了一个有意思的XSS,是运用了Angular JS的模板进行注入,从而执行了恶意代码,思路和技术比较新颖。Angular JS是一款比较流行的前端MVC框架,很多前沿的网站都在用。
一般,对于XSS都会进行一定的过滤,比如下面的代码:
html ng-app>
head>
src="./js/angular-1.4.6.js">
/head>
body>
p>
$q = $_GET['q'];
echo htmlspecialchars($q, ENT_QUOTES);?>
/p>  
/body>
/html>
但是对于模板注入,这种过滤是不起作用的。
本文先对模板注入的原理分析,最后给出自动化的扫描规则。另外,需要注意的是,0x02和0x03小节都是基于1.4.6版本进行说明的。
0x01正常语句解析
观察模板表达式{{1 1}}的解析过程:
在angular JS 1.4.6版本的13275行下断点,其中fn为表达式解析后的JS函数对象,fnString为解析后的代码,如{{1 1}}解析为JS代码后为:
"use strict"; 
var fn = function(s, l, a, i) { 
   return plus(1, 1); 
}; 
return fn;
可以看到fn是个函数对象,利用plus方法获取1 1的结果并返回,提交模板{{1 1}},angular内部就执行这个fn函数对象。
0x02利用constructor尝试绕过
提交{{constructor.constructor(“alert(1)”)()}}
ensureSafeObject函数,参数两个,一个是scope一个是模板的表达式,这里是{{constructor.constructor(“alert(1)”)()}}.
构造函数对象的代码:

将模板表达式转为函数对象,使用fn变量进行保存。可以看到new Function的时候指定了很多参数,其中ensureSafeMemberName,ensureSafeObject, ensureSafeFunction是安全检查函数,即安全沙箱,规定了模板语言中无法执行的区域,一旦发现有违规代码则抛出异常禁止执行。
这些函数一个一个过。
首先是ensureSafeObject函数,代码中检测obj参数:

有以下限制:
(1)    不允许使用Function对象
(2)    不允许使用window对象
(3)    不允许使用dom对象
(4)    不允许使用Object对象

注意,这里不仅检查obj参数,而且还检查obj的construct对象。
另一个检查函数ensureSafeFunction:

对obj对象的constructor进行检查,确保其不是Function对象,并且call,apply,bind等方法的调用也是不允许的。
0x03成功的payload原理分析
1.4版本成功执行的payload:
{{\’a\’.constructor.prototype.charAt = [].join;$eval(\’x=1} }};alert(1)//\’);}}

0x04 1.5.5版本中的状况
1.5.5版本中多了两个净化函数(14432行):

主要看看ensureSafeAssignContext函数:

这里限制了对构造函数进行赋值,也就是之前在1.4版本可以使用的:
{{\’a\’.constructor.prototype.charAt=[].join;$eval(\’x=1} }};alert(1)//\’);}}
在这里过不了这个if条件,结果抛出异常:

显示不允许给构造函数进行赋值。
基本能公开的内容就这些了~

周末挖掘漏洞的过程中,发现了一个有意思的XSS,是运用了Angular JS的模板进行注入,从而执行了恶意代码,思路和技术比较新颖。Angular JS是一款比较流行的前端MVC框架,很多前沿的网站都在用。
一般,对于XSS都会进行一定的过滤,比如下面的代码:
Default
1
2
3
4
5
6
7
8
9
10
11
12
html ng-app>
head>
src="./js/angular-1.4.6.js">
/head>
body>
p>
$q = $_GET['q'];
echo htmlspecialchars($q, ENT_QUOTES);?>

/p>  
/body>
/html>
但是对于模板注入,这种过滤是不起作用的。
本文先对模板注入的原理分析,最后给出自动化的扫描规则。另外,需要注意的是,0x02和0x03小节都是基于1.4.6版本进行说明的。
0x01正常语句解析
观察模板表达式{{1 1}}的解析过程:
在angular JS 1.4.6版本的13275行下断点,其中fn为表达式解析后的JS函数对象,fnString为解析后的代码,如{{1 1}}解析为JS代码后为:
"use strict"; 
var fn = function(s, l, a, i) { 
   return plus(1, 1); 
}; 
return fn;
可以看到fn是个函数对象,利用plus方法获取1 1的结果并返回,提交模板{{1 1}},angular内部就执行这个fn函数对象。
0x02利用constructor尝试绕过
提交{{constructor.constructor(“alert(1)”)()}}
ensureSafeObject函数,参数两个,一个是scope一个是模板的表达式,这里是{{constructor.constructor(“alert(1)”)()}}.
构造函数对象的代码:

将模板表达式转为函数对象,使用fn变量进行保存。可以看到new Function的时候指定了很多参数,其中ensureSafeMemberName,ensureSafeObject, ensureSafeFunction是安全检查函数,即安全沙箱,规定了模板语言中无法执行的区域,一旦发现有违规代码则抛出异常禁止执行。
这些函数一个一个过。
首先是ensureSafeObject函数,代码中检测obj参数:

有以下限制:
(1)    不允许使用Function对象
(2)    不允许使用window对象
(3)    不允许使用dom对象
(4)    不允许使用Object对象

注意,这里不仅检查obj参数,而且还检查obj的construct对象。
另一个检查函数ensureSafeFunction:

对obj对象的constructor进行检查,确保其不是Function对象,并且call,apply,bind等方法的调用也是不允许的。
0x03成功的payload原理分析
1.4版本成功执行的payload:
{{\’a\’.constructor.prototype.charAt = [].join;$eval(\’x=1} }};alert(1)//\’);}}

0x04 1.5.5版本中的状况
1.5.5版本中多了两个净化函数(14432行):

主要看看ensureSafeAssignContext函数:

这里限制了对构造函数进行赋值,也就是之前在1.4版本可以使用的:
{{\’a\’.constructor.prototype.charAt=[].join;$eval(\’x=1} }};alert(1)//\’);}}
在这里过不了这个if条件,结果抛出异常:

显示不允许给构造函数进行赋值。
基本能公开的内容就这些了~
 

 

 

相关文章
最新文章
热点推荐