Safely passing ids to form action? - php

Until now i have been using hidden fields in forms to pass data to the actions php. However i realise this is a massive security risk to the application and would like to be educated of the best method to currently passing form data from hidden fields in php?
<input type="hidden" value="sensitive_info">
Alex

I think sessions are probably what you're looking for.
See http://www.w3schools.com/php/php_sessions.asp for a nice easy guide to using them.
You need session_start(); at the very top of your php script, and then you can store information like so:
$_SESSION["stuff"] = "sensitive info";
Then simply access it on the next page with:
$stuff = $_SESSION["stuff"];
Simple :)
P.S. Make sure session_start(); is at the top of every php script that uses the session variables.

If you're unable to use sessions for some reason, you can always encrypt the ID. This is probably not ultra secure, but will prevent all but the most determined from mucking with things.
<?php
define("KEY", "Something much more random than this");
function encrypt($key, $plaintext)
{
$iv_size = openssl_cipher_iv_length('AES-256-CBC');
$iv = openssl_random_pseudo_bytes($iv_size);
$ciphertext = openssl_encrypt($plaintext, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
return base64_encode($iv . $ciphertext);
}
function decrypt($key, $ciphertext)
{
$iv_size = openssl_cipher_iv_length('AES-256-CBC');
$ciphertext = base64_decode($ciphertext);
$iv = substr($ciphertext, 0, $iv_size);
return openssl_decrypt(substr($ciphertext, $iv_size), 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
}
$encrypted_id = encrypt(KEY, $database_id);
?>
<input name="foo" type="hidden" value="<?php echo $encrypted_id?>"/>

Related

PHP Encrypt and Decrypt Parameter URL in URL

I'm trying to pass a download URL from page 1 to page 2 in a GET request.
Page 1 gets the raw URL through the database, then encrypts the URL and makes it available on the site. When it's passed through the URL, page 2 decrypts the URL and downloads the file.
The URL looks like this currently:
https://example.com/download.php?dl=x6%1A%D8j%C4%D2%9Cx%8FA%8B%29%23Y%D9%D6%B4%DE8%18%2C%7B%F4%86l%B0%0A+%D3%B1%01I%CFo%FF%BA%9C%22%A1%08%11%DB%12%282%DEi%B5%CA%14K%FF%21%CB%F3%9D%3C9f%3C%09%FA9%BB%BD%C9%B2%275%F0%06%A2%80%08h%A7f%8C%87%28%A4%A5%99%A9%A9%FA%D6f%C5%CA%9B%81.%92%CD%89%FA3%5C%0C%F0%ED%F6%D9%1E%B9%D0%B1%CFSA%F4%95k%1EZ%D1%3A%D4H%1D%93%40%087%92%88%C3%A5p%C7WH%FA%CF%9D%BAKd%A0%9A%D7a6%80%5Ex%A5%87%07AK%D7%5BQ%10%98%07%7E%82%9A%BA9%25%D5%EA%03%FD%C2%9A%22%8FBW%94k%D8T%93%F5%E3%D7-
It contains a lot of %%% because it's urlencoded, is there a way to change this to make the URL less long and make it look less messy, but keep it safe as it is now?
Hope someone can help me out.
This is the encryption and decryption script:
define("ENCRYPTION_KEY", "ducksandpizza");
function encrypt($pure_string, $encryption_key) {
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv);
return urlencode($encrypted_string);
}
function decrypt($encrypted_string, $encryption_key) {
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$decrypted_string = urldecode($encrypted_string);
$decrypted_string = mcrypt_decrypt(MCRYPT_BLOWFISH, $encryption_key, $encrypted_string, MCRYPT_MODE_ECB, $iv);
return $decrypted_string;
}
//$encrypted = encrypt($_GET['dl'], ENCRYPTION_KEY);
$decrypted = decrypt($_GET['dl'], ENCRYPTION_KEY);
//echo 'encrypted: ' . $encrypted . '<br>';
echo 'decrypted: ' . $decrypted . '<br>';
Use some type of compression on the unencrypted data, like gzcompress() and then pass that to your encryption method, and the output of that to base64_encode. Base64 encoding will still increase the overall size, but not as much as url encode does.
While using base64_encode() isn't necessarily a bad idea, no one has mentioned that stock base64 encoding is not URL-safe as it uses the characters significant in URL syntax.
However, there's a variant that is safe that's used for encoding JWT tokens:
function base64url_encode($bin) {
return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($bin));
}
function base64url_decode($str) {
return base64_decode(str_replace(['-', '_'], ['+', '/'], $str));
}
You should also bear in mind the GET requests are subject to length restrictions which vary between HTTP server implementations and languages. You'll probably want to use something like gzcompress() as suggested in the comments, but more likely you should be passing this data in a POST instead.

How to always get the same results when encrypting a string?

I have this function to encrypt strings:
public function encriptar($string) {
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC),
MCRYPT_DEV_URANDOM);
$encrypted = base64_encode($iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_128,
hash('sha256', getKey(), true),
$string, MCRYPT_MODE_CBC, $iv));
return $encrypted;
}
The problem is that I always return a different value even adding the same string.
Example:
I introduce: StackOverflow
Result: InT3g0AUXXTrmCAxrlht5ZVe8GBmlgGDMotXuVu11hI =
If I rerun the script:
I introduce: StackOverflow
Result: ImhWn5vPA / A2NY2wpUwg7VLWAiGBls80Z84fGU303Ws =
If I re-run the script:
I introduce: StackOverflow
Result: FqvxSsblSwz5riaDnnq7h20PzZTPdk / K + dikLHbLHTY =
How can I make it always the same value?
You are creating a different $iv using MCRYPT_DEV_URANDOM as the pseudo-random-number-generator, use the same $iv, and the result will be the same.
You can either store it in you database, in the class instance, or store it as a prefix/suffix of the final hash.
Albeit you shouldn't be reusing the $iv for security purposes...
A more insightful topic of the security implications of reusing the key, or even the IV can be found here: https://crypto.stackexchange.com/questions/10505/reusing-keys-with-aes-cbc
The result is dependent on the $iv variable which you keep regenerating. You need to generate it only once, save it in the database and then re-use it.
function getIv($database) {
// fictive database abstraction layer
$iv = $database->fetchIv();
if (!$iv) {
$iv = mcrypt_create_iv(
mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC),
MCRYPT_DEV_URANDOM
);
$database->saveIv($iv);
}
return $iv;
}
// in your class
public function encriptar($string) {
$encrypted = base64_encode($iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_128,
hash('sha256', getKey(), true),
$string, MCRYPT_MODE_CBC, getIv()));
return $encrypted;
}
However, for best practices, this should be kept in a configuration file.

Encrypt a string in PHP where the output is URL safe

I have a requirement where I need to move a string from one place to another via GET. e.g.
example.com?string=ENCRYPTED_STRING
Is there a algorithm or some other method to encrypt the string so it is URL safe?
By that I mean it will not have characters like = or & ...
I have tried openssl with AES-256-CBC but no luck.
The data is not overly very sensitive but I would prefer to obfuscate it in someway.
Oh hey, I've actually done this in one of my applications. My code looks a lot different (because of my custom tools, it's a one-liner), but works basically like this (uses defuse/php-encryption):
use \Defuse\Crypto\Crypto;
$url = "/my/endpoint?".http_build_query([
'something' => base64_encode(
Crypto::encrypt('my_secret_info', CRYPTO_SECRET_KEY)
)
]);
// Then you can either use $url in header('Location: '.$url) or in an HTML link safely.
Further reading:
base64_encode()
http_build_query()
urlencode() (if you don't want to use http_build_query())
Why you want authenticated encryption (which defuse/php-encryption provides) rather than just encryption (which OpenSSL's AES-CBC provides)
Footnote: If you (or anyone else) want a short encrypted URL parameter, read this answer instead. (I know what's not what you were asking for, but just in case someone finds this question years down the line...)
The code below allow you to encrypt (alpha/num) and decrypt a string. But you need Mcrypt php module installed to make it run.
static public function encrypt($text){
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "useasuperkey";
return (bin2hex(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv)));
}
static public function decrypt($text){
$len = strlen($text);
$text = pack("H" . $len, $text);
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "useasuperkey";
return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv));
}
I had to do exactly same thing.
My solution was encrypting string with openssl_encrypt($str, "AES-128-CBC", $key).
Then sending the URL using url_encode($str).
Destination page decodes data with openssl_decrypt($str, "AES-128-CBC", $key)

AES Cookie Data randomly not decryptable

I'm having a problem when writing and parsing some DATA out of stored cookies.
Here are my crypt and decrypt functions (which I have found in another topic here).
function decrypt($crypttext){
$crypttext = base64_decode($crypttext);
$plaintext = '';
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, '');
$ivsize = mcrypt_enc_get_iv_size($td);
$iv = substr($crypttext, 0, $ivsize);
$crypttext = substr($crypttext, $ivsize);
if ($iv)
{
mcrypt_generic_init($td, CRYPTKEY, $iv);
$plaintext = mdecrypt_generic($td, $crypttext);
}
return trim($plaintext);
}
function encrypt($plaintext){
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CBC, '');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, CRYPTKEY, $iv);
$crypttext = mcrypt_generic($td, $plaintext);
mcrypt_generic_deinit($td);
return base64_encode($iv.$crypttext);
}
My usage is fairly simple:
//read, split if neccesarry, check if already in it, if not-> add, crypt, write
if(isset($_COOKIE['DATA'])){
$data = decrypt($_COOKIE['DATA']);
$search = explode('#',$data);
if(!in_array($lnk, $search)){
$data.= "#".$lnk; // $lnk = additional data
$err = setrawcookie("DATA", encrypt($data));
}
$err = true;
}
In most tries, it doesn't work adding a $lnk. The decryption of the cookie after I've wrote it, is wrong. undefined junk. (so something doesn't work well).
I haven't been able to find any errors in the code at all. My best guess is that the problem is caused by :
$ivsize = mcrypt_enc_get_iv_size($td);
$iv = substr($crypttext, 0, $ivsize);
Specifically, that $ciphertext is smaller than $ivsize?
Any other ideas?
// to prevent questions about it:
the data which i store, are just php uniqueID()'s separeted by '#'. so maybe in future there will be 10 IDs stored (encrypted) in the cookie...i didin't know the max size of a cookie and the factor AES blow this up, but i thought a cookie should get it.
(if there is a easier synchronus way to encrypt (this should not be high security, but mostly safe) please feel free to tell me.
Try using bin2hex instead of base64_encode(). I previously answered a similar question on SO.

How to decrypt using Blowfish algorithm in php?

I am supposed to write a PHP script to decrypt Blowfish encrypted data.
The data I am receiving for decryption is encrypted by another application (I have no access to it).
The data decrypts fine when am check it using a javascript script (blowfish.js).
How can I decrypt the data in php?
I have tried the mcrypt function in PHP. The code works fine if I encrypt and decrypt using the same code. If I decrypt an encrypted code (in another app) it gives junk.
No idea about what mode to set.
Can anyone suggest on the code below or any PHP BlowFish code without using mcrypt?
<?php
class Encryption
{
static $cypher = 'blowfish';
static $mode = 'cfb';
static $key = '12345678';
public function encrypt($plaintext)
{
$td = mcrypt_module_open(self::$cypher, '', self::$mode, '');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, self::$key, $iv);
$crypttext = mcrypt_generic($td, $plaintext);
mcrypt_generic_deinit($td);
return $iv.$crypttext;
}
public function decrypt($crypttext)
{
$plaintext = "";
$td = mcrypt_module_open(self::$cypher, '', self::$mode, '');
$ivsize = mcrypt_enc_get_iv_size($td);
$iv = substr($crypttext, 0, $ivsize);
$crypttext = substr($crypttext, $ivsize);
if ($iv)
{
mcrypt_generic_init($td, self::$key, $iv);
$plaintext = mdecrypt_generic($td, $crypttext);
}
return $plaintext;
}
}
$encrypted_text = Encryption::encrypt('this text is unencrypted');
echo "ENCRY=".$encrypted_text;echo "<br/>";
////I am using this part(decryption) coz data already encryption
// Encrypted text from app
$encrypted_text = '29636E7ADA7081E7F5D73121C45E20D5';
// Decrypt text
$decrypted_text = Encryption::decrypt($encrypted_text);
echo "ENCRY=".$decrypted_text;echo "<br/>";
?>
The $iv you use when decrypting must be the same as the Initialization Vector used when encrypting the data. Your own functions transfer this information by prepending the IV to the ciphertext (return $iv.$crypttext;), but the other application might not do so.
You need to find out what IV the other app uses, and pass that to your own code. Since the decrypt function reads the IV from the beginning of the ciphertext you can simply prepend it.
Also, you can test a bit by encrypting the same text with your encrypt function and with the other application. If the outputs do not have the same length (your own is larger), then the app is not including the IV inside the ciphertext and you must obtain this information in another manner.
And of course the cipher mode used (CFB) must be the same between your code and the other app.
There's a nice, easy to implement solution here:
www.codewalkers.com: Encrypt and Decrypt using Blowfish
There is a PEAR Library for creating blowfish encyptions that allow you to choose weather to use MCRYPT Libs, or purely native PHP:
you may view the Library here: Crypt_Blowfish 1.1.0RC2
Select the PHP.php file will show you the source code to do this hard coded in native PHP.

Categories