Hi Yasuo,

> -----Original Message-----
> From: Yasuo Ohgaki [mailto:[email protected]]
> Sent: Thursday, July 28, 2016 8:43 AM
> To: Anatol Belski <[email protected]>
> Cc: [email protected]
> Subject: Re: [PHP-CVS] com php-src: Support Unicode characters in the local
> part of an e-mail address.: ext/filter/filter.c ext/filter/filter_private.h
> ext/filter/logical_filters.c ext/filter/tests/058.phpt
> 
> Hi Anatol,
> 
> I'm not comfortable with complex regex....
> 
> http://stackstatus.net/post/147710624694/outage-postmortem-july-20-2016
> This attack pattern works with PCRE even it has backtrack//stack limit.
> 
> 
> Try following ruby code. You'll see exponential execution time increase.
> 80 chars mail address requires 421 sec on my Core i7 fedora.
> We are using PCRE, but I'm not comfortable with complex ereg...
> 
> n = 5;
> while n < 12 do
>   s = "username@host"+".abcde"*n+"."
>   start = Time.now();
>   p /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i =~ s
>   p s.length.to_s + ': ' + (Time.now() - start).to_s;
>   n += 1
> end

Anything I've tried based on your Ruby snippet doesn't show times over 200us, 
whether it fails or passes. i7 here as well. The lenth is limited to 320 bytes 
in both cases. In the post you've linked, it's about over 20000 bytes length, 
and about replacing, not matching. The non UTF-8 pattern doesn't look simple as 
well, the new one extends it.

Do you have some snippet to reproduce an attack vector with this concrete patch?
 
Regards

Anatol

> --
> Yasuo Ohgaki
> [email protected]
> 
> 
> On Tue, Jul 19, 2016 at 5:44 PM, Yasuo Ohgaki <[email protected]> wrote:
> > Hi Anatol,
> >
> > Although I'm not certain, I worry about ReDoS risks with this complex regex.
> >
> > https://www.checkmarx.com/wp-content/uploads/2015/03/ReDoS-
> Attacks.pdf
> >
> > How about to use much simpler regex or string filter before applying
> > the complex regex to reduce ReDoS risk?
> >
> > --
> > Yasuo Ohgaki
> > [email protected]
> >
> >
> > On Tue, Jul 19, 2016 at 4:52 AM, Anatol Belski <[email protected]> wrote:
> >> Commit:    8f4050709c833b9d42cd65349b7747f8e61d171f
> >> Author:    Leo Feyer <[email protected]>         Thu, 15 Oct 2015 11:07:25
> +0200
> >> Committer: Anatol Belski <[email protected]>      Mon, 18 Jul 2016 21:52:35 
> >> +0200
> >> Parents:   42260325a47480bc97f7dceb2ac5d8e8d7799928
> >> Branches:  master
> >>
> >> Link:       http://git.php.net/?p=php-
> src.git;a=commitdiff;h=8f4050709c833b9d42cd65349b7747f8e61d171f
> >>
> >> Log:
> >> Support Unicode characters in the local part of an e-mail address.
> >>
> >> See RFC 6531 (https://tools.ietf.org/html/rfc6531).
> >>
> >> Encode IDNA domains.
> >>
> >> Add the missing "Done" to the expected output.
> >>
> >> Add the FILTER_FLAG_EMAIL_RFC6531 flag.
> >>
> >> Fix the filter_var() call.
> >>
> >> Changed paths:
> >>   M  ext/filter/filter.c
> >>   M  ext/filter/filter_private.h
> >>   M  ext/filter/logical_filters.c
> >>   A  ext/filter/tests/058.phpt
> >>
> >>
> >> Diff:
> >> diff --git a/ext/filter/filter.c b/ext/filter/filter.c index
> >> 2c8dde9..3d79a77 100644
> >> --- a/ext/filter/filter.c
> >> +++ b/ext/filter/filter.c
> >> @@ -286,6 +286,8 @@ PHP_MINIT_FUNCTION(filter)
> >>
> >>         REGISTER_LONG_CONSTANT("FILTER_FLAG_HOSTNAME",
> >> FILTER_FLAG_HOSTNAME, CONST_CS | CONST_PERSISTENT);
> >>
> >> +       REGISTER_LONG_CONSTANT("FILTER_FLAG_EMAIL_RFC6531",
> >> + FILTER_FLAG_EMAIL_RFC6531, CONST_CS | CONST_PERSISTENT);
> >> +
> >>         sapi_register_input_filter(php_sapi_filter,
> >> php_sapi_filter_init);
> >>
> >>         return SUCCESS;
> >> diff --git a/ext/filter/filter_private.h
> >> b/ext/filter/filter_private.h index 2f9abc3..ffce723 100644
> >> --- a/ext/filter/filter_private.h
> >> +++ b/ext/filter/filter_private.h
> >> @@ -57,6 +57,8 @@
> >>
> >>  #define FILTER_FLAG_HOSTNAME               0x100000
> >>
> >> +#define FILTER_FLAG_EMAIL_RFC6531          0x100000
> >> +
> >>  #define FILTER_VALIDATE_INT           0x0101
> >>  #define FILTER_VALIDATE_BOOLEAN       0x0102
> >>  #define FILTER_VALIDATE_FLOAT         0x0103
> >> diff --git a/ext/filter/logical_filters.c
> >> b/ext/filter/logical_filters.c index 5fd057d..03d4795 100644
> >> --- a/ext/filter/logical_filters.c
> >> +++ b/ext/filter/logical_filters.c
> >> @@ -598,7 +598,12 @@ void
> php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
> >>          * Feel free to use and redistribute this code. But please keep 
> >> this
> copyright notice.
> >>          *
> >>          */
> >> -       const char regexp[] = "/^(?!(?:(?:\\x22?\\x5C[\\x00-
> \\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-
> \\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-
> \\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-
> \\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-
> \\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-
> \\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-
> \\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-
> \\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-
> 9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-
> 9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-
> 9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-
> 9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-
> f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-
> 9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-
> 9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-
> 9]))){3}))\\]))$/iD";
> >> +       if (flags & FILTER_FLAG_EMAIL_RFC6531) {
> >> +               const char regexp[] = "/^(?!(?:(?:\\x22?\\x5C[\\x00-
> \\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-
> \\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-
> \\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-
> \\x7E\\pL\\pN]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-
> \\x5B\\x5D-\\x7F\\pL\\pN]|(?:\\x5C[\\x00-
> \\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-
> \\x39\\x3D\\x3F\\x5E-\\x7E\\pL\\pN]+)|(?:\\x22(?:[\\x01-
> \\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-
> \\x7F\\pL\\pN]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn-
> -)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-
> 9]+))(?:-+[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-
> 9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-
> 9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-
> 9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-
> 9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-
> 4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-
> 9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iDu";
> >> +       } else {
> >> +               const char regexp[] = "/^(?!(?:(?:\\x22?\\x5C[\\x00-
> \\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-
> \\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-
> \\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-
> \\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-
> \\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-
> \\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-
> \\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-
> \\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-
> 9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-
> 9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-
> 9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-
> 9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-
> f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-
> 9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-
> 9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-
> 9]))){3}))\\]))$/iD";
> >> +       }
> >> +
> >>         pcre       *re = NULL;
> >>         pcre_extra *pcre_extra = NULL;
> >>         int preg_options = 0;
> >> diff --git a/ext/filter/tests/058.phpt b/ext/filter/tests/058.phpt
> >> new file mode 100644 index 0000000..a10f844
> >> --- /dev/null
> >> +++ b/ext/filter/tests/058.phpt
> >> @@ -0,0 +1,57 @@
> >> +--TEST--
> >> +FILTER_VALIDATE_EMAIL unicode support
> >> +(https://tools.ietf.org/html/rfc6531)
> >> +--SKIPIF--
> >> +<?php if (!extension_loaded("filter")) die("skip"); ?>
> >> +--FILE--
> >> +<?php
> >> +$values = Array(
> >> +'niceä[email protected]',
> >> +'véry.ç[email protected]',
> >> +'a.lîttle.lengthy.but.fiñ[email protected]',
> >> +'dîsposable.style.é[email protected]',
> >> +'other.é[email protected]',
> >> +'üser@[IPv6:2001:db8:1ff::a0b:dbd0]',
> >> +'"verî.uñ[email protected]ñusual.com"@example.com',
> >> +'"verî.(),:;<>[]\".VERÎ.\"verî@\
> >> +\"verî\".unüsual"@strange.example.com',
> >> +'té[email protected]',
> >> +'té[email protected]',
> >> +'té[email protected]',
> >> +'té[email protected]',
> >> +'té[email protected]',
> >> +'tést@[255.255.255.255]',
> >> +'tést@[IPv6:2001:0db8:85a3:08d3:1319:8a2e:0370:7344]',
> >> +'tést@[IPv6:2001::7344]',
> >> +'tést@[IPv6:1111:2222:3333:4444:5555:6666:255.255.255.255]',
> >> +'té[email protected]',
> >> +'üñîçøðé@example.com',
> >> +'"üñîçøðé"@example.com',
> >> +'DžǼ੧ఘⅧ⒇৪@example.com',
> >> +);
> >> +foreach ($values as $value) {
> >> +       var_dump(filter_var($value, FILTER_VALIDATE_EMAIL,
> >> +FILTER_FLAG_EMAIL_RFC6531)); } echo "Done\n"; ?>
> >> +--EXPECT--
> >> +string(26) "niceä[email protected]"
> >> +string(25) "véry.ç[email protected]"
> >> +string(44) "a.lîttle.lengthy.but.fiñ[email protected]"
> >> +string(48) "dîsposable.style.é[email protected]"
> >> +string(34) "other.é[email protected]"
> >> +string(35) "üser@[IPv6:2001:db8:1ff::a0b:dbd0]"
> >> +string(43) ""verî.uñ[email protected]ñusual.com"@example.com"
> >> +string(74)
> ""verî.(),:;<>[]\".VERÎ.\"verî@\ \"verî\".unüsual"@strange.example.com"
> >> +string(17) "té[email protected]"
> >> +string(23) "té[email protected]"
> >> +string(24) "té[email protected]"
> >> +string(18) "té[email protected]"
> >> +string(23) "té[email protected]"
> >> +string(23) "tést@[255.255.255.255]"
> >> +string(52) "tést@[IPv6:2001:0db8:85a3:08d3:1319:8a2e:0370:7344]"
> >> +string(23) "tést@[IPv6:2001::7344]"
> >> +string(58) "tést@[IPv6:1111:2222:3333:4444:5555:6666:255.255.255.255]"
> >> +string(27) "té[email protected]"
> >> +string(26) "üñîçøðé@example.com"
> >> +string(28) ""üñîçøðé"@example.com"
> >> +string(31) "DžǼ੧ఘⅧ⒇৪@example.com"
> >> +Done
> >>
> >>
> >> --
> >> PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit:
> >> http://www.php.net/unsub.php
> >>
> 
> --
> PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit:
> http://www.php.net/unsub.php



--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to