DVWA-impossible代码审计

目录

DVWA-impossible代码审计

核心函数解释:

DVWA-xss_s-impossible

DVWA-file_upload-impossible


核心函数解释:

  • strrpos() 函数查找字符串在另一字符串中最后一次出现的位置。此函数是区分大小写的,与strripos()函数相反,strripos()函数不区分大小写

  • sys_get_temp_dir() :返回临时文件路径

  • ini_get(): 获取一个配置选项的值,成功是返回配置选项值的字符串,null 的值则返回空字符串。如果配置选项不存在,将会返回 FALSE

  • uniqid() :基于以微秒计的当前时间,生成一个唯一的 ID

  • getimagesize():是PHP中用于获取图像的大小和格式的函数,底层利用文件头来判断文件类型。它可以返回一个包含图像的宽度、高度、类型和MIME类型的数组。可以从本地获取,也可以从远程获取。如果目标地址是图片,就会返回数组,否则返回FALSE并产生一条 E_WARNING 级的错误信息。

  • imagecreatefromjpeg() 函数用于从 JPEG 文件或 URL 创建一个新图象,将新图像放入内存中,后面需要通过imagedestroy()函数释放内存中的图像资源

  • imagejpeg():

    • 1、imagejpeg()函数是php图像处理中的一个重要函数,用于将图像保存为jpeg格式文件。

    • 2、imagejpeg()函数的语法如下:

    • bool imagejpeg ( resource $image [, string $filename [, int $quality ]] )其中,image是图像资源,filename是保存的文件名,$quality是保存质量,取值范围从0-100,默认为75。

  • imagedestroy():释放内存中的图像资源

  • getcwd():获取当前目录

  • rename():函数用于重命名文件或目录,可以用于移动文件

    • bool rename ( string $source , string $target )

    • 参数:

      • $source:必需,表示源文件或目录的名称。

      • $target:必需,表示目标文件或目录的名称。

    • 返回值:

      • 在成功时返回TRUE,失败时返回FALSE。

  • file_exists():检查文件或目录是否存在

  • unlink():删除文件

DVWA-xss_s-impossible

正式审计开始

  • 判断是否正确提交参数btnSign,如果该参数存在才进行下面的代码

  • $_REQUEST['user_token']:这是从请求(无论是GET、POST还是COOKIE等)中获取名为user_token的值。这个值应该是由客户端(如浏览器)在发起请求时提供的。

  • mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message) 这行代码的作用是对 $message 字符串中的特殊字符进行转义,以防止 SQL 注入攻击,这里的转义操作是基于存储在 $GLOBALS["___mysqli_ston"] 中的 MySQLi 连接对象进行的。

  • 在 PHP 中,htmlspecialchars() 函数是一个非常重要的安全函数,用于将特殊字符转换为 HTML 实体。这意味着它会将诸如 &<>"(双引号)和 '(单引号,如果设置了 ENT_QUOTES 标志)这样的字符转换成它们的 HTML 实体形式,例如 &<>"'

 <?php
 ​
 if( isset( $_POST[ 'btnSign' ] ) ) {
     // Check Anti-CSRF token 利用 token 技术,防止CSRF跨站请求伪造攻击
     // $_REQUEST['user_token']`:这是从请求(无论是GET、POST还是COOKIE等)中获取名为user_token的值。这个值应该是由客户端(如浏览器)在发起请求时提供的。checkToken函数会比较$_REQUEST['user_token']和$_SESSION['session_token']的值。如果这两个值相等,说明用户提交的令牌与服务器会话中存储的令牌相匹配,可能是一个有效的请求。如果不相等,则可能表示请求被篡改或来自不受信任的来源,函数可能会采取相应的安全措施,如拒绝请求、记录日志、重定向到错误页面等。
     checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
 ​
     // Get input
     //去除提交参数mtxMessage和txtName的值中左右两边的空格
     $message = trim( $_POST[ 'mtxMessage' ] );
     $name    = trim( $_POST[ 'txtName' ] );
 ​
     // Sanitize message input
     $message = stripslashes( $message );   // 先删除$message中的反斜杠
     // 检查全局变量 $GLOBALS["___mysqli_ston"] 是否已设置(即存在),并且其值是一个对象。如果成立,则对 $message 字符串中的特殊字符进行转义,以防止 SQL 注入攻击,这里的转义操作是基于存储在 $GLOBALS["___mysqli_ston"] 中的 MySQLi 连接对象进行的。否则就抛出一个用户级别的错误,但我觉得更好的方式建议使用抛异常的方式。
     $message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
     $message = htmlspecialchars( $message );
     // 确保了当你将 $message 变量的内容输出到 HTML 页面时,那些原本可能被浏览器解释为 HTML 或 JavaScript 代码的特殊字符现在只是普通的文本字符,即特殊字符实体转换,防止 XSS 跨站脚本攻击
 ​
     // Sanitize name input
     // 作用和功能和上面是一样的
     $name = stripslashes( $name );  // 去除变量 $name 中的反斜杠
     $name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
     $name = htmlspecialchars( $name );
 ​
     // Update database 这部分防止SQL注入
     // 使用 PDO(PHP Data Objects)扩展来准备并执行一个 SQL 插入语句,该语句将用户提交的评论($message)和名称($name)插入到名为 guestbook 的数据库表中。这是一种非常好的做法,因为它可以防止 SQL 注入攻击,因为 PDO 会自动处理特殊字符的转义。
     $data = $db->prepare( 'INSERT INTO guestbook ( comment, name ) VALUES ( :message, :name );' );
     $data->bindParam( ':message', $message, PDO::PARAM_STR );
     $data->bindParam( ':name', $name, PDO::PARAM_STR );
     $data->execute();
 }
 ​
 // Generate Anti-CSRF token
 generateSessionToken();  // 生成session_token,用于与user_token进行比较
 ​
 ?>

DVWA-file_upload-impossible

  • checkToken():这是一个自定义的函数,其目的是比较传入的两个token是否一致。如果_REQUEST['user_token']与_SESSION['session_token']相匹配,则说明这次请求来自一个合法的、已验证身份的用户;如果不匹配,则可能表示请求无效或已被篡改,此时服务器可能会拒绝该请求,或者重定向至指定的URL,这里是指向 'index.php' 页面。

  • uniqid():生成一个基于当前时间戳(精确到微秒)的唯一标识符。这个标识符通常用于创建临时文件名、会话ID或其他需要唯一性的场景

  • ini_get():函数在PHP中用于获取PHP配置选项当前的值

  • strtolower():用于将一个字符串中的所有字符转换为小写。

  • getimagesize():getimagesize() 函数在PHP中用于获取图像文件的尺寸、类型等信息。getimagesize() 函数也会检查文件是否真的是一个图像文件,如果文件不是图像或无法读取,它将返回 FALSE。因此,在尝试访问 $width$height 变量之前,最好检查 getimagesize() 的返回值是否有效。

 <?php
 ​
 if( isset( $_POST[ 'Upload' ] ) ) {
     // Check Anti-CSRF token
     checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
 ​
     // File information
     // 定义一堆变量名
     $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];  // 上传的文件名
     $uploaded_ext  = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);  // 上传的文件名的后缀
     $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];  // 上传的文件的大小,以字节为单位
     $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];  // 上传的文件的类型
     $uploaded_tmp  = $_FILES[ 'uploaded' ][ 'tmp_name' ];  // 文件被上传后在服务器上存储的临时文件名。
     // $uploaded_tmp 变量包含的是上传文件在服务器上的临时文件名。
 ​
     // Where are we going to be writing to?
     $target_path   = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';  // 要上传的目标的部分目录路径
     //$target_file   = basename( $uploaded_name, '.' . $uploaded_ext ) . '-';
     $target_file   =  md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;  // 修改上传的文件名,这里可以考虑一下使用md5散列值作为文件名的好处
     $temp_file     = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) ); // $temp_file 变量包含的是 PHP 用于存储上传文件的临时目录的路径
     $temp_file    .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
     // DIRECTORY_SEPARATOR 目录分隔符 linux和mac等是 / ,windows是 \
     // 最终构成了完整的临时路径$temp_file,并且其文件名使用的是md5散列值
 ​
     // Is it an image?  其实就是进行了一次二次渲染
     // 将后缀全部转换为小写之后与白名单比较判断,并且上传的文件必须是图片,其大小要小于100000字节,类型必须是image/jpeg或image/png
     if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) &&
         ( $uploaded_size < 100000 ) &&
         ( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) &&
         getimagesize( $uploaded_tmp ) ) {
 ​
         // Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)
         if( $uploaded_type == 'image/jpeg' ) {
             $img = imagecreatefromjpeg( $uploaded_tmp );  // 通过上传的文件,二次渲染出新的图片资源
             imagejpeg( $img, $temp_file, 100);  // 将渲染出来的图片资源保存为jpeg格式的文件
         }
         else {
             $img = imagecreatefrompng( $uploaded_tmp );  // 通过上传的文件,二次渲染出新的图片资源
             imagepng( $img, $temp_file, 9);  // 将渲染出来的图片资源保存为jpeg格式的文件
         }
         imagedestroy( $img );  // 保存了图片文件之后,释放图片文件资源
 ​
         // Can we move the file to the web root from the temp folder?
         if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {
             // Yes! 表示已经成功移动文件
             $html .= "<pre><a href='{$target_path}{$target_file}'>{$target_file}</a> succesfully uploaded!</pre>";
         }
         else {
             // No
             $html .= '<pre>Your image was not uploaded.</pre>';
         }
 ​
         // Delete any temp files
         if( file_exists( $temp_file ) )
             // 如果临时文件还存在,那么就把他删掉,那么这里有是否会存在条件竞争呢
             unlink( $temp_file );
     }
     else {
         // Invalid file
         $html .= '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
     }
 }
 ​
 // Generate Anti-CSRF token
 generateSessionToken();
 ​
 ?>
 ​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值