网络安全学习渗透测试篇01-DVWA靶场环境搭建教程
Posted 才不是萌新呢
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络安全学习渗透测试篇01-DVWA靶场环境搭建教程相关的知识,希望对你有一定的参考价值。
渗透测试:通过经授权的模拟攻击,发现存在的漏洞,并以此对网络、主机、应用及数据的安全性进行评估。
靶场作用:在合法的环境下进行网络安全学习与演练
目录
为什么写这篇文章?
网上不乏有许多类似的教程,但经过笔者检验后发现,多数的文章内容相近且不详细。使笔者在进行环境搭建的过程中着实走了不少弯路。就连DVWA的下载链接也早已不可用,因此为帮助学习者节省时间,笔者重新归纳了整套流程并将其发布于此。
介绍及注意事项
DVWA(Damn Vulnerable Web Application)是一款php/mysql的网络应用程序,其设计目的主要是为了帮助安全专家们在合法的环境下测试他们的技能和工具,或是帮助学生和开发者们更好地理解和学习网络应用程序的安全知识,比如Web渗透。由于是开源的系统,因此在练习渗透技术的同时可阅读源代码,并以此学习常见漏洞的安全防护编码。
和它的名字一样,应用本身有很多糟糕的漏洞,因此,来自DVWA开发者的建议是使用虚拟机并在NAT网络模式下使用。笔者个人的建议是在配置完成后在断网或飞行模式下进入。
这篇文章主要是有关Windows系统下的搭建教程,Linux环境的话可浏览底下给出的官方原始链接进行具体研究。
环境搭建
1. 搭建对应的Web服务器
由于DVWA是通过PHP与MySQL开发的,因此首先要在系统中搭建一个支持PHP的Web服务器。对此,DVWA的开发者并没有要求。网上许多文章里推荐使用的是phpStudy,总体来说还是挺方便的,因此笔者这篇教程里也采用同样的软件。
首先是下载,通过官网下载对应安装包。
地址是:官网链接(https://www.xp.cn)
请根据自己的Windows系统下载对应版本的软件安装包。Linux系统下的安装可根据官网的说明来,对此不做赘述。
使用流程:
1) 安装完成后打开软件,在首页的一键启动里找到“WNMP”,点击启动。
2) 打开浏览器,键入"localhost"或"127.0.0.1",随后回车。此时网页上会出现"站点创建成功"的文字提示。
3) 再次切换到phpStudy,在首页的"套件"中将"Apache"与"MySQL"两个服务启动。
2. DVWA靶机环境搭建
网上的大部分链接已不可用。这里建议使用DVWA的开发链接进行下载,地址是:开发者链接(digininja的github)。
在README.md里找到DOWNLOAD栏,点击"Download a ZIP of the files"进行下载。
也可git下载:git clone https://github.com/digininja/DVWA.git
之后执行以下步骤:
1) 将下载好的压缩文件解压到phpStudy的目录内,具体地址是:(安装地址)/phpstudy_pro/WWW
2) 对解压后文件夹进行重命名,名称更改为"DVWA"。
3) 打开DVWA内的config文件夹,备份一次config.inc.php.dist文件,随后将原始文件重命名为"config.inc.php",也就是删除".dist"后缀。
4) 用记事本打开config.inc.php文件,找到具体信息并更改为如下:
$_DVWA = array();
$_DVWA[ 'db_server' ] = '127.0.0.1';
$_DVWA[ 'db_database' ] = 'dvwa';
$_DVWA[ 'db_user' ] = 'root';
$_DVWA[ 'db_password' ] = 'root';
$_DVWA[ 'db_port'] = '3306';
5) 浏览器键入"localhost/DVWA"回车,最底下找到并点击"Create/Reset Database"按钮
6) 在登录界面键入用户名"admin"与密码"password",点击"login"。登录界面地址是:http://localhost/DVWA/login.php或http://127.0.0.1/DVWA/login.php
7) 登录成功后可访问靶机
那么接下来就可以开始进行渗透测试啦!
敬请期待下一篇:【网络安全学习】渗透测试篇02-数据截取教程(上)
PHP代码审计入门-DVWA靶场暴力破解篇
0x00 写在前面
从零学习php,最终目的实现代码审计入门,软件采用sublime text,环境使用phpstudy搭建,数据库是navicat,需要有基本的前端基础、简单的php+mysql后端基础、渗透知识和漏洞原理,文章跟随流沙前辈学习记录,看看曾经遥不可及的代码审计能不能慢慢啃下来。
本章为代码审计入门第五篇-DVWA靶场篇,对DVWA靶场漏洞进行代码审计。
0x01 暴力破解
暴力破解模块,注释写在代码里,尽量用详细的语言描述代码含义。
level-low
存在万能密码,可绕过用户名
low.php
<?php
if( isset( $_GET[ 'Login' ] ) ) //isset函数检测变量非空且设置
// Get username
$user = $_GET[ 'username' ]; //GET方式接收用户名
// Get password
$pass = $_GET[ 'password' ]; //GET方式接收密码
$pass = md5( $pass ); //接收到的密码进行md5加密
// Check the database
$query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
//直接交互数据库,用户名存在万能密码
/*var_dump($query); //这里可以添加var_dump输出代码进行调式
exit();*/
$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>' );
//直接将SQL语句的执行结果显示给客户端
if( $result && mysqli_num_rows( $result ) == 1 )
//mysqli_num_rows()接受一个结果对象作为参数,检索返回给定结果的行数。实践见下图
// Get users details
$row = mysqli_fetch_assoc( $result );
//取一行比对
$avatar = $row["avatar"];
// Login successful
$html .= "<p>Welcome to the password protected area $user</p>";
$html .= "<img src=\\"$avatar\\" />";
//成功输出xxx调用图片
else
// Login failed
$html .= "<pre><br />Username and/or password incorrect.</pre>";
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
?>
//为什么可以爆破,因为没用作任何限制
数据库users表单是五行数据,使用mysqli_num_rows()返回总共的行数
初级基本就这么多了
level-medium
这里相较于low,最大的区别点在于使用mysqli_real_escape_string()函数进行转义以防止恶意注入,所以万能密码登陆用不了了。
但有可能存在宽字节绕过,这与本身使用的php版本有关,可参考之前文章的第三十六关:
SQLI-labs靶场Less1-37详细学习记录(7400字总结)_身高两米不到的博客-CSDN博客
level-high
high和之前相比最大的区别点在于token认证
high.php
<?php
if( isset( $_GET[ 'Login' ] ) )
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
//调用checkToken
// Sanitise username input
$user = $_GET[ 'username' ];
$user = stripslashes( $user ); //删除反斜杠,防注入的
$user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Sanitise password input
$pass = $_GET[ 'password' ];
$pass = stripslashes( $pass );
$pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$pass = md5( $pass );
// Check database
$query = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
$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>' );
if( $result && mysqli_num_rows( $result ) == 1 )
// Get users details
$row = mysqli_fetch_assoc( $result );
$avatar = $row["avatar"];
// Login successful
$html .= "<p>Welcome to the password protected area $user</p>";
$html .= "<img src=\\"$avatar\\" />";
else
// Login failed
sleep( rand( 0, 3 ) );
//随机slep0-3秒
$html .= "<pre><br />Username and/or password incorrect.</pre>";
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
// Generate Anti-CSRF token
generateSessionToken();
?>
跟进到checkToken方法,设置三个参数,如果user_token不等于session_token或者session_token为空,调用dvwaRedirect方法。
跟进到dvwaRedirect,发现起到跳转作用
F12可以查看随机生成的token,token爆破绕过可以参考之前文章
level-impossiable
既然是impossibale,那以咱水平肯定绕不过去,直接看代码,代码对防注入方面使用了PDO预处理,对于爆破而言最狗的是设置次数。实际目标站点渗透可以死猜个用户名,然后弱密码隔断时间试试,至于hw还是早点溜了。
impossiable.php
<?php
if( isset( $_POST[ 'Login' ] ) && isset ($_POST['username']) && isset ($_POST['password']) )
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Sanitise username input
$user = $_POST[ 'username' ]; //改成POST提交账号密码
$user = stripslashes( $user );
$user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Sanitise password input
$pass = $_POST[ 'password' ];
$pass = stripslashes( $pass );
$pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$pass = md5( $pass );
//前面还是token,以及防注入的函数使用
// Default values
$total_failed_login = 3; //登陆次数失败三次
$lockout_time = 15; //等十五分钟
$account_locked = false; //判断用户是否锁定
// Check the database (Check user information)
$data = $db->prepare( 'SELECT failed_login, last_login FROM users WHERE user = (:user) LIMIT 1;' );
$data->bindParam( ':user', $user, PDO::PARAM_STR );
//使用PDO
$data->execute();
$row = $data->fetch();
// Check to see if the user has been locked out.
if( ( $data->rowCount() == 1 ) && ( $row[ 'failed_login' ] >= $total_failed_login ) )
// User locked out. Note, using this method would allow for user enumeration!
//$html .= "<pre><br />This account has been locked due to too many incorrect logins.</pre>";
// Calculate when the user would be allowed to login again
$last_login = strtotime( $row[ 'last_login' ] );
$timeout = $last_login + ($lockout_time * 60);
$timenow = time();
/*
print "The last login was: " . date ("h:i:s", $last_login) . "<br />";
print "The timenow is: " . date ("h:i:s", $timenow) . "<br />";
print "The timeout is: " . date ("h:i:s", $timeout) . "<br />";
*/
// Check to see if enough time has passed, if it hasn't locked the account
if( $timenow < $timeout )
$account_locked = true;
// print "The account is locked<br />";
// Check the database (if username matches the password)
$data = $db->prepare( 'SELECT * FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
$data->bindParam( ':user', $user, PDO::PARAM_STR);
$data->bindParam( ':password', $pass, PDO::PARAM_STR );
$data->execute();
$row = $data->fetch();
// If its a valid login...
if( ( $data->rowCount() == 1 ) && ( $account_locked == false ) )
// Get users details
$avatar = $row[ 'avatar' ];
$failed_login = $row[ 'failed_login' ];
$last_login = $row[ 'last_login' ];
// Login successful
$html .= "<p>Welcome to the password protected area <em>$user</em></p>";
$html .= "<img src=\\"$avatar\\" />";
// Had the account been locked out since last login?
if( $failed_login >= $total_failed_login )
$html .= "<p><em>Warning</em>: Someone might of been brute forcing your account.</p>";
$html .= "<p>Number of login attempts: <em>$failed_login</em>.<br />Last login attempt was at: <em>$last_login</em>.</p>";
// Reset bad login count
$data = $db->prepare( 'UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;' );
$data->bindParam( ':user', $user, PDO::PARAM_STR );
$data->execute();
else
// Login failed
sleep( rand( 2, 4 ) );
// Give the user some feedback
$html .= "<pre><br />Username and/or password incorrect.<br /><br/>Alternative, the account has been locked because of too many failed logins.<br />If this is the case, <em>please try again in $lockout_time minutes</em>.</pre>";
// Update bad login count
$data = $db->prepare( 'UPDATE users SET failed_login = (failed_login + 1) WHERE user = (:user) LIMIT 1;' );
$data->bindParam( ':user', $user, PDO::PARAM_STR );
$data->execute();
// Set the last login time
$data = $db->prepare( 'UPDATE users SET last_login = now() WHERE user = (:user) LIMIT 1;' );
$data->bindParam( ':user', $user, PDO::PARAM_STR );
$data->execute();
// Generate Anti-CSRF token
generateSessionToken();
?>
关于PDO预编译防注入原理推荐文章:
0x02 总结
工作一年多重回校园,以打工人身份又转变到学生,这段时间开始忙碌,没有办法,作业考试太多。。。
以上是关于网络安全学习渗透测试篇01-DVWA靶场环境搭建教程的主要内容,如果未能解决你的问题,请参考以下文章
VulnHub渗透测试实战靶场 - ACID: SERVER