Did I find a bug in PHP's `crypt()`? - php

I think I may have found a bug in PHP's crypt() function under Windows.
However: I recognize that it's probably my fault. PHP is used by millions and worked on by thousands; my code is used by tens and worked on by me. (This argument is best explained on Coding Horror.)
So I'm asking for help: show me my fault. I've been trying to find it for a few days now, with no luck.
The setup
I'm using a Windows server installation with Apache 2.2.14 (Win32) and PHP 5.3.2. My development box runs Windows XP Professional; the 'production' server (this is an intranet setup) runs Windows Storage Server 2003. The problem happens on both.
I don't see anything in php.ini related to crypt(), but will happily answer questions about my config.
The problem
Several scripts in my PHP app occasionally hang: the page sits there on 'waiting for localhost' and never finishes. Each of these scripts uses crypt to hash a user's password before storing it in the database, or, in the case of the login page, to hash the entered password before comparing it to the version stored in the database.
Since the login page is the simplest, I focused on it for testing. I repeatedly logged in, and found that it would hang maybe 4 out of 10 times.
As an experiment, I changed the login page to use the plain text password and changed my password in the database to its plain text version. The page stopped hanging.
I saw that PHP's latest version lists this bugfix:
Fixed bug #51059 (crypt crashes when
invalid salt are [sic] given).
So I created a very simple test script, as follows, using the same salt given in an official example:
$foo = crypt('rasmuslerdorf','r1');
echo $foo;
This page, too, will hang, if I reload it like crazy. I only see it hanging in Chrome, but regardless of browser, the effect on Apache is the same.
Effect on Apache
When these pages hang, Apache's server-status page (which I explained here, regarding a different problem) increments the number of requests being processed and decrements the number of idle workers. The requests being processed almost all have a status of 'Sending Reply,' though sometimes for a moment they will show either 'Reading request' or 'keepalive (read).'
Eventually, Apache may crash. When it does, the Windows crash report looks like this:
szAppName: httpd.exe
szAppVer: 2.2.14.0
szModName: php5ts.dll
szModVer: 5.3.1.0 // OK, this report was before I upgraded to PHP 5.3.2,
// but that didn't fix it
offset: 00a2615
Is it my fault?
I'm tempted to file a bug report to PHP on this. The argument against it is, as stated above, that bugs are nearly always my fault.
However, my argument in favor of 'it's PHP's fault' is:
I'm using Windows, whereas most servers use Linux (I don't get to choose this), so the chances are greater that I've found an edge case
There was recently a bug with crypt(), so maybe it still has issues
I have made the simplest test case I can, and I still have the problem
Can anyone duplicate this? Can you suggest where I've gone wrong? Should I file the bug after all?
Thanks in advance for any help you may give.

The bugs 51059 (only about passing invalid inputs) or 50947 (not the same code, 5.3 has new algorithms and features implemented in php, on all platforms) are not related to this problem.
However http://bugs.php.net/bug.php?id=51424 is. I already posted a partial patch there, but it solves most of the possible locks but it is indeed not sufficient. A full fix will be present in the next 5.3 release.
By the way, it is not windows specific but about the threaded SAPI (windows apache 2.2 for example).

This question has now been viewed 128 times and upvoted 9 times. The only answer I've received says it's a bug, and points to one in the PHP bug database. I don't think it's exactly the same one, but it does seem to validate my diagnosis.
Therefore, with some hesitation, I have filed a bug report:
Bug #51666 - Using crypt() makes Apache hang or crash
Thanks to everyone who has looked at this with me - even if you didn't reply, just knowing that others were considering this with me, and not telling me I'm crazy, has been helpful.

Yes. It's a known bug,
http://bugs.php.net/bug.php?id=50947
You can simulate the crypt() result using mcrypt. If you can change your password hash, you should really use hash_hmac(), which is more secure and we have no issues with it On Apache. No experiences on Windows though.

Related

php mysql: Duplicate entry on production but not on dev

Oke, i've been busting my head on this one.
I'm gonna try and keep things short, however, if you need more info, don't hesitate to ask.
I've written an import repo for an external firm, so we can import their data into our service.
quick overview of implemented logic?
ftp, grab xml file, parse it with simple_xml and do db stuff using laravel eloquent component.
on my dev machine,
every run gets parsed fully and all data is inserted correctly into the database.
problem
when i try the same thing on my production server.
I'm receiving a duplicate entry error, always on the same exact record. (unless i'm using another file)
pre script setup to help detect the error
on each run i do the following:
make sure i'm using the exact same files on both dev and prod
environment... (i've disabled the ftpgrab and uploaded manually to
the correct location)
truncate all the related tables so i'm always
starting with empty! tables.
i've manually triple-zillion checked for duplicates in the xml, but they're not in there.... and the fact that
my dev machine parses the file correctly confirms this.
what i tried
at this point, i've got no more clues as to how i'm supposed to debug this properly.
by now, i've checked so many things (most of them i can't even remember), all of which seemed pretty unrelated to me, but i had to try them.
those things include:
automatic disconnects due to browser
mysql wait timeouts
php script timeouts
memory settings
none of them seem to help (which was exactly what i was expecting)
another fact
my php version on my dev is 5.4.4 and the version on the production server is 5.3.2 (i know this is bad practise, but i'm not using any new features, it's really dead easy code, though it has quite a few lines :-) )
i've been suspecting this to be the cause, but
i've now switched to 5.3.14 on my dev... still the import runs without an issue
the changes from 5.3.2 to 5.3.14 are probably pretty minor
i've tried to manually compile the exact same php version, but i'm to inexperienced to properly do this. moreover, it probably wouldn't have the exact same specs anyway (i think it's pretty impossibly to ./configure exactly the same, considering the use of MacOs vs Ubuntu? especially for a noob like me)
So i've abandoned this path.
I've tried to find the differences in the php versions, but i can't seem to stumble upon anything that might be the cause to all this.
there was a change related to non-numeric keys in arrays (or strings for that matter) in version 5.4.4 (i think) but since i've now come to the conclusion that 5.3.14 also works, this definitely is not the issue. --- looking around insecurely hoping not having said anything downright stupid ---
quick thought while writing this:
the thing is, even though i'm getting the duplicate error statement.
The record did get inserted into the database.
moreover, the error gets triggered when having processed about 2700 (of total 6000) records.
the bound data to the query is actually the data of the second record in the xml file.)
I'm sincerely hoping anyone could put me on the right track for this issue :(
If you made it this far, but don't have a clue about what's going on, thx for reading and sticking to it.
If you might have clue, please enlighten me!

Output buffer issue on XAMPP portable

I run a php script from xampp portable on windows. The script takes over a minute. Recently, the script is having flush() problem, as echo statements are not immediately displayed. The script used to work fine earlier with no buffering problem.
Interestingly, I ran the same script copying the xampp portable to another system and the flush statements were working without any problem. Same code, Same xampp portable.
What could be the reason?
Make the first line of your script ob_implicit_flush();.
or
Change the php.ini file setting implicit_flush = On.
From the documentation:
implicit_flush boolean, FALSE by default. Changing this to TRUE tells
PHP to tell the output layer to flush itself automatically after every
output block. This is equivalent to calling the PHP function flush()
after each and every call to print or echo and each and every HTML
block.
When using PHP within an web environment, turning this option on has
serious performance implications and is generally recommended for
debugging purposes only.
I read other responses and you keep insisting on the fact that your home environment and your work environment are the same. However, you can see that there is a difference. This point of view really help (at least to me) to investigate problems.
Since you did not provide many details about the problem, I would try the following checklist:
Settings
Is your PHP settings really identical? Try to compare results of phpinfo() on both environments.
Data
Do you really test your script on identical data? There are many subtle problems that are described in PHP manual:
Even the browser may buffer its input before displaying it. Netscape, for example, buffers text until it receives an end-of-line or the beginning of a tag, and it won't render tables until the tag of the outermost table is seen.
Some versions of Microsoft Internet Explorer will only start to display the page after they have received 256 bytes of output, so you may need to send extra whitespace before flushing to get those browsers to display the page.
http://php.net/manual/en/function.flush.php
or
http://www.php.net/manual/en/function.ob-flush.php#90529 (commenters point out many problems that you may experience)
Try dummy plaintext data instead of HTML. You may try to output simple lines like current time and check behaviour of your script.
Browsers
Try a few browsers (with cleared cache) to see if the issue is browser-specific or not.
I think it may be your browser. Have you cleaned the temporary settings of Iron Portable browser?
this occurs when you use gzip and there is some output have been send so the browser get confused to solve this , i uses this code always
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false)
{ob_start('ob_gzhandler'); ob_start();}
else
ob_start();
You have not mentioned about the versions of windows both the systems running. Are the systems completely identical?
You also said that you are running a portable version of XAMPP , if you are using a pen drive/thump drive there is a chance that data transfer speeds can vary due to USB speeds.
I had a similar issue where the First system had USB legacy ports and the second one I tested has usb 2+ ports or higher.
The speed and processing time changed based on the systems, while one system took 20 seconds , other took nearly 60 seconds to process.
The slow system produced undesired results [I was working on an image processor].
I guess your case is similar and had to do a lot with the system vitals.
Cheers
Clain
I figured out that the problem is with antivirus. I recently switched to Bitdefender from Avast. When I switched back to Avast, the problem disappeared miraculously. So, i guess antivirus is also a factor here.

PHP crypt() returning wrong answer

I think i'm losing my marbles here... I've got a problem on my web site where randomly it stops accepting logins. I've now been able to trace it to crypt() behaving very strangely.
In my database, i've got the crypted version of the users password - so let's say Og12345678.
When the user logs in, they enter their password, I read the salt out of the db and then crypt what they entered and compare - usually this works very well.
So i'm doing crypt($enteredPassword, $saltFromDb) - in this case, the salt would be Og of course. Normally for a given users password crypt works fine.
When things go wrong (and when they do it's a permanent change until I restart Apache) I found that crypt starts returning a DIFFERENT answer for the same input with the same salt.
It's consistent however, i.e. once the system has gone wrong crypt returns the wrong answer but it's always returning the same wrong answer. Repeated refreshes of the page show the same output. The same salt is also in evidence in the newly incorrect crypt result also, so it's not that the salt has gone missing somewhere.
If I then restart Apache and re-run the script without any changes at all, the results from crypt are then back to how they should be.
I appreciate it's not the latest PHP (5.2.8) but would value any views on this including whether it's a known bug fixed in a later version (upgrading PHP is not a happy task with lots of sites some of which still use unfortunate quirks that all need to be re-tested with each upgrade) - if it is a known fixed bug then obviously i'll get it all upgraded ASAP, beyond that it'll probably be easier to outsource the crypt externally since I only use it in one common place for my site.
Any input appreciated.
Matt Peddlesden
--- Update: 11 Mar 2011
Correction to comment previously given about operating system...
- Operating system is Windows Server 2008 SP1 64 bit. Apologies I should have double checked rather than assuming I could remember! Machine is a Dell 2950 8gb Ram, Xeon processors.
I am starting to think along the lines Krtek is suggesting - when the system has gone wonky, if I generate new crypt() (i.e a very simple example where i set a variable to a string, crypt it and then compare with the crypt) - all works great. When I restart the server, again it's all back to the previous calculations again. So I am definitely leaning towards something that is changing the algorithm used to calculate the crypt() result... any thoughts on what might cause this to happen? I printed out the values of the CRYPT_STD_DES etc and they don't change between restarts.
Anyone got any clues on what might cause this to happen?
Whatever it was seemed to happen twice in one day yesterday, most odd.
Thanks for the answers thus far.
--- Update: 16 Mar 2011
Just wanted to provide another update.
This is still happening, still no further understanding of why.
In case anyone comes across this in the future, I think my solution going forwards is going to be to do some nasty hack to push all the crypt() executions out to an external C# application and stop having to rely on PHP to do them. Something is going wrong somewhere and at this point the only solution I can see is to remove it from the equation entirely.
Of course if it still happens, that will be interesting to know too! :)
Thanks all.
Why are you reading the salt? And how are you getting the salt? Different algorithms use different methods for including the salt in the output.
Just use the whole output of the crypt function as the second argument:
$crypted='Og12345678';
if (crypt($_POST['password'], $crypted)==$crypted) {
....
And single pass DES? Really?
Last time I looked, the PHP crypt implementation would call the crypt() function provided by the system - so if it has broekn then its more likely to be your OS than PHP - but you didn't say what your OS is.
It might be the Suhosin PHP security patch affecting your crypt() function. It alters a lot of the encryption/random methods and may be the the cause of your problem.
Check a phpinfo() and see if 'suhosin' is anywhere on the page. If it's there, look into disabling some of it's features in the php config.
i had the same problem with crypt... I had that login-check working on 2 servers, but when i transfer it to the newest one it eventually stop working. I walk around it with md5 encryption as follows:
In register.php
$encrypted = md5($_POST["pass"]);
...
And then in login.php
$password = md5($_POST["password"]);
if ($password == $row["hash"])
{
// remember that user's now logged in by storing user's details in session
$_SESSION["id"] = $row["id"];
$_SESSION['username'] = $_POST['username'];
$_SESSION['logged'] = 'Yes';
// redirect to homepage
redirect("index.php");
}
I hope that helps :)
I faced the same problem. Since moving my vTigerCRM installation to local machine, user login with previously stored passwords started failing. It seems like crypt() is returning different hashes on different environments with the same arguments:
On local environment:
SYSTEM: Windows NT 6.1 build 7601 (Business Edition Service Pack 1) i586
PHP: 5.3.5
crypt('hello world','$1$ad0000000'):
$1$ad00000008tTFeywywdEQrAl9QzV.M1
On production environment:
SYSTEM: Linux 2.6.18-338.9.1.el5.lve0.8.32 #1 x86_64
PHP: 5.3.5
crypt('hello world','$1$ad0000000'):
$1$ad000000$8tTFeywywdEQrAl9QzV.M1

Page not fully loaded (html source cut off) in IE8

I have a strange problem: I have a PHP application that's working in all common browsers. But some pages are not fully loaded in IE8. If I look at the source code, it has been more ore less randomly cut off and half of the html source is missing, sometimes in the middle of a tag.
The strange thing is, it appears only on some IE-installations (in a big company), on others (I'd say the majority) it's working.
If I look up the apache error logs it says:
[notice] child pid 9393 exit signal Segmentation fault (11)
I don't know if it's related somehow, but how can the same page (called with the same parameters) work on one machine and not on another one (reproducable)?
I have not a single clue if it's some rendering problems in IE, if the browser is crashing internally or if the server really crashes and serving only half of the html source.
(Unfortunately I can't provide an example as it occurs on a web project yet to be released)
Update: I did some testing:
Upgraded Apache2, PHP5, libPHP5 on the Debian machine. Updated, activated, deactivated xdebug, mimicked the request header (user-agent) with apaches mod_header - still the same problem. Honestly I'm not sure, if the seg fault has something to do with the problem that IE only delivers half of the content.
Can this also be due to a virus scanner? Does anyone know of circumstances that IE only gets half the source code when there is no server error?
If your Apache logs say one of the worker processes segfaulted, it's not a client-side issue. No matter what the client does, it should not cause the server to crash.
The issue might be related to IE8, but only indirectly - IE8 could issue a different pattern of requests when visiting the page, or at the very least sends a different User-Agent string which the server might use to follow a different codepath.
Try upgrading your version of Apache. If that doesn't work, check for configuration errors in Apache, such as a bad extension module. If that doesn't do it, inspect your server hardware for flaws.
Sorry, no answer, bt if it were me I'd....
1) configure the php to do an auto-prepend (unless there's already one in place
2) write an include file to trap incomplete page loads (have a llok at ignore_user_abort, connection_status and register_shutdown_function)
If your code can detect occurrences of the problem, then its not related to the segfault.
You might also try installing mod_security which can log post vars and record a log entry at the start of a request - so you have some scope for investigating the segfaults.
After days of debugging (updated server software, moved to another machine and so on) we finally got the problem. It was a very old installation of the Novell Border Manager, some sort of proxy. The segmentation fault seems to be unrelated to this.
If anyone has similar problems, here are two related posts:
http://www.novell.com/support/search.do?cmd=displayKC&docType=kc&externalId=7007318&sliceId=1&docTypeID=DT_TID_1_1
http://forums.novell.com/novell-product-support-forums/access-manager-3/428004-access-manager-showing-partial-content-page-post2058485.html

Connection Interrupted. The connection to the server was reset while the page was loading

I am calling a PHP-Script belonging to a MySQL/PHP web application using FF3. I run XAMPP on localhost. All I get is this:
Connection Interrupted
The connection to the server was reset while the page was loading.
The network link was interrupted while negotiating a connection. Please try again.
There are a number of possible solutions ... depends on the "why" ... so it ends up being a bit of trial and error. On a fresh install, that's tricky to determine. But, if you made a recent "major" change that's a place to start looking - like modifying virtual hosts or adding/enabling XDebug.
Here's a list of things I've used/done/tried in the past
check for infinite loops ... in particular looping through a SQL fetch result which works 99% of the time except the 1% it doesn't. In one case, I was using the results of two previous queries as the upper and lower bounds of a for loop ... and occasionally got a upper bound of a UINT max ... har har har (vomit)
copying the ./php/libmysql.dll to the windows/system32 directory (Particularly if you see Parent: child process exited with status 3221225477 -- Restarting in your log files ... check out: http://www.java-samples.com/showtutorial.php?tutorialid=1050)
if you modify PHP's error_reporting at runtime ... in certain circumstances this can cause PHP to degenerate into an unstable state if, say, in your PHP code you modify the superglobals or fiddle around with other deep and personal background system variables (Nah, who would ever do such evil hackery? ahem)
if you convert your MySQL to something other than MyISAM or mysqli
There is a known bug with MySQL related to MyISAM, the UTF8 character set and indexes (http://bugs.mysql.com/bug.php?id=4541)
Solution is to use InnoDB dialect (eg sql set GLOBAL storage_engine='InnoDb';)
Doing that changes how new tables are created ... which might slightly alter the way results are returned to a fetch statement ... leading to an infinite loop, a malformed dataset, etc. (although this change should not hang the database itself)
Other helpful items are to ramp up the debug reporting for PHP and apache in their config files and restart the servers. The log files sometimes give a clue as to at least where the problem might reside. If it happens after your page content was finished it's more likely in the php settings. If it's during page construction, check your PHP code. Etc. etc.
Hope the above laundry list helps somebody someday ... probably myself when I run into it again and come back here looking for "how the heck did I fix it last time?" ... :)
It's possible that your script could be caught in an infinite loop. If that doesn't apply, then I'd check the error logs like TimB suggested.
It sounds like the PHP script you're calling is failing without returning a valid response. Depending on the level of logging that you have set up, this should generate an error in the Apache logfile, which will give you some idea of the problem. I'm not familiar with XAMPP, but you should be able to find out where the logs are, and look for an error that occurred at the time you made your request to the PHP script.
copying libmysql.dll to apache\bin folder may help you overcome this strange error
I solved this problem Upgrading the xampp\php\ext\xdebug\php_xdebug.dll
(changed to php xdebug v.2.0.5-5.3-vc9 )
I had the same problem and this is what i did.
I issued the http get command through php cli script, and as it turns out I had declared one class twice somewhere.
By the way , i use AMPPS on an mac
Hope this helps some one!
Try doing the request with Firebug enabled and see what info you can get out of that; I always find that using wget is helpful for seeing the raw HTTP interaction without worrying about Firefox's UI elements interfering.
If you are using certificates for ssl in Windows 2008 Server(iis 7) from old selfssl tool(iis 6), that is the problem. Sometimes Microsoft releases patches which can destruct all these old certificates. The solution is to generate them again.
copying libmysql.dll to apache\bin folder may help you overcome this strange error
Indeed this helped me to solve this problem
The connection to the server was reset while the page was loading.
Incase the issue is not working this did the trick for me.
1. I got a new zip directory for PHP and connected it with apache
2. I searched for the libmysql in the new php and inserted this to the apache/bin
its this libmysql.dll that is needed there and not the one form mySQL/bin.
ok at least thats the one that worked.
I experienced a very similar issue - which doesn't apply to the person who asked this question - but may be of help to others who are reading this page...
I had an issue where in certain cases PHP 5.4 + eAccelerator = connection reset. There was no error output in any log files, and it only happened on certain URLs, which made it difficult to diagnose. Turns out it only happened for certain PHP code / certain PHP files, and was due to some incompatibilities with specific PHP code and eAccelerator. Easiest solution was to disable eAccelerator for that specific site, by adding the following to .htaccess file
php_flag eaccelerator.enable 0
php_flag eaccelerator.optimizer 0
(or equivalent lines in php.ini):
eaccelerator.enable="0"
eaccelerator.optimizer="0"

Categories