Weak Session IDs
弱会话id 攻击者通过爆破简单的会话id从而获取正常用户的会话,进行各种操作,所以被攻击者猜解出来,等于饭卡被拿去乱刷。
sessionid sessionid是一个会话的key,浏览器第一次访问服务器会在服务器端生成一个session,有一个sessionid和它对应。服务端在创建了Session的同时,会为该Session生成唯一的sessionId,而sessionId会在随后的请求中会被用来重新获得已经创建的Session;Session被创建之后,就可以调用Session相关的方法往Session中增加内容了,而这些内容只会保存在服务器中,发到客户端的只有sessionId;当客户端再次发送请求的时候,会将这个sessionId带上,服务器接受到请求之后就会依据sessionId找到相应的Session,从而再次使用之。
sessionid存储位置 在HTTP请求的cookie报头中(request header),或在HTTP请求中的其它报头中,或者在HTTP请求的主体中
low级别
源码
$html = "";
if ($_SERVER['REQUEST_METHOD'] == "POST") {
if (!isset ($_SESSION['last_session_id'])) {
$_SESSION['last_session_id'] = 0;
}
$_SESSION['last_session_id']++;
$cookie_value = $_SESSION['last_session_id'];
setcookie("dvwaSession", $cookie_value);
}
按一下按钮sessionid+1,并且设置到cookie中
medium级别
源码
$html = "";
if ($_SERVER['REQUEST_METHOD'] == "POST") {
$cookie_value = time();
setcookie("dvwaSession", $cookie_value);
}
使用时间戳设置sessionid的值 时间戳是将当前时间转换成一串数字,这串数字也是有规律的 时间戳转换器
high级别
if ($_SERVER['REQUEST_METHOD'] == "POST") {
if (!isset ($_SESSION['last_session_id_high'])) {
$_SESSION['last_session_id_high'] = 0;
}
$_SESSION['last_session_id_high']++;
$cookie_value = md5($_SESSION['last_session_id_high']);
setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], false, false);
}
sessionid每次递增之后转换成md5,另外还设置了sessionid有效期,应该是1个小时
impossible级别
if ($_SERVER['REQUEST_METHOD'] == "POST") {
$cookie_value = sha1(mt_rand() . time() . "Impossible");
setcookie("dvwaSession", $cookie_value, time()+3600, "/vulnerabilities/weak_id/", $_SERVER['HTTP_HOST'], true, true);
}
sessionid设置为一个随机数+时间戳+impossible进行sha1加密后的值
XSS(DOM)
DOM型XSS攻击,不存在服务器端代码,所以没有与服务器端进行交互,只是在操作DO(文件对象),也就是HTML元素,攻击者可以构造js代码,闭合元素标签执行恶意的js代码
xss常用语句
- <script>alert(/xss/)</script>
- <svg οnlοad=alert(document.cookie)>
- <img src=1 οnerrοr=alert(1)>
- <a href=javascript:alert(1)>
low级别
随便选一个提交,看到提交的参数在option里显示 构造js代码 成功弹窗 查看源码,确实被插入到option标签中
medium级别
源码
if (stripos ($default, "<script") !== false) {
header ("location: ?default=English");
exit;
}
新增条件,过滤<script>标签 那我们可以使用img标签执行js代码,但是前提要把option和select标签闭合,这两个标签可以内嵌script标签,但不可内嵌img标签,详情自己查资料把 输入</option></select><img src=1 οnerrοr=alert(document.cookie)> 查看源码,可以看到img标签独立出来了
high级别
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
switch ($_GET['default']) {
case "French":
case "English":
case "German":
case "Spanish":
break;
default:
header ("location: ?default=English");
exit;
}
}
新增条件只能填写上述四种语言,否则跳转到英语 这里可以使用#位置标识符 #及后面的内容,不算入前面参数的值 浏览器读取这个URL后,会自动将#后指定的内容位置滚动至可视区域。 改变#不会触发网页重载,需要自己刷新页面进行重载 这里输入English#<script>alert(/xss/)</script>
impossible级别
源码
$decodeURI = "decodeURI";
if ($vulnerabilityFile == 'impossible.php') {
$decodeURI = "";
}
新增条件服务器不进行url的解码 我们的浏览器在请求页面的时候都会自动进行一次url的编码,但是服务器不解码,得到的内容都是url编码。 这意味着,我们提交的数据都是url编码,没有实际意义
XSS(Reflected)
反射型 xss 又称,非永久性 XSS 。它一般出现在服务器没有经过正确编码而直接使用客户端提供的数据的情况下出现。
low级别
header ("X-XSS-Protection: 0");
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
输入 <svg οnlοad=alert(document.cookie)> 查看源码,发现它是以源码的形式展现在页面中
medium级别
$name = str_replace( '<script>', '', $_GET[ 'name' ] );
将<script>标签替换为空字符 则使用<svg οnlοad=alert(document.cookie)>
high级别
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );
这里是绕过script标签的双写或大小写,换个标签搞定 输入<img src=1 οnerrοr=alert(1)>
impossible级别
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
$name = htmlspecialchars( $_GET[ 'name' ] );
新增token,和实体化特殊字符,就是说<>失去了作用,只是一个字符
XSS(Stored)
存储型xss,会把js插入在数据库中,所以具有持久性
low级别
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
$message = stripslashes( $message );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? 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)) ? "" : ""));
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
给message去掉反斜杠,分别给name、message的部分特殊字符进行转义,反正也不转义尖括号,在name和message加入js代码都可以
medium级别
$message = strip_tags( addslashes( $message ) );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? 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)) ? "" : ""));
$message = htmlspecialchars( $message );
$name = str_replace( '<script>', '', $name );
strip_tags(string,allow)剥去字符串中的 HTML 标签 新增条件message被剥标签,name将script标签替代,所以只能利用name 因为还限制了name的输入长度,所以给它修改为100
high级别
$message = strip_tags( addslashes( $message ) );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? 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)) ? "" : ""));
$message = htmlspecialchars( $message );
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
name过滤依旧不严
impossible级别
name和message都被实体化,GG
CSP Bypass
内容安全策略绕过 HTTP Content-Security-Policy(CSP)即内容安全策略,script-src指令指定 JavaScript 的有效来源。这不仅包括直接加载到<script>元素中的URL ,还包括可以触发脚本执行的内联脚本事件处理程序 ( onclick) 和XSLT 样式表。
<script src作用 有时,我们需要在网站的多个页面中运行 JavaScript。不需要重复编写相同的脚本,只需在单独的文件中创建 JavaScript,并以 .js 为后缀保存,然后使用 <script> 标签中的 src 属性引用该文件即可 js属于脚本文件,是由脚本代码组成的。其实把正常的标记之间的代码剪切到新文件中就是一个js文件了,然后把文件名放到script的src属性就行了。
low级别
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com hastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;";
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
<script src='" . $_POST['include'] . "'></script>
";
}
访问CSP允许访问的页面https://pastebin.com 这个网页可以生成js文件然后映射到一个url上
把这个网址放在dvwa包含,成功显示内容
medium级别
源码
$headerCSP = "Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';";
header($headerCSP);
header ("X-XSS-Protection: 0");
官方资料显示 ‘unsafe-inline’ 允许使用内联资源,例如内联<script>元素、javascript:URL 和内联事件处理程序。单引号是必需的。 内联式是指将js的代码直接写到html文件里面 ‘nonce-<base64-value>’ 使用加密随机数(使用一次的数字)的特定内联脚本的允许列表。服务器每次传输策略时都必须生成唯一的随机数值。提供不可猜测的随机数至关重要,否则绕过资源的策略是微不足道的。指定 nonce 会使现代浏览器忽略unsafe-inline它仍然可以为没有 nonce 支持的旧浏览器设置。
所以直接使用代码注释的内容输入即可 <script nonce=“TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=”>alert(1)</script>
high级别
$headerCSP = "Content-Security-Policy: script-src 'self';";
.....
<script src="source/high.js"></script>
可看出调用了外部脚本high.js,再结合页面的这句话,可看出要我们更改代码 找到它的high.js脚本看到点击按钮调用函数,然后在函数中新增一行代码alert(document.cookie); 保存之后,再次点击按钮
其实在修改high.js文件的时候,弹出了一个warning
该网站从一个网络请求了一个子资源,该网络由于其用户的特权网络位置而只能访问该子资源。这些请求将非公共设备和服务器暴露在internet上,增加了跨站点请求伪造(CSRF)攻击和/或信息泄漏的风险。为了降低这些风险,当从非安全上下文启动时,Chrome不推荐对非公共子资源的请求
所以这里也学到了一个防御手段,不让子资源被访问
impossible级别
与高级不同,它执行 JSONP 调用但不使用回调,而是硬编码要调用的函数。 CSP 设置只允许本地服务器上的外部 JavaScript,不允许内联代码。 但是使用high方法一样可以执行我们想要的js代码
JavaScript
js代码漏洞
low级别
查看源码,注意是index的源码不是low源码!low源码这么乱谁看得懂啊 str_rot13() 函数对字符串执行 ROT13 编码。 ROT13 编码把每一个字母在字母表中向前移动 13 个字母。数字和非字母字符保持不变。 可以看到只要token等于md5加密success全体移动13个字母后的字母,就能通过。 首先查看字母表,将success每个字母往前移13个字母,自己可以数 我这里直接写了个脚本
str = 'success'
changed_str = ''
lis = list(range(65,91))+list(range(97,123))
for s in str:
str_asc = ord(s)
str_changed_asc = str_asc + 13
if str_changed_asc not in lis:
str_changed_asc -= 26
str_changed = chr(str_changed_asc)
changed_str += str_changed
else:
str_changed = chr(str_changed_asc)
changed_str += str_changed
print(changed_str)
运行结果fhpprff 使用在线md工具进行加密,得到结果38581812b435834ebf84ebcc2c6424d6 使用bp修改token的值
成功
medium级别
strrev()反转字符串,将success反转输入到token中即可
high级别
将"XX" . strrev(“success”)) 进行sha256hash 将ZZ加到hash值后面再进行一次hash 拿着最终结果填入token
impossible级别
|