I've written a licensing script for some modifications I release freely, and part of my terms and conditions states that upon installation the modification will send the following information for storing in my database:-
Domain Name where the mod is installed
Email address of the site owner
Modification name
Modification version number
All of my modification code is ioncube encrypted, and I'm sending the values through an image URL like so:
http://www.example.com/licenses.php?modname=".$modname."&modversion=".$modversion."&domain=".$domain."&email=".$email."
I'm using an image so that I can return an image to the users browser showing whether a code update is available based on what the user currently has installed.
I'd like to ensure user privacy when sending between domains and send these values encoded, but I'm unsure what encryption is the most appropriate for this situation? I need to be able to decode the values for comparison against the database, but anything that can be decoded by me could easily be decoded by anyone else? What am I missing here? I'm sure others have tried to do this thousands of times before.
Any pointers would be most appreciated.
Don't reinvent the wheel. Use HTTPS/TLS/SSL. If you tell us what web server you're using for the destination, we can point you to setup guides. You may want to use POST in addition. However, it's not really necessary, because TLS will protect the entire query string. A common reason to use POST for secure data is to prevent people accidentally storing data in bookmarks, history, etc., which I don't think applies here.
"I need to be able to decode the values for comparison against the database, but anything that can be decoded by me could easily be decoded by anyone else?"
You can check mcrypt.* and mdecrypt.* which provide symmetric encryption and decryption using libmcrypt (available at the php manual).
you might try to alter your app a bit so that the customer registers on your system and then they get something like an API key which is passed back to you. That way you don't have to pass back their personal information on every request - just pass the anonymous API key.
otherwise you can crypt the data, but people will be able to see your crypt key. you could use public key encryption, of course but that may be tricky to implement
If you have a dedicated server running Apache, you can always rewrite htaccess modules.
This way you can hide Get variables or show to users whatever you want.
#Matthew Flaschen is a viable option too.
Related
I have built a simple read-only API for our database, so that users can retrieve data from our database.
For example, the URL "http://xxxxx/getAllProfiles" will return a JSON result containing all profiles stored in the database.
The API is read-only, it is only implemented with some 'select' SQL queries. Thus the user cannot modify any of the data in the database via the API.
My company worries the API will be exploited by some random bots online, and has been asking me to build a security mechanism for this API. (It is worried if there is no key or something that prevents anyone from accessing the URL, our server would be visited too much. It is a small server.)
What would be the simplest secure mechanism that I can implement, using PHP? (We are also using Slim for the API, Amazon EC2 server with Ubuntu and Apache running on it, if this helps.) Preferably it can be implemented without the use of any database on server or client side.
If there's anything not clear, please let me know, I'll clarify.
Thanks.
Add:
Thanks for the comments.
Is there a way to NOT use a database? Like a smart way to generate a key or something... I'm thinking I'll provide a page so that user can input the domain, and an algorithm will convert this domain to a key. Then, for each request, the user should include this key. The server will grab the domain from the request header and use the same algorithm to calculate again. If the two calculated key matches, the request is accepted. I think this, at a minimum level, ensures that at the beginning there must be someone to input the domain and get the key, thus filtering some random bots out?
I am not sure if this is secure (at all)? But it sounds to me like it can filter out something.
I posted this question when I know very little about web development.
There are many ways to secure a REST API, e.g. JWT, Cookie, Basic Auth, etc.
I have a website which is a front end to a MySQL database. This data is also exposed via a web service (fur use in Android application).
Currently I am maintaining the data via PHPMyAdmin but this is cumbersome and not that "pretty".
I want to create an /admin module where I log in (against values in a PHP Varialbe or a MySQL table) and once logged in I can edit,delete,add data.
Questions:
Is it acceptable in terms of security to compare entered credentials against static variables? There will only be one user so I feel like it is overhead to create a table for members.
Any guidelines on going down this route?
I don't see any reason why you couldn't do it this way, assuming you will always have just the one user. The main consideration would be if someone somehow got a look at your code, they would see the stored password. So, you could store it using password_hash to generate a one way hash, and then verify it with password_verify. Here's how I might do it:
Using password_hash(), generate a hash:
// copy the hash output, then delete this code
echo password_hash("thepassword", PASSWORD_DEFAULT);
Then, in your code, store the hash:
// paste hash here
$passwordKey = '$2y$10$j33UPA7gNxSOBsXQcyquLOZRuO6X8k8hZOb1RA79iN8gLlqp9eIPO';
Then run password_verify() to check the user input:
if (password_verify($userInput, $passwordKey))
echo "correct";
else echo "incorrect";
Demo: http://3v4l.org/PknTI
consider looking at this manual for encryption methods with php. My gut instinct is to make a user table, or at least a table with just the encrypted password in it, rather than just checking the variable against a value.
That being said, if you don't think anyone will really even consider trying to fool around with the system and get past it, you probably don't need to be this cautious. I've built a few front-ends as well as back-ends to communicate somewhat friendly with a database, and I've never experienced a considerable amount pressure on the security.
Hope this helps, if you have any questions about how I've designed the ones I've made, feel free to email me at spencer#codeshrub.com
If phpmyadmin is installed at your server localy, than it is NOT securely at all
You can use any MySQL client that supports ssh connection. E.g. Sequel Pro for Mac or HeidiSQL for WIN.
Also, you can use basic HTTP Authentication for you admin script. But, since it's very simple it's not protect you from bruteforce or password leaking, etc.
Anyway, if you prefer security you need to make your own authentication in PHP, You can use this package for example. It is simple and has many security features
I use the following url when I edit a post from the user :
../post/edit/3 //If the id of the post is 3 for example
To avoid that the user modifies the url intentionally, for example /post/edit/5, I use the following logic to make sure the user doesn't edit the post when he doesn't have permission:
if (//user is allowed to edit post){
//edit post
}
else {
throw new AccessDeniedException('You do not have the permission to edit this post');
}
Is this the general approach that you use when editing a post? Is there a way to do something cleaner so that the user cannot play with the id of the post in the url?
EDIT
The more I think about it, the more I realize that I have never seen an id in a url like this in a website that is concerned with security. So, I agree we can still use the id and check if the user can show/see this id, but still the user can already do too much.
Wouldn't it be better to hash the id, allowing us to generate a new encrypted ID using any available algorithm:
<?php
echo hash('md5', 'id_to_edit');
?>
What is the standard approach to secure an id in a url? In general, is it a good idea to display info like the id in a url?
Special situations may call for special measures, but in a typical situation, all that is necessary is:
Use SSL so that sessions can't be hijacked by eavesdroppers
Check the user's permissions before doing anything.
Plenty of sites do it similar to the way you described initially. For example, WordPress has URLs like https://example.com/wp-admin/post.php?post=112&action=edit. Clearly, a curious user could choose to edit the post=112 part.
So, one standard you might consider is: "Do I need to be more concerned about security and privacy than WordPress?"
If, for example, you don't want people looking at log files to know what IP addresses are editing what posts, you have a few options. Each approach has trade-offs so what the best one is will depend on what your biggest concerns are.
For example:
You might use a hash to conceal the post id number, like you suggest in your update to your question.
Or you might just send that info via a POST method (instead of GET) over SSL and not include it in your URL at all.
One advantage of the first approach is that people can use bookmarks to get back to the page. You might not want that. Or you might. Depends on your app.
One advantage of the second approach is that (for example) Google Analytics won't reveal if one post id is being accessed/edited over and over again or if many post ids are being accessed/edited. This may matter to you depending on whether such information might tell someone something and who has access to your Google Analytics stuff. Or it might not matter at all.
There are a lot of other possible considerations too, such as performance.
By the way, if you do use MD5, be sure to include something in the input that an attacker will not know. Otherwise, it will be trivial for an attacker to reverse a discovered hash via a lookup table and generate further legitimate hashes for sequential post ids. In PHP, you'd want to do something like:
hash('md5', $some_hard_to_guess_secret_string . $data_you_wish_to_hash);
There is no single best practice that applies to every situation. But in a typical situation, it is not necessary to hash the post id value or even send it through POST. In a typical situation, be sure to use SSL (so that sessions can't be hijacked) and check user permissions before doing anything and you are likely good to go.
You must treat all data coming from the client as suspect. This includes the URL. You should check that this client is indeed authenticated and that he is authorized to perform whatever action is indicated (by the URL, post data, etc). This is true even if you are only displaying data, not changing it.
It is not important if the record id is easily seen or modifiable in the URL. What matters is what can be done with it. Unless the id itself imparts some information (which would be surprising), there is no need hide it or obfuscate it. Just make sure you only respond to authenticated and authorized requests.
check permissions
don't use GET values for validation, authentication, authorization. session, post variables are ok.
to make things interesting... $x =md5(random number + post_id + userid) send all the values seperately like /edit/3?id=$x&y=rand_number when you get back to the edit page you check everything. else throw them an exception.
few more ideas involve db but if you are interested.
That's standard approach. You should alwasy check permissions on both: showing form and on action after submiting the form.
Regardless if you hash the ID or not, you must check permissions when editing a post, or someone could potentially stumble upon a page they are not supposed to be able to edit and they could cause serious damage. This could either be through randomly guessing, or through browsing through the history of another user that used your app.
Check permission before allowing someone to edit something.
That isn't to say you can't hash your IDs so they aren't quite as linear, but take a look at popular applications such as Wordpress, or even Stack Overflow. They are all based on incrementing numbers because regardless of knowing the ID or not, if you don't have permission, you can't edit it.
Obfuscating IDs will not increase security. As previously mentioned - you should always check permissions.
The reason why you might have an impression that you haven't seen url like this in a website that is concerned with security is because some of those websites are usually running on something like Java or .Net, and are using GUIDs ( http://en.wikipedia.org/wiki/Globally_unique_identifier ). Some of them however are using sequential IDs (e.g. gmail is using sequential IDs for emails).
MD5'ing is not a good idea. Cracking it is really easy, especially if it's something like md5(5684). I've looked up couple of hashes of numbers <100.000 here http://md5.noisette.ch/index.php and it found every single of them.
It can be better to use ACL for that. You can configure your application to deny everything and use ACL to give an access to the specific object.
It's a common practice not to use any hashes instead of ids in URL. Clean id allows you to grep apache logs, application logs with simple command. All logic must be in the code to give or deny access to the specific domain entity.
How much more secure do you need to be than checking if the user that's already confirmed who they are (logged in) has permission to edit the post in question? If you simply had a hashed value displayed in the address bar it would still be relatively easy to find the hashing algorithm and then they could still have control over what post they're trying to edit. Security through obscurity will always be a false sense of security.
I'm sending data from an Android app to a php script which recieves the information and procces it, I've found a security issue: if someone discovered the url (for example: mydomain.com/recievedata.php), anyone would be able to send data to my system.
What's the ideal method to ensure the client sending the data is the app?
Thanks!
One easy way that I've seen some companies do is to include a secret key. For example, you might have a secret=3CH6knCsYmvA2va8GrHk4mf3JqmUctCM parameter to your POST data. Then all you need at the top of receivedata.php is
if($_POST['secret'] != '3CH6knCsYmvA2va8GrHk4mf3JqmUctCM') {
header('HTTP/1.1 403 Forbidden');
error_log("ERROR: wrong secret: " . $_POST['secret']);
exit("Access denied");
}
You can easily generate the random string from random.org.
Of course, this is not the most secure method and that string might well be stored in plaintext in the APK (don't use this to send launch codes!), but it's easy and good enough to keep most people out. This might be adequate for, say, sending player scores for a game.
It's more like a PHP question. Here are the things you should do for security ;
Add a hash between your app and your PHP to sync (AKA secret key)
Make sure your script controls every input data
DO NOT send datas to query without escaping them (SQL Inject)
Try to use POST instead of GET or REQUEST
Keep your functions private as much as possible
Always parse the data you receieve (Check if its a number, or string or array etc)
With these, noone will be able to use any of your PHP files without your app. And they won't be able to receive any data without your permissions
The only proper way is not trusting the data you receive. Always treat it in a way suitable for crafted data coming from a bad guy.
Here's the story:
I have to pass some classified information from one script to another script. In the first script I need to encrypt the data first and then I have to attach the encrypted data into a GET request and send it to another script. The URL would look like this:
http://mydomain.com/mysecondscript.php?secret={encrypted stuff}
My current encrypt method is based on base64. The problem with this method is, that if I have a lot of stuff to encrypt, the encrypted result could get very long. If it's longer than 255 characters or so, the second script will not be able to decrypt it because the string will be chopped.
So I'm looking for a better encryption method, that can control the length of the encrypted result.
DANGER!
Base64 is NOT a form of encryption, but encoding. Base64 encoded strings are easy to recognize and trivial to decode. Base64 is used to encode data so they can be safely transmitted across non-binary safe medium (such as URLs and emails), but they do not hide the data itself.
What you need to do is encrypt the string using AES (see PHP's mcrypt), then base64 encode it. This of course will not solve your length problem. The question is pretty vague, but what you can do is:
Use POST instead of GET.
Store data in a database or a file which both scripts can access. Then just generate a sort of identifier and send it with the URL. The receiving script can use this identifier to retrieve the data. As an added bonus you won't have to send classified data with the URL.
EDIT: Now that I read your question more carefully, it seems like both scripts are sitting on the same server. In this case there is no reason whatsoever to pass this data via HTTP.
No matter how secure your encryption scheme is you will still need to base64 or URL-encode the result which, you have discovered, will likely exceed 255 characters. The best you can do is compress the data, then encrypt it, then encode it. It will still probably fail. You need to find an alternative to GET.
Why does it have to be transmitted in the URL at all? Save it to disk, put it in the database, add it to a message passing queue...
You can use an opaque token in the URL to identify which thing you're talking about, and then turn that token back into a useful thing on the other end by querying whatever storage mechanism you choose.
If this is sensitive information, base64 should not be used as it can be decoded easily. If you want the information to be securely encrypted, you shoule use PHP Mcrypt (link). Much more secure and can support encryption of much longer strings. Best of all, you set your own key and it cannot be decrypted without that key. It make require a tiny bit more work, but it will be safe. Also, if you are passing multiple variables that way, you can set them into an array, serialize and encrypt the array, pass the array via GET, and then decrypt/unserialize. It's as simple as that. One last thing, there are also some classes out there that will make Mcrypt a lot easier to use. May want to google to find one, it will make your life easier.
You can use MD5 to create a hash of the id so you get something like:
http://www.demo.com/displaycommittees.php?id=81dc9bdb52d04dc20036dbd8313ed055
In your db query you can do a select on the users table including a WHERE statement that also hashes the id column like:
WHERE MD5(id) = $_GET[id]
This works fine and i have always applied this algorithm. for instance assuming the actual value of the encrypted id 23, if you try to put 23 in place of the encrypted(hash) code it will not work( no result will be display).
Note: Reasons are best known to those who need a solution, so the question "why" may not come in for those who need it. they only ask for a solution and if it works fine for them, nice. But for transaction application (e.g cash transaction or transaction pins) please do avoid passing sensitive information via URL, because it can easily be cracked.
See more at: http://softideass.blogspot.com/