整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

CSS注入实例

CSS注入实例

习CSS注入的目的是学习计算机知识,千万不要做违反法律的事情,不然等待你的是法律的严惩。

CSS仅仅只是一种用来表示样式的语言吗?当然不是!CSS就已被安全研究人员运用于渗透测试当中。使用属性选择器和iFrame,并通过CSS注入来窃取敏感数据的方法。但由于该方法需要iFrame,而大多数主流站点都不允许该操作,因此这种攻击方法并不实用。这里为大家详细介绍一种不需要iframe且只需10秒,就能为获得CSRF token的方法。

一、背景

CSS属性选择器开发者可以根据属性标签的值匹配子字符串来选择元素。 这些属性值选择器可以做以下操作:

  • 如果字符串以子字符串开头,则匹配
  • 如果字符串以子字符串结尾,则匹配
  • 如果字符串在任何地方包含子字符串,则匹配

属性选择器能让开发人员查询单个属性的页面HTML标记,并且匹配它们的值。一个实际的用例是将以“https://example.com”开头的所有href属性变为某种特定的颜色。而在实际环境中,一些敏感信息会被存放在HTML标签内。在大多数情况下CSRF token都是以这种方式被存储的:即隐藏表单的属性值中。

可以将CSS选择器与表单中的属性进行匹配,并根据表单是否与起始字符串匹配,加载一个外部资源,例如背景图片,来尝试猜测属性的起始字母。通过这种方式,攻击者可以进行逐字猜解并最终获取到完整的敏感数值。想要解决这个问题受害者可以在其服务器实施内容安全策略(CSP),防止攻击者从外部加载CSS代码。

二、无 iFrames

要做到无iFrame,使用一种方法:创建一个弹窗,然后在设置计时器后更改弹出窗口的位置。使用这种方仍然可以加载受害者的CSS,不再依赖于受害者是否允许iFrame。因为最初的弹出是通过用户事件触发的,没有被浏览器阻止。为了强制重载,在CSS注入间弹出一个虚拟窗口,如下:

但由于CSRF是针对客户端的攻击,因此如果能想出一种不需要服务器的方法,那么就可以节省大量的开销和简化操作。为了接收客户端加载资源,可以利用Service Workers来拦截和读取请求数据。Service Workers目前只适用于同源请求,在演示中受害者和攻击者页面已处于同一源上。

不久后,chrome很可能会合并这个实验性的功能,允许Service Workers拦截跨域请求。这样,就可以确保在客户端的攻击100%的执行,并强制用户在10秒内点击链接执行CSRF攻击,演示如下:

三、Demo

如上所述,因为不想运行一个web服务器,所以使用service workers拦截和模拟服务器端组件。目前,该演示只适用于Chrome浏览器。首先创建了一个易受攻击的目标,它存在一个基于DOM的CSS注入漏洞,并在页面放置了一个敏感token。再对脚本标签添加了一些保护措施,对左尖括号和右尖括号进行了编码。

接下来将强制加载受害者的CSS,并且使用上述方法,可一次窃取(猜解)一个敏感字符。在接收端,定义一个拦截请求的service worker,并通过post-message将它们发送回域,然后将token存储在本地存储中以供后续使用。你也可以想象一个后端Web服务器,通过Web套接字或轮询将CSRF token回发给攻击者域。

如果你的浏览器支持的话,只需点击打开页面任意位置,你将看到CSRF token将逐一被猜解出来。

四、结束语

反射型CSS注入实际上比存储型CSS注入更致命,因为存储型CSS注入需要一个服务器在受害者渲染之前来更新CSS。一段时间以来,CSS注入在严重程度上来回变化。过去IE浏览器是允许用户在CSS中执行Javascript代码的。这个演示也从某种程度上表明了CSS注入,以及渲染不受信任的CSS仍会导致严重的安全问题。所以在设计软件一定要测试,才能及时发现和修复各种漏洞。

让我们看看如下这个web应用示例:

<html>
 <meta http?equiv="Content?Security?Policy"
 content="script?src 'nonce?...' 'unsafe?eval'">
 <div id="template_target"></div>
 <script type="application/template" id="template">
 Hello World! 1 + 1={{ 1 + 1 }}
 </script>
 Your search is <?php echo $_GET['q']; ?>
 <script nonce="...">
 let template=document.getElementById('template');
 template_target.innerHTML=template.innerText.replace(/{{(.?)}}/g,eval)
 </script>
</html>

以上这段简单的HTML代码可能反映了现在渗透测试人员经常碰到的模板化Web应用。某些模板内容存储在Web页面中,然后再转换为HTML代码的一部分。上段代码中含有id为template的HTML元素内容先被读取,然后再执行{{}}括号内的内容,最后在某个单独HTML元素中呈现出来。

Hello World! 1 + 1=2
Your search is ........... 

其次,这段代码应用程序会在页面上打印URL中的参数值。这显而易见是一个XSS漏洞,但由于CSP(内容安全策略)的存在,攻击者并不能直接执行javascript。虽然直接运行javascript的路被堵死,但是我们可以找到其他绕过方法。

乍一看,貌似eval函数是一个可以利用的点,我们或许可以直接插入某些特制代码,让eval函数去执行。

为了实现这点,我们必须插入HTML元素中id为template的代码。但在我们插入语句的前面已有id为template的HTML元素,而document.getElementById('template')只会去获取第一个HTML元素,并不是我们所输入的语句。

此刻,我们需要换个角度,看看浏览器是否能出现“意外”,以前就出现过很多浏览器的异常解析所导致的XSS攻击。我把所有能使用的tag都收集起来进行测试,看看是否有惊喜。测试代码如下:

<div id="template">First Tag</div>
 {% for tag in tag_list %}
 <{{tag}} id="template">{{tag}}</{{tag}}>
 {% endfor %}
<script>console.log(document.getElementById('template'));</script>

当程序运行完毕时,我得到一个奇怪的结果:当轮到<html>时,页面结构似乎发生了大变,此时已不再是<div>排在前面。让我们看下当插入<html id="template">时的变化:

此时<html>已排在文档顶部(在我所测试的所有浏览器中都是如此!),现在getElementById('template')将获取<html>中的恶意数据,而不是<div>的内容。

只需简单的?q=<html id="template">{{ alert("xss") }}</html>就可进行攻击

最终,由于浏览器这个“莫名其妙”的特性,我们绕过了CSP成功进行了XSS攻击!

本文由白帽汇整理并翻译,不代表白帽汇任何观点和立场

来源:https://nosec.org/home/detail/2860.html

原文:https://pagedout.institute/download/PagedOut_001_beta1.pdf(该PDF文档的第62页

白帽汇从事信息安全,专注于安全大数据、企业威胁情报。

公司产品:FOFA-网络空间安全搜索引擎、FOEYE-网络空间检索系统、NOSEC-安全讯息平台。

为您提供:网络空间测绘、企业资产收集、企业威胁情报、应急响应服务。

移动应用程序开发中,有一种情况是用户希望将他们的交互式 Web 内容作为原生 Android 或 iOS 应用程序。 为此,开发人员有 2 个选项,他们可以从头开始构建应用程序,这需要额外的时间和资源,或者是将网页作为 web 视图嵌入到原生 android 应用程序中的最简单和更快的选项。 它将减少开发人员开发本机应用程序 UI 并仅使用当前网页中的 UI 的时间。

但是,这种方法存在局限性,例如某些任务或手势只能在移动应用程序中发生,而不能在浏览器中发生,例如语音命令或滑动手势。 为了适应这一点,我们需要在原生应用程序中添加额外的代码,并将这个原生任务连接到我们的 webview 应用程序。 在这种情况下,javascript 注入作为将本机代码(Java 或 Swift)桥接到网页代码(Javascript)的解决方案


Android 中的 Javascript 注入

在这里,我将尝试解释在 Native android 应用程序中加载网页所需完成的基本设置。首先,您需要在活动布局中设置 webview,下面是如何在 Android XML 文件中添加 <Webview> 标记的示例

<WebView
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
/>

之后,我们需要访问互联网才能在我们的应用程序中工作,为此我们应该在 Android 清单文件中添加以下语法

<manifest ... >
    <uses-permission android:name="android.permission.INTERNET" />
    ...
</manifest>

现在,我们可以移动到 MainActivity.java 文件,在这里我们需要在 onCreate() 函数中添加以下语法。因为 onCreate 函数是我们初始化一切的第一个地方,所以下面的语法帮助我们初始化我们的 webview。 setJavaScriptEnabled(true) 语法需要设置为 true,以授予在此使用 javascript 注入的权限。 addJavascriptInterface(this,"android") 语法将有助于创建可用作 Java 和 Javascript 之间的桥梁的 Web 界面。在这里,我们的界面将被称为android。最后一个语法是 loadUrl ,它有助于在 Native 应用程序中加载我们的网页。

WebView webViewMain;
webViewMain=findViewById(R.id.webview);

webViewMain.getSettings().setJavaScriptEnabled(true);
webViewMain.addJavascriptInterface(this, "android");
webViewMain.loadUrl("https://www.example.com");

仍然在 MainActivity.java 文件中,我们需要在 onCreate() 函数之外添加一个类。这个类将存储我们想要在 javascript 中运行的所有函数,我们也可以从 javascript 中获取任何值以传输到 Java 原生应用程序变量。示例之一是 getId 函数,它将 HTML 标签中的 id 传输到本地应用程序中进行识别。

public class WebAppInterface {
    String value="hello"
    
    @JavascriptInterface
    public String runValue() {
       return value;
    }
    @JavascriptInterface
    public int getId(id) {
       return id;
    }
}

要使用上述函数,下面是我们可以在 onCreate() 或其他侦听器函数中添加的语法。您可以识别出我们使用 loadUrl 来注入 javascript,在 loadurl 中我们可以使用每种 javascript 语法来导出网页。同样在 loadurl 中,我们需要添加上面已经创建的函数,并将 android 作为父函数。

webViewMain.loadUrl("javascript:window.onclick=function(e) {\n" +
    "android.getId(e.target.id);}");
webViewMain.loadUrl("javascript:android.getSpeechIndex()");

关注七爪网,获取更多APP/小程序/网站源码资源!