Form Security

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Scott

    Form Security

    I've been trying to come up with a way to ensure user input is coming
    from the form on my site, and not auto-submitted from elsewhere, and I
    don't want to use the "enter the code shown in the image" method. I know
    the $_SERVER['HTTP_REFERER'] contents can be spoofed, so I thought of
    doing something similar to this:

    <?php
    session_start() ;
    $code = mt_rand(0,10000 00);
    $_SESSION['code'] = $code;
    ?>

    Then in my form have:
    <input type="hidden" name="originato r" value="<?=$code ?>">

    On the page receiving the form:

    <?php
    session_start() ;
    if(isset($_POST['originator'])) {
    if($_POST['originator'] == $_SESSION['code']) {
    // process the form
    }
    }
    ?>

    I'm looking for feedback on this method. Do you think this is an
    effective way to ensure the input you're receiving is indeed from your
    form? Obviously, the random code key will be visible to the client, but
    without the matching session variable, it will be useless.

    Your thoughts?

    Scott
  • Justin Koivisto

    #2
    Re: Form Security

    Scott wrote:[color=blue]
    > I've been trying to come up with a way to ensure user input is coming
    > from the form on my site, and not auto-submitted from elsewhere, and I
    > don't want to use the "enter the code shown in the image" method. I know[/color]

    Even using a captcha (enter code shown in image) you can not be 100%
    certain that the form posted was from your site...
    [color=blue]
    > the $_SERVER['HTTP_REFERER'] contents can be spoofed, so I thought of
    > doing something similar to this:[/color]

    <snip>
    [color=blue]
    > I'm looking for feedback on this method. Do you think this is an
    > effective way to ensure the input you're receiving is indeed from your
    > form? Obviously, the random code key will be visible to the client, but
    > without the matching session variable, it will be useless.[/color]

    Great for protecting against CSRF, but you can still "submit" the form
    without opening your site up in a browser.

    The session/token can be gotten around with things like curl. This is
    the same method that Chris Shiflett outlined in his Essential PHP
    Security book (phpsecurity.or g) in Chapter 2.

    By all means, use this method, but don't forget that you also need to
    check that all the fields you expect are there, that you don't use any
    fields that shouldn't be there, and that you filter all input and escape
    all output.

    Comment

    • Chung Leong

      #3
      Re: Form Security

      Scott wrote:[color=blue]
      > I've been trying to come up with a way to ensure user input is coming
      > from the form on my site, and not auto-submitted from elsewhere, and I
      > don't want to use the "enter the code shown in the image" method. I know
      > the $_SERVER['HTTP_REFERER'] contents can be spoofed, so I thought of
      > doing something similar to this:
      >
      > <?php
      > session_start() ;
      > $code = mt_rand(0,10000 00);
      > $_SESSION['code'] = $code;
      > ?>
      >
      > Then in my form have:
      > <input type="hidden" name="originato r" value="<?=$code ?>">
      >
      > On the page receiving the form:
      >
      > <?php
      > session_start() ;
      > if(isset($_POST['originator'])) {
      > if($_POST['originator'] == $_SESSION['code']) {
      > // process the form
      > }
      > }
      > ?>
      >
      > I'm looking for feedback on this method. Do you think this is an
      > effective way to ensure the input you're receiving is indeed from your
      > form? Obviously, the random code key will be visible to the client, but
      > without the matching session variable, it will be useless.
      >
      > Your thoughts?
      >
      > Scott[/color]

      Yes, that's precisely what you want to do. The function uniqid() can
      also be used to generate the random key.

      A check on HTTP_REFERER is actually sufficient too, since ordinary
      users aren't going to be spoofing the Referer headers.

      Comment

      • Justin Koivisto

        #4
        Re: Form Security

        Chung Leong wrote:[color=blue]
        >
        > A check on HTTP_REFERER is actually sufficient too, since ordinary
        > users aren't going to be spoofing the Referer headers.[/color]

        Anyone that is running a firewall program like Norton's Personal
        Firewall won't send the referrer... There are a number of web proxies
        out there that do the same. Don't even bother with the HTTP_REFERER for
        anything.

        Comment

        • Scott

          #5
          Re: Form Security

          Thanks for the feedback guys. I know not to rely on HTTP_REFERER. I
          think the plan is to use a combination of the method I described
          earlier, along with filtering the input with regular expressions to
          ensure I'm only getting valid data.

          This is for a contact form, so if you can think of any more obvious
          holes I need to watch for, let me know.

          Thanks again!

          Scott

          Scott wrote:[color=blue]
          > I've been trying to come up with a way to ensure user input is coming
          > from the form on my site, and not auto-submitted from elsewhere, and I
          > don't want to use the "enter the code shown in the image" method. I know
          > the $_SERVER['HTTP_REFERER'] contents can be spoofed, so I thought of
          > doing something similar to this:
          >
          > <?php
          > session_start() ;
          > $code = mt_rand(0,10000 00);
          > $_SESSION['code'] = $code;
          > ?>
          >
          > Then in my form have:
          > <input type="hidden" name="originato r" value="<?=$code ?>">
          >
          > On the page receiving the form:
          >
          > <?php
          > session_start() ;
          > if(isset($_POST['originator'])) {
          > if($_POST['originator'] == $_SESSION['code']) {
          > // process the form
          > }
          > }
          > ?>
          >
          > I'm looking for feedback on this method. Do you think this is an
          > effective way to ensure the input you're receiving is indeed from your
          > form? Obviously, the random code key will be visible to the client, but
          > without the matching session variable, it will be useless.
          >
          > Your thoughts?
          >
          > Scott[/color]

          Comment

          • Chung Leong

            #6
            Re: Form Security


            Justin Koivisto wrote:[color=blue]
            > Chung Leong wrote:[color=green]
            > >
            > > A check on HTTP_REFERER is actually sufficient too, since ordinary
            > > users aren't going to be spoofing the Referer headers.[/color]
            >
            > Anyone that is running a firewall program like Norton's Personal
            > Firewall won't send the referrer... There are a number of web proxies
            > out there that do the same. Don't even bother with the HTTP_REFERER for
            > anything.[/color]

            If HTTP_REFERER is empty, then bypass the test. Really, one should
            consider each scenario carefully instead of just blindly repeating some
            axiom. In this case, making cross-site posting not functional a
            majority of the times is sufficient in deterring sites from doing it.

            Comment

            • Gordon Burditt

              #7
              Re: Form Security

              >I've been trying to come up with a way to ensure user input is coming[color=blue]
              >from the form on my site, and not auto-submitted from elsewhere, and I[/color]

              Why? What are you *really* trying to accomplish?

              If the original objective was to drain the swamp, and you find
              yourself assigning Social Security numbers to alligators chomping
              your ass to limit them to one bite each, you need to step back and
              re-evaluate what you are doing.

              Remember, if a browser can return the values of hidden fields and/or
              cookies, so can bots. CURL is pretty good at this.

              If the original objective is for the browser to not bypass
              the input field checking done by Javascript, you're toast anyway,
              as Javascript can be Turned Off(tm). You need the checks
              server-side anyway.

              Captchas can be defeated by outsourcing the task to humans (often
              unwitting dupes). The bot writer puts up a web page offering
              something "valuable", say, free porn, and sends responders the same
              captcha you sent the bot. They respond with the code to get their
              free porn. Actually providing the porn is optional. I believe I
              have heard of spammers actually using this technique. But for
              someone to bother with this, you have to be protecting something
              valuable to the bot.

              I didn't see any code to prevent the bot from doing the equivalent
              of "SUBMIT, BACK, repeat". Even if you put that code in, you still
              have a problem. If the original objective is to stop the bots from
              pounding your server, there's nothing preventing them from getting
              a new page from your server with the funky code on that, then
              submitting it, thereby doubling the number of hits on your server.

              You're really going to have trouble if the bot does the equivalent
              of Go to URL, get page, submit it with values filled in, forget
              all session cookies, and repeat. This looks like a bunch of people
              with different browsers all visiting your page.

              If the original problem is to prevent ballot-box stuffing in a vote
              or a poll, you're stuck with one of two basic methods: (a) issue
              credentials to voters and make sure credentials can only be used
              once, or (b) try to identify users on the fly by some characteristic
              of their computer, such as IP address, browser ID string, cookie,
              or some combination of these, all of which have problems with both
              excluding legitimate voters and allowing cheaters. It's going to
              be difficult to get a reliable vote or survey if you don't use
              method (a), but this may require effort like a professional survey
              firm uses. (b) is doomed to failure, but you can try to make
              cheating non-trivial. Remember, a dedicated fan determined to stuff
              a ballot box can cast thousands of ballots a day MANUALLY.
              [color=blue]
              >don't want to use the "enter the code shown in the image" method. I know
              >the $_SERVER['HTTP_REFERER'] contents can be spoofed, so I thought of[/color]

              The most serious problem with 'HTTP_REFERER' is that there are lots
              of users who can't UN-block it to save their lives. Perhaps it's
              their own firewall, but they don't know how to configure it. Perhaps
              it's an office firewall.

              Then there's the hardcore bad guys who can spoof it.
              [color=blue]
              >doing something similar to this:
              >
              ><?php
              >session_start( );
              >$code = mt_rand(0,10000 00);
              >$_SESSION['code'] = $code;
              >?>
              >
              >Then in my form have:
              ><input type="hidden" name="originato r" value="<?=$code ?>">
              >
              >On the page receiving the form:
              >
              ><?php
              >session_start( );
              >if(isset($_POS T['originator'])) {
              > if($_POST['originator'] == $_SESSION['code']) {
              > // process the form
              > }
              >}
              >?>
              >
              >I'm looking for feedback on this method. Do you think this is an
              >effective way to ensure the input you're receiving is indeed from your
              >form?[/color]

              Ensuring that the input is from your form is meaningless, a lot
              like preventing air disasters by permitting only *LICENSED* bombs
              on board. WHat are you REALLY trying to accomplish?
              [color=blue]
              >Obviously, the random code key will be visible to the client, but
              >without the matching session variable, it will be useless.[/color]

              The client can submit both the random code key with the form AND
              pass through the session cookie. Browsers do this quite well.
              It's not that hard for a bot to do it (see CURL).
              [color=blue]
              >Your thoughts?[/color]

              CURL is very good at fetching a URL, picking up a cookie from it,
              and using it to submit the form it fetched.

              Gordon L. Burditt

              Comment

              • Scott

                #8
                Re: Form Security

                It's just a contact form. The end result will be emailed, and possibly
                stored in a database. It's no gateway into bank accounts or anything
                along those lines. I had already planned on filtering the data with
                regular expressions, strip_tags(), etc. when I thought of the
                aforementioned $_SESSION['code'] method, and just wanted to bounce the
                idea off of the group.

                I liked your alligator analogy, though. Thanks for that!

                Scott

                Gordon Burditt wrote:[color=blue][color=green]
                >>I've been trying to come up with a way to ensure user input is coming[/color]
                >[color=green]
                >>from the form on my site, and not auto-submitted from elsewhere, and I[/color]
                >
                > Why? What are you *really* trying to accomplish?
                >
                > If the original objective was to drain the swamp, and you find
                > yourself assigning Social Security numbers to alligators chomping
                > your ass to limit them to one bite each, you need to step back and
                > re-evaluate what you are doing.
                >
                > Remember, if a browser can return the values of hidden fields and/or
                > cookies, so can bots. CURL is pretty good at this.
                >
                > If the original objective is for the browser to not bypass
                > the input field checking done by Javascript, you're toast anyway,
                > as Javascript can be Turned Off(tm). You need the checks
                > server-side anyway.
                >
                > Captchas can be defeated by outsourcing the task to humans (often
                > unwitting dupes). The bot writer puts up a web page offering
                > something "valuable", say, free porn, and sends responders the same
                > captcha you sent the bot. They respond with the code to get their
                > free porn. Actually providing the porn is optional. I believe I
                > have heard of spammers actually using this technique. But for
                > someone to bother with this, you have to be protecting something
                > valuable to the bot.
                >
                > I didn't see any code to prevent the bot from doing the equivalent
                > of "SUBMIT, BACK, repeat". Even if you put that code in, you still
                > have a problem. If the original objective is to stop the bots from
                > pounding your server, there's nothing preventing them from getting
                > a new page from your server with the funky code on that, then
                > submitting it, thereby doubling the number of hits on your server.
                >
                > You're really going to have trouble if the bot does the equivalent
                > of Go to URL, get page, submit it with values filled in, forget
                > all session cookies, and repeat. This looks like a bunch of people
                > with different browsers all visiting your page.
                >
                > If the original problem is to prevent ballot-box stuffing in a vote
                > or a poll, you're stuck with one of two basic methods: (a) issue
                > credentials to voters and make sure credentials can only be used
                > once, or (b) try to identify users on the fly by some characteristic
                > of their computer, such as IP address, browser ID string, cookie,
                > or some combination of these, all of which have problems with both
                > excluding legitimate voters and allowing cheaters. It's going to
                > be difficult to get a reliable vote or survey if you don't use
                > method (a), but this may require effort like a professional survey
                > firm uses. (b) is doomed to failure, but you can try to make
                > cheating non-trivial. Remember, a dedicated fan determined to stuff
                > a ballot box can cast thousands of ballots a day MANUALLY.
                >
                >[color=green]
                >>don't want to use the "enter the code shown in the image" method. I know
                >>the $_SERVER['HTTP_REFERER'] contents can be spoofed, so I thought of[/color]
                >
                >
                > The most serious problem with 'HTTP_REFERER' is that there are lots
                > of users who can't UN-block it to save their lives. Perhaps it's
                > their own firewall, but they don't know how to configure it. Perhaps
                > it's an office firewall.
                >
                > Then there's the hardcore bad guys who can spoof it.
                >
                >[color=green]
                >>doing something similar to this:
                >>
                >><?php
                >>session_start ();
                >>$code = mt_rand(0,10000 00);
                >>$_SESSION['code'] = $code;
                >>?>
                >>
                >>Then in my form have:
                >><input type="hidden" name="originato r" value="<?=$code ?>">
                >>
                >>On the page receiving the form:
                >>
                >><?php
                >>session_start ();
                >>if(isset($_PO ST['originator'])) {
                >> if($_POST['originator'] == $_SESSION['code']) {
                >> // process the form
                >> }
                >>}
                >>?>
                >>
                >>I'm looking for feedback on this method. Do you think this is an
                >>effective way to ensure the input you're receiving is indeed from your
                >>form?[/color]
                >
                >
                > Ensuring that the input is from your form is meaningless, a lot
                > like preventing air disasters by permitting only *LICENSED* bombs
                > on board. WHat are you REALLY trying to accomplish?
                >
                >[color=green]
                >>Obviously, the random code key will be visible to the client, but
                >>without the matching session variable, it will be useless.[/color]
                >
                >
                > The client can submit both the random code key with the form AND
                > pass through the session cookie. Browsers do this quite well.
                > It's not that hard for a bot to do it (see CURL).
                >
                >[color=green]
                >>Your thoughts?[/color]
                >
                >
                > CURL is very good at fetching a URL, picking up a cookie from it,
                > and using it to submit the form it fetched.
                >
                > Gordon L. Burditt[/color]

                Comment

                • Jerry Stuckle

                  #9
                  Re: Form Security

                  Chung Leong wrote:[color=blue]
                  > Scott wrote:
                  >[color=green]
                  >>I've been trying to come up with a way to ensure user input is coming
                  >>from the form on my site, and not auto-submitted from elsewhere, and I
                  >>don't want to use the "enter the code shown in the image" method. I know
                  >>the $_SERVER['HTTP_REFERER'] contents can be spoofed, so I thought of
                  >>doing something similar to this:
                  >>
                  >><?php
                  >>session_start ();
                  >>$code = mt_rand(0,10000 00);
                  >>$_SESSION['code'] = $code;
                  >>?>
                  >>
                  >>Then in my form have:
                  >><input type="hidden" name="originato r" value="<?=$code ?>">
                  >>
                  >>On the page receiving the form:
                  >>
                  >><?php
                  >>session_start ();
                  >>if(isset($_PO ST['originator'])) {
                  >> if($_POST['originator'] == $_SESSION['code']) {
                  >> // process the form
                  >> }
                  >>}
                  >>?>
                  >>
                  >>I'm looking for feedback on this method. Do you think this is an
                  >>effective way to ensure the input you're receiving is indeed from your
                  >>form? Obviously, the random code key will be visible to the client, but
                  >>without the matching session variable, it will be useless.
                  >>
                  >>Your thoughts?
                  >>
                  >>Scott[/color]
                  >
                  >
                  > Yes, that's precisely what you want to do. The function uniqid() can
                  > also be used to generate the random key.
                  >
                  > A check on HTTP_REFERER is actually sufficient too, since ordinary
                  > users aren't going to be spoofing the Referer headers.
                  >[/color]

                  In addition to what Justin said - if someone DOES want to spoof your
                  site, they will set HTTP_REFERER to your site. That check is worthless.


                  --
                  =============== ===
                  Remove the "x" from my email address
                  Jerry Stuckle
                  JDS Computer Training Corp.
                  jstucklex@attgl obal.net
                  =============== ===

                  Comment

                  • Chung Leong

                    #10
                    Re: Form Security

                    Jerry Stuckle wrote:[color=blue]
                    > In addition to what Justin said - if someone DOES want to spoof your
                    > site, they will set HTTP_REFERER to your site. That check is worthless.[/color]

                    I think you misunderstand the problem. Here's how an
                    auto-form-submission attack works:

                    1. Victim logs into site A
                    2. Victim is fooled into going to site B
                    3. Page at site B has a prefilled form targetting a script at site A.
                    Through Javascript the form is submitted without any intervention from
                    the victim.
                    4. The POST request arrives at site A and is processed as though the
                    victim has filled and submitted.

                    The solution proposed by the OP would stop this type of attacks but it
                    has to be implemented on every form. A check on the referer header
                    offers incomplete protection but can be easily implemented as a global
                    check.

                    In this scenario, it's the victim's computer which is making the POST,
                    thus spoofing isn't a real concern.

                    Comment

                    • Jerry Stuckle

                      #11
                      Re: Form Security

                      Chung Leong wrote:[color=blue]
                      > Jerry Stuckle wrote:
                      >[color=green]
                      >>In addition to what Justin said - if someone DOES want to spoof your
                      >>site, they will set HTTP_REFERER to your site. That check is worthless.[/color]
                      >
                      >
                      > I think you misunderstand the problem. Here's how an
                      > auto-form-submission attack works:
                      >
                      > 1. Victim logs into site A
                      > 2. Victim is fooled into going to site B
                      > 3. Page at site B has a prefilled form targetting a script at site A.
                      > Through Javascript the form is submitted without any intervention from
                      > the victim.
                      > 4. The POST request arrives at site A and is processed as though the
                      > victim has filled and submitted.
                      >
                      > The solution proposed by the OP would stop this type of attacks but it
                      > has to be implemented on every form. A check on the referer header
                      > offers incomplete protection but can be easily implemented as a global
                      > check.
                      >
                      > In this scenario, it's the victim's computer which is making the POST,
                      > thus spoofing isn't a real concern.
                      >[/color]

                      I know *exactly* how auto-form-submission works. In fact, from your
                      posts here I expect I know a lot more about it than you do. I've been
                      in this field too many years. What you describe is only *one way* it can
                      happen. And it's not even the most common.

                      Much more common or 'bots which fake the user and post forms. They can
                      set anything they want in the headers, including HTTP_REFERER.

                      Another way is to act as a kind of proxy - intercepting the data as it
                      flows between the user and the site, changing the HTTP_REFERER and
                      anything else they want (unless you're using SSL).

                      And this is only the beginning of the number of ways it can be spoofed.
                      It is NOT a reliable source of information!


                      --
                      =============== ===
                      Remove the "x" from my email address
                      Jerry Stuckle
                      JDS Computer Training Corp.
                      jstucklex@attgl obal.net
                      =============== ===

                      Comment

                      • Chung Leong

                        #12
                        Re: Form Security

                        Jerry Stuckle wrote:[color=blue]
                        > I know *exactly* how auto-form-submission works. In fact, from your
                        > posts here I expect I know a lot more about it than you do. I've been
                        > in this field too many years. What you describe is only *one way* it can
                        > happen. And it's not even the most common.[/color]

                        What I described was a vulnerability that can be countered by the
                        method proposed by the OP. Thus I assumed that is in fact what he is
                        referring to when he said auto-submission and responded accordingly. I
                        don't really feel the need to interpret other people's statements in
                        the worst light in order to show that I'm more knowledgeable.

                        Comment

                        • Jerry Stuckle

                          #13
                          Re: Form Security

                          Chung Leong wrote:[color=blue]
                          > Jerry Stuckle wrote:
                          >[color=green]
                          >>I know *exactly* how auto-form-submission works. In fact, from your
                          >>posts here I expect I know a lot more about it than you do. I've been
                          >>in this field too many years. What you describe is only *one way* it can
                          >>happen. And it's not even the most common.[/color]
                          >
                          >
                          > What I described was a vulnerability that can be countered by the
                          > method proposed by the OP. Thus I assumed that is in fact what he is
                          > referring to when he said auto-submission and responded accordingly. I
                          > don't really feel the need to interpret other people's statements in
                          > the worst light in order to show that I'm more knowledgeable.
                          >[/color]

                          And I wasn't interpreting it in the "worst of light". I was
                          interpreting it in the light of simple security.

                          What he's proposing is false security - which is worse than no security
                          at all. At least with the latter you know you have potential
                          vulnerabilities .

                          And no, this isn't great security - but what he's proposing will NOT
                          stop auto-submission by any means.

                          --
                          =============== ===
                          Remove the "x" from my email address
                          Jerry Stuckle
                          JDS Computer Training Corp.
                          jstucklex@attgl obal.net
                          =============== ===

                          Comment

                          • Chung Leong

                            #14
                            Re: Form Security

                            Jerry Stuckle wrote:[color=blue]
                            > And I wasn't interpreting it in the "worst of light". I was
                            > interpreting it in the light of simple security.
                            >
                            > What he's proposing is false security - which is worse than no security
                            > at all. At least with the latter you know you have potential
                            > vulnerabilities .[/color]

                            I really don't know what to say. The OP proposed a method for stopping
                            one type of cross-site scripting attack and here you are insisting that
                            it's crap because it doesn't stop bots.

                            Comment

                            • Jerry Stuckle

                              #15
                              Re: Form Security

                              Chung Leong wrote:[color=blue]
                              > Jerry Stuckle wrote:
                              >[color=green]
                              >>And I wasn't interpreting it in the "worst of light". I was
                              >>interpretin g it in the light of simple security.
                              >>
                              >>What he's proposing is false security - which is worse than no security
                              >>at all. At least with the latter you know you have potential
                              >>vulnerabiliti es.[/color]
                              >
                              >
                              > I really don't know what to say. The OP proposed a method for stopping
                              > one type of cross-site scripting attack and here you are insisting that
                              > it's crap because it doesn't stop bots.
                              >[/color]

                              And it doesn't stop what he's trying to stop!

                              --
                              =============== ===
                              Remove the "x" from my email address
                              Jerry Stuckle
                              JDS Computer Training Corp.
                              jstucklex@attgl obal.net
                              =============== ===

                              Comment

                              Working...