If there are two users that can execute the script that caches a WSDL,
but the script is owned by a single user, then the caching code will
name the cached file with the file owner username and a hash of the uri.
When one of the two tries to rename the file created by the other
process, this does not work because it has no permission to do so.
This then leaves temporary files floating in the temp directory.
To fix the immediate problem, unlink the file after rename has failed.
On the long term, this has to be fixed by taking the username of the
process instead of the username of the file owner.
Closes GH-12841.
Setting the stream context via php_stream_context_to_zval() will
increase the reference count. So if the new context is created, then it
will end up with a reference count of 2 while it should be 1.
Credits to cmb for the analysis. I arrived at the same patch as he did.
Closes GH-12523.
When we have two processes both trying to cache a WSDL, they might start
writing the data to the same temporary file, causing file corruption due
to the race condition. Fix this by creating a temporary file first, and
then moving it to the final location. If moving fails then we know
another process finished caching first.
This also fixes#67617 as a consequence of its implementation.
Closes GH-12469.
There are two issues:
- UAF because the hashmap resized while being iterated over, yet the local
variables used internally in the macros are not updated.
- The hashmap being iterated over is modified: entries are deleted after
other entries have been added. This causes the deletion to fail sometimes
because indices of buckets have shifted.
Fix it by using a while loop iteration and HashPosition position tracker
instead.
Issue exists on PHP 8.1 too, but is much harder to trigger.
The test file reproduces the issue reliably on PHP 8.2 and up.
Closes GH-12409.
Fixes GHSA-3qrf-m4j2-pcrr.
To parse a document with libxml2, you first need to create a parsing context.
The parsing context contains parsing options (e.g. XML_NOENT to substitute
entities) that the application (in this case PHP) can set.
Unfortunately, libxml2 also supports providing default set options.
For example, if you call xmlSubstituteEntitiesDefault(1) then the XML_NOENT
option will be added to the parsing options every time you create a parsing
context **even if the application never requested XML_NOENT**.
Third party extensions can override these globals, in particular the
substitute entity global. This causes entity substitution to be
unexpectedly active.
Fix it by setting the parsing options to a sane known value.
For API calls that depend on global state we introduce
PHP_LIBXML_SANITIZE_GLOBALS() and PHP_LIBXML_RESTORE_GLOBALS().
For other APIs that work directly with a context we introduce
php_libxml_sanitize_parse_ctxt_options().
If php_random_bytes_throw fails, the nonce will be uninitialized, but
still sent to the server. The client nonce is intended to protect
against a malicious server. See section 5.10 and 5.12 of RFC 7616 [1],
and bullet point 2 below.
Tim pointed out that even though it's the MD5 of the nonce that gets sent,
enumerating 31 bits is trivial. So we have still a stack information leak
of 31 bits.
Furthermore, Tim found the following issues:
* The small size of cnonce might cause the server to erroneously reject
a request due to a repeated (cnonce, nc) pair. As per the birthday
problem 31 bits of randomness will return a duplication with 50%
chance after less than 55000 requests and nc always starts counting at 1.
* The cnonce is intended to protect the client and password against a
malicious server that returns a constant server nonce where the server
precomputed a rainbow table between passwords and correct client response.
As storage is fairly cheap, a server could precompute the client responses
for (a subset of) client nonces and still have a chance of reversing the
client response with the same probability as the cnonce duplication.
Precomputing the rainbow table for all 2^31 cnonces increases the rainbow
table size by factor 2 billion, which is infeasible. But precomputing it
for 2^14 cnonces only increases the table size by factor 16k and the server
would still have a 10% chance of successfully reversing a password with a
single client request.
This patch fixes the issues by increasing the nonce size, and checking
the return value of php_random_bytes_throw(). In the process we also get
rid of the MD5 hashing of the nonce.
[1] RFC 7616: https://www.rfc-editor.org/rfc/rfc7616
Co-authored-by: Tim Düsterhus <timwolla@php.net>
If you build soap as a shared object, then these tests fail on
non-Windows, or when the PHP install hasn't been make install-ed yet,
but is executed from the development directory.
Closes GH-11211.