Bug #72963 [Asn]: Null-byte injection in createFromFormat

From: Date: Fri, 20 May 2022 13:55:11 +0000
Subject: Bug #72963 [Asn]: Null-byte injection in createFromFormat
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-241559@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=72963&edit=1

 ID:                 72963
 Updated by:         derick@php.net
 Reported by:        qoqe at inbox dot lv
 Summary:            Null-byte injection in createFromFormat
 Status:             Assigned
 Type:               Bug
 Package:            Date/time related
 Operating System:   Linux, Windows
 PHP Version:        7.0.10
 Assigned To:        derick
 Block user comment: N
 Private report:     N

 New Comment:

https://github.com/php/php-src/pull/8593


Previous Comments:
------------------------------------------------------------------------
[2016-08-29 11:24:24] qoqe at inbox dot lv

Description:
------------
createFromFormat method from DateTime class is sensitive to null-byte injection. 

According to best practices to verify if date is valid in PHP, the best way is to use
DateTime::createFromFormat because it returns false if date isn't valid. This way to verify
date is used in many CMS systems (for example, in Drupal).

The problem is that DateTime::createFromFormat second parameter is vulnerable to null-byte which can
be passed to it when createFromFormat method is used to verify GET or POST param.

Here are results if application calls DateTime::createFromFormat('m/d/Y',
$_GET['startFrom']); where

startFrom=8/8/2016 - will return true
startFrom=8/8/2016asd - will return false
startFrom=8/8/2016%00asd - will return true

It seems to be reliable verification if date is valid and developer might not use htmlspecialchars
or real_escape_string after it. This may lead to SQL Injection or XSS.



Test script:
---------------
 <?php
 
    function verifyDate($date, $strict = true) {
        $dateTime = DateTime::createFromFormat('m/d/Y', $date);
        if ($strict) {
            $errors = DateTime::getLastErrors();
            if (!empty($errors['warning_count'])) {
                return false;
            }
        }
        return $dateTime !== false;
    }
    
    if(!empty($_GET['startFrom']) && verifyDate($_GET['startFrom'])) {
    
        // query to database without escaping $_GET['startFrom']
        // because it has passed verification of valid date
    
    }
    
    // tests
    
    var_dump(verifyDate('asd')); // false
    var_dump(verifyDate('8/8/2016')); // true
    var_dump(verifyDate('8/8/2016asdasd')); // false
    var_dump(verifyDate("8/8/2016\x00asdasd")); // true
 
 ?>



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=72963&edit=1


Thread (1 message)

  • derick@php.net
  • Unknown Message
    • derick@php.net
« previous php.bugs (#241559) next »