Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[破事日常] -- 千奇百怪欺骗作用域 #6

Open
jschyz opened this issue Mar 22, 2017 · 0 comments
Open

[破事日常] -- 千奇百怪欺骗作用域 #6

jschyz opened this issue Mar 22, 2017 · 0 comments

Comments

@jschyz
Copy link
Owner

jschyz commented Mar 22, 2017

前言

看过 You-Dont-Know-JS 欺骗词法作用域 的人应该或多还记得:

eval setTimeout setInterval Function 这些都可以接受字符串参数,字符串的内容可以被解释为一段动态生成的函数代码。换句话说,在运行时来“修改”词法作用域。

先来一段代码熟悉下:

function foo(str, a) {
  eval( str ); // 欺骗!
  console.log( a, b );
}
var b = 2;
foo( "var b = 3;", 1 ); // 1, 3

这段代码实际上在 foo(…) 内部创建来一个变量 b,并遮蔽了外部(全局)作用域中的同名变量。

今日破事

今天耗子姐在群里丢出一道题,来考验大伙们该如何实现攻击手段。

此题一出,群里炸开锅,纷纷给出答案见解。

(function(){
  'use strict';
  var alert, prompt, confirm, location, window, top, self, 
      parent, document, Function, execScript, 
      setTimeout, setInterval, localStorage, sessionStorage, console;
  // 在这里插入代码,弹出 alert(1)
})()

细心的你会发现,这是严格模式下,重写了一些关键字变量,this 在这时会绑定到 undefined上。

那么this.alert(1)是行不通的。

首先大多会想到如果能直接访问 window.alert,那么正好可以实现,可惜在立即执行匿名函数里重新声明了 window,也就是覆写了 window,访问时也会得到 undefined

方案 1

frames.alert(1)
// 或
var w = open()
w.opener.alert(1)
w.close

这类都是属于借助其他窗口获得alert访问权限:

frames 访问框架集上的引用,通过框架集访问到当前页面上下文

opener 是借用新窗口,通过 opener 访问到当前页面上下文

类同的方式有:top self parent,不过被 var 覆写了。

方案 2

Object.constructor('alert(1)')()

任何Javascript值类型(除 Object.create(null)、null、undefined)的原型链最上级构造器都是 Function,而 Function 执行上下文总是包含全局对象 (global) 作用域链。

类似方式:

new Error.apply.constructor('alert(1)')()
Array.constructor('alert(1)')()
2333..constructor.constructor('alert(1)')()

方案 3

var e = eval
e('alert(1)')

方案 4

(0, eval)('alert(1)')

原理同方案3,只是省了个临时变量,逗号运算符对它对每个操作对象求值(从左至右),然后返回最后一个操作对象的值。括号运算符改变了运行顺序。

方案 5

addEventListener('click', function(){ this.alert(1) })
dispathEvent(new Event('click'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant