Passing parameters in URL

  • Thread starter Alan Harris-Reid
  • Start date
A

Alan Harris-Reid

I have a web-page where each row in a grid has edit/delete buttons to
enable the user to maintain a selected record on another page. The
buttons are in the form of a link with href='/item_edit?id=123', but
this string appears in the URL and gives clues as to how to bypass the
correct sequence of events, and could be risky if they entered the URL
directly (especially when it comes to deleting records).

Is there another way of passing a record-id to a method
a) without it appearing in the URL?
b) without the user being able to fathom-out how to attach which id to
which URL?

As each link contains row-id, I guess there is nothing to stop someone
from getting the id from the page source-code. Is it safe to use the
above href method if I test for authorised credentials (user/password
stored as session variables, perhaps?) before performing the edit/delete
action?

I am currently using CherryPy 3.2, but I guess the theory could apply to
any HTTP framework or web app..

Any help would be appreciated.
Alan Harris-Reid
 
J

John Bokma

Alan Harris-Reid said:
I have a web-page where each row in a grid has edit/delete buttons to
enable the user to maintain a selected record on another page. The
buttons are in the form of a link with href='/item_edit?id=123', but
this string appears in the URL and gives clues as to how to bypass the
correct sequence of events, and could be risky if they entered the URL
directly (especially when it comes to deleting records).

You should *never* use a GET request to do actions like deleting
records. You already are aware of it being risky, so don't do this. You
should use GET for getting information, and POST for modifying information.
Is there another way of passing a record-id to a method
a) without it appearing in the URL?

Use a POST request. Note that the user still has to select something,
and that this information is send by the browser, and hence the user can
see this information (and maybe others), and repeat the action with, for
example, a Python program.
b) without the user being able to fathom-out how to attach which id to
which URL?

I am not sure what you want to prevent here. If you're afraid that user
A can delete things that belong user B, than "hiding" things or making
them "hard to guess" are not going to help much. If you have several
users, you must use some login procedure (and sessions).
As each link contains row-id, I guess there is nothing to stop someone
from getting the id from the page source-code. Is it safe to use the
above href method if I test for authorised credentials (user/password
stored as session variables, perhaps?) before performing the
edit/delete action?

Yes. But still make sure that session ids are not easy to guess, and
expire. And make very sure that session ids can't leak to others.

Moreover, each time you modify a database use POST. One could argue to
also use POST for logging out, otherwise another site might be able to
log your users out if they visit that site.
 
P

Paul Rubin

Alan Harris-Reid said:
As each link contains row-id, I guess there is nothing to stop someone
from getting the id from the page source-code. Is it safe to use the
above href method if I test for authorised credentials (user/password
stored as session variables, perhaps?) before performing the
edit/delete action?

Well, if it's really ok for them to delete records programmatically even
if it's ok for them to delete through the web site. I'd probably
encrypt the post parameters if this was a concern.
 
D

Diez B. Roggisch

Am 03.02.10 19:11, schrieb John Bokma:
You should *never* use a GET request to do actions like deleting
records. You already are aware of it being risky, so don't do this. You
should use GET for getting information, and POST for modifying information.

You should *never* say never, because there might be situations where
exceptions from rules are valid. This is one such cases. Making this a
post means that you need to resort to javascript to populate & submit a
hidden HTML-form. Just for the sake of a POST.

And there are people who say "you should *never* write web-apps that
only work with enabled javascript"... catch 22.

Also, your claim of it being more risky is simply nonsense. GET is a
tiny bit more prone to tinkering by the average user. But calling this
less risky is promoting security by obscurity, at most.

Diez
 
P

Paul Rubin

Diez B. Roggisch said:
Also, your claim of it being more risky is simply nonsense. GET is a
tiny bit more prone to tinkering by the average user. But calling this
less risky is promoting security by obscurity, at most.

GET parameters also tend to get recorded in the http logs of web proxies
and web servers while POST parameters usually aren't. This was an
annoyance in a web chat package I fooled with for a while. Because the
package sent user messages by GET, if I ran the software the way the
developers set it up, the contents of all the user conversations stayed
in my server logs. I was unable to convince the chat package
maintainers that this was a bug. I ended up doing some fairly kludgy
hack to prevent the logging.
 
D

Diez B. Roggisch

Am 03.02.10 19:01, schrieb Alan Harris-Reid:
I have a web-page where each row in a grid has edit/delete buttons to
enable the user to maintain a selected record on another page. The
buttons are in the form of a link with href='/item_edit?id=123', but
this string appears in the URL and gives clues as to how to bypass the
correct sequence of events, and could be risky if they entered the URL
directly (especially when it comes to deleting records).

Is there another way of passing a record-id to a method
a) without it appearing in the URL?

You can populate an invisible HTML-form with the values, and submit that
- of course you need javascript for this.

But this doesn't increase security a bit. Using an extension to FF such
as HTTP live headers, it's easy enough to figure out what parameters are
passed, and simply forge a request.

b) without the user being able to fathom-out how to attach which id to
which URL?

Paul already mentioned that - you can create a server-side,
session-stored action-item that is identified by a hash of some sort.
Then use that hash as parameter.

But I'd say you should instead make sure that your serve actions perform
authorization checking before performing any operations. Then you don't
need to worry - even guessing a hash argument won't work then.
As each link contains row-id, I guess there is nothing to stop someone
from getting the id from the page source-code. Is it safe to use the
above href method if I test for authorised credentials (user/password
stored as session variables, perhaps?) before performing the edit/delete
action?

You should of course always do that. Every http-action except login
should be guarded (unless you allow anonymous access of course).

Diez
 
D

Diez B. Roggisch

Am 03.02.10 23:09, schrieb Paul Rubin:
GET parameters also tend to get recorded in the http logs of web proxies
and web servers while POST parameters usually aren't. This was an
annoyance in a web chat package I fooled with for a while. Because the
package sent user messages by GET, if I ran the software the way the
developers set it up, the contents of all the user conversations stayed
in my server logs. I was unable to convince the chat package
maintainers that this was a bug. I ended up doing some fairly kludgy
hack to prevent the logging.

If somebody happens to have access to a proxy & it's logs, he can as
well log the request body.

Don't get me wrong, I don't want to propagate the use of GET as one and
only method for parameter passing. But whatever is transmitted clear
text over the wire is subject to inspection of all hops in between. Use
SSL if you bother.

Diez
 
P

Paul Rubin

Diez B. Roggisch said:
If somebody happens to have access to a proxy & it's logs, he can as
well log the request body.

I'm not talking about a malicious server operator. In this situation, I
was the server operator and I didn't want to be recording the
conversations. I had to go out of my way to stop the recording. SSL
doesn't help and in fact I was using it, but web server logging happens
after the SSL layer. I suppose SSL would help against a malicious
proxy.

Many people back in those days (before AJAX became a buzzword du jour)
wanted to do encryption on the client in java or javascript, but that
was almost unworkably kludgy, and SSL was the only approach that made
any sense. It might be easier now that the javascript API's are richer
and the interpreters are faster.
 
D

Diez B. Roggisch

Am 03.02.10 23:35, schrieb Paul Rubin:
I'm not talking about a malicious server operator. In this situation, I
was the server operator and I didn't want to be recording the
conversations. I had to go out of my way to stop the recording. SSL
doesn't help and in fact I was using it, but web server logging happens
after the SSL layer. I suppose SSL would help against a malicious
proxy.

Well, we actually implemented POST-parameter logging (inside the
WSGI-app), because we *want* all parameters users pass. They end up in
the application anyway, and aid debugging. Of course we blind sensitive
parameters such as passwords & creditcard numbers.

Of course only information not gathered is really safe information. But
every operation that has side-effects is reproducable anyway, and if
e.g. your chat-app has a history, you can as well log the parameters.

Diez
 
P

Paul Rubin

Diez B. Roggisch said:
Of course only information not gathered is really safe
information. But every operation that has side-effects is reproducable
anyway, and if e.g. your chat-app has a history, you can as well log
the parameters.

No I can't. The chat-app history would be on the client, not the
server, so I'd have no access to it. Put another way: as server
operator, I'm like the owner of a coffee shop. I can't stop patrons
from recording their own conversations with each other, and it's not
even really my business whether they do that. But it would be
outrageous for the shop owner to record the conversations of patrons.
 
D

Diez B. Roggisch

Am 04.02.10 00:39, schrieb Paul Rubin:
No I can't. The chat-app history would be on the client, not the
server, so I'd have no access to it. Put another way: as server
operator, I'm like the owner of a coffee shop. I can't stop patrons
from recording their own conversations with each other, and it's not
even really my business whether they do that. But it would be
outrageous for the shop owner to record the conversations of patrons.

Which is the exact thing that happens when you use an email-provider
with IMAP. Or google wave. Or groups. Or facebook. Or twitter. Which I
wouldn't call outrageous.

This discussion moves away from the original question: is there anything
inherently less secure when using GET vs. POST. There isn't.

Users can forge both kind of requests easy enough, whoever sits in the
middle can access both, and it's at the discretion of the service
provider to only save what it needs to. If you don't trust it, don't use it.

Diez
 
P

Paul Rubin

Diez B. Roggisch said:
Which is the exact thing that happens when you use an email-provider
with IMAP. Or google wave. Or groups. Or facebook. Or twitter. Which I
wouldn't call outrageous.

Those are not comparable. IMAP is a storage service, and groups,
facebook, and twitter are publishing systems (ok, I've never understood
quite what Google Wave is). Yes, by definition, your voice mail
provider (like IMAP) has to save recordings of messages people leave
you, but that's a heck of a lot different than your phone carrier
recording your real-time conversations. Recording live phone
conversations by a third party is called a "wiretap" and doing it
without suitable authorization can get you in a heck of a lot of
trouble.
This discussion moves away from the original question: is there
anything inherently less secure when using GET vs. POST. There isn't.

Well, the extra logging of GET parameters is not inherent to the
protocol, but it's an accidental side effect that server ops may have to
watch out for.
Users can forge both kind of requests easy enough, whoever sits in the
middle can access both,

I'm not sure what you mean by that. Obviously if users want to record
their own conversations, then I can't stop them, but that's much
different than a non-participant in the conversation leaving a recorder
running 24/7. Is that so hard to understand?

Interception from the middle is addressed by SSL, though that relies on
the PKI certificate infrastructure, which while somewhat dubious, is
better than nothing.
and it's at the discretion of the service provider to only save what
it needs to. If you don't trust it, don't use it.

I certainly didn't feel that saving or not saving client conversations
on the server side was up to my discretion. When I found that the
default server configuration caused conversations to be logged then I
was appalled.

Do you think the phone company has the right to record all your phone
calls if they feel like it (absent something like a law enforcement
investigation)? What about coffee shops that you visit with your
friends? It is not up to their discretion. They have a positive
obligation to not do it. If you think they are doing it on purpose
without your authorization, you should notify the FBI or your
equivalent, not just "don't use it". If they find they are doing it
inadvertently, they have to take measures to make it stop. That is the
situation I found myself in, because of the difference in how servers
treat GET vs. POST.
 
J

John Bokma

Diez B. Roggisch said:
Am 03.02.10 19:11, schrieb John Bokma:

You should *never* say never, because there might be situations where
exceptions from rules are valid. This is one such cases. Making this a
post means that you need to resort to javascript to populate & submit
a hidden HTML-form. Just for the sake of a POST.

Make each edit/delete button a submit button and optionally style it.
Also, your claim of it being more risky is simply nonsense. GET is a
tiny bit more prone to tinkering by the average user. But calling this
less risky is promoting security by obscurity, at most.

Maybe you should think about what happens if someone posts:
<img src="http://example.com/item_delete?id=123"> to a popular forum...
 
N

Nobody

GET parameters also tend to get recorded in the http logs of web proxies
and web servers while POST parameters usually aren't.

More significantly, they'll appear in the Referer: header for any link the
user follows from the page, so they're visible to anyone who can get a
link to their site onto the page (whether <a href=...>, <img src=...> or
whatever).

Even if this isn't possible at the moment, will you remember to fix it the
first time you allow an off-site link?

You should assume that anything which goes into a GET request is visible
to the entire world. Don't put anything even remotely private in there.
 
D

Diez B. Roggisch

I'm not sure what you mean by that. Obviously if users want to record
their own conversations, then I can't stop them, but that's much
different than a non-participant in the conversation leaving a recorder
running 24/7. Is that so hard to understand?

Is it so hard to understand that this is not about laws and rights, but
about technical properties of the HTTP-protocol?

Your web-based chat uses HTTP, no P2P-protocol, and thus the service
provider *can* log conversations. I don't say he should, I don't say I
want that, I don't say there are now laws that prevent them from doing
so, all I say is he *can*.
I certainly didn't feel that saving or not saving client conversations
on the server side was up to my discretion. When I found that the
default server configuration caused conversations to be logged then I
was appalled.

Then stop logging. Or get a hosting-provider that allows you to
configure it to strip QUERY_STRINGS from log-entries. And if they refuse
to, maybe using POST solves the issue.

But wait, there is

http://www.cyberciti.biz/faq/apache-mod_dumpio-log-post-data/

So what if they run that?

So, for the umpteenth time: data sent over the wire can be recorded.
From the user's POV, your nitpicking of who's the actual culprit - the
IT-guys, or the programmers - is fruitless. You have a nice anecdote
where switching from GET to POST allowed you to trick whoever wasn't
acting to your wishes. Good for you. But John B. and your posts indicate
that using POST is inherently more secure. It *isn't*.

Do you think the phone company has the right to record all your phone
calls if they feel like it (absent something like a law enforcement
investigation)? What about coffee shops that you visit with your
friends? It is not up to their discretion. They have a positive
obligation to not do it. If you think they are doing it on purpose
without your authorization, you should notify the FBI or your
equivalent, not just "don't use it". If they find they are doing it
inadvertently, they have to take measures to make it stop. That is the
situation I found myself in, because of the difference in how servers
treat GET vs. POST.

If they have a positive obligation not to do it, it doesn't matter if
they run their service over GET or POST.

Again, this is not about laws and what service providers should or must
do. It's about POST vs. GET, and if either of them is more secure or
not. It isn't.


Diez
 
D

Diez B. Roggisch

Am 04.02.10 01:42, schrieb John Bokma:
Make each edit/delete button a submit button and optionally style it.

*slap* Yep, you are right, no JS needed. I should have thought about that.
Maybe you should think about what happens if someone posts:
<img src="http://example.com/item_delete?id=123"> to a popular forum...

And the difference to posting

from urrlib2 import open
from urllib import encode

open("http://example.com/item_delete", data=encode([("id", "123")]))

to that same public "hacker" forum is exactly what?

If your webapp happens to allow item_delete to be called without
authentication & authorization, then *that's* your problem.

Diez
 
D

Diez B. Roggisch

Am 04.02.10 03:52, schrieb Nobody:
More significantly, they'll appear in the Referer: header for any link the
user follows from the page, so they're visible to anyone who can get a
link to their site onto the page (whether<a href=...>,<img src=...> or
whatever).

Even if this isn't possible at the moment, will you remember to fix it the
first time you allow an off-site link?

You should assume that anything which goes into a GET request is visible
to the entire world. Don't put anything even remotely private in there.

You mean like

http://www.google.de/search?q=dirty+buttsex

? Which is the key example for when to use GET - non-modifying queries.

I agree though that you have to be cautious about that, and using POST
makes it easier to do so.

Diez
 
P

Paul Rubin

Diez B. Roggisch said:
Your web-based chat uses HTTP, no P2P-protocol, and thus the service
provider *can* log conversations. I don't say he should, I don't say I
want that, I don't say there are now laws that prevent them from doing
so, all I say is he *can*.

Sure, my complaint is that the default setup caused this to actually
happen so lots of people using that software were recording user
conversations without realizing it and maybe without caring. This
is a bad erosion as I see it.
Then stop logging. Or get a hosting-provider that allows you to
configure it to strip QUERY_STRINGS from log-entries. And if they
refuse to, maybe using POST solves the issue.

I did stop logging. There wasn't an issue with the hosting provider
since I was running the server myself. But I had to resort to some ugly
software kludge to stop logging those particular strings. More
frustratingly, I filed a bug report about the issue against the chat
software but the conversation was sort of like the one you and I are
having now. I just couldn't convince them that there was a problem and
that they should change the default.

That sounds like something someone would have to go out of their way to
install and use. It's not the default. Of course if someone is
malicious they can do all sorts of nasty stuff. A coffeeshop that
wanted to mess with me on purpose wouldn't have to do high tech crap
like recording my conversations--they could just poison my coffee. I
have to trust them to not do this on purpose, but then I see a situation
where their coffee sweetener accidentaly has a harmful chemical, so of
course I'd ask them to do something about it.
So, for the umpteenth time: data sent over the wire can be recorded.

And for the umpteenth time, I'm less concerned about "can be" than "is".
POST isn't logged unless you go to some lengths to have it logged. GET
is logged unless you go to some lengths to prevent it. It's not enough
in a software deployment to only consider what actions are possible.
It's important to make sure that the default actions are the right ones.
If they have a positive obligation not to do it, it doesn't matter if
they run their service over GET or POST.

GET makes it harder for them to fulfill their obligations. As a
security nerd, I saw what was happening and took measures against it,
but a more typical operator might never notice or care.

There is also the matter of the referer header which an anon mentioned,
though it didn't apply to this particular situation because of how
the application worked.
 
P

Paul Rubin

Bruno Desthuilliers said:
...At least use "POST" requests for anything that Create/Update/Delete
resources.

There's also the issue that a user can change "123" to "125" and
possibly mess with someone else's resource, unless you use some server
side authentication. Or just seeing how often the numbers change could
reveal patterns about what other users are doing. I always think it's
best to encrypt anything sensitive like that, to avoid leaking any info.
 
B

Bruno Desthuilliers

Alan Harris-Reid a écrit :
I have a web-page where each row in a grid has edit/delete buttons to
enable the user to maintain a selected record on another page. The
buttons are in the form of a link with href='/item_edit?id=123', but
this string appears in the URL and gives clues as to how to bypass the
correct sequence of events, and could be risky if they entered the URL
directly (especially when it comes to deleting records).

Basic HTTP stuff - this is definitely not Python-related.
<OT>
Do yourself (and your users / customers / etc) a favor and read the HTTP
rfc. "GET" requests should NOT modify the server state. At least use
"POST" requests for anything that Create/Update/Delete resources.

For the record, someone once had serious problems with GET requests
deleting records - turned out to be a very bad idea when a robot started
following these links...
Is there another way of passing a record-id to a method
href="/item/23/edit"
href="/item/edit/23"

etc

a) without it appearing in the URL?
b) without the user being able to fathom-out how to attach which id to
which URL?

Wrong solution. The correct solution is to
1/ make correct use of the request method (GET and POST at least).
2/ make sure the user performing the action has the permission to do it.


1/ won't protect your data from malicious users, but will at least avoid
accidental mistakes.

2/ by checking the user's perms when handling the POST request of course
- not by hidding "forbidden" urls.
As each link contains row-id, I guess there is nothing to stop someone
from getting the id from the page source-code.

Nor even from trying any other id (brute-force attack).
Is it safe to use the
above href method if I test for authorised credentials (user/password
stored as session variables, perhaps?) before performing the edit/delete
action?

cf above.
I am currently using CherryPy 3.2, but I guess the theory could apply to
any HTTP framework or web app..

Indeed.
</OT>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top