Setting up phpThumb for a website, and I want to secure the script by using hash-url's for each image.
I have enabled the security-option in phpThumb.config.php:
// * Security configuration
$PHPTHUMB_CONFIG['high_security_enabled'] = true; // if enabled, requires 'high_security_password' set to be set and requires the use of phpThumbURL() function (at the bottom of phpThumb.config.php) to generate hashed URLs
$PHPTHUMB_CONFIG['high_security_password'] = ' '; // required if 'high_security_enabled' is true, and must be at complex (uppercase, lowercase, numbers, punctuation, etc -- punctuation is strongest, lowercase is weakest; see PasswordStrength() in phpThumb.php). You can use a password generator like http://silisoftware.com/tools/password-random.php to generate a strong password
I use the function phpThumbURL() as described in the documentation;
require_once('img/phpThumb.config.php');
echo '<img src="'.phpThumbURL('src=/wp-content/uploads/2011/08/wall140-73.jpg&w=640&h=400&zc=1').'">';
Still, all I get is Error: Invalid hash
I got phpThumbs to work without this security-option, but I really do not want to have the script open for anyone to generate thumbnail-images on my server.
I don't understand how the hash can be invalid, and why it doesn't work.
For me helped INFO at the bottom of phpThumb.config.php
//////////////////////////////////////////////////////////////////////////////
// Function for generating hashed calls to phpThumb if 'high_security_enabled'
// example:
// require_once('phpThumb/phpThumb.config.php');
// echo '<img src="'.htmlspecialchars(phpThumbURL('src=/images/pic.jpg&w=50', '/phpThumb/phpThumb.php')).'">';
so to make thumb I use function htmlspecialchars(phpThumbURL(...)):
$path = 'C:\wamp\www\_img_test\\'; // YOUR PATH
require_once($path.'phpThumb\phpThumb.config.php');
$img = '1.jpg'; // YOUR IMAGE
$ParameterString = 'w=200&h=200'; // YOUR PARAMS
$url = 'http://localhost/_img_test/'; // YOUR URL
$path = htmlspecialchars(phpThumbURL('src=../'.$img.'&'.$ParameterString, $url.'phpThumb/phpThumb.php'));
echo '<img src="'.$path.'">'; // YOUR IMAGE
echo $path; // // YOUR IMAGE PATH
Of course in phpThumb.config.php set:
$PHPTHUMB_CONFIG['high_security_enabled'] = true;
$PHPTHUMB_CONFIG['high_security_password'] = 'V_8r}ZZj-)p4vVx0H6.4'; // YOUR PASSWD from: http://silisoftware.com/tools/password-random.php
$PHPTHUMB_CONFIG['disable_debug'] = true;
For me it works.
I had an same issue, sadly on production so I had to solve it.
There is a function at the bottom of "phpThumb.config.php" which calculates hash from "$parameterString" combined with "high_security_password", this hash is compared to the hash calculated in "phpThumb.php". Everything seems to be ok, but on my case "$parameterString" in "phpThumb.config.php" contained special HTML entities and "$_SERVER['QUERY_STRING']" in phpThumb.php didn't. So my solution was to add "htmlspecialchars_decode" for "$parameterString".
phpThumb v.1.7.11
This may seem silly, but in my config it seems the error I got of "invalid hash" was due to the use of GLOBALS in the phpThumbURL function at the end of phpThumb.config.php, the reason I got an invalid hash match was because the hash check in phpThumb.php was matching using the high_security_password and high_security_url_separator, whilst the function has itself inside the phpThumb.config.php was generating it without because despite the GLOBAL declaration of $PHPTHUMB_CONFIG vars, my server was ignoring it as the php_flag register_globals was off.
I merely changed
return $path_to_phpThumb.'?'.$ParameterString.$PHPTHUMB_CONFIG['high_security_url_separator'].'hash='.md5($ParameterString.$PHPTHUMB_CONFIG['high_security_password']);
to
return $path_to_phpThumb.'?'.$ParameterString.'&'.'hash='.md5($ParameterString.'my_high_security_password');
Replacing the high_security_password and high_security_url_separator with their actual values to fix this,
As of PHP 4.2.0, the register_globals directive defaults to off,
You could I guess use .htaccess if your host allows it and add a .htaccess entry: php_flag register_globals on.
I should note I did not get any error messages to warn me that this was happening, and it took a bit of debugging to back track to the fact that no password or separator was being used in the config to generate the hash which caused the mismatch.
I even ran the phpThumb.demo.check.php which indicated that my server was ready to go and did not specify this as a potential problem.
To be fair as PHP 5 is now the standard on all webservers, with register globals off by default, having this required to be enabled for phpThumb to work as default seems like a bit of an oversight as you would expect the class to work under typical defaults for the current version of PHP.
As someone else mentioned, register_globals is off by default in most environments and removed as of PHP 5.4.0 you can still use $GLOBALS though.
Before
function phpThumbURL($ParameterString, $path_to_phpThumb='phpThumb.php') {
}
put
$GLOBALS['PHPTHUMB_CONFIG'] = $PHPTHUMB_CONFIG;
That fixed it in my case
This might seem like a rather silly question, but you did fill in a sufficiently strong high_security_password?
Allthough #user3270861 is right about what causes the issue, there's a much easier solution:
You only need to place global $PHPTHUMB_CONFIG; somewhere at the beginning of the phpThumb.config.php file, for example right after the // START USER CONFIGURATION SECTION: part.
I just bumped into this problem myself.
I was using filters in the form of url params like :
&fltr[]=mask|../images/test.png&
It was working fine on Chrome but it turns out Firefox changes the
[] into %5B%5D
So the hash was messed up.
The solution was to replace [] by %5B%5D in my url. Chrome understood it ok and firefox did not have change it.
Looks like it is going to work when working on a live environment.
It just didn't on my localhost.
Related
Long ago, this code used to work but now it seems something is going on preventing it from functioning properly. I'm hoping somebody can tell me whats going on. I'm concerned upgrades to PHP have killed this code. Or has it?
I use this code (posted below) to check and to see if an html file exists, and if it does it'll use it. If not, it will use the file index2.html.
<?php if ((file_exists("$id.html")) == true) { require ("$id.html"); } else { require ("index2.html"); } ?>
I use this code on my homepage, index.php. However for some odd reason, when I type in a link: example: index.php?id=exampleurlhere, the code isn't checking to see if the file exists and is automatically using the index2.html file, despite my code telling that if the file exists (which it does), then it's required to use it. Why is it now ignoring my command?
Been using this code for years and never had any problems with it until recently it seems. Any suggestions to fix it?
I think the problem lies in the "register_globals" setting. This used to be on by default in the (very) older versions of PHP, but has been removed in the newer versions, as this caused a lot of variable injection attacks in the old PHP.
Your $id came directly from the value in the URL. Now that it no longer auto registers, you can add in a line "$id=$_GET['id'];" just above that line to get it to work again.
This is just a quick fix. I suggest you rewrite the program so that there will not be any change of users accessing files illegally using the URL.
I'm designing a web application that can be customized based on which retail location the end user is coming from. For example, if a user is coming from a store called Farmer's Market, there may be customized content or extra links available to that user, specific to that particular store. file_exists() is used to determine if there are any customized portions of the page that need to be imported.
Up until now, we've been using a relatively insecure method, in which the item ID# and the store are simply passed in as GET parameters, and the system knows to apply them to each of the links within the page. However, we're switching to a reversible hash method, in which the store and item number are encrypted (to look something like "gd651hd8h41dg0h81"), and the pages simply decode them and assign the store and ID variables.
Since then, however, we've been running into an error that Googling extensively hasn't found me an answer for. There are several similar blocks of code, but they all look something like this:
$buttons_first = "../stores/" . $store . "/buttons_first.php";
if(file_exists($buttons_first))
{
include($buttons_first);
}
(The /stores/ directory is actually in the directory above the working one, hence the ../)
Fairly straightforward. But despite working fine when a regular ID and store is passed in, using the encrypted ID throws this error for each one of those similar statements:
Warning: file_exists() expects parameter 1 to be a valid path, string given in [url removed] on line 11
I've had the script spit back the full URL, and it appears to be assigning $store correctly. I'm running PHP 5.4.11 on 1&1 hosting (because I know they have some abnormalities in the way their servers work), if that helps any.
I got the same error before but I don't know if this solution of mine works on your problem you need to remove the "\0" try replace it:
$cleaned = strval(str_replace("\0", "", $buttons_first));
it worked on my case.
Run a var_dump(strpos($buttons_first,"\0")), this warning could come up when a path has a null byte, for security reasons. If that doesn't work, check the length of the string and make sure it is what you'd expect, just in case there are other invisible bytes.
It may be a problem with the path as it depends where you are running the script from. It's safer to use absolute paths. To get the path to the directory in which the current script is executing, you can use dirname(__FILE__).
Add / before stores/, you are better off using absolute paths.
I know this post was created on 2013 but didn't saw the common solution.
This error occurs after adding multiple to the file submit form
for example you are using files like this on php: $_FILES['file']['tmp_name']
But after the adding multiple option to the form. Your input name became file => file[]
so even if you post just one file, $_FILES['file']['tmp_name'] should be change to $_FILES['file']['tmp_name'][0]
phpThumb is a PHP library that converts large images to image thumbnails and caches the result. It takes such a syntax: http://domain.com/phpThumb.php?src=/images/image.jpg
However in my web application I'm following a strict MVC architecture, so I changed the syntax to this: http://domain.com/thumb/images%2Fimage.jpg/width/height
However now the output image is now complaining
Usage: /workspace/urs/index.php?src=/path/and/filename.jpg
Even though I've checked the $_GET dump and it reads:
array(1) {
["src"]=>
string(42) "/workspace/urs/images/portfolio/shoopm.jpg"
}
This is the code that runs up to the error (in my web application):
// If getting a thumbnail
if($qa[0] == "thumb")
{
if(!isset($qa[1]) || !isset($qa[2]) || !isset($qa[3]))
die("Bad thumb request. Needs 3 parameters!");
unset($_GET["q"]);
$_GET["src"] = $qa[1];
$_GET["w"] = $qa[2];
$_GET["h"] = $qa[3];
include("phpThumb/phpThumb.php");
exit();
}
Now, what I'm fearing is that phpThumb checks the actual URL, and not just the $_GET parameters... It's hard to confirm since the source contains thousands and thousands of lines of code and I haven't a clue where to start.
Thanks for any helpful replies
Judging from reading some of the source, it looks like it tries to do it's own PATH_INFO parsing. You can prevent this by either changing the disable_pathinfo_parsing config variable, or setting $_SERVER['PATH_INFO'] to null.
This may be important because the "Usage: ..." error happens only when the src attribute of the $phpThumb object is empty. It populates this attribute by looking for it in $_GET, and it does some pretty serious $_GET['src'] manipulation when it tries to process PATH_INFO.
In the alternative, you might want to try just using it's own native PATH_INFO-based URLs instead of your own, just to avoid the futzing.
I had a similar issue when working on a windows system.
My src paths had a mix of forward / and back \ slashes in the so I was converting them all o PHP's DIRECTORY_SEPARATOR constant (a backslash in windows).
When I converted them all to a forward slash it just worked
I am working on my first PHP based website, and I was wondering what solutions were out there for a username/password system? I have tried using a .htaccess file for basic security, and while it works, I want something a little easier for a layman to administer. Are there any other solutions out there that I could try? I don't have a database server available, so it would have to support flat file databases...thanks!
Edit I have determined that I do have SQLite support, so I do have a database option available. Also, I feel I should mention a little further some requirements that I have. I originally looked to using .htaccess to protect my website, since I need security over the entire directory. Most of the files I am trying to protect are .pdf and .doc...any solution would have to allow me to secure those files as well as any web pages in the directory.
If I could find a good solution to more or less "skin" the .htaccess method of locking a directory, so that I could do things like have an actual login/register page, etc. then I would just stick to the .htaccess method. I would however like something that is more manageable, I just need the directory security.
I wrote up this code quickly, it is syntacticly correct but I have not tested it.
There are 2 things that I did not do here, first, I did not provide a function to remove a user and second I did not provide a function to change a users password, these you'll have to write yourself.
However this should provide for a good place to start.
These functions will store your usernames/passwords in a file called passwords in the following format
username0:password0
username1:password1
username2:password2
...
.
function authenticate($username, $password)
{
//ALWAYS use a salt to secure the encryption of your passwords, this can be any value of any
//length, the longer and the more characters the better
//I like to use a "perfect password" from Steve Gibbson's https://www.grc.com/passwords.htm
//This must the exactly the same as the salt in theaddUser() function
$salt = 'voDeaFWckErOPPGwiapYBwEoc4O2d1M60m2QsYc7A15PUshrLamoVioG1wUmEgF';
//First we need to get the contents of the file that has the usernames/passwords in it.
//we don't want to use fopen() or we may end up with a locked file error if another access is
//attempted before we've closed it.
//this line will get the contents of the file named passwords and store it in the $fh variable
$fh = file_get_contents('passwords');
//Now lets take the file and split it into an array where each line is a new element in the array.
$fh = split("\n", $fh);
//Now lets loop over the entire array spliting each row into it's username/password pair
foreach($fh as $r)
{
//Every time this loop runs $r will be populated with a new row
//Lets split the line into it's username/password pairs.
$p = split(':', $p);
//Since we don't need all the usernames/password to be in memory lets stop when we find the one we need
if($p[0] == $username && $p[1] == sha1($salt . $password))
{
//We've found the correct use so lets stop looping and return true
return true;
}
}
//If we've reached this point in the code then we did not find the user with the correct password in the 'database'
//so we'll just return false
return false;
}
function addUser($username, $password)
{
//ALWAYS use a salt to secure the encryption of your passwords, this can be any value of any
//length, the longer and the more characters the better
//I like to use a "perfect password" from Steve Gibbson's https://www.grc.com/passwords.htm
//This must the exactly the same as the salt in the authenticate() function
$salt = 'voDeaFWckErOPPGwiapYBwEoc4O2d1M60m2QsYc7A15PUshrLamoVioG1wUmEgF';
//We need to parse out some preticularly bad characters from the user name such as : which is used to seperate the username and password
//and \r and \n which is the new line character which seperates our lines
$username = preg_replace('/\r|\n|\:/', '', $username);
//Now lets encrypt our password with the salt added
$password = sha1($salt . $password);
//Lets build the new line that is going to be added
$line = $username . ':' . $password . "\n";
//Lets open the file in append mode so that the pointer will be placed at the end of the file
$fh = fopen('passwords', 'a');
//Write the new entry to the file
fwrite($fh, $line);
//Close the file
fclose($fh);
//Typicaly one would write a bunch of error handling code on the above statments and if something
//goes wrong then return false but if you make it this far in the code then return true
return true;
}
Have a look at Zend_Auth. It's open source, so you can sniff around to get a feel for how an authentication module should (or could) be implemented. From the doc:
Zend_Auth is concerned only with
authentication and not with
authorization. Authentication is
loosely defined as determining whether
an entity actually is what it purports
to be (i.e., identification), based on
some set of credentials.
Sure, there are plenty of flat file database PHP security systems available. Doing a quick Google search will pull up many results. Here is a tutorial:
http://www.devshed.com/c/a/PHP/Private-Pages-with-PHP-and-Text-Files/
Check if you have support for sqlite, it doesn't require a server so it might work for you.
And don't forget to hash your passwords. ;)
To check create a file (ex. php_info.php) add:
<?php
phpinfo();
Then upload the file to your host, load it in your browser (example.com/php_info.php) and do a search for sqlite.
You should see several references to sqlite in the page that shows if you have support. The line with "SQLite Library" will tell you the version of sqlite you have (if you have it).
Also once you are done you should delete the php_info.php file from your site, since it does give some information on your setup which can be helpful to crackers.
have you seen if you have SQLite available? It is PHP's built in database. If not you could just use read/write to a file hope this helps a bit
According to this page from the Apache website:
In general, you should never use .htaccess files unless you don't have access to the main server configuration file. There is, for example, a prevailing misconception that user authentication should always be done in .htaccess files. This is simply not the case. You can put user authentication configurations in the main server configuration, and this is, in fact, the preferred way to do things.
Its easy to see why this is so, too. Its far preferable to have centralized control, rather than digging through EVERY SINGLE DIRECTORY when debugging a faulty configuration.
I urge you to transfer your .htaccess file config to your main configuration file ASAP, for your own good!
I have inherited some legacy PHP code what was written back when it was standard practice to use register_globals (As of PHP 4.2.0, this directive defaults to off, released 22. Apr 2002).
We know now that it is bad for security to have it enabled. The problem is how do I find all the places in the code where I need to use $_GET or $_POST? My only thought was to set the error reporting to warn about uninitialized variables and then test each part of the site. Is there an easier way? Will I have to test each code path in the site or will PHP give a warning on a file basis?
If you set error reporting to E_ALL, it warns in the error log about undefined variables complete with filename and line number (assuming you are logging to a file). However, it will warn only if when it comes across an undefined variable, so I think you will have to test each code path. Running php from the command line doesn't seem to help also.
There is a debugging tool named xdebug, haven't tried it, but maybe that can be useful?
I wrote a script using the built-in Tokenizer functions. Its pretty rough but it worked for the code base I was working on. I believe you could also use CodeSniffer.
You could manually 'fake' the register globals effect but add some security. (I partly grabbed this from the osCommerce fork called xoops)
// Detect bad global variables
$bad_global_list = array('GLOBALS', '_SESSION', 'HTTP_SESSION_VARS', '_GET', 'HTTP_GET_VARS', '_POST', 'HTTP_POST_VARS', '_COOKIE', 'HTTP_COOKIE_VARS', '_REQUEST', '_SERVER', 'HTTP_SERVER_VARS', '_ENV', 'HTTP_ENV_VARS', '_FILES', 'HTTP_POST_FILES');
foreach ($bad_global_list as $bad_global ) {
if ( isset( $_REQUEST[$bad_global] ) ) {
die('Bad Global');
}
}
// Make global variables
foreach ($_REQUEST as $name -> $value) {
$$name = $value; // Creates a varable nammed $name equal to $value.
}
Though you'd want to tweak it to make your code more secure, at least by adding your global configuration variables (like the path and base url) to the bad globals list.
You could also use it to easily compile a list of all used get/post variables to help you eventually replace all occurrences of, say $return_url, with $_REQUEST['return_url];
I know that there's a way to set php.ini values for that script with a certain command, I thus went looking and found this too - Goto last post on page
I also found the following post which may be of use - Goto last post on the page
I will add to this more if nobody has found an answer but I must now catch a train.