03-xss攻防

xss学习可以步骤参考:https://www.cnblogs.com/tangtou/p/17281696.html

xss的构造

利用<>构造html/js关键字

这个之前已经学习过,在搜索框输入JS代码,就可以,还是用cms虚拟机,在本站搜索输入即可

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

javascript伪协议

可以通过url载入资源的标签,不知道a标签可以看 html语言

<a href=javascript:alert(/xss/)>click me!</a>

产生自己的事件

事件是一种重要的编程思想

事件类型 说明
window事件 对window对象触发的事件
form事件 html表单内触发的事件
keyboard事件 键盘事件
mouse事件 鼠标事件
media事件 由多媒体触发的事件

把以下代码放在cms搜索框,会显示图片

 <img src="http://192.168.2.133/html/style/img/smallcat.jpg" width="" height="99" border="0">

image-20230403142225470

那么可以在img中插入onmouseover,就是鼠标悬停,触发xss,只要把鼠标放在上面就可以触发

 <img
 onmouseover = 'alert(/dont touch me!/)'     
 src="http://192.168.2.133/html/style/img/smallcat.jpg" width="" height="99" border="0">

image-20230403142311407

<input type = 'text' onkeydown = 'alert(/xss/)'> 
<input type = 'text' onkeyup = 'alert(/xss/)'>

onkeydown:按下按键触发,比如按下键盘不松手

onkeyup;抬起按键触发,松手键盘

XSS的变形

大小写绕过

已知虚拟机里面的cms搜索框存在XSS反射型漏洞,POC如下

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

尝试站在代码角度,对xss漏洞进行修复,通过发现URL

http://192.168.2.133/cms/search.php?keywords=%3Cscript%3Ealert%28%2Fxss%2F%29%3C%2Fscript%3E&button=%E6%90%9C%E7%B4%A2

发现是把参数提交了search.php这个文件,进去这个文件后,先备份文件,再修改

主要对$_GET['keywords']进行过滤

查找以下代码,$_GET是预定义超全局变量,参考PHP学习相关部分

这就是接收一个keywords参数,然后直接输出

image-20230406114114328

把以上代码进行修改,增加一个$keywords

<?php 
$keywords = @$_GET['keywords']; 
echo $keywords;

增加完之后,输入搜索框内容,看命令还能不能正常工作,搜索框输入后,能正常显示搜索相关就没问题

这时候,对$keywords进行过滤,就是把<script>替换掉,代码如下

<?php 
$keywords = @$_GET['keywords'];   
$keywords = str_replace("<script>","",$keywords);
echo $keywords;
?>
//str_replace是替换,他会搜索$keywords,把里面的<script>替换为空

这时候再去检索,没有xss弹窗,显示正常检索内容

image-20230406131541805

但是浏览器对于html的大小写不敏感,通过查看网页源代码可以发现如下可能自己输入的<script>消失了,可能被替换

image-20230406132101027

所以将<script>进行任意替换大写字母,比如替换为<sCRipt>alert(/xss/)</script>发现又能弹窗,查看源代码如下,js代码被正确执行

image-20230406132307343

所以要通过正则匹配,忽略大小写,preg_replace本身是区分大写小的,要通过//i忽略大小写,然后通过\转义两边的尖尖,如下代码

<?php 
$keywords = @$_GET['keywords'];   
$keywords = preg_replace("/\<script\>/i","",$keywords);
echo $keywords;
?>

双写绕过

双写绕过的意思就是在<script>中间再插入<script>,这样中间的<script>被过滤之后,外面的还能组成一个<script>,如下代码,已久可以实现XSS攻击

 <?php 
$keywords = @$_GET['keywords'];   
$keywords = preg_replace("/\<scr<script>ipt\>/i","",$keywords);
echo $keywords;
?>

那么,不论是大小写绕过,还是双写绕过,可以想办法做字符匹配,只要里面含有script,并且按照这个顺序,就会过滤掉,代码如下

其中.表示匹配任意字符,*表示匹配任意次数

<?php 
$keywords = @$_GET['keywords'];   
$keywords = preg_replace("/\<s(.*)c(.*)r(.*)i(.*)p(.*)t\>/i","",$keywords);
echo $keywords;
?>

为了避免误拦截,可以尝试把script倒过来输入<tpircs>,在搜索框输入

<tpircs>alert(/dont /)</script>

结果如下

image-20230407144134370

事件绕过

先尝试用事件绕过,比如用如下代码:

<input type = 'text' onkeydown = 'alert(/xss/)'> 

可以正确弹窗,观察所有的事件都有on,可以处理on,把on替换为on_,用如下代码进行过滤

$keywords = preg_replace("/on/i","on_",$keywords);

检查网页源代码,发现on已经被替换且页面无弹窗

image-20230407150746399

伪协议转码

HTML编码:

字母 ASCII码 十进制编码 十六进制编码
a 97 &#97; &#x61;
c 99 &#99; &#x63;
e 101 &#101; $#x65;

如果采用如下编码,则无法进行过滤:

<a href=javascript:alert(/xss/)>click me!</a> 
//原本代码为这个,对javascript进行十六进制编码

<a
href = '&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:alert(/xss/) '>click me!</a>
//该代码无法被过滤

htmlspecialchars

将特殊字符转换为普通字符

<?php 
    $keywords = @$_GET['keywords'];   
    $keywords = htmlspecialchars($keywords);
		echo $keywords;
?>

最终就是搜索什么,显示什么

image-20230412164529566

这个函数基本可以防御xss漏洞

如果想要完全防御,那可以参考DVWA里面的绝对防御

<?php

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $name = htmlspecialchars( $_GET[ 'name' ] );

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

把xsschallenge放在www目录下面,最终目标就是让网站弹窗

下载地址:链接: https://pan.baidu.com/s/193DDfuoGxfNFjxcpsld02A?pwd=dugn 提取码: dugn

XSS漏洞防御

针对用户的输入进行过滤,以dvwa的command inject绝对防御为例,发现是检查点分十进制

<?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $target = $_REQUEST[ 'ip' ];
    $target = stripslashes( $target );

    // Split the IP into 4 octects
    $octet = explode( ".", $target );

    // Check IF each octet is an integer
    if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
        // If all 4 octets are int's put the IP back together.
        $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];

        // Determine OS and execute the ping command.
        if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
            // Windows
            $cmd = shell_exec( 'ping  ' . $target );
        }
        else {
            // *nix
            $cmd = shell_exec( 'ping  -c 4 ' . $target );
        }

        // Feedback for the end user
        echo "<pre>{$cmd}</pre>";
    }
    else {
        // Ops. Let the user name theres a mistake
        echo '<pre>ERROR: You have entered an invalid IP.</pre>';
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

终极测试代码,只要提交就可以看到哪些被过滤,哪些转码,然后做针对性绕过

<sCr<ScRiPt>IPT>OonN'"\/(hrHRefEF)</sCr</ScRiPt>IPT>

至此跨站脚本攻击学习先告一段落。即将开始学习跨站请求伪造CSRF

posted @ 2023-04-13 15:35  热死也要烫头  阅读(64)  评论(0编辑  收藏  举报