views:

144

answers:

3

I have the user submit a form and if my spam filter catches it i redirect() the user into a captcha page to make sure it isnt a bot (reCaptcha appears not to be broken yet).

My question is how do i handle going back to the original page?

I was thinking i could generate a random number (check if there is a current session tag with that number), push all the POST data into a an object, put the object into ses[randomId]=obj; append the ID in the GET data (?sesTag=randId) then pull the get data from the ses when the user correctly passes the captcha. Is this a good solution? is there a problem with putting the object into a session?

How is pushing the post data into a dictionary? i can write a foreach loop to push all data into the dict? or will i get enough objects to eat up memory? (i am pushing HttpContext.Current.Request.Params which has many keys)

A: 

I'm not sure that this is a good solution, but if you must use it (or until someone posts a better alternative), you can store the Request.Params into the Session.

The Request.Params (or Request.Form) is a NameValueCollection which is serializable so you should have no problem storing it in Session even if you are using out-of-proc Session state. IOW, you do not need to pull out the data into a separate dictionary.

Cerebrus
You don't *need* to, but it is far far preferable to save only validated and expected data on the server side. A malicious user could send megabytes (or more) of data in the post. He could also send hundreds (or more) different parameters. That data could contain malicious strings designed to exploit vulnerabilities in log-file viewers, session-cache engines or anything. NEVER trust user-supplied data and store it untested.
Cheekysoft
A: 

Why not just place the captcha on the original page and save yourself some grief?

RichardOD
Because the captcha is only to be shown to the user if they are suspected of being a spambot. Saving the programmer grief here, will merely reflect that grief onto every user.
Cheekysoft
So only add it to the original page if you suspect a spambot. You can hide it, or dynamically add it when needed.
chris
Chris is right- I meant it the way he describes. Only show if possible spam candidate.
RichardOD
+1  A: 

You should never be storing or processing arbitrary params. The page that receives the user's post data should know exactly which parameters to expect and what formats they may be in.

First validate each expected parameter and if validation passes -- with the exception of the spambot criteria -- populate an object with the validated parameters and save that object in the session. You can get it back out if the captcha is succesful.

Edit

In response to your comment: From a security POV, you are trying to architect your function at too high a level. By having no "local knowledge" you have no option but to open yourself up to security problems. Have a think about how to introduce your method call at a lower level.

Here's a loosely worked example:

Let each page/controller/action/whatever validate their own data first (only the local code knows how to validate it's own data), then let each action call your spambot filter/redirect component/method, passing the validated form data it wishes to be persisted along with the fieldnames that need to be spam-checked.

Your method can spam-check the potential problem fields, persist the data and redirect to re-captcha.

In pseudo-code, each web action that needs a spam check can do something like below. It reqiures just one method call e.g.

void someAction( untrustedData ) {
  trustedData = object;
  trustedData.id      = makeInt( badData.id );
  trustedData.name    = safeCharsOnly( untrustedData.name ); 
  trustedData.message = safeCharsOnly( untrustedData.message ); # <-- spam-check this 

  fieldsToSpamCheck = ['message']; 
  successUrlBase = '/myapp/sandwiches/postMessage';

  if (!spamChecker.check( trustedData, fieldsToSpamCheck, successUrlBase )) {
    // spamChecker will check specified params
    //  if not spam, it returns true
    //  if spam it sets a http redirect and returns false
    return;
  }

  processData( trustedData );

}

Cheekysoft
I read your comment http://stackoverflow.com/questions/1085764/how-do-i-handle-post-session-page-asp-net/1085806#1085806 is that really a problem? i want to use this solution as a generic function ready to use in any page/situation.
acidzombie24
Is it a problem? Well if you want to let me put hundreds of gigabytes of data into your session store and fill up your disk: no it's not a problem. If you want malicious data hanging around in your system to bite you later when your code evolves and you start handling requests differently 6 months later: no, it's not a problem. Oh you want to allow this code to be used in lots of places - its n times "not-a-problem" now.
Cheekysoft