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

Reality Check: Session Hijacking

P: n/a
Tell me if my assertion is wrong here:

The only way to prevent session hijacking is to NEVER store
authentication information (such as name/password) in the session.
Well, to never authenticate a user from information you got from the
session. Each secure app on a site must challenge the user for name
and password, each and every time the user accesses it (not just once
and then store it in the session). If a secure app is multi-page,
then you must only pass session data in hidden form fields between
each page, on forms that POST over https.

That's my assertion. Is that right? If you disagree, consider this
scenario:

1. User goes to a web site's homepage, over http. The site remembers
him, Welcome, Joe. In other words, there's his session ID, travelling
over insecure http in a plain text cookie that anyone can read with a
packet sniffer.

2. User goes to edit some private data, such as his name and address
or cc number or whatever, over https, and IS NOT CHALLENGED for his
name/password, because the site knows who he is from his session.

3. The above is security breach. Someone with a packet sniffer could
see his session id, as well as everything else about his requests-
browser, ip address, etc, in plain text, when he was making requests
over http. Then with that, the sniffer could make an https request to
the same application that displays his private information. The
sniffer doesn't know the user's loginname/password, and he doesn't
have to, he's never asked for it. All he needs is the sesid cookie.

If you agree, then look at this from the zend site, and isn't it
fundamentally wrong?:

http://www.zend.com/zend/spotlight/s...y.php#Heading5
------------------------------------------
Signature:
Never buy the services of newsfeed.com. I am a paying customer but
I'm using google to post messages, so that I can avoid their damn
advertisement showing up in every post I make.
------------------------------------------
Jul 17 '05 #1
Share this Question
Share on Google+
27 Replies


P: n/a
mrbog <dt******@hotmail.com> wrote:
The only way to prevent session hijacking is to NEVER store
authentication information (such as name/password) in the session.
Wrong. Hijacking is independend of data contained in a session.
Well, to never authenticate a user from information you got from the
session. Each secure app on a site must challenge the user for name
and password, each and every time the user accesses it (not just once
and then store it in the session).
Ehhh, that is one of the things sessions are mainly used for (to
prevent)
If a secure app is multi-page, then you must only pass session data in
hidden form fields between each page, on forms that POST over https.
So instead of sendig it once and storing something in session you want
to send the vulnerable data over and over again? (Note that I said
something instead of login/password).
That's my assertion. Is that right? If you disagree, consider this
scenario:

1. User goes to a web site's homepage, over http. The site remembers
him, Welcome, Joe. In other words, there's his session ID, travelling
over insecure http in a plain text cookie that anyone can read with a
packet sniffer.
SessionIDs are nothing more than random data (standard PHP session
string is a 128bit hexstring (32chars)).
2. User goes to edit some private data, such as his name and address
or cc number or whatever, over https, and IS NOT CHALLENGED for his
name/password, because the site knows who he is from his session.

3. The above is security breach. Someone with a packet sniffer could
see his session id, as well as everything else about his requests-
browser, ip address, etc, in plain text, when he was making requests
over http. Then with that, the sniffer could make an https request to
the same application that displays his private information. The
sniffer doesn't know the user's loginname/password, and he doesn't
have to, he's never asked for it. All he needs is the sesid cookie.
Correct. So this has to be prevented. At this point there isn't much one
can do about the hijacker reading the userdata, only thing that has to
be prevented is the hijacker changing data, The most simple way to do
this is to ask for a PIN at these points, offcourse transactions that
ask for a PIN should only be done over secured (eg ssl) connections.
If you agree, then look at this from the zend site, and isn't it
fundamentally wrong?:

http://www.zend.com/zend/spotlight/s...y.php#Heading5


I dont' see anything wrong with this. $authdata doesn't contain a
user/password combo, it's either false or an array (containing
loginname).

--

Daniel Tryba

Jul 17 '05 #2

P: n/a
"Daniel Tryba" wrote
If a secure app is multi-page, then you must only pass session
data in hidden form fields between each page, on forms that
POST over https.


So instead of sendig it once and storing something in session you want
to send the vulnerable data over and over again?


A single (even GET) parameter can be usefull: simply store some random value
in both session and that parameter, and compare the two. This makes random
session hijacking (where one would try to guess a session id without any
sniffing, which indeed is difficult) a lot more difficult. And when
refreshing the random value for each page this can be used to control the
use of the Back button or avoiding multiple hits on a submit button (but
that is not session or security related).

Adriaan
Jul 17 '05 #3

P: n/a
Daniel Tryba <ne****************@canopus.nl> wrote in message news:<c7**********@news.tue.nl>...

So instead of sendig it once and storing something in session you want
to send the vulnerable data over and over again? (Note that I said
something instead of login/password).
(snip) Correct. So this has to be prevented. At this point there isn't much one
can do about the hijacker reading the userdata, only thing that has to
be prevented is the hijacker changing data, The most simple way to do
this is to ask for a PIN at these points, offcourse transactions that
ask for a PIN should only be done over secured (eg ssl) connections.


No, you're not thinking deeply enough. Think this through. There IS
"much one can do about the hijacker reading userdata". If you do it
my way- always challenge the user for name and password when he's
viewing secure data, and then pass name/password on hidden form
fields, then you can prevent session hijacking. (With the one
exception of those rare hackers than can actually decript 128 bit ssl,
obviously, which I don't think is what you're arguing here).

With your way, and the way recommended by that zend site, sessions
are wide open to be hijacked. If you challenge the user for
name/password, and then store some "authenticated" bit in the session
(even if it's not name/password, whatever it doesn't matter), then
someone else can see the session id, and create a duplicate request,
going into secure https with that session id, just as user would, and
do whatever he wants (whatever the user could). And neve be
challenged for the password.

Think deeper, don't click the respond button until you get it.

------------------------------------------
Signature:
Never buy the services of newsfeed.com. I am a paying customer but
I'm using google to post messages, so that I can avoid their damn
advertisement showing up in every post I make.
------------------------------------------
Jul 17 '05 #4

P: n/a
dt******@hotmail.com (mrbog) wrote in message news:<cb**************************@posting.google. com>...
Tell me if my assertion is wrong here:


<snip>

Not an answer to your question. But, this logic is what I prefer
<http://martin.f2o.org/php/login>

--
| Just another PHP saint |
Email: rrjanbiah-at-Y!com
Jul 17 '05 #5

P: n/a
"mrbog" wrote
Correct. So this has to be prevented. At this point there isn't much one
can do about the hijacker reading the userdata, only thing that has to
be prevented is the hijacker changing data
.... No, you're not thinking deeply enough. Think this through. There IS
"much one can do about the hijacker reading userdata". If you do it
my way- always challenge the user for name and password when he's
viewing secure data, and then pass name/password on hidden form
fields, then you can prevent session hijacking.


But then you're always using SSL, for otherwise you method is simply
decreasing security. In essence, the session id *is* a way of authentication
just like user name and password, but at least one that's only valid for the
current session. But in your solution the authentication is no longer
temporary valid! If you're indeed using SSL for each page, then there's
simply no need for your worries, and no need for your solution. Even more:
some browsers *do* save SSL pages to disk -- so repeating the user name and
password in hidden form fields is *very* bad practice, even worse than
saving them in the session itself (which you should not do either).

By the way: your solution makes your pages much more difficult to create, as
all pages suddenly need to be a FORM, which is also a pain for the visitor
when using the browser's Back button. I would hate such a site!

Your solution only helps for shared servers (such as Apache's virtual
hosting) where other webmasters could read all the session IDs (and
contents) from the temp folder. But that setup can be changed, and shared
servers should simply never be used for sensitive applications (and those
webmasters could also read your code and as such get your database password
and open that database). Daniel's solution to prompt for the PIN is right,
and is implemented on many sites -- if not for hijacking then for avoiding
someone actually using *your* computer to change such details after you
logged in and left the browser open (maybe showing a different site, but the
Back button might take that person back to your sensitive pages) when going
for lunch -- which is not taken care of by your solution either.

Adriaan.
Jul 17 '05 #6

P: n/a
"R. Rajesh Jeba Anbiah" wrote
Not an answer to your question. But, this logic is what I prefer
<http://martin.f2o.org/php/login>


So you're storing the IP address in your database. But HTML being stateless
by design, doesn't this break when using dial-up networking (totally valid,
especially for ISDN that might drop the connection after a timeout that is
much shorter than the timeout of your session) or proxy servers?

Adriaan.
Jul 17 '05 #7

P: n/a
mrbog <dt******@hotmail.com> wrote:
No, you're not thinking deeply enough. Think this through. There IS
"much one can do about the hijacker reading userdata". If you do it
my way- always challenge the user for name and password when he's
viewing secure data, and then pass name/password on hidden form
fields, then you can prevent session hijacking. (With the one
exception of those rare hackers than can actually decript 128 bit ssl,
obviously, which I don't think is what you're arguing here).
This is actually worse since every page contains the necesary
credentials to create a new session.
With your way, and the way recommended by that zend site, sessions
are wide open to be hijacked. If you challenge the user for
name/password, and then store some "authenticated" bit in the session
(even if it's not name/password, whatever it doesn't matter), then
someone else can see the session id, and create a duplicate request,
going into secure https with that session id, just as user would, and
do whatever he wants (whatever the user could). And neve be
challenged for the password.
Guess you did miss my suggestion to ask for additional credentials on
editing data?
Think deeper, don't click the respond button until you get it.


Duhhhhh!

Solution found: only use https.

--

Daniel Tryba

Jul 17 '05 #8

P: n/a
R. Rajesh Jeba Anbiah <ng**********@rediffmail.com> wrote:
Not an answer to your question. But, this logic is what I prefer
<http://martin.f2o.org/php/login>


Like Adriaan suggested, this actually locks out some users (those behind
loadbalancing proxies at least). Also it only limits the number of users
that can hijack to the users that can product the same
$_SERVER['REMOTE_ADDR'] (eg everyone on the same proxy).

To bad this was fixed:

http://www.computerbytesman.com/privacy/supercookie.htm

:)

--

Daniel Tryba

Jul 17 '05 #9

P: n/a
Daniel Tryba <ne****************@canopus.nl> wrote in message news:<c7**********@news.tue.nl>...
R. Rajesh Jeba Anbiah <ng**********@rediffmail.com> wrote:
Not an answer to your question. But, this logic is what I prefer
<http://martin.f2o.org/php/login>
Like Adriaan suggested, this actually locks out some users (those behind
loadbalancing proxies at least). Also it only limits the number of users
that can hijack to the users that can product the same
$_SERVER['REMOTE_ADDR'] (eg everyone on the same proxy).


I could be able to differentiate the proxy to some extent. And I
agree that it is not a 100% foolproof.
To bad this was fixed:

http://www.computerbytesman.com/privacy/supercookie.htm


Will look at there later.

--
| Just another PHP saint |
Email: rrjanbiah-at-Y!com
Jul 17 '05 #10

P: n/a
"Adriaan" <re*@de.solidareit> wrote in message news:<40***********************@dreader19.news.xs4 all.nl>...
But then you're always using SSL, for otherwise you method is simply
decreasing security. In essence, the session id *is* a way of authentication
just like user name and password, but at least one that's only valid for the
current session. But in your solution the authentication is no longer
temporary valid! If you're indeed using SSL for each page, then there's
simply no need for your worries, and no need for your solution.


No- I'm not saying to use SSL for every page. Use SSL for every page
of applications that are transmitting sensitive data- (in other words,
use SSL jsut as much as it was intented). If the entire site is over
https, then yea, there's no problems with any method (unless hackers
decode the ssl obviously).

As for the browser caching the HTML, that's solved easily enough- just
encode the name and password before you write it to the input
type="hidden" fields, and decode it when you get it back.

You've caused me to enhance my solution- So here it is again:

1. ALWAYS challenge the user for name/password when he BEGINS to use
an application that's over https, in other words, an application that
involves sensitive data. Do NOT store this data in the session.

2. On evey subsequent page of the given sensitive application, write
an encoded (encrypted) version of the authenication information
(name/password) into hidden fields, and re-authenticate using those
(unencoded) fields again when the form is submitted.

3. If the user LEAVES the secure application and goes to an http (no
s) part of the site, and then comes back to a secure part again, he
will be re-challenged for name and password and has to login again,
see step 1, because the app can't get his auth info from anywhere.

4. There is no possibility of session hijacking in the above, except
obviously if someone can decode SSL's 128 bit encryption.

Now, is what I've come up with essentially the same thing as what you
two are talking about with setting a "PIN"- where isntead of storing
encrypted authentication info into hidden fields, you're saying I
could store a random number and then check for it again when the form
comes back? If so, I'll go with that, and we're essentially on the
same page, EXCEPT FOR THE FACT THAT THAT ZEND ARTICLE DOESN'T SUGGEST
THAT, and is therefore wide open for session hijacking, which is the
whole point of my post.
Jul 17 '05 #11

P: n/a
"mrbog" wrote
Now, is what I've come up with essentially the same thing as what you
two are talking about with setting a "PIN"- where isntead of storing
encrypted authentication info into hidden fields, you're saying I
could store a random number and then check for it again when the form
comes back?


We're not talking about setting a PIN. The PIN Daniel suggested and I
repeated (and that many sites use) is really a username and password. So
forget the word PIN, and whereever we were referring to it read "username
and password". The username could have been stored in the session. Whenever
something requires new authentication, the application can prompt for the
password.

Apart from that: I still don't see any reason to go with your difficult
solution, but well that's just me. You solution still allows for session
hijacking for those who're sniffing the data sent. When the hijacker gets to
the SSL he's stuck: little or no difference compared to using plain sessions
and prompting for the password when changing data. And if really that
important than I'd favor using SSL for each page rather than effectively
disabling the browser Back button by using your hidden FORM.

Cheers,
Adriaan
Jul 17 '05 #12

P: n/a
mrbog <dt******@hotmail.com> wrote:
You've caused me to enhance my solution- So here it is again:

1. ALWAYS challenge the user for name/password when he BEGINS to use
an application that's over https, in other words, an application that
involves sensitive data. Do NOT store this data in the session.

2. On evey subsequent page of the given sensitive application, write
an encoded (encrypted) version of the authenication information
(name/password) into hidden fields, and re-authenticate using those
(unencoded) fields again when the form is submitted.
You are contradicting yourself. Where are you getting the user/passwd
data from? You have it stored somewhere, so you might just as well store
it in a session.
3. If the user LEAVES the secure application and goes to an http (no
s) part of the site, and then comes back to a secure part again, he
will be re-challenged for name and password and has to login again,
see step 1, because the app can't get his auth info from anywhere.

4. There is no possibility of session hijacking in the above, except
obviously if someone can decode SSL's 128 bit encryption.


Our break the encryption on the data you're sending on every page....

BTW The biggest problem with privacy isn't in the session but in the
browser. Ligit user uses your application, logs out but leaves browser
open, the next person only has to do a couple of back's and can see
whatever is left in the history of the browser (and in your case the
encoded challenge responses).

If you want to the stuff you are proposing, DON'T USE static data. Use
random stuff to make URLs/forms unique and check for the correct unique
key in the session. But that solution was already suggested.

--

Daniel Tryba

Jul 17 '05 #13

P: n/a
R. Rajesh Jeba Anbiah <ng**********@rediffmail.com> wrote:
Also it only limits the number of users
that can hijack to the users that can product the same
$_SERVER['REMOTE_ADDR'] (eg everyone on the same proxy).


I could be able to differentiate the proxy to some extent. And I
agree that it is not a 100% foolproof.


Sure, if you only look to the x-forwarded-for (or equiv) header you are
totally screwed.... with my own proxy/network I can put any IP address
in there I want :)

--

Daniel Tryba

Jul 17 '05 #14

P: n/a
"Adriaan" <re*@de.solidareit> wrote in message news:<40***********************@dreader14.news.xs4 all.nl>...
Apart from that: I still don't see any reason to go with your difficult
solution, but well that's just me. You solution still allows for session
hijacking for those who're sniffing the data sent.
The only way you can sniff the data in my solution is by decrypting
the ssl. If you don't see that, then you still don't understand my
method. You're forgetting the statelessness of the web. You only
prompt at the beginning of an SSL app session, and then get name/pw
from the session thereafter. What if the user logs in over SSL, views
the first page of your app, then the user leaves https and goes to
http. The hacker can see his sessid, create a duplicate request using
a fake session cookie, to the SECOND PAGE of your https app, and your
secure app will let him in because it gets name/pw from session.
And if really that
important than I'd favor using SSL for each page rather than effectively
disabling the browser Back button by using your hidden FORM.


That's where we differ. I'd rather not use SSL for my entire site to
prevent session hijacking. Instead, I use this method and both A.
prevent session hijacking and B. use SSL only as needed. Your saying
that you'd rather choose only one of those two, and I don't understand
why. But if you want to run your sites that way, so be it.
Jul 17 '05 #15

P: n/a
"mrbog" wrote
The only way you can sniff the data in my solution is by decrypting
the ssl.
No. You wrote you're *not* using SSL if the data is no longer too sensitive,
and that you're putting some encrypted thing in a hidden FORM field for
those pages. So: those pages are not viewed over SSL, and hold some static,
encrypted value which you (and so: anybody) can also decrypt. That't what
you were writing, right? But even without decrypting that value anyone who's
sniffing into the data can use that hidden value just like that sniffer
could use the session id. I don't see any difference except for your
solution disabling the browser's Back button and making it harder to create
and maintain the website, and probably even decreasing security if the
encrypted value is not seeded with random (so: is not temporary).
You're forgetting the statelessness of the web.
Sure. Then why do you think I'm using sessions?
You only prompt at the beginning of an SSL app session, and then
get name/pw from the session thereafter.
Wrong: I would never store the password in the session, but indeed I would
store an indicator that the user is authenticated.
What if the user logs in over SSL, views the first page of your app, then the user leaves https and goes to http. The hacker can see his sessid, create
a duplicate request using a fake session cookie, to the SECOND PAGE
of your https app, and your secure app will let him in
And where is this any different from the so-called hacker copying your
encrypted hidden FORM field, apart from the fact that the session ID at
least is temporary so cannot be used at any later time?
I use this method


Wow...

Adriaan.
Jul 17 '05 #16

P: n/a
"Adriaan" <re*@de.solidareit> wrote in message news:<40***********************@dreader9.news.xs4a ll.nl>...
No. You wrote you're *not* using SSL if the data is no longer too sensitive,
and that you're putting some encrypted thing in a hidden FORM field for
those pages. So: those pages are not viewed over SSL, and hold some static,
encrypted value which you (and so: anybody) can also decrypt. That't what
you were writing, right?


No. That is not my method. I'm not putting hidden fields in http
forms. You still don't get it, and actually, I'm relieved that you
don't get it because it means you're not an asshole, it's just that
you're not getting it! I'm going to explain it again again again, in
yet another way. THINK THINK THINK. I know this will seem slow but
after we've spent so much time, this is my last attempt to correct
your thinking:

Let's define the setting:

A web site, which has both sensitive pages/apps and non-sensitive.
For example of non-sensitive- some flat html pages that just go over
http and are public, for forms. This site also has sensitive apps
like a user editing his home address and credit card number, whatever-
private data.

The user needs to be able to both see this data and edit it. Without
exposing this data.

So, with my method:

1. The user is always challenged when he starts to use a secure app,
and I don't mean just the first time, I mean each and every time he
STARTS to use the secure app. Subsequent pages of the app don't
challenge him because subsequent pages are getting his auth info from
hidden fields. And NOT from the session.

2. If the user, or a hacker, attempts to make a request (get or post)
to ANY PAGE of a secure application, without also including the auth
info in that post request, then the secure app has no way of
recognizing who he is (because that data isn't in the session either),
and it prompts him for name/pw and starts him on page 1 of that secure
app. (That is not true of your method).

3. If the user logs into a secure application, and then leaves it
(goes and clicks on a flat http page in another window for example),
he is exposing his session cookie. With my method, that's not a
problem. There is no security consequence to that. If a hacker gets
his session cookie, the hacker won't be able to login to any secure
apps with it. Why? because there's nothing in the session about being
logged in- there's no "isauthenticated" bit, or username/pw, whatever,
NONE of that is in the session. The secure app may not know the
difference between the user and the hacker, but so what? It won't
allow either one of them in unless the request includes auth data,
name/pw.
---------------------------------------------------
And now, your method:

1. User starts to use a secure app over HTTPS, and is prompted for
login the FIRST time, and the first time only, and will never be
prompted for login again until his session expires.

2. After logging in, the user wanders away from the secure app (clicks
on a flat http page in another window, for example), and therefore
exposes his session cookie over unencrypted http.

3. A hacker pulls down that session cookie- it's in plain text when
it goes over http, when the user wandered away from the secure app and
went to http. He then creates an https request to the SECOND page of
your secure app- using a fake session cookie he created, which is
identical to the user's session cookie.

4. Your app accepts this spoofed request as though it came from the
LOGGED IN user, because it just checks the hacker's session and the
session has your "isauthenticated" bit set to true. The secure
information has been compromised.

5. MY METHOD DOESN'T ALLOW THAT.

The hacker can't get authentication information from my method unless
he decrypts the SSL and reads the hidden fields- which only travel
over SSL in the hidden fields of secure https apps in my method.

I AM NOT SAYING that you are transmiting name/pw over http. I AM
SAYING that in your method, after a user has logged in, the single
only criteria that the subsequent pages of your application require in
order to verify that a user is who he says he is, is the session
cookie. And session cookie themselves aren't secure.
Jul 17 '05 #17

P: n/a
Daniel Tryba <ne****************@canopus.nl> wrote in message news:<c7**********@news.tue.nl>...
R. Rajesh Jeba Anbiah <ng**********@rediffmail.com> wrote:
Also it only limits the number of users
that can hijack to the users that can product the same
$_SERVER['REMOTE_ADDR'] (eg everyone on the same proxy).


I could be able to differentiate the proxy to some extent. And I
agree that it is not a 100% foolproof.


Sure, if you only look to the x-forwarded-for (or equiv) header you are
totally screwed.... with my own proxy/network I can put any IP address
in there I want :)


Just curious... what is your proxy? and what will be the result of
print_r($_SERVER) if your real ip is say x.y.z.a?

--
| Just another PHP saint |
Email: rrjanbiah-at-Y!com
Jul 17 '05 #18

P: n/a
mrbog <dt******@hotmail.com> wrote:
You still don't get it, and actually, I'm relieved that you
don't get it because it means you're not an asshole, it's just that
you're not getting it!
I have the exact same impression about your persistence to tour broken
plan. It's a shame you are not responding to my postings...
So, with my method:

1. The user is always challenged when he starts to use a secure app,
and I don't mean just the first time, I mean each and every time he
STARTS to use the secure app. Subsequent pages of the app don't
challenge him because subsequent pages are getting his auth info from
hidden fields. And NOT from the session.
If someone can read session cookies, that someone can also read the
rest of the http response, so he also has the required post data.
3. If the user logs into a secure application, and then leaves it
(goes and clicks on a flat http page in another window for example),
he is exposing his session cookie.
I'm wondering why tou are still using a sessioncookie? The session could
be hidden with you other authentication fields in a form.
And now, your method:

2. After logging in, the user wanders away from the secure app (clicks
on a flat http page in another window, for example), and therefore
exposes his session cookie over unencrypted http.
Ehhhh, you know that the domain/path in cookies can be used to not
expose the cookie in certain places?
I AM NOT SAYING that you are transmiting name/pw over http. I AM
SAYING that in your method, after a user has logged in, the single
only criteria that the subsequent pages of your application require in
order to verify that a user is who he says he is, is the session
cookie. And session cookie themselves aren't secure.


Everything in a http request/response isn't secure. If someone is
sniffing data (kind of man-in-the-middle attack) your screwed unless all
data is being encrypted (with something like ssl). But hte problem in
most cases isn't sniffing... it's crosssite scripting bugs enabeling
potential harmful (java)script to send data to a 3rd party, this script
isn't limited to cookies...

It's a shame you're not responding to my suggestion not to use static
data in the post fields... because your solution is nothing more than
disabling sessioncookies and putting the session identifier in forms
(which php already has support for AFAIK).

--

Daniel Tryba

Jul 17 '05 #19

P: n/a
R. Rajesh Jeba Anbiah <ng**********@rediffmail.com> wrote:
Sure, if you only look to the x-forwarded-for (or equiv) header you are
totally screwed.... with my own proxy/network I can put any IP address
in there I want :)


Just curious... what is your proxy? and what will be the result of
print_r($_SERVER) if your real ip is say x.y.z.a?


I'm running a simple squid setup, with my local network behind a nat
box (linux which also runs squid). So I can assign any network I want to
my localnet and it gets translated to x.y.a.z as the
$_SERVER['REMOTE_ADDR'], squid sees the request coming from my chosen
internal IP address d.e.f.g and puts that in $_SERVER['X-FORWARDED-FOR']

--

Daniel Tryba

Jul 17 '05 #20

P: n/a
Daniel Tryba <ne****************@canopus.nl> wrote in message news:<c7**********@news.tue.nl>...
Everything in a http request/response isn't secure. If someone is
sniffing data (kind of man-in-the-middle attack) your screwed unless all
data is being encrypted (with something like ssl). But hte problem in
most cases isn't sniffing... it's crosssite scripting bugs enabeling
potential harmful (java)script to send data to a 3rd party, this script
isn't limited to cookies...

It's a shame you're not responding to my suggestion not to use static
data in the post fields... because your solution is nothing more than
disabling sessioncookies and putting the session identifier in forms
(which php already has support for AFAIK).


You're closer, but what you're talking about is each user having two
session cookies. Or, you're talking about all apps on the site that
use sessions being over https, and the http apps/pages couldn't have
sessions. One of the two. In PHP.ini I only see one way to specify
cookie name:

; Name of the session (used as cookie name).
session.name = PHPSESSID

Can I have two distinct sessions per user with php?

In any case, once again, that's not what that zend site says to do.
They're promoting Adriaan's insecure way.

thanks for weighing in
Jul 17 '05 #21

P: n/a
"mrbog" wrote
1. The user is always challenged when he starts to use a secure app,
and I don't mean just the first time, I mean each and every time he
STARTS to use the secure app. Subsequent pages of the app don't
challenge him because subsequent pages are getting his auth info from
hidden fields. And NOT from the session.
Ok, I'm finally getting your point! And I agree: if one authenticates over
SSL, then goes to non-SSL pages while the PHP session is kept alive, some
sniffer could get the session id while that session would have some
"isAuthenticated" set to true. Next, the so-called hacker could even jump
into the SSL pages if those do not enforce one to re-present some
credentials. And though I feel we already agreed that a user would be
reprompted for credentials whenever something really sensitive should be
done, even then the so-called hacker could jump into the application a
second later.

Still, first of all, rather than storing some encrypted authentication
details I'd then store some random number, and set the same number in the
session. On a non-shared server only your application can read that number
from your session, and using SSL for the secure parts also makes sure no
sniffer can get that random number. I guess that number doesn't even need to
change every time the user re-enters some credentials, as long as it is only
encoded into pages that are requested over SSL.

But, though I did not give it much thought yet: then why not simply store
the SSL session id (as taken from $_ENV['SSL_SESSION_ID'] or likewise
$_SERVER, so obviously not the value of PHPSESSID) in the PHP session, and
compare the two values instead of using "isAuthenticated"? As far as I know
the SSL session id should be maintained across requests, even over proxy
servers. No need for any extra fields in your pages then, and your visitor
will be happy that the brower's Back button is still fully operational!
Hmmm, too bad, I might be wrong here: quick tests with non-official server
cert show that the SSL session id does change with each page refresh, so
it's probably not the "master" session id that is used to create temporary
keys for each subsequent request :-(

To extend on Daniel's suggestion to set an explicit path for the session
cookie: http://php.net/session-set-cookie-params also allows one to specify
a value for session.cookie_secure. I wonder if that setting also enforces
the SSL session id to match, but as it enforces a SSL connection no matter
what, that's not what you want anyhow, as for performance you want to be
able to use non-SSL whenever possible. Fair enough. You could still call
this method to set the path though, and to set cookie_secure to get two
sessions: one for SSL and another for non-SSL. However, you might want to
sync those two, which is not really possible I guess.

If using the SSL session id is not possible, then (as we did already agree
on re-authenticating whenever a sensitive page should be shown) a more
user-friendly and easier to implement solution might be the following. This
doesn't mess up the browser's Back button (I guess one does not want to
encode the credentials into the URL GET parameters as those might show up in
the browser's history, even though I think those should not be sent along in
any HTTP Referer header when jumping to another site), though less secure:

- when page is accessed over SSL: check if "isAuthenticated" in session is
true, if not: prompt for credentials
- whenever page is accessed over non-SSL: remove the "isAuthenticated" no
matter what

This, of course, could still be abused: if a so-called hacker gets the
session id from a non-secure page, and then actually waits until the user
uses the same session id to continue on a SSL secured page (after presenting
a password) then that session id could be used to jump into the secured
session, as long as the user did not yet go to a non-SSL page. Obviously, as
your first concern is about someone sniffing into the data, it then indeed
is feasible that such hacker will be waiting for one to log in. Furthermore
the user might close the browser while on a SSL page, leaving the hacker
with a functional session id. So: certainly less secure than your solution.
1. User starts to use a secure app over HTTPS, and is prompted for
login the FIRST time, and the first time only


Well, not only the first time, but also when sensitive parts of the
application are entered, but like I wrote: I felt we already agreed on that.

Adriaan
Jul 17 '05 #22

P: n/a
"Adriaan" wrote
Hmmm, too bad, I might be wrong here: quick tests with non-official server
cert show that the SSL session id does change with each page refresh, so
it's probably not the "master" session id that is used to create temporary
keys for each subsequent request :-(


In fact, if I refresh qickly in Mozilla Firefox it alternates between two
values. Hmmm...

Adriaan
Jul 17 '05 #23

P: n/a
"Adriaan" <re*@de.solidareit> wrote in message news:<40*********************@news.xs4all.nl>...
"mrbog" wrote

- when page is accessed over SSL: check if "isAuthenticated" in session is
true, if not: prompt for credentials
- whenever page is accessed over non-SSL: remove the "isAuthenticated" no
matter what

This, of course, could still be abused: if a so-called hacker gets the
session id from a non-secure page, and then actually waits until the user
uses the same session id to continue on a SSL secured page (after presenting
a password) then that session id could be used to jump into the secured
session, as long as the user did not yet go to a non-SSL page. Obviously, as
your first concern is about someone sniffing into the data, it then indeed
is feasible that such hacker will be waiting for one to log in. Furthermore
the user might close the browser while on a SSL page, leaving the hacker
with a functional session id. So: certainly less secure than your solution.


Adriaan I love you, and I want to have your babies, you are not an
asshole after all.

I thought of your solution above before- "when a page is accessed over
ssl, set isauthenticated to true, when he leaves and goes to http set
it to back false." But there are three other problems with that,
besides the problems you came up with-

You could have the reverse security problem- the user could be wrongly
locked out. Take this example:

Problem 1:

1. User logs in over SSL, "IsAuthenticated" is set to true. He is
presented with a form to edit his personal info, name/address.

2. In another window, the user views a page over HTTP. During that
request, his IsAuthenticated is set to false.

3. In the original ssl window, he clicks the submit button, and the
app wrongly denies him.

Problem 2:

Every page of the site would need to have php on it. For some sites
with tons of flat data, that really sucks.

Problem 3:

Admittedly somewhat obscure- but since we're geeks I'll mention it for
fun. Even if every page has php in all of it's html, a user could
still view an individual image in his web browser- a jpg or png. When
he does so, the browser still sends the session cookie, thus exposing
it, but there's no php running anywhere to unset the isauthenticated
bit. Like I say, obscure but true.
In general, tho, we still don't have a solution here- I guess maybe we
could make our own (second) session cookie who's path is set so that
it only is sent over applications in the secure directory of the site,
and that cookie has the session ID of a session we created "manually"
in PHP. The only thing stored in that session is authentication info,
(and by the way, it has to be more than just "isauthenticated" because
you have to know who the user is, but that's not so bad, I guess). I
haven't tried making my own session cookie, but in theory I guess it
could work.

Incidentally, I'll tell you the real reason I came here to post- I was
using my method and passing auth info in hidden fields, when I ran
into a problem. Pagination. With my method, I had to make every
"next page" or "submit" button a form field so that it would do a POST
request, otherwise it would put name/pw into the browser address bar
(GET). I was making seperate forms for every page number button and
"next" and "previous", it's horrible.

BUT IN ANY CASE!!! Why are we the only two people who get this, and
when someone (me) suggests that the conventional method is no good,
they get flamed! I'M RIGHT!!! VINDICATED!! That zend article should
be pulled down. The fact that it's on the zend site is sad. We need
to spread the word here and make the whole community get it, and then
fix it for us! At least I convinced one person.
Jul 17 '05 #24

P: n/a
"mrbog" wrote
Adriaan I love you, and I want to have your babies, you are not an
asshole after all.
Well, _I_ never suggested I was even close to being an asshole ;-)
I thought of your solution above before- "when a page is accessed over
ssl, set isauthenticated to true, when he leaves and goes to http set
it to back false." .... Problem 2:

Every page of the site would need to have php on it. For some sites
with tons of flat data, that really sucks.
Aha, so this might be your lucky day (read on) as I assume you've made the
choice to force the visitor to accept session cookies to keep the session
alive? Is that really a choice or just something that hasn't been given
thought yet?

I'd say that people who've disabled *session* cookies don't really
understand why those cookies are not harmful (just to be sure: a session
cookie is simply a cookie that dies when the browser is closed, not a cookie
that is necessarily related to any PHP session data). But if those people
still need to access your site, then you need to be able to fall back to
session URL rewriting (where the PHP session id is automatically added as a
GET parameter to all relative URLs on your page, if the cookie is not
accepted). Yes, I know the session id will be sent in Referer headers when
navigating to another site. And yes, I know some people will send around
such URLs (even https:// URLs) including that GET parameter to friends, but
well, you just blame it on the user and make sure the disclaimer covers it.
So basically: yes, I know PHP has URL rewriting disabled by default for a
reason.

Still, as I like my sites to be available to everyone:

With Apache's rewrite engine you could easily serve any html file (or any
file for that matter, even your JPGs) through a custom PHP script and then
keep the normal session alive. In php.ini enable session.use_trans_sid.
Next, in Apache's .htaccess something like

Options FollowSymLinks
RewriteEngine on
RewriteRule ^(.*\.htm|.*\.html) serve-html.php?name=$1

and in serve-html.php something like

start_session();
if(name indeed indicates to be html){
// include it and have PHP do its URL rewriting magic (note
// that the curly braces are required for include to work here):
include($_GET['name']);
}
else{
// ignore, or see http://php.net/readfile but then make sure
// this very script cannot be called for just any file, like
// PHP source files or a password file...
}

Note that the visitor will not see the new URL in the browser (it still says
foo.html, not serve-html.php?name=foo.html).

The above obviously does not solve any security issues (but would allow you
to add any security related code, of course). Nevertheless it might be kind
towards your visitors to maintain the PHP session anyhow, even without
implementing "if not SSL then unset isAuthenticated". It's a bit off-topic
though.
Even if every page has php in all of it's html, a user could
still view an individual image in his web browser- a jpg or png. When
he does so, the browser still sends the session cookie, thus exposing
it, but there's no php running anywhere to unset the isauthenticated
bit. Like I say, obscure but true.
Fair enough, but would viewing a single JPG be a reason to un-authenticate a
user? And is a non-authenticated user allowed to see any JPG (like: are
there any generated JPGs that should be protected)? By the way: note that
when right-clicking an image on a 100% SSL enabled page, then the URL for
that image would still be a https:// URL. And the session cookie might
already have been exposed before -- like I wrote: counting on "when a page
is accessed over ssl, set isauthenticated to true, when he leaves and goes
to http set it to back false" will always allow a sniffer to jump into the
SSL part a few seconds after the user has browsed from non-SSL to SSL...
In general, tho, we still don't have a solution here- I guess maybe we
could make our own (second) session cookie who's path is set so that
it only is sent over applications in the secure directory of the site
I suddenly remember that IE is not cooping with multiple cookies with the
same name for different subdomains. Whereas the RFCs state that the most
specialized cookie (the one with the best match for the subdomain or path)
should be sent first, IE 6.x sends the cookies in the order in which it once
received them :-( So, I guess you should not try to use multiple cookies
with the same name (but different domains or paths), just to be sure...
With my method, I had to make every
"next page" or "submit" button a form field so that it would do a POST
request, otherwise it would put name/pw into the browser address bar
(GET). I was making seperate forms for every page number button and
"next" and "previous", it's horrible.
Yes, that's why I wrote it's hard to maintain, let alone horrible for the
user's Back button. First of all, again, I think you should really not
encrypt username and password into the contents sent to the browser, but
only some random token that you compare to a value stored in the session!
Then at least all gets to be temporary again, and will be more secure for
those using an internet café or some office computer. Still then I agree
that using GET parameters to pass the token is quite bad: you'd need a
disclaimer for your users not to send around such URLs, you need to
gracefully handle bookmarked URLs, and above all you need to make sure
there's no external links on your page as those will expose the token in the
Referer header... By the way: the latter could be handled by creating a PHP
script for all external links, which would only redirect after removing the
GET parameters.

If above you've really decided *not* to fall back to URL rewriting and as
such: enforce the user to accept session cookies, then this is your lucky
day. You can simply use another standard (albeit: SSL-only) cookie to pass
that random token:

- on every SSL page check if a cookie named 'token' is set
- if yes: compare against the value stored in the session
- if cookie not set, or if no match:
- prompt for credentials
- create a (new) random token, store it in the session
- set a cookie for that token and set it to be used for SSL only
- when limiting the lifetime: set the cookie again (same value) to keep it
alive

Above the PHPSESSID cookie is still simply allowed for both SSL and non-SSL,
so the browser will present this cookie for each and every request it makes.
So: your session will be kept alive as long as the browser is not closed.

However, the token cookie (explicitely set to be used for SSL only) will
only be sent by the browser if the request is indeed using SSL, so: not for
non-SSL pages. Thus: if the visitor browses from SSL to non-SSL, the cookie
will no longer be sent back to the server. But when coming back to SSL the
token cookie is sent along again, and even more: that token is still valid.
Therefore I can image that at some point (like when saving user data, or
when changing user password) you explicitely prompt for the credentials
again to avoid abuse when a user leaves the computer and someone else
continues using it. Bottomline is: a sniffer certainly can not get the token
value. To avoid abuse by someone who has access to the computer (or to make
your site "feel" more secure to the visitor) you might also want to limit
the lifetime of the token cookie without actually limiting the lifetime of
the PHP session. That's why above you need to set the token cookie with a
new expiry time whenever a page is requested.

If you explicitely want to enforce the user to re-authenticate whenever
browsing from non-SSL to SSL then simply check the Referer header to see
where the user is coming from.

However, when not enforcing the visitor to accept session cookies (this not
being your lucky day) it would still be very nice to be able to use
SSL_SESSION_ID rather than embedding your own token in hidden fields. Note
that Microsoft IIS is said not to expose the value at all, so only keep
reading when using Apache...

Maybe the id in my tests is not constant as I did not use a valid server
cert for my tests. Take a look at
https://cgi.ccs.neu.edu/home/cgiadmi...es/phpinfo.php (which is not my
page, but I get different values for every refresh) and
https://sslap.wind.surfnet.nl:8889/cgi-bin/envir.pl (not my page either, but
constant if refreshed quite fast, but changing when waiting a minute; just
ignore the request for a client certificate).

New to me: http://php.net/session-regenerate-id This is not going to help us
(as then we still need to know when the user leaves SSL, to re-generate
again) but a user comment on that page also suggests using the SSL session
id. Maybe behavior for Refresh and Ctrl-Refresh are different, which makes
the id change in my tests. Some relevant discussions:

Verifying SSL_SESSION_ID
"It is known to work with the Apache server with mod_ssl,
and with Microsoft Internet Explorer, Netscape, and Mozilla
browsers. [..] Konqueror 3.1, available for KDE on Linux,
does not generate SSL_SESSION_ID values [..]"
http://wiki.oscommerce.com/proposalSecurityAndPrivacy

Improvements in session management?
"As you might guess when running with SSL you gain really
secure session cross-checking by looking at SSL_SESSION_ID
since you can rely on the SSL session managment of
e.g. Apache/mod_ssl."
http://seclists.org/lists/webappsec/...-Jun/0002.html

SSL Session Id Changing?
"The session ID should not be changed for each new page"
"The caching of a session ID on the server-side [..] is
expected behavior."
http://google.com/gr****************...*@colubris.com

but also...

HTTP state management without cookies?
"You can't count on the SSL session ID staying constant."
http://google.com/gr****************...*@stroeder.com

So: maybe it is indeed the way to go and simply needs some better testing!
That zend article should be pulled down.


http://www.zend.com/zend/spotlight/s...y.php#Heading5

Well, I can't see where SSL is mentioned there? When never using SSL (not
even while authenticating), or when always using SSL, the above is not an
issue, is it? When never using SSL one accepts the risk that a sniffer will
get the full credentials rather than just an authenticated session; when
always using SSL there is no issue whatsoever. So only when using both SSL
and non-SSL one should not rely on a "isAuthenticated" thingy in the
session.

The article is very bad for another reason though: anyone who knows that
authentication is based on this example could send the $authdata array in
GET parameters, as it relies on register globals to be enabled. But well, it
dates from 2001 and meanwhile register globals is no longer enabled upon
installation... No worries.

Adriaan
Jul 17 '05 #25

P: n/a
"Adriaan" wrote
you might also want to limit the lifetime of the token cookie


In fact I guess you want to limit the lifetime by yourself, not relying on
the browser to limit it. So: store the time at which the token was last used
in the session and invalidate when too much time has passed. Thus:

On every SSL page:
- check if a cookie named 'token' is set
- if yes: compare against the value stored in the session
- if cookie not set, or if no match, or if not used in the last xx minutes:
- prompt for credentials
- create a (new) random token, store it in the session
- set a cookie for that token and set it to be used for SSL only
- set or update the last token usage time in the session

On non-SSL pages:
- don't bother about the token at all. Or: invalidate the session altogether
if a token cookie is sent though you explicitely set it to be used on SSL
only, telling the visitor that security has been compromised and to get a
more secure browser...

Adriaan
Jul 17 '05 #26

P: n/a
"Adriaan" <re*@de.solidareit> wrote in message news:<40***********************@dreader6.news.xs4a ll.nl>...
"Adriaan" wrote
you might also want to limit the lifetime of the token cookie


In fact I guess you want to limit the lifetime by yourself, not relying on
the browser to limit it. So: store the time at which the token was last used
in the session and invalidate when too much time has passed. Thus:

On every SSL page:
- check if a cookie named 'token' is set
- if yes: compare against the value stored in the session
- if cookie not set, or if no match, or if not used in the last xx minutes:
- prompt for credentials
- create a (new) random token, store it in the session
- set a cookie for that token and set it to be used for SSL only
- set or update the last token usage time in the session

On non-SSL pages:
- don't bother about the token at all. Or: invalidate the session altogether
if a token cookie is sent though you explicitely set it to be used on SSL
only, telling the visitor that security has been compromised and to get a
more secure browser...

Adriaan


Well, what I ended up doing is pretty much the same way you suggested.
I'm creating a cookie which contains a random number/character string,
and has it's path set so that it's only sent in the directory where my
ssl apps live. I may also create a seperate ip for the secure section
of the site and make secure.mysite.com and set the cookie for that
domain only (and set the php session cookie to .mysite.com).

Some notes about the rest of your post:

HTTP referrer is unreliable (as is, btw, the IP address being
consistent between requests, but you probably knew that). Referrer is
blocked by a lot of consumer virus software. Norton is set to not
send referrer by default. Essentially, the role of HTTP referrer has
been relegated to just being something you look at in your traffic
analysis files, and not something you can practially (reliably) use in
applications. I saw a chart somewhere about the percentage of hits
that have no referrer over like the past 8 years, and it just goes up
and up and up, I can't find it now in searches..

I think you said this, but- the "secure" bit in cookies isn't reliable
either. The browsers aren't all so great about paying attention to
it, or so I'm told I haven't done tests. You can still get around it
with path I guess.

Thanks Adriaan, I will remember your email address,

mrb
Jul 17 '05 #27

P: n/a
In article <cb**************************@posting.google.com >, mrbog wrote:
Tell me if my assertion is wrong here:

The only way to prevent session hijacking is to NEVER store
authentication information (such as name/password) in the session.
Thats not the only way, but, perhaps the most secure way.

Another way dates back to UUCP, where you had counters. Each time you
connect, you set a cookie on the browser, say "1", then store "1" in the
session. Next time, set the cookie to "2", store "2" in the session and
so on. As soon as the cookie from a request has a number that is
different that the one in the session, clear the session and bump them
both out. Not 100% fail-safe, but pretty close. Also, a major source of
bugs with the counters not lining up. (I've tried it before, make one
mistake, change the order of the pages, provide an off-link and then
return, etc... BAM it logs you out, which is highly inconvenient)

I have an option where I track their last IP number used, if it's
different, they get bumped out. Not 100% safe either, but some what of a
deterrent. (and, a source of bugs when used with proxy servers that
alternate IP numbers, for this reason, it's only good for a specific
applications.)
Well, to never authenticate a user from information you got from the
session. Each secure app on a site must challenge the user for name
and password, each and every time the user accesses it (not just once
and then store it in the session). If a secure app is multi-page,
then you must only pass session data in hidden form fields between
each page, on forms that POST over https.


The only real way to do it is to run _everything_ through SSL and store
critical data on a machine that isn't TCP/IP connected. If you ask them
for their password each time (even as hidden variables) over regular
HTTP, it's available to Mr & Mrs. cracker. If you do the counter thing,
it'll become desynchronized whenever you "break the normal flow" of the
order screens are submitted. Suppose you could use javascript to do some
kind of cypher trick.. good luck making that reliable though.

Jamie

--
http://www.geniegate.com Custom web programming
User Management Solutions Perl / PHP / Java / UNIX

Jul 17 '05 #28

This discussion thread is closed

Replies have been disabled for this discussion.