One thing that really irks me is when people publish security vulnerabilities they discover without publishing the fix. Doing so only benefits the hacker (most specifically, the script kiddie) community, begging the question, “which side are you on?” Whenver I discover a vulnerability or exploit, I make it a point to first and foremost contact the vendor (or group responsible if it is not a commercial product) and then only announce the exploit after a fix is available (if then). Not enlisting vendor support or at very least describing how a vulnerability can be patched does not help users of that software unless they are savvy enough to figure out the fix on their own. One such example is the announcement of a SQL injection vulnerability in Zen-Cart <= 1.2.6d.

Here is how to fix it:
The simplest and most comprehensive option, which I recommend because it handles both vulnerabilities immediately, is to protect the admin directory with a directory-wide http auth scheme. This will require a login and password to access any file in the directory, protecting you not only from this vulnerability but any others that might be discovered in the future in the admin directory. This approach means your admins will need to enter two sets of login/password combinations–the http auth, and the normal Zen Cart login/password. After implementing this as an immediate fix, you will probably want to still continue on with the fixes mentioned below.

There are two problems to fix:

1) the SQL injection:

Here the second simplest and most straightforward approach would be to delete the password_forgotten.php file altogether. Assuming you and your admins know your passwords and have not / will not use this feature in the future, this handles it. The third option is to patch the sql injection with some basic output escaping. The most straightforward approach is to modify this line:

$sql = “select admin_id, admin_name, admin_email, admin_pass from ” . TABLE_ADMIN . ” where admin_email = ‘” . $admin_email . “‘”;

to this:

$sql = “select admin_id, admin_name, admin_email, admin_pass from ” . TABLE_ADMIN . ” where admin_email = ‘” . mysql_real_escape_string($admin_email) . “‘”;

effectively escaping the user-defineable $admin_email variable so that it can not be used for an SQL injection attack.

2) the path disclosure:

edit your php.ini file, and set display_errors = Off and log_errors = On. This is the default behavior for later versions of PHP, and is recommended to prevent display of sensitive information via reporting errors on web pages.

It only took me a couple of minutes to explain the fixes here. Discovering and reporting the vulnerability must have taken much longer. But not finishing the job by at least describing the fix potentially leaves users of Zen Cart with a greater problem than by not reporting it at all–because even now script kiddies are likely at work crafting exploit scripts based on this information.