原文链接: All is XSS that comes to the .NET

原作者: Paweł Hałdrzyński

笔者: M09ic@星盟安全团队

portswigger发布的2019年十大web攻击技术中发现了这篇文章,仔细研究了一番,觉得挺有意思,故尝试翻译。

portswigger对这个技术的评论是:

Paweł Hałdrzyński takes a little-known legacy feature of the .NET framework and shows how it can be used to add arbitrary content to URL paths on arbitrary endpoints, causing us some mild panic when we realised even our own website supported it.

Reminiscent of Relative Path Overwrite attacks, this is a piece of arcana that can sometimes kick off an exploit chain. In the post it's used for XSS, but we strongly suspect alternative abuses will emerge in future.

第一次翻译文章,如果建议或者有错误请在评论区指出,我会看到一定会回复或修正的。

(部分语句我按照我自己的理解进行重构,以防止翻译体降低阅读体验,如果有疑问,可以对照原文阅读)

正文

在很多框架中,往项目中简便地添加自己的资源(如.css和.js)是一个重要的特性。手动插入带有一堆../资源属实恶心.如果使用绝对路径,则会在更改文件或目录结构时仍需要再次花费时间修改资源的路径,而且将应用程序部署到子目录或者更改部署位置的时候,也会使绝对路径失效.幸运的是,对于开发人员,在部署ASP.NET时可以通过与应用程序根目录相对的URL来解决上述问题.更幸运的是,对于攻击人员,这将导致了一些新的方法攻击方法。

How does it work?

让我们看一下Control.ResolveUrl方法,该方法可以解析相对于应用程序根目录的路径。

<%@ Page Language="C#" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="<%= ResolveUrl("~/Script.js") %>"></script>
</head>
<body>
    .NET version: <%=Environment.Version%>
</body>
</html>

这段程序会在将~/Script.js这个路径转化为特定路径。如果开发者将Script.js部署在应用的根目录,并在A/B/C/default.aspx文件中用了上面这段代码,当我们访问http://localhost/A/B/C/default.aspx时,会看到

<script src="/Script.js"></script>

这功能看起来很方便,ASP.NET将~(波浪号)解析为应用程序的根目录,即Script.js的确切位置。就算我们把项目移动到其他位置部署,路径也会跟着更改,使得Script.js依旧可以被访问。

这个行为似乎很安全,不是吗?那如果我告诉你可以任意修改Script.js的URL地址呢?

回到以前

让我们回到那个连浏览器都还不支持Cookie头的灰暗年代,没有Cookie管理用户session似乎是一个问题.然而ASP.NET直接在把session保存在URL中来解决这个问题,正如 了解ASP.NETCookie功能如何工作) 中所述:

在ASP.NET的早起版本(V1.0和V1.1)中, 只有Session State使用了Cookieless这个特性。

(...)

在V2.0版本,匿名身份认证和表单认证也使用了这个功能。

随着时间流逝,现在普遍将session存储在Cookie头中.但是,开发人员依旧得处理不支持Cookie的浏览器。ASP.NET 介绍了SessionStateSection.Cookieless property 如何定义和保存session(使用Cookie或在URL中)。

我们不需要深入了解Cookieless session是怎么运作的,我们只需要知道session ID是如何传递以及如何在URI中表示。

根据MSDN):

ASP.NET自动将唯一的session ID插入页面的URL中来维护Cookieless会话状态。例如,ASP.NET中通过以下URL保存唯一的session ID lit3py55t21z5v55vlm25s55:
http://www.example.com/(S(lit3py55t21z5v55vlm25s55))/orderform.aspx

URL还可以有一些其他的Cookieless身份标识符(cookieless identifiers):

  • (A(?)) - Anonymous ID
  • (S(?)) - Session ID
  • (F(?)) - Form Authentication Ticket

对于现代浏览器,SessionStateSection.Cookieless属性的默认值AutoDetect等于将会话ID存储在Cookie头中(而不是将其保存在URL中)。但是,即使强制ASP.NET禁用Cookieless功能(在web.config中将Cookieless参数设置为UseCookies也不会导致带cookieless identifiers的请求报错。

这意义着两种方式访问http://localhost/(A(ABCD))/default.aspx结果是一样的。

而且,在访问http://localhost/default.aspx的时候,ResolveUrl会将这些标识符解析到URL中。

让我们快速浏览一下文档:https://msdn.microsoft.com/en-us/library/system.web.ui.control.resolveurl(v=vs.110).aspx

如果你的应用程序依赖于Cookieless session或者从需要Cookieless session的浏览器接收到请求,在路径中使用波浪号(〜)可能会创建一个新session并可能导致丢失session数据

现在,让我们回到最早的ResolveUrl代码段,它位于A/B/C/default.aspx,如图:

当我们打开*http://localhost/(A(ABCD))/A/B/C/default.aspx(A(ABCD))也被加到Script.js路径中了。

<script src="/(A(ABCD))/Script.js"></script>

A(ABCD)放到不同的位置效果也一样,例如:访问http://localhost/A/B/C/(A(ABCD))/default.aspx

<script src="/(A(ABCD))/Script.js"></script>

正像我刚才说的那样,现在可以看到我们成功控制了Script.js的URI路径。

这个控制可以让我们开始XSS了!例如:

http://localhost/A/B/C/(A(%22onerror=%22alert`1`%22))/default.aspx

这只是一个简单的alert,(译者注:虽然大部分情况用alert就可以证明存在xss了,但并不一定能执行任意js代码).因为地方并不是允许所有字符的,所以真正的欢乐时光就要开始了。

Fuzz一下,从0x00-0xF7,找出处哪些字符无法使用。

从0x00到0x1F直接都会导致服务器返回400,这些是不可打印的ASCII字符,因此我们忽略它们.进一步测试,其他禁止使用的字符(返回400或404)是:

| % | 0x25 |
| ---- | ---- |

点击收藏 | 3 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖