tags:

views:

550

answers:

3

The basics:

  • I have a contact form that uses php to validate the forms. (in addition to client side) This could be done in any server side language though.
  • The server side only allows A-z 0-9 for certain fields (it is acceptable to validate this field to English only with that extremely limited range)
  • If the form contains errors, I repopulate the fields so the user doesn't have to retype before submitting again
  • I am willing to not let other sites post to my form, even if legitimate use could be found there.

I can easily make a form on a different web site that posts a dirty word to a field. Certain dirty words are perfectly legit according to the validation rules, but my employeer obviously wouldn't like that to happen.

I am under the impression that dedicated hackers can affect cookies, php sessions and of course hidden fields are easy to spoof along with referrers and such. How can I block third party sites from posting to my page?

Please feel free to help me Google for this too. My search terms are weak and bringing up methods I know will fail.

What if somebody submits "d03boy eats cats" via a form on their site and gets people to click a link that submits it to my form? (Admit it is possible, and my company cannot accept any risk) Then when a user clicks the link they see inside the "name" field "d03boy eats cats" and gets super offended and contacts PETA about our site's content. We just cannot explain to the user what happened. True, nothing happened, but upsetting a single users isn't acceptable to my employer.

Our current solution is to not report any user input, which in my opinion is a big usability issue.

A: 

I'm not sure I entirely understand your question but I'll do my best to give you a basic answer.

Cross Site Scripting (XSS) happens generally when someone else puts in HTML into your forms. Your website allows this to happen because it isn't escaping the HTML properly. If you use PHP you probably want to make use of the htmlentities($str, ENT_QUOTES) function.

htmlentities($str, ENT_QUOTES)

PHP htmlentities

Joe Philllips
Right. I covered that. I will edit my question
MrChrister
+1  A: 

This sounds like you need a moderation system in place for user generated content, not a technical solution. Obviously you can check the referrer field, content scrub and attempt to filter the profane, but enumerating badness never works. (It can be an acceptable "first pass", but humans are infinitely resourceful in avoiding such filters).

Put the user submitted content into a queue and have moderators review and approve content. To lighten the load, you can set trusted users to "pre approved", but you have said your client can't accept any risk.

Frankly, I find that impossible: even with moderators there is the risk that a moderator will subvert your system. If that is actually true (that they have zero risk tolerance) then I suggest they not accept any user input, don't trust moderators and in fact eliminate the site itself (because an insider could go rogue and put something improper up). Clearly every act has risk; you need to find out how much they can accept, such as a moderator based approval queue.

Godeke
This is a good argument. Not want I want to hear, but a good argument. Usability will suffer, but based on the requirements it has to.
MrChrister
Sorry to hear that. One thing to realize is that some people are less risk adverse than they originally think they are. My avatar is from Second Life, infamous for a "seedy" side. Yet, amid all the chaos is the LDS church with several "sims" (regions of the world).
Godeke
A: 

My attempt

...
<?
$form_token = "";
$token = "";
$encoded_token = "";
$salt = "ThiséèÞ....$ÖyiìeéèÞ";  //it is 70 characters long
...
...
$blnGoodToken = false;
...
...
//Check for the encoded token
session_start();
$encoded_token = GetSuper('POST', 'TOKEN');
if (isset($_SESSION['TOKEN'])) {
    if (sha1($_SESSION['TOKEN'] + $salt) === $encoded_token) {
     $blnGoodToken = true;
     //echo "Good Token";
     }
    else {
     //echo "Bad Token";
     $blnGoodToken = false;
     unset($_SESSION);
     session_unset();
     session_destroy();
     session_start();
     }
    }
else {
    $blnDoit = false;
    echo "No Token, possible no session";
    }

$token = uniqid(rand(), TRUE);
$_SESSION['TOKEN'] = $token;
$form_token = sha1($token + $salt);
...
...
?>
...
...
<form action="request.php?doit=y" method="post">
    <input type="text" name="TOKEN" id="TOKEN" value="<?=$form_token?>" />
    <!--
    form stuff
    -->
    <input type="reset"  value="Clear" />
    <input type="submit" value="Submit" />
</form>

Since I don't use sessions anywhere else on the site, I don't think we are exposed much to session hijacking. The token changes each load, and to get the token to match the session you would have to know

  1. I am using SHA. An easy guess to make on my php code
  2. I keep it in the session. I suppose the session is gettable
  3. My salt. I think this is a good secret. If they know my salt they already owned my server
MrChrister