By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,441 Members | 979 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,441 IT Pros & Developers. It's quick & easy.

preserve POST data when using the back-button

P: n/a
Hi.

Every time i post data in a form the contents are being checked for
validity.
When i click the back-button, all data is gone and i have to retype it.
It's obvious that only a few or none of the visitors will retype it all
so i'm asking: "how to preserve POST-data when clicking the
back-button?"

i've already tried to print post data as a value in a HTML tag but
since it's not reparsed, this won't help either.

Is this a browser-issue?

---
14 sept 2006 02:14h GMT +1 (CET)

Sep 14 '06 #1
Share this Question
Share on Google+
23 Replies


P: n/a
Bjorn wrote:
Hi.

Every time i post data in a form the contents are being checked for
validity.
When i click the back-button, all data is gone and i have to retype it.
It's obvious that only a few or none of the visitors will retype it all
so i'm asking: "how to preserve POST-data when clicking the
back-button?"

i've already tried to print post data as a value in a HTML tag but
since it's not reparsed, this won't help either.

Is this a browser-issue?

---
14 sept 2006 02:14h GMT +1 (CET)
Bjorn,

It isn't clear to me whether you are talking about a site you visited or
one you are creating.

If the former, you are somewhat at the mercy of the site designer. Some
browsers, on some occasions, seem to save the POST data and will prompt
you to warn that it will be resent if you use BACK. Some don't.

If you are dealing with something like a contact form, where you filled
in few specific fields and then typed a long description, you can swipe
and copy the description into the clipboard before submitting the form.
At least that will preserve the bulk of the data in case the form is
rejected. BUT, you have to remember to do this every time you fill out
a form, which is unlikely.

All of the above, however, indicates poor design of the site, so if
we're talking about a site you are working on, you should avoid the
situation entirely, thus:

1. Optionally, the page on which the form exists should contain
Javascript checks of the data entered. If data fails these checks, a
message can be presented to the user without ever submitting the form,
and leaving all the data intact. Note that some users will have
Javascript disabled, so this check will not take place and the user will
move to the next step.

2. The server should check the data submitted. If the checks fail, the
server should regenerate the page containing the form, with all
user-entered data re-presented for editing. The user should never need
to use the BACK button because of syntactical errors in the input data.

3. It is possible that the user's data is correct, but that an error
still occurs when the server tries to process that data. Again, a
well-designed system would preserve the user input and either
automatically regenerate the form (as above) or give the user the option
to do so.

If you can provide more specifics, you might get a more detailed answer.

Chris Beall
Sep 14 '06 #2

P: n/a
In reply to Chris Beall's message:

Very useful hints you gave me.
thank you.
It's a site that i'm writing in PHP atm.
the back button is used to reduce the amount of code so it would be a
lot easier for me to write.

i will use JS to check the form entries where the values were only
checked server-side.
Maybe i can solve this problem by loading certain variables into the
(reparsed) form by redirecting instead of using the back-button.

f.e.
<form name="somename" action="script.php?p=contact" method="post">
<input type="hidden" name="contactmessage" id="contactmessage"
value="line1\nthis is line2\nlast line" />
<input type="submit" name="submit" id="submit" />
</form>

server-side code:
<textarea name="contactmessage" id="contactmessage"><?php
echo($_POST['contactmessage']); ?></textarea>

If you could suggest a better way to preserve the values, other
opinions are welcome.

Thank you in advance.
---
14 sept 2006 - 18:06h GMT+1 (CET)

Sep 14 '06 #3

P: n/a
Bjorn wrote:
In reply to Chris Beall's message:

Very useful hints you gave me.
thank you.
It's a site that i'm writing in PHP atm.
the back button is used to reduce the amount of code so it would be a
lot easier for me to write.

i will use JS to check the form entries where the values were only
checked server-side.
Maybe i can solve this problem by loading certain variables into the
(reparsed) form by redirecting instead of using the back-button.

f.e.
<form name="somename" action="script.php?p=contact" method="post">
<input type="hidden" name="contactmessage" id="contactmessage"
value="line1\nthis is line2\nlast line" />
<input type="submit" name="submit" id="submit" />
</form>

server-side code:
<textarea name="contactmessage" id="contactmessage"><?php
echo($_POST['contactmessage']); ?></textarea>

If you could suggest a better way to preserve the values, other
opinions are welcome.

Thank you in advance.
---
14 sept 2006 - 18:06h GMT+1 (CET)
Bjorn,

I think we're on the same wavelength here. I did mine in Perl and the
relevant part of it looks like this:

print <<'ENDPART1';
...snip irrelevant stuff...
<form action="contact.pl" method="post">
ENDPART1
unless ($input_error eq "none") {
print "<div class=\"error\">$input_error</div>" ;
}
if (defined $email) { # Input from prior pass -
regurgitate value.
print "Your E-mail address: <input type=\"text\" id=\"parm1\"
name=\"parm1\" size=\"35\" value=\"$email\"><br>" ;
}
else {
print "Your E-mail address: <input type=\"text\" id=\"parm1\"
name=\"parm1\" size=\"35\"><br>" ;
}
print <<'ENDPART2';
<p>
Please check what you just typed above.&nbsp;
If your e-mail address is incorrect, I won't be able to respond to you,
which will frustrate both of us.
</p>
Message<br>
ENDPART2
if (defined $comments) { # Input from prior pass -
regurgitate value.
print "<textarea rows=\"15\" cols=\"45\" wrap=\"virtual\"
id=\"parm2\" name=\"parm2\">$comments" ;
}
else {
print "<textarea rows=\"15\" cols=\"45\" wrap=\"virtual\"
id=\"parm2\" name=\"parm2\">" ;
}
print <<'ENDPART3';
</textarea>
<input class="button" type="submit" value="Send Message">
</form>

In my case, the Perl code is called repeatedly. When it is first
called, there is no user input, so it generates a page with the blank
form on it. When the form is submitted, the SAME Perl code is called.
It now sees that the user has provided some input, so that is validity
checked. If it fails those checks, the form is created again, with an
error message ($input_error) above it and previous data regenerated by
putting it into into a value= attribute.

The basic flow is:
Link from another page to contact.pl, which sees no user input.
Generate contact.html and serve it to the user.
User enters invalid data and submits it.
Submit to contact.pl, which now detects presence of user input.
Data error detected.
Generate contact.html with error message and regenerated input.
Serve to user.
User corrects the data and submits it.
Submit to contact.pl, which again detects presence of user input.
Data validated.
Process form (in this case a Sendmail).
Generate response.html and serve it to the user.

I'm not familiar with PHP, so I can't evaluate your solution. One
difference I see is that you seem to be using the hidden= attribute,
which I don't.

NOTE: This function can be improved on. See my proposed more elaborate
specification at http://pages.prodigy.net/chris_beall/TC/Contact.html,
Tip #3. Someday I'll get around to implementing it...

Chris Beall

Sep 14 '06 #4

P: n/a
Chris Beall wrote:
Bjorn wrote:
>In reply to Chris Beall's message:

Very useful hints you gave me.
(snip)
>>
Bjorn,

I think we're on the same wavelength here.
(snip)

In the following description, "Generate contact.html" isn't quite
correct. The user never sees 'contact.html' as a URL. Rather,
contact.pl (which the user DOES see as a URL) sends data of
Content-type: text/html to the client, using the Perl print directive.
Subtle difference.
The basic flow is:
Link from another page to contact.pl, which sees no user input.
Generate contact.html and serve it to the user.
User enters invalid data and submits it.
Submit to contact.pl, which now detects presence of user input.
Data error detected.
Generate contact.html with error message and regenerated input.
Serve to user.
User corrects the data and submits it.
Submit to contact.pl, which again detects presence of user input.
Data validated.
Process form (in this case a Sendmail).
Generate response.html and serve it to the user.
Chris Beall
Sep 14 '06 #5

P: n/a
"Bjorn" <in***@bjornroesbeke.bewrites:
f.e.
<form name="somename" action="script.php?p=contact" method="post">
<input type="hidden" name="contactmessage" id="contactmessage"
value="line1\nthis is line2\nlast line" />
<input type="submit" name="submit" id="submit" />
</form>

server-side code:
<textarea name="contactmessage" id="contactmessage"><?php
echo($_POST['contactmessage']); ?></textarea>
Use
<?php echo(htmlspecialchars($_POST['contactmessage'])); ?>
or else a textarea posted with </textareainside it gives odd effects
(can be used for cross-site scripting attacks)

If magic_quotes_gpc is on in PHP, you'll also want to do wrap a
stripslashes() in it.

--
Chris
Sep 14 '06 #6

P: n/a
Chris Beall <Ch*********@prodigy.netwrites:
if (defined $email) { # Input from prior pass -
regurgitate value.
print "Your E-mail address: <input type=\"text\" id=\"parm1\"
name=\"parm1\" size=\"35\" value=\"$email\"><br>" ;
}
[...]
if (defined $comments) { # Input from prior pass -
regurgitate value.
print "<textarea rows=\"15\" cols=\"45\" wrap=\"virtual\"
id=\"parm2\" name=\"parm2\">$comments" ;
}
It's not clear if you've done this from the partial script, but if
it's not been done elsewhere, you need to do:
$email =~s/"/&quot;/;
and
$comments =~s/</&lt;/;
or there's a probable cross-site scripting attack.

Less essential, but needed to avoid some possible problems with
validity (and resultant browser fixup attempts) is
=~s/&/&amp;/
for both.

--
Chris
Sep 14 '06 #7

P: n/a
Chris Morris wrote:
Chris Beall <Ch*********@prodigy.netwrites:
> if (defined $email) { # Input from prior pass -
regurgitate value.
print "Your E-mail address: <input type=\"text\" id=\"parm1\"
name=\"parm1\" size=\"35\" value=\"$email\"><br>" ;
}
[...]
> if (defined $comments) { # Input from prior pass -
regurgitate value.
print "<textarea rows=\"15\" cols=\"45\" wrap=\"virtual\"
id=\"parm2\" name=\"parm2\">$comments" ;
}

It's not clear if you've done this from the partial script, but if
it's not been done elsewhere, you need to do:
$email =~s/"/&quot;/;
and
$comments =~s/</&lt;/;
or there's a probable cross-site scripting attack.

Less essential, but needed to avoid some possible problems with
validity (and resultant browser fixup attempts) is
=~s/&/&amp;/
for both.
Chris,

I wasn't aware of the 'quote in email address' exposure. Can you point
me to a good detailed reference?

Thanks,
Chris Beall
Sep 14 '06 #8

P: n/a
Dan

Bjorn wrote:
When i click the back-button, all data is gone and i have to retype it.
Other writers have already given some good hints about form validation
and re-presenting the field values on the "error" page, so I don't need
to repeat that.

But as for the contents vanishing on pressing the back button, it
sounds like your site is somehow doing something to defeat the normal
caching that would allow the back button to work without data loss.
Are you using any weird HTTP headers or meta tags to stop caching?
Anyway, such behavior does tend to be browser-specific. Recent
versions of Mozilla browsers have some special caching behavior to
prevent back-button data loss even in sites that try to suppress this,
I believe.

--
Dan

Sep 14 '06 #9

P: n/a
In reply to Chris Morris:

People could exploit the script like it was shown by me but i'll use my
custom function secure() for it.
it does nothing more than the same you said but thank you anyway.

To Chris Beall: i only understand as much perl as you understand PHP
:wink:
i had a look at the page you referred me to and i'll implement what you
suggest there.

I still prefer to add a JS check because the site i'm working on
requires JS to work.

---
14 sept 2006 22:47h GMT+1 (CET)

Sep 14 '06 #10

P: n/a
To Dan:

i don't use anti-cache headers.
IE is an exception but it doesn't make a difference.
One site i made stored form data, the others don't.
i still don't understand what causes this but now i have a solution.

---
14 sept 2006 22:53h GMT+1 (CET)

Sep 14 '06 #11

P: n/a
Chris Beall <Ch*********@prodigy.netwrites:
Chris Morris wrote:
It's not clear if you've done this from the partial script, but if
it's not been done elsewhere, you need to do:
$email =~s/"/&quot;/; and
$comments =~s/</&lt;/;
or there's a probable cross-site scripting attack.

I wasn't aware of the 'quote in email address' exposure.
It's not specific to it being an email address. Any user input that
gets echoed back to them has the same potential problem.
Can you point me to a good detailed reference?
http://www.cgisecurity.com/articles/xss-faq.shtml seems a good article
on the subject.

Consider the situation where you have:
<input name="email" value="$email">
and the value of $email is (long line)
bo*@example.com"><script type='text/javascript'>alert("Oops!")</script><input type='hidden' name='dummy' value="dummy

The Javascript specified by the attacker then runs in the browser in
the context of your site, which can then steal the user's cookies and
email them to the attacker (allowing session hijacking) or try to
exploit a JS-based bug in the user's browser.

There are other variants on the theme that don't use Javascript that
redirect the form submission to another site for phishing purposes (or
simply insert other text into your site that you might rather wasn't
there).

There have even been some that have spread as worms across 'social
networking' sites.

Obviously for the user to have the value of $email set to that they
must have clicked on a malicious link or submitted a malicious form
(depending on whether you're getting $email from GET or POST data) but
it's not always that hard to do.

It's a very common form of reported vulnerability for two reasons:
- echoing back user input is a very common thing to do across an application
- commonly-used web programming languages (PHP, Perl, etc) have no safeguards
other than those the programmer enters.

--
Chris
Sep 14 '06 #12

P: n/a
Chris Morris wrote:
Chris Beall <Ch*********@prodigy.netwrites:
>Chris Morris wrote:
>>It's not clear if you've done this from the partial script, but if
it's not been done elsewhere, you need to do:
$email =~s/"/&quot;/; and
$comments =~s/</&lt;/;
or there's a probable cross-site scripting attack.
I wasn't aware of the 'quote in email address' exposure.

It's not specific to it being an email address. Any user input that
gets echoed back to them has the same potential problem.
>Can you point me to a good detailed reference?

http://www.cgisecurity.com/articles/xss-faq.shtml seems a good article
on the subject.

Consider the situation where you have:
<input name="email" value="$email">
and the value of $email is (long line)
bo*@example.com"><script type='text/javascript'>alert("Oops!")</script><input type='hidden' name='dummy' value="dummy

The Javascript specified by the attacker then runs in the browser in
the context of your site, which can then steal the user's cookies and
email them to the attacker (allowing session hijacking) or try to
exploit a JS-based bug in the user's browser.

There are other variants on the theme that don't use Javascript that
redirect the form submission to another site for phishing purposes (or
simply insert other text into your site that you might rather wasn't
there).

There have even been some that have spread as worms across 'social
networking' sites.

Obviously for the user to have the value of $email set to that they
must have clicked on a malicious link or submitted a malicious form
(depending on whether you're getting $email from GET or POST data) but
it's not always that hard to do.

It's a very common form of reported vulnerability for two reasons:
- echoing back user input is a very common thing to do across an application
- commonly-used web programming languages (PHP, Perl, etc) have no safeguards
other than those the programmer enters.
Chris,

Thanks for the enlightenment.

So, it's not that the evil email address will cause trouble when sent to
me; it will cause trouble for the user when echoed back to their
browser. That opens a whole can of worms.

Time to add more checks...

Thanks,
Chris Beall
Sep 14 '06 #13

P: n/a
Bjorn:
so i'm asking: "how to preserve POST-data when clicking the
back-button?"
Not a how-to, but I think what RFC2616 says on the matter might come as
a surprise:

...a history mechanism is meant to show exactly
what the user saw at the time when the resource
was retrieved.

(sec. 13.13)

What strikes me - ignoring for the moment its preoccupation with the
sense of sight - is its pronouncement that Histories are meant to
present what was presented *at the time when the resource was
retrieved*. If that means before any user-interaction, any form fields
filled in by the user would have their initial values after going Back.

That's one interpretation anyway.

--
Jock

Sep 15 '06 #14

P: n/a
Chris Morris wrote:
Chris Beall <Ch*********@prodigy.netwrites:
>Chris Morris wrote:
>>It's not clear if you've done this from the partial script, but if
it's not been done elsewhere, you need to do:
$email =~s/"/&quot;/; and
$comments =~s/</&lt;/;
or there's a probable cross-site scripting attack.
I wasn't aware of the 'quote in email address' exposure.

It's not specific to it being an email address. Any user input that
gets echoed back to them has the same potential problem.
(snip)

I was starting get paranoid about all this, so I sat down and gave it
some more thought. Although I understand the concept of rigorously
checking user input, I think I'm in the clear with my specific case...

Contact form, using POST. The user is prompted for their email address
and a message. The former is truncated at the first CR/LF, if any.

1. If there is an error in the user input (currently defined simply as a
missing field), the form is regenerated with the user's input
regurgitated. It is possible for the user to:
- View the page source.
- Determine what string could be used to 'break out' of the form HTML.
- Enter such a string in one of the fields, along with more HTML.
- Leave the other field blank, thus generating the error case.
In this event, the form will be regenerated with the injected HTML
present, which may cause strange displays on the user's system or could,
theoretically, vector the user to another page (which might be malicious).
BUT, this is a case of shooting yourself in the foot. The user can only
influence his own experience, since the form is regenerated only on the
system where the original, malicious, data was entered. Nothing to lose
sleep over.

2. If there is no error in the user input, i.e. both fields contain
data, the email address is plugged into From: and Reply to: headers,
followed by Content-type: text/plain and a double new line, then the
message text.
There's no need to substitute characters (&amp; for &), any more than
there is a need to do it here on the newsgroup, because the content is
specified as text/plain. (Had it been text.html, I agree the recipient
of the message could be sent out into left field.) In fact, if I DID
make such substitution, that's what I would see when I received the
message, which would be ugly.
It is, perhaps, conceivable that certain characters in the email address
could cause a problem IF I were to reply to the message without looking
at the return address. At worst, however, it appears that this would
result in my reply being sent to multiple recipients; I see no way for
malicious CONTENT to be injected into that reply.

This is a more narrowly defined situation than that of the original
poster. I would be very interested in any information that indicates I
am exposed to XSS in this specific case.

Chris Beall
Sep 16 '06 #15

P: n/a
Chris Beall <Ch*********@prodigy.netwrites:
Contact form, using POST. The user is prompted for their email
address and a message. The former is truncated at the first CR/LF, if
any.
Hmm, I'd just reject it outright if it contained any CR/LF characters,
but okay.
1. If there is an error in the user input (currently defined simply as
a missing field), the form is regenerated with the user's input
regurgitated. It is possible for the user to:
- View the page source.
- Determine what string could be used to 'break out' of the form HTML.
- Enter such a string in one of the fields, along with more HTML.
- Leave the other field blank, thus generating the error case.
In this event, the form will be regenerated with the injected HTML
present, which may cause strange displays on the user's system or
could, theoretically, vector the user to another page (which might be
malicious).
BUT, this is a case of shooting yourself in the foot. The user can
only influence his own experience, since the form is regenerated only
on the system where the original, malicious, data was entered.
Nothing to lose sleep over.
Say your form is at http://www.example.com/mailform

I have a page at http://badsite.example.com/exploit that contains the
following code:
<form action="http://www.example.com/mailform" method="post">
<input type="hidden" name="email" value="&quot;&gt;etc.etc.">
....some other fields...
<input type="submit" value="Shoot me in the foot">
</form>

If I can trick a user of your site into submitting my form, then the
attack succeeds. It's not quite as serious as some XSS problems, since
it requires user interaction, but that's really not a major barrier.

--
Chris
Sep 17 '06 #16

P: n/a
Chris Morris wrote:
Chris Beall <Ch*********@prodigy.netwrites:
>Contact form, using POST. The user is prompted for their email
address and a message. The former is truncated at the first CR/LF, if
any.

Hmm, I'd just reject it outright if it contained any CR/LF characters,
but okay.
>1. If there is an error in the user input (currently defined simply as
a missing field), the form is regenerated with the user's input
regurgitated. It is possible for the user to:
- View the page source.
- Determine what string could be used to 'break out' of the form HTML.
- Enter such a string in one of the fields, along with more HTML.
- Leave the other field blank, thus generating the error case.
In this event, the form will be regenerated with the injected HTML
present, which may cause strange displays on the user's system or
could, theoretically, vector the user to another page (which might be
malicious).
BUT, this is a case of shooting yourself in the foot. The user can
only influence his own experience, since the form is regenerated only
on the system where the original, malicious, data was entered.
Nothing to lose sleep over.

Say your form is at http://www.example.com/mailform

I have a page at http://badsite.example.com/exploit that contains the
following code:
<form action="http://www.example.com/mailform" method="post">
<input type="hidden" name="email" value="&quot;&gt;etc.etc.">
...some other fields...
<input type="submit" value="Shoot me in the foot">
</form>

If I can trick a user of your site into submitting my form, then the
attack succeeds. It's not quite as serious as some XSS problems, since
it requires user interaction, but that's really not a major barrier.
Chris,

OK, let's see if I follow this. Bad Guy creates a site and gets
Innocent User to go there. On that site is a form, which Innocent User
is induced to submit (free tickets or whatever...). Instead of pointing
to Bad Guy's form processor, it points to mine, passing it the hidden
data. In this case it passes ONLY the 'email' variable and does NOT
pass a 'comments' variable. My form processor detects the omission,
and, thinking the submission came from itself, generates a form page
with an error message and regurgitating what WAS supplied, the email
address. But this email address contains characters that will break out
of the <inputtag and allow the injection of Evil Stuff. (The Innocent
User does not need to respond to MY form; the mere displaying of it will
initiate the damage.) When things go west, the footprints of my site
will be all over the place.

[I think in the example above, you intended to insert literal quote and
greater-than symbols, which is what is needed to cause the breakout when
the HTML is parsed by the browser. Had character references been used,
there would be no problem (which leads to the solution)]

Now a ways back, you said I should convert certain literals to the
equivalent entity references, thus:
$email =~s/"/&quot;/; and
$comments =~s/</&lt;/;

The first of these prevents early termination of the value= attribute on
the <inputtag; the second prevents initiation of another tag within
the <textareatext. Right so far?

Oh, one other bit. This conversion should be done ONLY if the data is
being used to regurgitate my form page as a result of an error; if
everything is OK and I'm going to send the message, the characters
should remain untouched, or else I'd start getting messages with things
like, "On your About page you've spelled &quot;mishmash&quot; incorrectly."

Then you added that I should:
=~s/&/&amp;/ for both values, citing "possible problems with
validity". As I see it, that would prevent the user, or Bad Guy, from
stuffing his own entity references into the text, but I don't see why it
would be a problem if they got in there. Again, within the comments,
changing & to &amp; will cause it to display as &amp; to me, since the
message is sent as plain text, not HTML. Did you mean that the user
could insert an INVALID entity reference, like &badstuff; (which is
displayed literally as entered)? Or can something worse happen?

Chris Beall, learning a lot
Sep 18 '06 #17

P: n/a
Chris Beall <Ch*********@prodigy.netwrites:
Chris Morris wrote:
<input type="hidden" name="email" value="&quot;&gt;etc.etc.">

OK, let's see if I follow this. Bad Guy creates a site and gets
[...]
mere displaying of it will initiate the damage.) When things go west,
the footprints of my site will be all over the place.
Spot on.
[I think in the example above, you intended to insert literal quote
and greater-than symbols, which is what is needed to cause the
breakout when the HTML is parsed by the browser. Had character
references been used, there would be no problem (which leads to the
solution)]
Actually, no. It's your site, not my evil form, that I want to
sabotage. If I insert literal symbols than my own form breaks.
Now a ways back, you said I should convert certain literals to the
equivalent entity references, thus:
$email =~s/"/&quot;/; and
$comments =~s/</&lt;/;

The first of these prevents early termination of the value= attribute
on the <inputtag; the second prevents initiation of another tag
within the <textareatext. Right so far?
More importantly, it prevents a textarea closing tag being inserted. I
think in most browsers that's necessary.
Oh, one other bit. This conversion should be done ONLY if the data is
being used to regurgitate my form page as a result of an error; if
everything is OK and I'm going to send the message, the characters
should remain untouched, or else I'd start getting messages with
things like, "On your About page you've spelled &quot;mishmash&quot;
incorrectly."
Yes, it's only for data you display out, and it would be wrong to do
it elsewhere. So you should run the escaping function at the last
possible moment.
Then you added that I should:
=~s/&/&amp;/ for both values, citing "possible problems with
validity". As I see it, that would prevent the user, or Bad Guy, from
stuffing his own entity references into the text, but I don't see why
it would be a problem if they got in there. Again, within the
comments, changing & to &amp; will cause it to display as &amp; to me,
since the message is sent as plain text, not HTML. Did you mean that
the user could insert an INVALID entity reference, like &badstuff;
(which is displayed literally as entered)? Or can something worse
happen?
I think it's not a problem for security, that one (at least, not in
*this* context), but it's about redisplaying the form exactly as the
user submitted it.

Try entering this
&amp;amp;amp;amp;amp;amp;amp;
as your comment, and persistently messing up the email address part so
the form gets redisplayed.

After 7 cycles, you would as far as I can tell be left with
&
whereas if you escaped ampersands you'd get
&amp;amp;amp;amp;amp;amp;amp;
which is what you want.

--
Chris
Sep 18 '06 #18

P: n/a
Chris,

OK, I think I'm coming around. embedded responses below:

Chris Morris wrote:
Chris Beall <Ch*********@prodigy.netwrites:
>Chris Morris wrote:
>><input type="hidden" name="email" value="&quot;&gt;etc.etc.">
(snip)
>
>[I think in the example above, you intended to insert literal quote
and greater-than symbols,
(snip)
>
Actually, no. It's your site, not my evil form, that I want to
sabotage. If I insert literal symbols than my own form breaks.
Got it. I can reproduce this by invoking the form, typing some entity
references into one field, and submitting the form. With the other
field blank, the form is returned to me, the entity references now
replaced (not in the source, but in the on-screen field) with literals.
The gun is now cocked. If I Submit THAT form, firing the gun, the
literals are passed to my CGI script, which faithfully regurgitates them
into the SOURCE of a third iteration of the form, and Bad Things can happen.

Actually, this makes me feel a bit better. For this to work, Innocent
User has to click on the trap at Bad Guy's site and then, upon seeing my
hijacked contact form:
- Fail to notice that the domain name in the address bar has changed.
- Fail to notice that the general style of the site (colors, fonts,
layout) has changed (unless Bad Guy did a really good job of replicating
that appearance on the trap page)
- Fail to notice that there's funny-looking stuff already in one of
the input fields.
- Fail to modify that stuff, since doing so would likely mess up the
ammunition.
- Refrain from entering anything in the other (blank) field, since
that would clear the error condition and result in the form being sent
to me, not regurgitated.
- Press the Submit button.

I've been around long enough to know that, yes, there are people who
would just say, "That's odd" and hit Submit (and I'll get around to
making your suggested changes to fence them in) but this seems like an
unlikely scenario, so I won't panic in the meantime.

Unless...I've missed something else.
>Now a ways back, you said I should convert certain literals to the
equivalent entity references, thus:
$email =~s/"/&quot;/; and
$comments =~s/</&lt;/;

The first of these prevents early termination of the value= attribute
on the <inputtag; the second prevents initiation of another tag
within the <textareatext. Right so far?

More importantly, it prevents a textarea closing tag being inserted. I
think in most browsers that's necessary.
Right. I knew that. :-) Naturally, I meant to say "insertion of a
closing textarea tag followed by assorted devious stuff".

(snip part we agree on)
Try entering this
&amp;amp;amp;amp;amp;amp;amp;
as your comment, and persistently messing up the email address part so
the form gets redisplayed.
(snip)

Ah, yes. I was worrying about iteration effects. Thanks for the crisp
example and easy fix.

Thanks,
Chris Beall
Sep 18 '06 #19

P: n/a
Chris Beall <Ch*********@prodigy.netwrites:
replaced (not in the source, but in the on-screen field) with
literals. The gun is now cocked. If I Submit THAT form, firing the
gun, the literals are passed to my CGI script, which faithfully
regurgitates them into the SOURCE of a third iteration of the form,
and Bad Things can happen.

Actually, this makes me feel a bit better. For this to work, Innocent
User has to click on the trap at Bad Guy's site and then, upon seeing
my hijacked contact form:
Not necessarily - what if the bad guy passes the information from the
second iteration in? Then the bad things happen at the point they
arrive on the site, and they don't necessarily get a chance to notice
anything odd. (Users who've disabled Javascript *will* get such a
chance, of course, but they're hardly the majority)

--
Chris
Sep 18 '06 #20

P: n/a
Chris Morris wrote:
Chris Beall <Ch*********@prodigy.netwrites:
replaced (not in the source, but in the on-screen field) with
literals. The gun is now cocked. If I Submit THAT form, firing the
gun, the literals are passed to my CGI script, which faithfully
regurgitates them into the SOURCE of a third iteration of the form,
and Bad Things can happen.

Actually, this makes me feel a bit better. For this to work, Innocent
User has to click on the trap at Bad Guy's site and then, upon seeing
my hijacked contact form:

Not necessarily - what if the bad guy passes the information from the
second iteration in? Then the bad things happen at the point they
arrive on the site, and they don't necessarily get a chance to notice
anything odd. (Users who've disabled Javascript *will* get such a
chance, of course, but they're hardly the majority)

--
Chris
Darn, now I'm confused again.

On the second iteration, my CGI will receive literal values that will
cause it to generate an HTML page with literal values within a value=
attribute or <textareatext. Those values come from the first-pass
entity references and the action of the browser, i.e. it converts the
HTML source into displayed values in the actual form entry fields.

Is there a way for Bad Guy to pass literal values to my CGI other than
that? As you've already poinhted out, Bad Guy can't put literals into
the value= or <textareastrings on his own site, 'cause that would
trigger the trap on his own site.

I guess I need to see a step-by-step on this one to fully understand
it.

Regards,
Chris Beall

Sep 21 '06 #21

P: n/a
"Chris Beall" <Ch*********@prodigy.netwrites:
On the second iteration, my CGI will receive literal values that will
cause it to generate an HTML page with literal values within a value=
attribute or <textareatext. Those values come from the first-pass
entity references and the action of the browser, i.e. it converts the
HTML source into displayed values in the actual form entry fields.

Is there a way for Bad Guy to pass literal values to my CGI other than
that? As you've already poinhted out, Bad Guy can't put literals into
the value= or <textareastrings on his own site, 'cause that would
trigger the trap on his own site.
Right, but they can put escaped values.
I guess I need to see a step-by-step on this one to fully understand
it.
Okay, so you have the equivalent of (removing all unnecessary items,
including the textarea and submit button)
print ("<form action='http://www.example.com/form' method='post'>
<input name=\"email\" value=\"$email\">
</form>");
where $email is filled with the POSTed 'email' variable and the form
is at http://www.example.com/form

Now construct a form on a static HTML page (on your local filesystem
will do) with the contents:
<form action='http://www.example.com/form' method='post'>
<input name='email' value='&quot;&gt;&lt;script&gt;alert(&quot;Oops&qu ot;)&lt;/script&gt;&lt;br title=&quot;'<!-- normally type='hidden' of course... -->
<input type='submit' value='Oops'>
</form>

Obviously replace the http://www.example.com/form URL with the real
URL of your script.

Now (with Javascript enabled) go to the static form page (nothing
unusual happens) and submit the form (you go to your email page and
get the error message).

--
Chris
Sep 22 '06 #22

P: n/a
Chris Morris wrote:
"Chris Beall" <Ch*********@prodigy.netwrites:
On the second iteration, my CGI will receive literal values that will
cause it to generate an HTML page with literal values within a value=
attribute or <textareatext. Those values come from the first-pass
entity references and the action of the browser, i.e. it converts the
HTML source into displayed values in the actual form entry fields.

Is there a way for Bad Guy to pass literal values to my CGI other than
that? As you've already poinhted out, Bad Guy can't put literals into
the value= or <textareastrings on his own site, 'cause that would
trigger the trap on his own site.

Right, but they can put escaped values.
I guess I need to see a step-by-step on this one to fully understand
it.

Okay, so you have the equivalent of (removing all unnecessary items,
including the textarea and submit button)
print ("<form action='http://www.example.com/form' method='post'>
<input name=\"email\" value=\"$email\">
</form>");
where $email is filled with the POSTed 'email' variable and the form
is at http://www.example.com/form

Now construct a form on a static HTML page (on your local filesystem
will do) with the contents:
<form action='http://www.example.com/form' method='post'>
<input name='email' value='&quot;&gt;&lt;script&gt;alert(&quot;Oops&qu ot;)&lt;/script&gt;&lt;br title=&quot;'<!-- normally type='hidden' of course... -->
<input type='submit' value='Oops'>
</form>

Obviously replace the http://www.example.com/form URL with the real
URL of your script.

Now (with Javascript enabled) go to the static form page (nothing
unusual happens) and submit the form (you go to your email page and
get the error message).

--
Chris
Chris,

OK, got it. My CGI has obligingly converted Bad Guy's entity
references into literals which, when combined with the HTML it
generates, will create bad stuff (in your example a JavaScript
fragment) that is executed as soon as the form page is displayed by the
victim's browser. This could be harmful to the victim and that harm
may be traceable to my site.

So the fixes you suggested earlier in this thread are critical.

What would be better? IF the internet were architected such that the
domain of a site providing input to a CGI could be reliably identified,
then the CGI could detect cross-site invocations and both decline to
respond to them and log the attempt, perhaps reporting it to the
appropriate ISP. Not yet, though...

Many thanks,
Chris Beall

Sep 26 '06 #23

P: n/a
"Chris Beall" <Ch*********@prodigy.netwrites:
[cross site scripting]

What would be better? IF the internet were architected such that the
domain of a site providing input to a CGI could be reliably identified,
then the CGI could detect cross-site invocations and both decline to
respond to them and log the attempt, perhaps reporting it to the
appropriate ISP. Not yet, though...
You can use the optional HTTP Referer header for this if you
want. However, not every browser provides it, some HTTP firewalls swap
it for a fixed string, etc. so it's not all that useful. Log it anyway
in server logs, since you can track down *some* [1] XSS sources after the
fact with it, if the worst comes to the worst.

Anyway, cross-site invocations are very much an essential part of the
web - at the simplest example, what about one of the Google search
boxes you can put on your own website (or given that most XSS attacks
are GET based, any link to another website that contains a query string)

The *solution* to XSS, in my opinion, is to use a web programming
language/library that treats tags, element content and attribute
values as different types, and doesn't allow them to be used
interchangeably. My current language of choice [2], I do:

p = addParagraph(cblock,"A <ptag is used to open a paragraph element.");
and the output of that is
<p>A &lt;p&gt; tag is used to open a paragraph element.</p>

Similarly, if I have a form that I want re-filling, I do:
autoFill(form,DataPost);
and it's all handled automatically with all the escaping of user input
in the proper places.

I don't believe it should be the responsibility of the application
programmer to ensure every bit of user input is properly escaped on
output - that clearly doesn't work reliably in practice, and with the
right development model is entirely unnecessary.

[1] Of course, there are other XSS-style attacks where the attacker
submits content to a site that then isn't escaped properly and gets
displayed back to every other person who views that page without any
further interaction. There have even been web-based worms that run
that way.

[2] Disclaimer: I wrote most of the functions I'm describing, so I can
hardly be described as unbiased on it. On the other hand, they're
functions that I kept wishing existed in other web development
languages, so it's a reasonable view of my vision of how web
development languages/libraries "should be", which is very different
to the 'standard'
print ("<p>".$contents_of_paragraph."</p>");
method that PHP and Perl use.

--
Chris
Sep 27 '06 #24

This discussion thread is closed

Replies have been disabled for this discussion.