跳转到帖子

游客您好,欢迎来到黑客世界论坛!您可以在这里进行注册。

赤队小组-代号1949(原CHT攻防小组)在这个瞬息万变的网络时代,我们保持初心,创造最好的社区来共同交流网络技术。您可以在论坛获取黑客攻防技巧与知识,您也可以加入我们的Telegram交流群 共同实时探讨交流。论坛禁止各种广告,请注册用户查看我们的使用与隐私策略,谢谢您的配合。小组成员可以获取论坛隐藏内容!

TheHackerWorld官方

基于Esprima的JS语义分析

精选回复

发布于

### Esprima 是什么\r

Esprima 是一个遵循ECMAScript 的JavaScript 解释器,目前支持最高ES6 的语法解析。 \r

通过Esprima提供的API可以将一段JavaScript代码解析为节点语法树。 \r

\r

#### 源代码\r

```javascript=\r

变量名称='xray'\r

````\r

#### 语法树\r

```JSON\r

[\r

{\r

\'类型\': \'变量声明\',\r

\'声明\': [\r

{\r

\'类型\': \'变量声明符\',\r

\'id\': {\r

\'类型\': \'标识符\',\r

\'名称\': \'名称\'\r

},\r

\'初始化\': {\r

\'类型\': \'文字\',\r

\'值\': \'xray\',\r

\'原始\': \''xray'\'\r

}\r

}\r

],\r

\'kind\': \'var\'\r

}\r

]\r

````\r

\r

### 为什么要对JS进行语义分析\r

之前挖掘过一些DOM-XSS,感觉手动审计js来挖掘漏洞更准确,但效率较低。 \r

我也尝试过使用chrome扩展来做一些hook分析,但是结果并不理想。 \r

\r

总结了一些之前发现的XSS漏洞。大多数漏洞中,漏洞点出现在“赋值表达式”和“危险函数调用”中。 \r

\r

**赋值表达式引起的DOM-XSS**\r

```javascript=\r

//标签\r

document.getElementById('id').innerHTML=代码\r

//属性\r

document.getElementById('id').src=代码\r

//伪协议\r

window.location.href=代码\r

````\r

\r

**由危险函数调用引起的XSS**\r

```javascript=\r

//评估\r

评估(代码)\r

//文档.write\r

文档.write(代码)\r

````\r

上面两类,一看就很明显是代码有问题。 \r

然而,随着前端技术的不断进步,自从引入了webpack技术之后,审计JS就变得不再那么容易了。代码压缩、变量名混淆等都让代码审计很头疼,比如下面的代码\r

\r

#### 源代码\r

```javascript=\r

函数getQueryString(名称) {\r

var reg=new RegExp(\'(^|)\' + name + \'=([^]*)(|$)\', \'i\');\r

var r=window.location.search.substr(1).match(reg);\r

if (r !=null) return unescape(r[2]);\r

返回空值;\r

}\r

\r

var url=getQueryString(\'url\')\r

window.location.href=url\r

````\r

#### 网页包\r

```javascript=\r

!函数(e) {\r

var n={};\r

\r

函数t(r) {\r

if (n[r]) 返回n[r].exports;\r

var o=n[r]={i: r,l:1,exports: {}};\r

返回e[r].call(o.exports, o, o.exports, t), o.l=!0, o.exports\r

}\r

\r

t.m=e,t.c=n,t.d=函数(e, n, r) {\r

至(e, n) || Object.defineProperty(e, n, {enumerable:0, get: r})\r

}, t.r=函数(e) {\r

\'未定义\' !=typeof Symbol Symbol.toStringTag Object.defineProperty(e, Symbol.toStringTag, {value: \'Module\'}), Object.defineProperty(e, \'__esModule\', {value:0})\r

}, t.t=函数(e, n) {\r

if (1 n (e=t(e)), 8 n) 返回e;\r

if (4 n \'object\'==typeof e e e.__esModule) return e;\r

var r=Object.create(null);\r

if (t.r(r), Object.defineProperty(r, \'默认\', {\r

可枚举:0,\r

值: e\r

}), 2 n \'string\' !=typeof e) for (var o in e) t.d(r, o, function (n) {\r

返回e[n]\r

}.bind(null, o));\r

返回r\r

}, t.n=函数(e) {\r

var n=e e.__esModule ?函数() {\r

返回e.default\r

} : 函数() {\r

返回e\r

};\r

返回t.d(n, \'a\', n), n\r

}, t.o=函数(e, n) {\r

返回Object.prototype.hasOwnProperty.call(e, n)\r

}, t.p=\'\', t(t.s=0)\r

}([函数(e, n) {\r

var t, r,\r

o=(t=new RegExp(\'(^|)\' + \'url\' + \'=([^]*)(|$)\', \'i\'), null !=(r=window.location.search.substr(1).match(t)) ? unescape(r[2]) : null);\r

window.location.href=o\r

}]);\r

````\r

一个DOM-XSS demo打包后,不仅对于初学者,对于常年看JS的人来说都是一件非常麻烦的事情。如果加上一些逻辑判断和加密算法,代码审计就变得更加困难。 \r

\r

### 这个解决方案可行吗? \r

\r

如果我们静下心来仔细阅读代码,我们会发现,无论代码多么混乱,都是有源头的。最终触发XSS的核心代码就是这一段:\r

````\r

var t, r,\r

o=(t=new RegExp(\'(^|)\' + \'url\' + \'=([^]*)(|$)\', \'i\'), null !=(r=window.location.search.substr(1).match(t)) ? unescape(r[2]) : null);\r

window.location.href=o\r

````\r

\r

核心是变量`o`的值,可以追溯到`location.search.substr(1).match(t)t`,可以拆分为:\r JS1.png

\r

\r

最终触发点是:\r

`window.location.href=o`\r

\r JS2.png

\r

\r

\r

我们只需要解析语法树,最终确定o来自哪里。由于condition中的条件很难判断(我的偏好),所以暂时不考虑。你只需要知道这个参数来自URL即可。 \r

\r

于是借助MDN Web文档,查询了一些字符串处理的方法:\r

````\r

'split'、'replace'、'concat'、'match'、'matchAll'、'sub'、'substr'、'substring'、'toLocaleLowerCase'、'toLocaleUpperCase'、'tirm'、'toLowerCase'、'toUpperCase'、'toString'、'trimEnd'、'trimStart'、 'valueOf', '原始'\r

````\r

如果字符串的属性是这些方法之一,则说明大多数情况下该字符串仍在可控范围内。 \r

如果字符串的属性是length,那么就不需要继续跟踪后面的表达式了。 \r

\r

那么通过上面这个简单的例子,我们可以确认通过语法树解析DOM-XSS是可行的。 \r

\r

### 该计划的难点和陷阱是什么?\r

\r

该方法当然是可行的,但是我在尝试解析它时遇到了哪些陷阱? \r

\r

- 剧本爽一会,重建火葬场\r

\r

我第一次使用Esprima的时候,直接拉了一段代码进去,尝试解析。解析了一段时间,发现js表达式比我想象的要复杂很多。 \r

\r

分配操作可能需要考虑许多因素。 \r

`var a=b;`\r

\r JS3.png

\r

\r

\r

- 茴香豆的“茴香”一词有多少种写法? \r

\r

js的语法非常灵活,这也使得解析变得非常困难。我们常见的赋值表达式大概包括以下几种\r

````\r

//AssignmentExpression表达式\r

a=父.顶部.窗口\r

b=父.顶部.窗口.位置\r

c=父.顶部.窗口.位置.href\r

d=父.顶部.窗口.文档\r

e=parent.top.window.document.cookie\r

f=父.top.window.document.URL\r

g=窗口.名称\r

h=父.顶部.窗口.名称\r

我=位置\r

j=窗口\r

k=父级\r

l=文档\r

m=文档['cookie']\r

n=top.parent.window.parent['名称']\r

o=top.parent.window['父级']['名称']\r

p='位置'\r

q=窗口[p]\r

````\r

有些对象是可控的,例如window.location.href和window.name,有些对象是部分可控的,例如document.URL和document.cookie,而document.domain则不可控。我们要做的就是区分哪些对象是可控的,哪些是不可控的。 \r

\r

````\r

b - 位置\r

c - 位置.href\r

电子文档.cookie\r

f - 文档.cookie\r

g - 窗口名称\r

h - 窗口名称\r

i-位置\r

m - 文档.cookie\r

n - 窗口名称\r

o - 窗口名称\r

q - 位置\r

````\r

经过分析,我们得到可控值。当表达式左边是单个变量名时,就比较简单。如果表达式的形式如下\r

````\r

a.b.c=d.e.f\r

````\r

需要分割出每个变量的原始值和范围,分析对象是否可控。 \r

\r

希望有兴趣的同学可以一起研究一下JS语法树,让简单的、表层的DOM-XSS更容易挖掘,从而可以有更多的精力和时间去学习更深层次的语法特征。

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。