I sent emails out that contains an email registration confirmation link:


I do not hash the link above. Before I sent an email containing this link, the user registered as a new member. Email address is inserted as a new record in the database together with a confirm_key.

So in my database there are two fields that are first filled up email and confirm_key. The confirm_key is generated by the PHP function uniqid().

My question is, what are the security risk in using this method, if any?

3 Answers 3


uniqid() does not create a cryptographically secure hash, and sending sensitive data over plaintext channels such as email or http means that anyone in between can read them.

Is this a problem? No, not really (with the exception stated in the last paragraph).

The information you send out consists of the user's email address and a confirmation key. This is also what's stored in the database. There is no way of sending an email without revealing the recipient's email address, so transmitting that address in plaintext as part of an URL is no problem either. If some Great Evil is going to happen, then it has already happened.

Now what about the confirmation key?

You could be giving out consecutive integers as confirmation keys (actually uniqid() is not very far from that!), and it would not matter. A malicious person could intercept someone else's key or they could trivially generate their own, but neither is going to allow them to register a fake account, since your database query looks for the pair <username, confirm_key>. A stolen or random/fake/calculated confirmation key thus does not work for another (random) username, it is worthless for an attacker.

The only attack that is reasonably plausible is that someone could intercept your email and confirm your legitimate account with the correct email address and confirmation key before you are able to do so.
This is indeed a problem if your system is designed so that confirming a user account automatically logs you into your first session, too (some sites do just that!).

  • This is only on the premise that the site owner isn't interested in accounts being properly verified. If they want to make sure an account belongs to bob@example.com this completely bypasses that verification. If you want such weak verification you might as well drop the key totally and just have the query string as ?email=bob@example.com. Additionally this answer defeats the point of the question... It should just ask how to send an email address to a server securely rather than mentioning verification if it is not required at all. Aug 8, 2014 at 21:33
  • Also you are incorrect in assuming that if the email is intercepted then the http request can also be. Many email systems allow ssl access so this can secure the connection over the local network, whereas a http link won't be secure. Aug 8, 2014 at 21:35
  • To summarise, this approach allows a fake account to be registered as the token can be predicted. Aug 8, 2014 at 22:08
  • @SilverlightFox: No, you need to read properly. It does not allow a fake account to be registered. Not unless you are also able to do insert records into the database (but in that case you have a much more severe problem!). Security is not lessened, nothing is leaked (nothing that isn't leaked anyway). TSL access on email is irrelevant. There is no end-to-end encryption, mail on the server is not only stored unencrypted, but also regularly being machine scanned and read by several parties. Further, it is not possible to send a mail without recipient even if you encrypt the mail body.
    – Damon
    Aug 9, 2014 at 7:26
  • I did read properly. If user bob@example.com self registers and the system sends the user an email to make sure it is really bob@example.com, a CSPRNG needs to be used to prevent evil@example.edu who really registered from confirming Bob's account. The site admin will think it is really someone with access to Bob's email but it is not. This is not bulletproof, but it confirms that the user that has registered has access to Bob's email account. In the context of the account email verification system a CSPRNG does this job of verification, an integer or something from uniqid() does not. Aug 9, 2014 at 11:12

The only issue is that you're leaking information, in this case, the user's email address. Since it's plaintext in the querystring, it's going to be stored by any logging that's occurring anywhere between the client and your server, potentially in bookmarks if the user bookmarks that page, if the URL is copied and stored or sent to anyone, etc.

I'll additionally point out that anything you do is going to be vulnerable to sniffing, since you're using HTTP rather than HTTPS.

  • 1
    Is there really any additional risk by using HTTP? The whole E-Mail is usually sent over an insecure channel, so all information in the mail should be regarded "public knowledge" If the confirmation just sends this data, HTTPS is not needed.
    – Falco
    Aug 7, 2014 at 9:55
  • 1
    @Falco HTTPS does more than just keeping data private. it also is a tamper protection that ensures that the data you receive genuinely comes from the server. Else, I can do what the Tunisian Government did to Facebook a few years ago and inject my own javascript and/or other content into the page you receive, and the only way you'd notice is if you suspected something and checked the page source. Troy Hunt has a fine example in the second video on this blog article: troyhunt.com/2014/06/ndc-2014-vikings-passwords-and.html
    – Nzall
    Aug 7, 2014 at 13:36
  • 1
    @Falco The insecure channel is only between the sending server and the receiving server (and depending on the servers involved it might not even be that insecure). The channel between the receiving server and the client is usually encrypted, either via HTTPS (webmailer) or POP3/IMAP over TLS. Aug 7, 2014 at 13:54
  • @Falco Both Nate and CodesInChoas have responded with good details. To sum up in the terms of your original question: Yes, there is additional risk. Passing sensitive data over an additional communication channel without encryption adds additional surface area to attack, and therefore necessarily more risk. Is it a large amount of risk? For this function, likely not, but it is accepted that when sensitive data is involved, HTTPS should be used, so this would likely be a more general finding in an audit, not necessarily a finding specific to each flawed function which would include this one.
    – Xander
    Aug 7, 2014 at 19:55

uniqid() should not be used for anything security related:

This function does not create random nor unpredictable strings. This function must not be used for security purposes. Use a cryptographically secure random function/generator and cryptographically secure hash functions to create unpredictable secure IDs.

Also, you should make your link a HTTPS instead of plain HTTP to protect against MITM attacks and to prevent any caching by proxy servers.

It might be better to send the confirm_key only as the emailed link, and then ask the user to log in to associate the email address to the account. This will confirm that only the registered user is actually logging in to confirm the account rather than anyone else who may gain access to the registration link.

  • Thanks! I am now considering changing my codes by either sending the confirm_key only or using mcrypt_encrypt Aug 6, 2014 at 20:09
  • @LimGuangJian I'd consider mcrypt_create_iv with DEV_URANDOM as second parameter. Aug 7, 2014 at 13:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.