Running PHP exec() Shell Functions On WAMP

WAMP servers (such as WampDeveloper Pro) default configuration does not restrict executions of PHP functions – such as exec() and shell_exec(). You can verify this by checking the website’s Apache and PHP error log files.

If you are able to run your commands manually from the command-line, but not via WAMP, than the user the Apache Service runs as does not have the needed permissions to execute your commands and binaries (nor interact with the desktop if they are GUI related).

If you create a test.php file and place this inside:

<?php
echo exec('whoami');
?>

When run via a URL, Apache will output:

nt authority\system

But if you run “whoami” from the command-line yourself, it will output:

<computer-name>\<user-name>

The user difference is why those commands do not run via Apache.

To execute privileged shell commands via Apache, you’ll have to run “services.msc”, select the Apache service, and change the “Log On” account From “Local System” to another user/account.

To avoid permissions issues, create a user in the Administrators group, and make sure to set the user’s password (as password-less accounts are “unauthenticated” which causes further issues).

Later on, once you verify that everything is working, you can fine-tune the account’s permissions. And check if what you are trying to execute requires Admin privileges.

WordPress – Changing the Temp Directory

A user was trying to secure different WordPress installations from each other (and the rest of WAMP) by setting each to use a different Temp directory:

We currently host 4 different WordPress websites using WAMP. Is it possible to configure the temp directory for each site separately, perhaps as a subdirectory in C:\WampDeveloper\Temp directory?

This way a compromised WordPress base will not spread a downloaded payload or script to another base (as normally all PHP scripts share a common Temp folder).

Checking the WordPress source-code, WordPress uses this function to find and derive the path of the temporary directory:
get_temp_dir()

The first thing get_temp_dir() checks for is this PHP runtime constant:

WP_TEMP_DIR

If you edit the WordPress configuration file wp-config.php, and place this line in, it should set the new temporary folder:

define('WP_TEMP_DIR', 'C:\WampDeveloper\Temp\WP1');

The above example is for a sub-directory “WP1″ under the original WampDeveloper Temp directory (on drive C). This sub-directory will need to be created manually.

If you use a path outside the \WampDeveloper\Temp directory, note that:
1. You could have issues with Apache not being able to read/write into it (a network share directory, required permissions, etc).
2. Also, PHP’s “open_basedir” setting (it is not enabled by default) would need to be updated in the website’s VirtualHost or .htaccess files to allow the script access to the path (or in php.ini if using PHP-FCGI).

If you are using older WordPress plugins that do not use the proper WordPress function get_temp_dir() to get the temp dir, but instead rely on the environmental variables, you can also add a second line into wp-config.php to set env variable TMPDIR:

putenv('TMPDIR=' . 'C:\WampDeveloper\Temp\WP1');

Laravel – Key size not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported.

The new version of PHP 5.6+ is now enforcing proper key sizes. If your Laravel APP_KEY is not the proper (supported) character length, you will get the following error:

mcrypt_decrypt(): Key of size 5 not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported.

There are 2 ways to fix this:

A) “Pad” the key to a valid size. This will preserve your existing encrypted data such as: any data that was saved with Crypt::encrypt() in the database, passwords saved with Hash::make() [note – there is conflicting information on if the key is used during password hashing and storage], and current sessions.

B) Or generate a new key and lose your previously encrypted data:

php artisan key:generate

Pad Laravel APP_KEY to Next Supported Length

To preserve your existing encrypted data, manually “pad” your existing key to the next valid size (16, 24, 32 characters). This is how invalid size keys were handled internally by the PHP mcrypt_decrypt() function before the change in PHP 5.6+…

Previously keys and IVs were padded with ‘\0′ bytes to the next valid size.

Example:
If it is 10 characters, pad it to 16.
If it is 20 characters, pad it to 24.
If it is 25 characters, pad it to 32.

app.php

1. Open your Laravel configuration file:

laravel\config\app.php

2. Find line:

'key' => env('APP_KEY', 'SomeRandomString'),

The above line attempts to read the value of Laravel’s environmental variable APP_KEY (as defined in Laravel’s .env file), and if unable to do so, uses the quoted value.

3. Count the number of characters the key value is (without the quotes), and make it valid-sized by adding null bytes to the end. You will need to replace the quotes that surround the key value from single quotes to double quotes – so PHP interprets the null bytes correctly.

For example, if your key is “12345”, than it is 5 characters long, and it needs to be made 16 characters long like so:

"12345\0\0\0\0\0\0\0\0\0\0\0"

With the above app.php line like so:

'key' => env('APP_KEY', "12345\0\0\0\0\0\0\0\0\0\0\0"),

.env

The above key value is also stored in Laravel’s .env file (which itself usually acts as the primary source for APP_KEY).

1. Open your Laravel .env file:

laravel\.env

2. Find line:

APP_KEY=SomeRandomString

3. Update it to the padded value, surrounded by double quotes like so:

APP_KEY="12345\0\0\0\0\0\0\0\0\0\0\0"

Notes

As an alternative, you can use the PHP function str_pad to automatically do the above manual padding. For example, to pad a 17-23 character length key to 24:

str_pad($str, 24, "\0", STR_PAD_RIGHT);

Also the PHP function chr can be used to return the null byte instead of specifying it with special escape sequences:

chr(0)

Laravel uses PHPDotEnv (3rd-party library) to read the .env file and load the environmental variables. PHPDotEnv uses its own basic text/string format – and you cannot embed PHP code into the .env file. If you are unable to place the null-byte padded value into the .env file, you can comment out (#) the APP_KEY line so Laravel uses the default/fallback value from the app.php file.

The issue is referenced here: mcrypt_decrypt() throws error when PHP 5.6 is used if key is not 32 characters #6722

Laravel – No supported encrypter found. The cipher or key length are invalid.

A user was trying to install Laravel under WAMP and got the following error:

RuntimeException in compiled.php line 6904: No supported encrypter found. The cipher and / or key length are invalid.

Looking at the Laravel installation instructions, the only WampDeveloper specific change that would need to be done is to load the PHP sockets extension:

1. Open file C:\WampDeveloper\Config\Php\php.ini (via Notepad)

2. Find this line and uncomment it (remove front “;”) –

;extension=php_sockets.dll

3. Save file. Restart Apache.

All the other Laravel required PHP extensions and Apache modules under WampDeveloper are loaded and enabled by default.

The above error seems to be Laravel-specific (rather than having something to do with WAMP) and here is how to fix it…

1. Make sure that in Laravel’s config\app.php file, the 'cipher' is defined as so:

'cipher' => 'AES-256-CBC',

2. Make sure Laravel’s “.env” file exists. If this file does not exist, open the command-line (run cmd.exe), change the command-line’s “working directory” to Lavavel’s installed-to path, and create this file from the provided example template file:

C:
cd \path\to\laravel\folder
cp .env.example .env

The first line (“C:”) changes to drive “C”, the second line changes to the path (on C)… substitute-in for your Laravel installed location. The third line makes a properly-named copy of the base example file. Because this file starts with a period, it’s much simpler to make a copy using the command-line (otherwise you’ll run into issues).

3. The cause of the issue is – the above cipher “AES-256-CBC” needs a 32 character key, but the default random key is only 16 characters long.

Generate a new 32 character string for the key by running (from cmd.exe):

php artisan key:generate

The command should automatically update the app.php file (and also the .env file) with a new proper-size key, and output something similar to this afterwards:

Application key [g8MOZ9dYU4ap5F12m95PIPAA5AJG3Sh6] set successfully.

4. Verify that the above key is now in Laravel's .env file:

APP_KEY=g8MOZ9dYU4ap5F12m95PIPAA5AJG3Sh6

If it's not, manually add it in as shown above (substitute in your key, and without the brackets).

* On another unrelated but similar cause, if this is happening sometime after a successful installation - after your app is fully installed and running - then it is possible that the APP_KEY was changed and now the encrypted data cannot be decrypted. In this case, unless you can revert to the previous key, you'll have to either delete the encrypted data or start over.

MySQL ERROR 1045 (28000): Access denied for user ‘db_user_name’@’localhost’

I have software that requires direct access to the MySQL database. If I run it on the same computer as WAMP it works, but if I access the database with this software from another computer, it then reports error:

MySQL ERROR 1045 (28000): Access denied for user 'db_user_name'@'localhost' (using password: YES)

Create the same database user (i.e., with the same name + password as the existing user) in MySQL (via \phpmyadmin), except set the “Host:” field to either the connecting remote IP address, or to “%” (which means any IP can connect).

This way you’ll be able to use this user to access the database from 127.0.0.1 (Host:127.0.0.1), and also from an outside system (Host:%).

Also make sure that you have already:

  • Re-bound MySQL from IP 127.0.0.1 to 0.0.0.0
  • Opened incoming port 3306 requests in Windows Firewall (and removed any existing blocking MySQL rules).
  • Port-forwarded port 3306 in the Router from WAN:3306 to LAN-IP:3306 (if accessing from outside the LAN).

And that this database user has all permissions granted on the specific database(s), and the outside application is using the proper: IP, database name, user name, user password – to establish the connection.

If you have the mysql client on the remote system, you can also manually test this from the command-line via:

mysql -u db_user_name -p -h ip.address.here -P 3306

Accessing MySQL or phpMyAdmin From Outside

Running .NET 3.5 App on .NET 4.5 of Windows 8 and Server 2012

There is a very easy way to run .NET 3.5 applications under .NET 4.5 (and 4.0), without having .NET 3.5 installed…

Edit the application’s app.exe.config file:

C:\WampDeveloper\WampDeveloper.exe.config

And within the “<configuration>” section, add in the support for runtime v4:

<startup>
  <supportedRuntime version="v2.0.50727"/>
  <supportedRuntime version="v4.0"/>
</startup>

The above configuration will have the system use .NET 3.5 if it finds it [.NET v3.5 uses runtime “v2.0″], otherwise it will use .NET 4.0 or 4.5 (which use runtime “v4.0″).

And if your application is having issues (e.g., nothing shows on-screen except the application border with a background color inside) on a Windows 7 + (or Server 2008 +) system with .NET v4, that also has .NET 3.5 enabled, try placing the <suppportedRuntime version="v4.0"/> line above the 2.0 line – so it tries to use .NET v4 first… As some systems with both .NET v4 and v3.5 have the later in a corrupted state.

Whether this works depends on whether the code used in the application is compatible with the changes that were made in the newer releases of .NET version and runtime. Most applications will be 100% compatible with the higher version.

Related Information

1. Graph of the default .NET version that shipped with the Windows OS version:
Windows .NET Versions

2. Microsoft documentation on the above configuration changes: How to Configure an App to Support .NET Framework 4 or 4.5

3. Microsoft documentation on which versions of .NET that can be installed per Windows OS version: .NET Framework Versions and Dependencies

MySQL Error “Incorrect integer value ” for column ‘name’ at row 1″

If a PHP script tries to set a string value, such as an empty string, into a MySQL integer data type or column, you will likely see this error message:

Incorrect integer value ” for column ‘name’ at row 1

In this situation, what is happening is that the script is attempting to insert or update a row with the integer entry taking on either the default value (e.g., of 0 or NULL) or the next AUTO_INCREMENT value.

But MySQL is not interpreting this action as valid due to its SQL_MODE being in STRICT mode.

In this case, to not treat this action as an error, edit my.ini and comment out (#) this line:

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

Save my.ini, restart MySQL.

Afterwards, the value of '' (empty string) will just default to whatever:

A. Is specified as the default value of the column (set when the table was created).

B. Is the underlining designated default value for the integer data type.

If this does not help, then the script needs to be searched (in your editor of choice) for the column name, and the PHP code or the SQL statements on the found lines edited to set either a proper value, or the column name removed from those statements.