-4

I am currently running my website in shared hosting, and I am not able to register TLS/SSL for my website. However, I implemented jsencrypt [A Javascript library to perform OpenSSL RSA Encryption, Decryption, and Key Generation] to encrypt all form data by AJAX or normal POST/GET.

Currently, I got into an issue with password reset link or some other important links that I sent to user for important actions regarding user account. For example:

example.com/password?resetcode=%CODE%

But After thinking of TLS/SSL, this url can be seen easily using any traffic monitoring tools, then, an attacker can get the link before user and reset the password.

One way to prevent this is to use fragment identifier (#) after url such as:

example.com/password#code=%CODE%

Then using:

<script>
var securykey = "<?php echo $_SESSION['securykey']; ?>";//random secure key
var hash = encrypt(window.location.hash.substring(1)+"|count="+securykey );
window.location = "example.com/password?code=hash"; //hash encryped
</script>

And then at Server side:

<?php
$code = decrypt($hash);
if($_SESSION['securykey'] == $securykey_from_user){
 //its valid 
}
?>

Dose above technique is strong? and shall we use fragment identifier even for TLS/SSL?

UPDATE:

  1. I didn't used my encryption. Sorry for mentioning AES it was not AES but openSSL using JavaScript.
  2. Google Also implemented HTML Fragment identifier! example:https://www.google.iq/#newwindow=1&safe=active&q=security.stack+exchange
  3. jsencrypt: is the library that I used in client side. https://github.com/travist/jsencrypt and then I used PHP openssl to decrypt it at server-side.

Source Code demo:

  1. javaScript: https://jsfiddle.net/da7jmxnu/
  2. PHP:
<?php
$config = array(
    "digest_alg" => "sha512",
    "private_key_bits" => 4096,
    "private_key_type" => OPENSSL_KEYTYPE_RSA,
);
$res = openssl_pkey_new($config);
//$privKey = key saved in google cloud and accessed with https using curl
openssl_pkey_export($res, $privKey);
// Extract the public key from $res to $pubKey
$pubKey = openssl_pkey_get_details($res);
$pubKey = $pubKey["key"];
$data = 'plaintext data goes here';//$_POST['data']
// Encrypt the data to $encrypted using the public key
openssl_public_encrypt($data, $encrypted, $pubKey);
// Decrypt the data using the private key and store the results in $decrypted
openssl_private_decrypt($encrypted, $decrypted, $privKey);
?>
Gruber
  • 115
  • 4
Akam
  • 1,337
  • 3
  • 15
  • 24
  • 2
    "I am not able to register TLS/SSL for my website" .... SERIOUSLY ? There's NO excuse for not having SSL. SSL certificates are cheap these days ... heck, you can even get free ones from https://letsencrypt.org/. Number one rule in security .... "DON'T ROLL YOUR OWN CRYPTOGRAPHY". – Little Code May 21 '16 at 07:48
  • I didn't used my cryptography, I knew this rule from last century :) – Akam May 21 '16 at 12:38
  • 4
    You used a 3rd party library, but the cryptosystem as a whole is still your own design and implementation. Even if you correctly encrypt form values, what is the goal? What is your threat model? Why are you concerned about form values from client to server but nothing sent from server to client? There are many details you're omitting here, such as the source of the encrypt and decrypt functions. You're asking us to speculate about a completely underspecified problem, and when it comes to security, underspecification is a bad thing. Don't build it yourself. Use TLS. – Mark E. Haase May 21 '16 at 13:13
  • @mehaase: yes that's correct... but I selected the best option between list of bad options. my main concern here even with TLS/SSL, url can be seen with important query string attached to it... such as password reset link. – Akam May 21 '16 at 13:18
  • 1
    " even with TLS/SSL url can be seen with important query string attached to it... such as password reset link" ... NO, IT CAN'T. Go RTFM on how TLS and URLs work. – Little Code May 21 '16 at 13:19
  • @LittleCode: :( I got the answer now, http://security.stackexchange.com/a/34795/20070 – Akam May 21 '16 at 13:31
  • "I selected the best option between list of bad options" If you know it's a bad option, then when are you here asking if it's good? – Mark E. Haase May 21 '16 at 13:39

1 Answers1

8

I am currently running my website in shared hosting, and I am not able to register TLS/SSL for my website.

There is no reasonable alternative to TLS, and trying to re-create it on your own is certainly doomed. Never roll your own crypto. If your shared host doesn't support TLS, then find one that does, or else accept that your site is insecure.

However, I implemented AES encryption in client side to encrypt all form data by AJAX or normal POST/GET.

This won't do much. Anybody who visits your site will be able to view source and extract the AES key, then decrypt any traffic they have captured.

However, I implemented jsencrypt [A Javascript library to perform OpenSSL RSA Encryption, Decryption, and Key Generation] to encrypt all form data by AJAX or normal POST/GET.

Oh wait, now you're saying it wasn't AES, it was actually RSA. Your confusion on this point is a warning sign, because not only are those different algorithms, they are two entirely different types of cryptography (symmetric vs asymmetric), with entirely different purposes.

Using RSA still doesn't prevent man-in-the-middle attacks because you're distributing the public key over the same insecure channel that you're trying to secure. So a man in the middle intercepts your public key, changes it to a public key of their choosing and now has access to everything the client is doing. It has gone from a passive attack to an active attack, assuming that your cryptosystem doesn't have any flaws.

Pro tip: TLS includes man-in-the-middle in its threat model.

Currently, I got into an issue with password reset link or some other important links that I sent to user for important actions regarding user account.

If you are emailing a password reset token to the user, then you have no control over transport encryption: if the user uses plaintext IMAP or POP, there's nothing you can do to prevent the token from being sniffed.

One way to prevent this is to use fragment identifier (#) after url such as...

I have no idea what you think this accomplishes. You could just as easily encrypt the token when you send them the e-mail.

We still don't know if your cryptosystem has flaws or not, because you didn't post any source code for the encrypt() and decrypt() functions. The encrypt() function mysteriously takes only a message, not a key, and for some reason you concatenate the key onto the end of the message. I have no idea what you're trying to accomplish, but you haven't provided nearly enough detail here for anybody to give you an accurate answer. The confusing nature of your code and of your question leads me to believe that you're not qualified to develop a cryptosystem.

But if your question is whether the URL fragment is sent to the server, then that's a question for StackOverflow, not Security.SE. The answer to that question is completely orthogonal to the strength of your cryptosystem. Yes, it avoids leaking a plaintext at one particular moment but it just shifts the problem elsewhere.

Is the above technique is strong?

You admitted in your own comment that you, "selected the best option between list of bad options." Why are you asking if its good? Why are you arguing that its good when you already know its bad?

It's not just bad. It's awful. Either use TLS, or accept that it will be insecure. Don't try to fake security by building it all yourself. Crypto experts routinely screw up crypto code. The average novice (myself included) doesn't stand a chance of implementing all the crypto correctly.

Mark E. Haase
  • 1,912
  • 2
  • 15
  • 24
  • Big thanks and then: 1- I didn't used my encryption, 2- JavaScript AES not include any private key only public key to encrypt and then decrypt at server-side using PHP, 3-when user click on the password reset link then the URL can be get even using SSL. Fragment identifier (#) means anything after it will not be sent to server and an attacker can't see it using traffic monitoring, i.e an attacker will se (just example.com/password) without the code. – Akam May 21 '16 at 00:41
  • 2
    @Akam AES is a symmetric encryption algorithm, there is only one key that is used for both encryption and decryption – Neil Smithline May 21 '16 at 02:20
  • @NeilSmithline: I am sorry it was not AES it was (A Javascript library to perform OpenSSL RSA Encryption, Decryption, and Key Generation) Link: https://github.com/travist/jsencrypt – Akam May 21 '16 at 12:33
  • Google using fragment identifier in Search (https://www.google.iq/?#newwindow=1&safe=active&q=mehaase) the part after (#) will not be sent to server! Google will get this part in client side and then send it via AJAX to server – Akam May 21 '16 at 12:39
  • @Akam Why are you arguing? You came here to ask a question and you got an answer. If you want a debate, you should ask in a chat room. Since you don't understand the difference between AES and RSA, maybe *you* are the one who needs to start Googling. – Mark E. Haase May 21 '16 at 12:54
  • @mehaase: I will do, and please search for (HTML fragment identifier) to learn more about HTML basics. I asked about using fragment identifier, and in your answer you just didn't answered this part... I updated my question in this regard. – Akam May 21 '16 at 13:01
  • 3
    @Akam " the part after (#) will not be sent to server". Actually, it *should* not normally be sent to the server. But there is no guarantee of that, infact the RFC says "URI may have additional information attached in the form of a fragment identifier". So you are essentially relying on browser developers past, present and future to adhere to the unwritten rule you are relying on. – Little Code May 21 '16 at 13:25
  • updated with source code for both PHP and JavaScript – Akam May 21 '16 at 14:14