Stopping Bot [SO] - PHP

2019-07-15 15:33发布

I saved this code in index.php and after filling i clicked Submit button, and then a verification page was shown to me !
My question is how did it detected that it was not from the original server ?
[i hope they do not use the referrer as it can be disabled easily]

My Fake Code

<html>
 <form id="post-form" action="http://stackoverflow.com/questions/ask/submit" method="post">
  <input id="title" name="title" type="text" maxlength="300" tabindex="100" class="ask-title-field" value="">                        
  <textarea id="wmd-input" name="post-text" cols="92" rows="15" tabindex="101"></textarea>
  <input id="tagnames" name="tagnames" type="text" size="60" value="" tabindex="103">
  <input id="submit-button" type="submit" value="Post Your Question" tabindex="120">  
 </form>
</html>  

Can anyone guide me creating such secure page [where if a user tries to post from a dull page, he will be asked for verification] ?

2条回答
Evening l夕情丶
2楼-- · 2019-07-15 16:16
  1. Generate a token on the server.
  2. Put that token into a hidden input element.
  3. Save that token on the server in a list of generated forms.
  4. When a form submission comes in
    1. check whether the token was passed and is valid,
    2. remove the token from the list of generated forms.

I suspect that this is what <input id="fkey" type="hidden" value="..." name="fkey"> on the question submission form is for.

查看更多
叼着烟拽天下
3楼-- · 2019-07-15 16:25

good idea, but it puts pressure on the DB too :(

You can create an anti-XSRF token without the element of having to remember them all on the server.

You can do this by putting the information you want to verify inside the token, typically including:

  • user ID, so one user can't create a form that submits for another user
  • an expiry timestamp, so that tokens don't last forever

then hash this information together with a secret key and spit it out in the hidden field. When the token comes back in, you can look at the information given, hash it with the key again and see if the hash matches the user's submission.

So for example, for user ID 18936 with expiry timestamp 1304861680 (Unix time for about now), you could create a token like:

18936.1304861680.2A956E39.11E859E44B9308B812257BEE660330D9D0566189

where 2A956E39 is some random salt, and the bit at the end is the hex-encoded HMAC-SHA1 hash of 18936.1304861680.2A956E39 using the not-very-good secret key secretkey.

This achieves the anti-XSRF purpose, but sometimes the one-time-server-stored-token is also used to prevent a form double-submission. As-is, the hash method doesn't help with that bit. But in the specific case of creating a new entity, which is a common place double-submission-prevention is deployed, you can use the token as a unique value inserted into the DB as part of the new entity, and then refuse to create a new entity if there's already one with the token in it.

查看更多
登录 后发表回答