Encrypt part of HTML in PHP and decrypt in JavaScript - php

I'm looking for a way to encrypt a HTML form in PHP in a way so I can then decrypt it in the browser using JavaScript. This should work transparently to the user and JavaScript input validation must also work on the form (I know how to do this). When user submits the form, it must be encrypted again and sent to the server using an "AJAX" request.
Edit: this will be used as an alternative CAPCHA system, so scripts cannot submit forms, unless by some clever design.
Edit 2: I know this is brakeable, everything is. Car locks are brakeable, but we still use them. It is not meant to be ultimate CAPTCHA, but a speed bump, which will drive all but the most persistent people away.
Thank you

This is the same problem as with DRM: User has the ciphertext. The decryption is done on user's system, so user must have the key too. If user has both key and ciphertext, all encryption is pointless.
If you just want to transmit data safe from outside snoopers, why not just use SSL (HTTPS)?

You can use base64.
<?php
echo base64_encode('html source');
<?
and then you can use jquery plugin: http://plugins.jquery.com/project/base64 or javascript http://www.webtoolkit.info/javascript-base64.html to decode that.

If you're trying to use this to stop spam, I've got some bad news for you:
The price of humans who'll spam blogs is falling to zero
This is a reality. On a site I run, I had a captcha system set up that spam was getting through. All but about 2 were coming from poorer regions of the world, so I had suspicions that there were companies paying people to spam. To test this I set accounts created by people in certain regions to be only visible to them and after they posted some content to alert them to the fact that their account was auto hidden. I provided them a form to contact us and complain if they were a legitimate user. Upon doing this we started getting about 10 emails a day from people angry that we had hidden their account, however upon checking the content they had added, they were spammers! It sounds crazy, but unfortunately it now seems to be humans doing the bulk of the spam. The spammers know we use captcha's, so they have adapted. :(
CAPTCHAs are fast becoming useless (if not so already). Adding a link so users can report spam and having karma levels where users are granted admin privileges so that their flagging leads to automatically hiding spam without prior confirmation (like stackoverflow does) is really the only effective way to stop spam now.

For a CAPTCHA, the only way to defeat scripts is something that can only done by a human - such as recognizing something in an image, or doimg some math.
All decryption that's done by the browser can be just as easily done by automated scripts.

Related

Without using SSL, what's the most secure way to make an AJAX request to a PHP page?

So, it's impossible to do AJAX requests securely without using SSL. I get it. You can either view-source the data that's being sent via Javascript, or you can directly access the PHP page by spoofing headers, yada yada.
But let's say this web app doesn't particularly require true security, and instead it's just a sort of game to keep most reverse-engineers at bay. What sort of hurdles should I employ?
I'm not looking for some ridiculously over-the-top Javascript implementation of an encryption algorithm. I want simplicity as well as mild security... if that isn't contradictory by nature. So, what would you guys recommend?
For example, I'm running a contest where if a user clicks an image successfully (jQuery), it passes their userid and a timestamp to a PHP page, both MD5 salted by random data and then encoded with MIME. The PHP page then validates this userid and timestamp, then returns a winning "code" in the form of another salted MD5 hash. I'm also employing multiple header checks to help ensure the request is from a valid location. Am I missing anything, or is that about all I can do? It seems like someone could just fire the jQuery click event and ruin the whole thing, but I don't see how I can prevent that.
I'll be awarding the answer to anyone who comes up with an ingenious faux-security mechanism! Or... just whomever tells me why I'm stupid this time.
I believe header checks can be easily fooled. Doesn't hurt though.
Since your algorithm is exposed on the client side, the user can simply send the appropriate data to your server with an automated script to fool your server into thinking it was clicked.
In addition to that, you have to watch out for session hijacking. A user can essentially submit this ajax request on behalf of someone else, especially if they have the algorithm. Does your application have different behavior for certain users? If so, then the session hijacking could turn into priviledge escalation issue.
It is not necessarily true that you need to encrypt the payload with SSL in your case in order to build a secure application. From what you've described, there is no sensitive data being sent over the wire.
Ensure that you have some basic silly checks on the server side to check for automated or malicious behavior. For example, if you find that the header information is missing, you may want to have some sort of flag/alert that someone is toying with the response. Another place you may want to do this is the pattern of requests.
A more secure model is to have the server assign the user some session token that they cannot reverse-engineer. This session token ideally should begin with the timestamp instead of the username to promote the avalanche effect of the salted hashing algorithm.
Since it seems like your application deals with prizes and potentially money, I would invest some more time in securing this app. Hope these tips have helped you.

How to allow PHP upload from only one domain?

In the HTML form I wrote user can upload a file that is sent out on submission using ajax. The script is located on exampledomain.com/upload.php.
I want to avoid a situation that somebody is going to make his own form with action pointing to upload.php and start spamming my server with unauthorized files.
Everybody can fill out my HTML form so login/password protection for upload is not an option for me. Is there any efficient way of making sure that upload.php is going to be triggered only from the HTML form on my website?
One way of dealing with that problem would be using sessions, but I'm not sure how well it works with ajax. Any suggestions?
Although Cross Site Request Forgery is normally classed as an attack on already-authenticated users' accounts via another site, the techniques used to combat it will work for you to some degree, even though, as you say, your users aren't authenticated as such.
Specifically, generating a nonce (one-time unique value) with every form, as described in Jeff Atwood's article here will help by preventing other sites from simply POSTing data to your servers -- if you validate that the nonce value sent with the POST request is one that you've recently generated, it must at least have come from someone who's "visited" your site somehow.
However, that won't prevent spammers from attacking your site by scraping the nonce values from your site, i.e. pretending to be your users and using your actual forms. For that, you probably want to look into various techniques like CAPTCHAs, blacklists, and other validations.
Personally, I think if you're not going to use authenticated users (by which I mean at least requiring a CAPTCHA plus an email address validation for a user to register, then requiring them to authenticate before uploading) then I'd say you'd pretty much have to use a good CAPTCHA system, probably combined with regular checking for unusual activity, and sampling of the uploads to combat the inevitable spam and attacks. There's a reason most popular web services require these checks, sadly.
(Incidentally, sessions work fine with Ajax -- just make sure to use the same session-handling code in the page that responds to the Ajax request. But without an authenticated user, the sessions won't buy you anything in the way of security, as far as I can see. A spambot can cope perfectly well with sessions.)
I want to avoid a situation that somebody is going to make his own form with action pointing to upload.php and start spamming my server with unauthorized files.
That's impossible.
How to allow PHP upload from only one domain?
To let you know, files being uploaded not from "domain" but merely from the user's PC.
As long as you have unrestricted registration on your site, anyone could spam. You have to choose another protection against this imaginary threat.
the best way to protect against spammers is captcha(Try recaptcha). other techniques to come in mind is unique code in an hidden form(good for protecting against clrf attacks), verify domain name with $_SERVER[''] but are relatively easy to counter
Add a PHP variable to the page to act like a password, but rather than a static value which could be copied use a calculated value that will change every minute.
The calculated value sent will have to match the calculated value in the upload.php file to allow the file to be sent.
This still doesn't stop spamming via your site though.
You could also calc the size of the file uploaded in Kbytes and attach that integer to the session variable, and check that variable in the next landing page after the login!

Is email verification with a link a bad idea

In my registration process, the user registers, they get emailed a verification link, and if they click it, only then would their account be verified. But isn't this verification method too easy for the bots?
I think an email could be created by a bot, but for sure if the verification is just clicking a link, it could also be automated by a bot. I'm not sure since I haven't done this and don't care to test it just to know, but my question is isn't this verification method flawed?
I'm thinking about sending the verification code to the user as a text which they would have to copy/paste manually into a form AND the form is captcha protected. Is this a better idea? any flaws with it?
Most of the suggestions are about verifying emails and using CAPTCHAs which of course you should do, but keep in mind that none of these methods is completely bulletproof.
Email verification
A bot can easily "click" on links in any email. Copying and pasting something would be slightly more annoying for the bot author but not much. Generally email verification is just that - email verification.
You verify if the email is likely to be controlled by whoever tries to register, but of course since email is usually sent in cleartext over untrusted TCP and relies on insecure DNS, then until we're all using DNSSEC and encrypt all traffic it will be easy to sniff emails and spoof servers and clients. The important thing to realize is that using email verification you get only a certain degree of confidence that whoever or whatever you are talking to is really a user of that email address.
Turing test
Answering a question that only human should know the answer to would be still more annoying but considering that you probably wouldn't have an infinite number of questions, the bot author might redirect unknown question to a real human and use cached answers if any question repeats more than once. Answering a question like "what is 12+8" like I've seen in some websites lately as a Turing test is completely counterproductive since this question is actually easier for bots than for humans. Probably the most popular Turing test for that are CAPTCHAs but here you also have to realize that they can be fooled.
First of all people are showing methods of circumventing CAPTCHAs, for example see the Decoding reCAPTCHA talk from DEFCON 18. Many CAPTCHAs are much easier for robots to decipher since they are generated by algorithms that are trivial to reverse. The reCAPTCHA distortions are also pretty simple but the words that they use are real scanned words that was hard for OCRs so in principle it should be much harder for bots, but it is not always the case.
And there is also a possibility to display captchas that you want to guess on other websites and have people answer it for you. Also there is a black market of people actually solving captchas so if your bot author doesn't mind paying something like two cents for a dozen then no matter how hard it is for humans, actual humans will solve it anyway.
Bottom line
The bottom line is that using any of the bot-stopping techniques will always be a compromise of how much would a bot owner (a spammer or anyone else who wants to register a lot of users in your system) be willing to spend time, effort and money to do it, and how much inconvenience for your users are you going to tolerate, because ultimately you will never be able to do any automated test to tell humans and bots apart without actually annoying humans and alienating people with disabilities (has anyone ever tried to guess the audio version of reCAPTCHA?), and still your bots may actually be human-powered, so not really bots but cyborgs, so to speak.
It's an arms race for which your honest users are paying a price. Please keep all of that in mind.
The questions is what are you trying to verify? When you send a link to an email address, what you can know is that whoever registered that account has access to the email address. It doesn't tell you anything about them other than that.
So yeah, bots can create an account, and use it for registration. If you want to stop bots, then yeah, a captcha is what you need to add. Note that there's little point in adding the code to copy/paste - that's both easy for a bot to do, and also doesn't gain you anything over the captcha.
As always, security and convenience are generally competing with each other.
A link in an email simply validates that it is an active email address. Yes, it's easy for the bots to handle this. But is your service so valuable that bots will be attacking it?
A CAPTCHA is always the way to go to ensure your users are human. The additional coding and frustrations involved with it are a trade-off.
In the end, keep things as simple as possible, but not simpler.
As pointed out already, you simply have some CAPTCHA validation.
My suggestion is though do human validation before your app creates the user account and sends the verification email. Added value of your site can't easily be forced to just spam verification emails and create bogus waiting to be verified accounts.
Nothing wrong with a link if you do that.
Yes, bots can enter emails and check the responses. I've also heard of endeavors toward bots getting better at image recognition and answering captchas, although I can't say for sure how good they are. If you are really really concerned, I would go with:
Email verification
Captcha
Simple random questions (How many ears/fingers do most humans have?)
Cell phone number that sends a code via SMS
The last one might prove to be the best in eliminating bots, but it will also limit who signs up for your website. Also, the more validations you have, the more you'll annoy users and the more you'll increase the barriers to getting them to sign up, which could also be a pretty big drawback. Personally, I think captchas are a good balance of bot protection vs. user inconvenience.
Are you verifying an email only or doing a full registration?
I always verify the email account first. then once verified complete the registration process.
so add a captcha at the verify email step.
In other words, ask the user to enter their email address, enter the captcha and submit the form.
That way only real people get the verification email sent.
It doesn't prevent human bots of course.
DC
It also means you don't need to store failed/bad registration data.
One problem is a user validating with one email address and then changing it during the registration process, I handle that this way..
When a user submits their email address the data is not stored at all. Instead I use $validation_code = md5(trim($email)+$secret) to generate the verification code. That way they can't change the email address on the actual registration form. The email and verification code is carried as a hidden field to the end to validate the email address. if the email address is altered from the verified one, registration will fail as the md5 no longer matches.
DC
I ran into similar problems with verification emails and testing. If you want to end-to-end test email verification try EmailE2E.com — it's free.
You can send and receive emails from randomly generated inboxes via an API.
It's perfect for testing Firebase, Amazon Cognito, or other OAuth providers that use email verification codes during sign up. Plus it has clients in Java and JS.

Activation on site

I have been running my website for a few months now and occasionally I find my activation isnt great. After the user signs up, they will receive an email which has an activation link provided.
I have a few problems and want to improve this if possible.
Firstly, the email sometimes doesnt arrive? Any reason for this?
How can I stop it going into the junk mail?
Secondly, at the moment, the activation is their username and an md5 of their username.
Is there a better way to do activations?
I'm always looking to improve and find better ways of doing things!
Thanks for your time.
Email doesn't arrive
First at all, you cannot really rely on mail. Never. Because you can't even know if it was received or read. A mail may be blocked as spam on server side, can be filtered on client side, or can just be lost or ignored.
There may be plenty of causes. For example, you may use e-mail authentication mechanisms. You may also start to check if there is reverse DNS for your domain.
Further, you may want to read some documentation and books to know how spam filters work. It will show you some obvious methods to reduce filtering of your mails, like sending mails in plain text instead of full-HTML, but also less obvious stuff like the words to use, etc.
If you have no choice and you must send mail, probably the most easy solution to prevent spam filtering would be to ask the users to add your domain to the list of safe senders. In practice, nobody will do it for you.
Activation through MD5
There is obviously a better way, since the one you implemented does not provide anything. If the activation is a hash from user name, you can as well just tell the users to calculate the hash themselves (thus avoiding all the problems with mails filtered as spam).
Normally, the users may not know what their activation code would be. It means that the activation code must be random or difficult to guess.
Generate a set of random characters, save them to database and send the code by mail. Then you would just need to validate the code against the one you keep in your database.
Some emails will always end up in the trash folder. It's probably best to put up a notice so that people know to check there, and make it possible for the user to re-request the activation email.
Using the MD5 hash of the username is not a very good idea because anyone can automate that. At the very least add some salt before hashing it, or even better, use a completely unrelated random token saved in your database.
For your second question, you may want to generate a random activation code and store it in a database. When the user clicks the activation link you could verify the code in the database using their e-mail address. This way a malicious user will have a more difficult time automating registration on your site.
$code = md5(uniqid(rand(), true));
If you're on a shared server, services like Yahoo are apt to label you spam. They want you to have a dedicated IP. It's almost impossible to get users to check the 1000 messages in their spam folders for your one activation message.
The MD5 hash is fine if you're hashing with a timestamp.
Keep this implementation, but supplement it with OpenID. That will take care of your Gmail and Yahoo users.
Yes, that's wrong. You shouldn't use MD5 for that.
The most popular way of do it is generating a rand code and saving it in the users table in the DB and send it by email as a GET parameter of the link.
About the emails, I would tell users to look in theit junk folders.
First problem: Make sure your mail isn't spammy. Follow the default guidelines for setting up mail... things like making sure you've got your SPF records configured, your mail is well-formatted, doesn't include spammy words. I generally test against Gmail, Hotmail and a server running SpamAssassin to check mails I send out; examine the headers to see if you're triggering any serious anti-spam rules.
Second problem: You'll want to make sure that the user cannot guess what his activation key is (thus removing the need for receiving the email). An MD5 of the username is insufficient for this. However, if you salt the MD5 you can easily prevent people from generating the MD5's in an automated way (that's an open invitation for automated signups). Adding Salt refers to adding a large amount of pregenerated random data to your input before hashing it. That way, the attacker can't lookup the hash in a 'rainbow table', as he no longer knows what the input for your hash was. Of course, you could just as well use a randomly generated string, which would probably be easier.
Another look on user registration. Let yourself inspire at stackoverflow and use OpenId and you don't have to care about user registration.
Update
You don't need to validate OpenId user via email. A user which signed up via Google or MyOpenId account is valid.
You don't have to care about questions if user is a bot? This servers did it already.
I have never got verification email from stackoverflow.
Mail arriving in the junk folder is a perpetual problem. The range of 'not looking like spam' strategies are numerous. Beyond the Junk folder I think that the overwhelming majority of reported 'not received' situations are actually just delays in propagating the email.
I'm currently implementing a resend for the activation email confirmation despite the fact that it should only actually be necessary in cases where the user has accidentally deleted the email and purged their trash or a transient error has discarded the mail. These cases are going to be rare but do exist so needed to be coded for.
I think the most important reason for implementing the resend of the activation confirm is customer service. It provides the user with an action that they can take while waiting for their mail and in the course of doing so and re-checking their email the activation email will eventually appear.
I wouldn't use the md5 as it creates too predictable a result. You want something that has a random or at least less predictable element. It is then problematic if you are invalidating the hash/token in the original email by resending a new mail so I would avoid overwriting the existing token and would instead re-use the same token which you should have stored or better stored the values from which it can be validated. This does constrain how you create the token as you want to be able to recreate it in the later resend mails or at least to be able to continue to validate all the inflight mails as valid. I am using a session aging model to resend the same token if that token is still valid. There is no reason why the user shouldn't see it as the same token and hence understand that they are all valid. In the case of an expired session/token a new one needs to be generated.
It's good practice to expire the activation mail token in case the mailbox falls into the wrong hands weeks or months later and the old mail is found. Assuming this can have some undesirable effect on the state of the users account at that later point.

PHP: Anti-Flood/Spam system

I'm actually working on a PHP project that will feature a user system (Login,Register,Send lost password to email,..) and I think that this may be very vulnerable to Brute-Force attacks and/or Spam (Send a password to someone's email like 1000 times, etc. use your fantasy)
.
Do today's webservers (Apache, IIS) have some sort of built-in defense against Brute-Force?
What would be the best way to implement an Anti-Spam/Flood system, if I e.g.: want a page not be able to be called more than two times a minute, however another page may be called up to 100 times a minute or so.
I would definitely have to store IP adresses, the time when they last visited a page and the number of visits somewhere - but would it be efficient enough storing it in a text-file/database (MySQL)
Should I use captchas for things like registering/recovering lost passwords?
Are "text" captchas viable? (Something like "What is 5 plus 9 minus 2? ")
The page won't be used by that many users (100-200), do I actually have to implement all these things?
Regarding CAPTCHAs: I would recommend against using CAPTCHAs unless you really need it. Why?
it's ugly.
it's annoying for your users. You shouldn't make them jump through hoops to use your site.
There are some alternatives which are very simple, can be very effective and are entirely transparent to (almost all) users.
Honeypot fields: add a field to your forms with a common name like "website". Beside it, add a label saying something to the effect of "don't write in this box". Using Javascript hide the input and label. When you receive a form submission, if there's anything in the field, reject the input.
Users with JS won't see it and will be fine. Users without JS will just have to follow the simple instruction. Spambots will fall for it and reveal themselves.
Automatic faux-CAPTCHA: This is similar to the above. Add an input field with a label saying "Write 'Alex'" (for example). Using Javascript (and knowing that most automated spam bots won't be running JS), hide the field and populate it with 'Alex'. If the submitted form doesn't have the magic word there, then ignore it.
Users with JS won't see it and will be fine. Users without JS will just have to follow the simple instruction. Spambots won't know what to do and you can ignore their input.
This will safeguard you from 99.9% of automated spam bots. What it won't do, even in the slightest, is safeguard you against a targeted attack. Someone could customise their bot to avoid the honeypot or always fill in the correct value.
Regarding Brute Force blocking: A server-side solution is the only viable way to do this obviously. For one of my current projects, I implemented a brute force protection system very similar to what you describe. It was based on this Brute Force Protection plugin for CakePHP.
The algorithm is fairly simple, but a little confusing initially.
User requests some action (reset password, for example)
Run: DELETE * FROM brute_force WHERE expires < NOW()
Run:
SELECT COUNT(*) FROM brute_force
WHERE action = 'passwordReset'
AND ip = <their ip address>
If the count is greater than X then tell them to wait a while.
Otherwise, run:
INSERT INTO brute_force (ip, action, expires)
VALUES (<their ip address>, 'passwordReset', NOW() + Y minutes)
Continue with the reset password function.
This will allow users to only try resetting a password X times in Y minutes. Tweak these values as you see fit. Perhaps 3 resets in 5 minutes? Additionally, you could have different values for each action: for some things (eg: generate a PDF), you might want to restrict it to 10 in 10 minutes.
Yes, storing an IP address, last accessed and times accessed in a database would be fine.
Using CAPTCHAs for register/recovering password is advised so that e-mail addresses cannot be spammed. Also to stop brute forcing.
Yes, text CAPTCHAs are possible, although far easier for someone to crack and write a script to automate the answer. For a free CAPTCHA, I'd recommend Recaptcha.
That really depends on how much you care about security. I'd certainly recommend using a CAPTCHA as they are simple to implement.
Don't try to implement all the logic in your PHP - the lower in your stack you can implement it, the more efficiently it can be dealt with.
Most firewalls (including iptables on BSD/Linux) have connection throttling. Also, have a look at mod_security for DDOS/brute force attack prevention.
You should design your application around the idea that these kind of attacks will not give the attacker access to the app - at the end of the day there's no way you can prevent a DOS attack, although you can limit its effectiveness.
There's not a lot of value in relying on a consistent IP address from your attacker - there's lots of ways of getting around that.
e.g. keep track of the number of password reset requests between logins by each user. In your password reset form, respond (to the client) in exactly the same way if the user submits an unknown email address. Log invalid email addresses.
HTH
C.
Besides doing what Gazler is telling you, you should also have some way of counting the login attempts in general. It the total of all login attempts are bigger then X then either start using the sleep command or just say the servers have a high load.
Storing IP addresses is good practise for loggin and tracking but I think that just a captcha would stop spamming, brute-force attacks and flooding.
Recaptcha is indeed a good solution.
sure, Your target audience might not be large but if it's in the public domain then it's vulnerable,
text captcha's are cracked easily these days believe me
for an Anti-Spam/Flood system you could log IP addressses (MySQL preferably) and add a time limit login retries

Categories