I have this url:
https://www.example.com/?p=user#provider.it
What is the best way to encrypt the email inside my URL in order to don't let user knows there is an email in the URL, something like:
https://www.example.com/?p=skckqbsBDoia27d
Obviously I will be able to decrypt skckqbsBDoia27d to get user#provider.it and skckqbsBDoia27d MUST be unique based on email.
The solution MUST works with PHP 5.5.
Use base64_encode() and base64_decode() accordingly.
some#email.com will get encoded as c29tZUBlbWFpbC5jb20=
$email = "some#email.com";
$url = "http://www.example.com?param=" . strrev(base64_encode($email));
Then on the receiving side:
echo base64_decode(strrev($_GET['param']));
If you're concerned about disclosing email then the best way would be to just not include the email in any form. Rather, use some other unique identifier that's associated with the user record. If it's not important that it be unguessable, you can just use the database row's pkey field user.id or whatever. If it needs to be unguessable, I'd create a new field like user.public_id with a unique constraint and then populate it with a hash or uuid.
Related
For a simple mailinglist, i use flat-file (.txt) files for storing the date from subscribers.
The name of the .txt files is the same as the id i assign to a subscriber.
A .txt file with the data inside (name and email) looks so something like this:
id-8759874589.txt
In every email i send, i send an unsubscribe link so that the subscriber can unsubscribe from receiving mails. I encode the unsubscribe link with base64_encode. Only for the mask of the eye.
An unsubscribe-link looks something like this:
http://example.com/unsubscribe.php?id=aWQtMjAxOTEyMjMNDUyMTQ%3D&email=amNtZy5tYWVzc2VuQGdtYWlsLmNvbQ%3D%3D
For unsubscribing, i use this code:
<?php
$id = $_GET['id'];
$email = $_GET['email'];
// decode the id and email string
$id_decode = base64_decode($id);
$email_decode = base64_decode($email);
if( isset($id_decode) ) {
$filename = 'subscribers/'.$id_decode.'.txt';
// delete subscribers entry
if(file_exists($filename)) {
unlink($filename);
echo '<div class="alert alert-success"><b>'.$email_decode.'</b> is successfully removed from our mailinglist!</div>';
}
else {
echo '<div class="alert alert-danger">Email not found or you already have unsubscribed from our mailinglist!</div>';
}
}
?>
As you can see: the id, which is assigned to the .txt file, will be unlinked. The subscriber is deleted from the mailinglist.
My worries:
Lets say: you were a subscriber and you did unsubscribe, then you know how the url is created.
You can start guessing: How will the subscriber be unsubscribed? Lets say: you know that every subscriber has his data in a .txt file with the name of the id. You can let a robot guess the identities in the url string and execute this url. In worse case scenario, he found an id that really exists and the file will be deleted. A random subscriber is removed from the list without doing itself.
How can i protect this better?
Create a unique code and store this code in the file, also provide this code in unsubscribe url:
http://example.com/unsubscribe.php?id=aWQtMjAxOTEyMjMNDUyMTQ%3D&email=amNtZy5tYWVzc2VuQGdtYWlsLmNvbQ%3D%3D&token=WHATEVER
In this case you can also get a token from url as $_GET['token'] and check if it is the same as one in the file. If it is the same (and no one except you knows the algorithm with which token is created) - you can unsubscribe the user. In case of failure you can consider that someone is cheating)
You should worry when you only encode your parameters.
As you already expected gives Base64 no security, also the fact that you expect an Id and a email gives information to hack you.
The third risk is your response, there you als give information away, just inform your that the request is processed.
You should use encryption see to be safe.
I need to append an user id to a public url, I'm not a security expert and I need to know the best way to secure it.
I thougt that cypher the id and the append it to the url, and decypher it on the function called by the url, but I need to be the only one thant can decypher it.
Any suggestions?
If you want a one-time-only or limited-time-only unique ID to give to the user (I'm guessing this is maybe in some kind of email link or something?) then you could potentially create a GUID or UUID and associate that with the user (via a database table perhaps), and have a field to mark when it's been used or expired.
A GUID/UUID is near-enough guaranteed to be unique and isn't easy to randomly guess.
The best way to do that is by implementing a SSO mecanism (Single Sign On).
The user will enter his password on the first app and use a secure link to access the second app.
The first app generates a public key encrypted with a private key known by the two apps.
The second app generates the public key to and if it matches the key appended to the URL then its safe to log the user.
Here an example :
The first app will create a public key :
$privateKey = `123azerty456`;
$publicKey = hash('sha512', 'user_id' . $privateKey);
$url = 'second_app.com/example.php?user_id=foo&key='.$publicKey;
The script on the second app will compute the key on its own based on the user_id passed as an argument and using the same private key :
$privateKey = `123azerty456`;
$checkPublicKey = hash('sha512', $_GET['user_id'] . $privateKey);
if($checkPublicKey == $_GET['key']) {
echo 'OK';
} else {
echo 'UNAUTHORIZED';
}
I am making a plugin that provides a form, letting anyone submit a post to my Wordpress site (custom post type). I am looking for a very basic means of deterring bots/spammers though, so I want to e-mail a confirmation code that they can click and change the status to Published.
I would prefer not to store anything in the database, so I was thinking of just sending something like "verification.php?id=12", where the ID is the post ID. That is pretty obvious though, so I would like to make that single number look more complex, then "decrypt" it when the link is clicked to reveal the actual Post ID.
Pseudo Code:
If ($_GET['veriID'] != '')
$lastchar = substr($_GET['veriID'], -1);
publish_post($lastchar);
What would be some options to achieve this? Should I just generate a random string and append the post ID to the end or is there a better method?
You can use HMAC to authenticate the request. The resulting url will look like the following:
.../verification.php?post=12&hash=5f13532e49447facaa3dce9080bfffec3c6731eca6b4d590670dd0b1137e7476
To generate the hash, the HMAC algorithm is used. This has the advantage that a secret value is used. Therefore the value cannot be computed by the message (the post id) alone.
Code to generate the hash value:
define('secret', 'really super secret value');
$post_id = 12;
// Get the hash
echo hash_hmac('sha256', $post_id, secret);
You can store the secret in a constant value or better: one per plugin-installation.
Since you can always compute the hash from the post-id, no data needs to be stored in a database.
You could always encode the post ID as base64, then decode on confirmation.
This will be relatively obvious to most programmers, but not necessarily to the average user.
http://php.net/manual/en/function.base64-encode.php
A simple way would be adding a custom field to your post and store a random code in it like this
$code = '';
for ( $i = 1; $i <= 3; ++$i ) {
$code .= chr(rand(97,122)) . rand(0,9);
}
Its true this is stored in the db post meta but you will not be explicitly doing it instead you do it the same way WP works by using:
get_post_meta( $post_id, $key, true );
Is checking against my table with the user's email and dedicated hash enough to verify and activate an account if a match is found against those two values?
A user is asked to register themselves with user data and their email id. They are then sent a URL to their email which they are asked to click on to confirm and activate their account.
This is my current setup:
<?php //The user-account-creation processing page
$email_id = taken from user input;
$randomnessWhateverItsCalled = "lots-of-randomness-here";
UPDATE advert SET advert_hash = SHA1(CONCAT($email_id, $randomnessWhateverItsCalled))
//For simplicity's sake I omitted the PDO stuff
INSERT INTO table_name (..., user_email, hash, account_activated, ...) VALUES (..., usersEmail, advert_hash, NO, ...)
/**
Send an email with some php code with the URL that would look like this
URL to click on attached to email body:
*/
$attachStringToEmailBody = "http://www.domainname.com/activate-user?email_id=" . $usersEmail . "&hash=" . $randomnessWhateverItsCalled;
enter code here
//Send email from this process page with a little email php code
//Redirect user to a page informing the user to activate the account by visiting their email and clicking on the url
?>
Then in the activate-user.php page I have the following:
<?ph
$user_email = $_GET['email_id'];
$hash = $_GET['hash'];
/**
search database and return a row if there is a match containing both the $user_email and the $hash
if(match){
Update database and set the `account_activated` column to `YES`
}
else{
//Tell if there was no match then activation failed
//Let the user know that we do not recognise the link they used to try and activate their account.
}
*/
?>
It seems secure enough, as long as you made the "randomness" part hard to guess. You can put there the email, username, password, etc. and mix them up with another key - all encrypted - that's what I usually do.
But I would advise you to use 0/1 for active/inactive - why using strings, when you can do the same with smallint (1) - and save some space, thus making the database a bit lighter ?
Sorry if the title's unclear, couldn't think of anything better since I'm still new to this area. :)
Anyway, my question is this: I want to send some information from one page (let's call it 1.php) to another page (let's call it 2.php) using this (don't know the formal name, sorry):
http://localhost/X/2.php?user_id=5&user_type=2&ssn=1234567890&first_name=John&last_name=Doe
As you can see, the information is in plain text, which I dislike. Is there an easy way to encrypt the string after the question mark above in 1.php, and then let the 2.php (that gets the passed-along info) decrypt it? I'd like for it to be something along:
http://localhost/X/2.php?user_id=rj3i15k&user_type=8109fk1JIf&ssn=6893kfj399JFk...
Sorry if this is a stupid question. Many thanks in advance!
If you don't want information to be modified, use a hash string to verify them.
For instance :
$hash = sha1($user_id."haha".$user_type.$ssn.$first_name.$last_name);
The "haha" here, is a salt. Use a random string, it will be use so someone can't reuse your algorithm to inject fake data.
Then put this hash at the end of your url, eg
http://localhost/X/2.php?user_id=5&user_type=2&ssn=1234567890&first_name=John&last_name=Doe&hash=$hash`
When you'll get this information, make the hash again, and compare it to the hash sent : If the information was modified, the hash won't match.
Maybe you're going about it the wrong way.
Thought about storing the data in a serverside session variable?
Or even in a database (if you're passing to another machine), then you just need to send the unique identifier of the database entry.
page2 will then read the session variable, or retrieve it out of the database again.
Basically, keep the data serverside and then you wont need to encrypt/decrypt.
Session Example:
page1
<?
session_start();
$_SESSION['pagedata'] = array(
'user_id'=>5,
'user_type'=>2,
'ssn'=>1234567890,
'first_name'=>'John',
'last_name'=>'Doe'
);
header('Location: page2.php');
?>
page2
<?
session_start();
$user_id = $_SESSION['pagedata']['user_id'];
$user_type = $_SESSION['pagedata']['user_type'];
$user_ssn = $_SESSION['pagedata']['user_ssn'];
$user_first_name = $_SESSION['pagedata']['first_name'];
$user_last_name = $_SESSION['pagedata']['last_name'];
// use variables to do stuff
?>
Its called GET, never relate 100% on 2 Way Decryption but this may help you Best way to use PHP to encrypt and decrypt passwords?
you could use base64_encode on the one side and bas64_decode on the other - just as one possibility - but note that this is only for "better looking" url als you want it (for me, this is ugly). this isn't encrypting your data for being more safe or something like that - to achive this, use https and don't confuse your users by doing such crazy stuff.
You should use $_SESSION.