Dvwa是一个网站渗透测试演练平台,里面包括了Xss攻击,Sql注入攻击,Csrf漏洞、文件上传漏洞、命令注入漏洞等,而且每个漏洞都分为Low(低等级)、Medium( 中等级 )、High( 高等级 )、Impossible( 没漏洞等级 )
下载过程和安装过程网上可以找到我就不讲解了。
首先将Dvwa
等级设置成Low
:
Low
Xss反射型:
当输入hello
在输入框点击Submit后,会输出一个Hello iamfree
,那么我们来看看这是如何实现的
实现的代码:
因为这是Low
级别的,所以我们可以清楚的看见这里没有做任何过滤,我们只需要输入一串而已的Js代码就可以实现盗取别人Cookie,做钓鱼之类的功能,下面我来简单的演示一下~
输入<img src=x onerror=alert('iamfree')>
后,Url变成http://127.0.0.1/dvwa/vulnerabilities/xss_r/?name=%3Cimg+src%3Dx+onerror%3Dalert%28%27iamfree%27%29%3E#
,效果:
<img src=x onerror=alert('iamfree')>
的src表示img图片的地址,可以是本地也可以是Url形式;onerror的意思是如果图片没有正常显示的话就会执行=
后面的代码,因为这里src=x
而x
是不存在的,所以无法显示,就会报错了~
如何防御
这里的话防御很简单的,只需要一个函数即可:
继续访问刚才的Url(http://127.0.0.1/dvwa/vulnerabilities/xss_r/?name=%3Cimg+src%3Dx+onerror%3Dalert%28%27iamfree%27%29%3E#
),看看是否有效:
成功的防止了Xss反射型攻击了~
htmlspecialchars函数的官方解释:
Medium
查看Medium
源代码:
点开后是这样的:
代码:
<?php
header ("X-XSS-Protection: 0");
// 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>";
}
?>
这里的代码部分也很好理解,比上一章仅仅多了一个过滤,下面来详细讲解一下。
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL )
这段代码的意思是,如果$_GET中有name这个key并且$_GET[ 'name' ]
的值不为空的话就执行{}
里面的代码。$name = str_replace( '<script>', '', $_GET[ 'name' ] );
这句话的意思是把$_GET[' name ']
中的<script>
过滤为空( 并不安全 ),最后一段代码就是输出Hello+name的值在页面上
看懂代码后,如何利用呢?
我们在上面看代码的时候明白了,在这个Medium
等级中,只做了把<script>
字符给过滤了,那么我下面就来演示一下如何绕过
先来输入<script>
后看看是否为空:
可以看到这里的输出是为空的,下面来讲绕过
绕过方法1:
在输入框中输入<scr<script>ipt>alert('iamfree')</script>
,来看看结果先:
解释:
绕过方法2:
用大写的绕过,输入<SCRIPT>alert('iamfree')</SCRIPT>
如何防御
防御方法1:
其实防御的方法也和上篇一样,但还有一个也很棒的方法哟。
代码:
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
// $name = str_replace( '<script>', 'xss', $_GET[ 'name' ] );
foreach ( $_GET as $key => $value ) { //把$_GET数组里的值分成$key和$value
$name = $_GET[ $key ] = htmlspecialchars( $value ); //把$_GET数组中$key对应的$value值html实例化,并且赋值给$name变量
}
// Feedback for end user
$html .= "<pre>Hello ${name}</pre>";
}
?>
防御方法2:
只需要加上一条preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] )
,这也是high
的防御方法
htmlspecialchars介绍
htmlspecialchars — 将特殊字符转换为 HTML 实体
执行转换表
字符 | 替换后 |
---|---|
& (和号) | 成为 & |
“ (双引号) | 成为 " |
‘ (单引号) | 成为 ' |
< (小于) | 成为 < |
> (大于) | 成为 > |
未过滤
先看一段代码简单的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo</title>
</head>
<body>
<?php
$name = $_GET['name'];
?>
<h1>你好,<?php echo $name;?></h1>
</body>
</html>
访问http://127.0.0.1/myphp/demo.php?name=1
:
访问http://127.0.0.1/myphp/demo.php?name=<img src=x>
:
可见,这个是存在Xss的,那么我们用htmlspecialchars
函数来过滤~
过滤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo</title>
</head>
<body>
<?php
$name = $_GET['name'];
$name = htmlspecialchars( $name );
?>
<h1>你好,<?php echo $name;?></h1>
</body>
</html>
继续访问http://127.0.0.1/myphp/demo.php?name=<img src=x>
:
看到这里,你们就会好奇了,为什么会直接把输入的内容输出出来,而不是以代码被解析?我们打开审查元素看一看(F12)
我们可以发现这里是把<
变成了<
,把’>’变成了>
,从而导致了代码只会原样输出而不会当成代码来编译
如果你还困惑的,我再给你看一段代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo</title>
</head>
<body>
<h1>你好,<img src=x></h1> <!-- 注意看这里 -->
</body>
</html>
访问http://127.0.0.1/myphp/demo.php
: