Discussion:
session_start() and a bad guy
Vernon Nemitz
2014-02-18 16:17:06 UTC
Permalink
Hello.

m developing a future web site and have basic session stuff
working OK. In thinking about what someone might do to bypass
the security tests I've associated with the $_SESSION data, it
occurred to me to experiment with a session ID that did not exist.
Could someone create their own session outside of my carefully
constructed hodgepodge? Yes....

I should mention that I'm not using the "cookie" system for
session-data propagation; I'm using the URL method with AJAX.
The user never sees the URLs being specified, unless a JavaScript
debugger is fired up, to set breakpoints and look at various
variables in the AJAX JavaScript code. With enough patience
it should be quite possible to identify a session ID, and
copy it.

To see what might be done with that ID, first go to the "tmp"
(or other) directory where session data gets stored, and pick
any session that happens to be there. Suppose it is
"sess_pq89kf43rsmjfb75mb9bddko46"; copy the name to a note
somewhere, and now delete ALL the session data files from that
session directory.

Now create a URL to call the initial .php file that the web
site would normally call, which would start a session create a
session-data file in the session (tmp) directory. Here I'll
call that file "first.php", and I'll use a "relative" URL
address: "./first.php?SessionName=pq89kf43rsmjfb75mb9bddko46".
We make the assumption that some "bad guy" has constructed a
URL similar to this one. When the URL is invoked, so as to
cause the Web Server to run the PHP code in "first.php",
one of the first things in that file is likely to be a call
to the "session_start()" function.

NORMALLY, you want session_start() to create a new and unique
session-data-file, when no file exists in the session directory.
NORMALLY, if the URL includes a session ID, we want session_start()
to look for the previously-created session-data-file, in the
session directory, and open it. In this particular case,
however, there is no previously-created session-data-file
(because in this scenario, all such files were deleted a
couple paragraphs ago).

LOGICALLY, the session_start() function should EITHER (1) create
a new session-data file, unrelated to the ID in the URL, OR
(2) do nothing and return FALSE, because of not actually
starting a session.

But what actually happens is that session_start() creates
a brand-new session-data-file using the ID that had been
supplied in the URL. Our bad guy now has his own private
session started!

If the above is deliberate behavior, then I need to know
what session-function can I use (and I've examined most of
them fruitlessly) to say, "Hey, the session ID in this URL
is invalid, because no such session-data-file exists!".

Yes, I know I can work around the problem by making an
effort to extract the session name from the URL and
using the file_exists() function. But that cannot be the
most efficient way, in an environment where we want PHP
code to run as fast as possible. Not to mention that
such a work-around automatically prevents session_start()
from being the first thing in the file, so the trick can't
be used with the cookie method for session propagation --and
I assume a bad guy could construct a cookie OR a URL....

Finally, in reading through the wiki page at:
https://wiki.php.net/rfc/howto
It mentions some ordinary stuff about seeking out other
efforts that might coincide with one's own ideas, and,
sure enough, there exists an RFC about adding a set of
arguments to the session_start() function (currently it
takes no arguments).

In thinking about how to deal with the issue I encountered,
I could see that an easy way to handle it is to have an
argument that would trigger any of 3 different behaviors,
for the function. The default would be the existing
behavior, for compatibility. One option would cause the function
to return False if a URL contained a session ID that did not exist.
And one option would cause the function to ignore that session ID
in the URL, and just create a brand-new session-and-ID.

This particular argument would of course be "extra", relative
to the other arguments proposed in that existing RFC for the
session_start() function.

Thank you!
vernonner3voltazim
Vernon Nemitz
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Aziz Saleh
2014-02-18 16:52:50 UTC
Permalink
Post by Vernon Nemitz
Hello.
m developing a future web site and have basic session stuff
working OK. In thinking about what someone might do to bypass
the security tests I've associated with the $_SESSION data, it
occurred to me to experiment with a session ID that did not exist.
Could someone create their own session outside of my carefully
constructed hodgepodge? Yes....
I should mention that I'm not using the "cookie" system for
session-data propagation; I'm using the URL method with AJAX.
The user never sees the URLs being specified, unless a JavaScript
debugger is fired up, to set breakpoints and look at various
variables in the AJAX JavaScript code. With enough patience
it should be quite possible to identify a session ID, and
copy it.
To see what might be done with that ID, first go to the "tmp"
(or other) directory where session data gets stored, and pick
any session that happens to be there. Suppose it is
"sess_pq89kf43rsmjfb75mb9bddko46"; copy the name to a note
somewhere, and now delete ALL the session data files from that
session directory.
Now create a URL to call the initial .php file that the web
site would normally call, which would start a session create a
session-data file in the session (tmp) directory. Here I'll
call that file "first.php", and I'll use a "relative" URL
address: "./first.php?SessionName=pq89kf43rsmjfb75mb9bddko46".
We make the assumption that some "bad guy" has constructed a
URL similar to this one. When the URL is invoked, so as to
cause the Web Server to run the PHP code in "first.php",
one of the first things in that file is likely to be a call
to the "session_start()" function.
NORMALLY, you want session_start() to create a new and unique
session-data-file, when no file exists in the session directory.
NORMALLY, if the URL includes a session ID, we want session_start()
to look for the previously-created session-data-file, in the
session directory, and open it. In this particular case,
however, there is no previously-created session-data-file
(because in this scenario, all such files were deleted a
couple paragraphs ago).
LOGICALLY, the session_start() function should EITHER (1) create
a new session-data file, unrelated to the ID in the URL, OR
(2) do nothing and return FALSE, because of not actually
starting a session.
But what actually happens is that session_start() creates
a brand-new session-data-file using the ID that had been
supplied in the URL. Our bad guy now has his own private
session started!
If the above is deliberate behavior, then I need to know
what session-function can I use (and I've examined most of
them fruitlessly) to say, "Hey, the session ID in this URL
is invalid, because no such session-data-file exists!".
Yes, I know I can work around the problem by making an
effort to extract the session name from the URL and
using the file_exists() function. But that cannot be the
most efficient way, in an environment where we want PHP
code to run as fast as possible. Not to mention that
such a work-around automatically prevents session_start()
from being the first thing in the file, so the trick can't
be used with the cookie method for session propagation --and
I assume a bad guy could construct a cookie OR a URL....
https://wiki.php.net/rfc/howto
It mentions some ordinary stuff about seeking out other
efforts that might coincide with one's own ideas, and,
sure enough, there exists an RFC about adding a set of
arguments to the session_start() function (currently it
takes no arguments).
In thinking about how to deal with the issue I encountered,
I could see that an easy way to handle it is to have an
argument that would trigger any of 3 different behaviors,
for the function. The default would be the existing
behavior, for compatibility. One option would cause the function
to return False if a URL contained a session ID that did not exist.
And one option would cause the function to ignore that session ID
in the URL, and just create a brand-new session-and-ID.
This particular argument would of course be "extra", relative
to the other arguments proposed in that existing RFC for the
session_start() function.
Thank you!
vernonner3voltazim
Vernon Nemitz
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
The only issue I see with your issue is if the user has access to the tmp
directory and/or a user is using that session they hijacked. If that is so,
why not use a local directory to store sessions, which on most shared
hosting (at least the smart ones) will limit access to your directories
from other users.

Why not use the database to store sessions? It is more secure than using
the URL/Cookies only.I usually use the session_start() along with a random
cookie string as salt and store this session in the DB along with other
user parameters (agent string, ip, geo, etc..).

Aziz
Aziz Saleh
2014-02-18 21:30:06 UTC
Permalink
Post by Aziz Saleh
Post by Vernon Nemitz
Hello.
[snip]
The only issue I see with your issue is if the user has access to
the tmp directory and/or a user is using that session they hijacked.
If that is so, why not use a local directory to store sessions,
which on most shared hosting (at least the smart ones) will limit
access to your directories from other users.
What I described was a bad guy inspecting my JavaScript code and
imitating what it does, for his own purposes. If there is a file
called "first.php" which the JavaScript calls, then he can call it,
too. If he sees that the JavaScript passes a session ID, then
he can imitate that, too. I'm not seeing any requirement for
him to know where the session stuff is located on the Server;
he is simply calling various .php files to see what he can get
away with doing, that the normal users are prevented from doing.
(I'm leaving the details out, because no matter what I think
a bad guy might do, chances are his goal is something else.)
I think I got what you meant. Why not customize the the session_id() to be
more random. So random that someone has better luck winning the lottery.
Post by Aziz Saleh
Why not use the database to store sessions? It is more secure than using
the URL/Cookies only.I usually use the session_start() along with a
random
Post by Aziz Saleh
cookie string as salt and store this session in the DB along with other
user parameters (agent string, ip, geo, etc..).
Aziz
As far as I can tell, the client still needs to know what session
it has been assigned, so it can keep telling the Server that it
is still participating in that session. That's why one of the
standard behaviors is for a session cookie to exist. So, I'm
not understanding how ONLY having the Server know about the
session (regardless of where the data is stored on the Server)
can work.
vernonner3voltazim
Vernon Nemitz
My way, I don't even change the session default usage (cookies). What I do
is add another layer of protection that if someone wants to hijack the
session, it would be very hard to (if not impossible). For example, in my
session handler I associate the session with the current user's user agent
and random cookie salt. This way if someone even guesses the session id
correctly, once they try to use it and my session handler sees that there
is a difference in user, it destroys the session. Normal users do not copy
sessions across browsers, and for someone to hijack the session they would
need to know the exact user agent of the user and that cookie salt.

Aziz
Christoph Michael Becker
2014-02-18 22:00:15 UTC
Permalink
Post by Aziz Saleh
Post by Aziz Saleh
Post by Vernon Nemitz
Hello.
[snip]
The only issue I see with your issue is if the user has access to
the tmp directory and/or a user is using that session they hijacked.
If that is so, why not use a local directory to store sessions,
which on most shared hosting (at least the smart ones) will limit
access to your directories from other users.
What I described was a bad guy inspecting my JavaScript code and
imitating what it does, for his own purposes. If there is a file
called "first.php" which the JavaScript calls, then he can call it,
too. If he sees that the JavaScript passes a session ID, then
he can imitate that, too. I'm not seeing any requirement for
him to know where the session stuff is located on the Server;
he is simply calling various .php files to see what he can get
away with doing, that the normal users are prevented from doing.
(I'm leaving the details out, because no matter what I think
a bad guy might do, chances are his goal is something else.)
I think I got what you meant. Why not customize the the session_id() to be
more random. So random that someone has better luck winning the lottery.
Well, if I'm not mistaken the default session handler uses session IDs
with 128bit at least, so guessing a valid session ID is already way
harder than winning the lottery.

Anyway, it still seems to me Vernon is afraid that an attacker might use
an arbitrary session ID -- what shouldn't do any harm.
--
Christoph M. Becker
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Christoph Becker
2014-02-18 22:00:38 UTC
Permalink
Post by Aziz Saleh
Post by Aziz Saleh
Post by Vernon Nemitz
Hello.
[snip]
The only issue I see with your issue is if the user has access to
the tmp directory and/or a user is using that session they hijacked.
If that is so, why not use a local directory to store sessions,
which on most shared hosting (at least the smart ones) will limit
access to your directories from other users.
What I described was a bad guy inspecting my JavaScript code and
imitating what it does, for his own purposes. If there is a file
called "first.php" which the JavaScript calls, then he can call it,
too. If he sees that the JavaScript passes a session ID, then
he can imitate that, too. I'm not seeing any requirement for
him to know where the session stuff is located on the Server;
he is simply calling various .php files to see what he can get
away with doing, that the normal users are prevented from doing.
(I'm leaving the details out, because no matter what I think
a bad guy might do, chances are his goal is something else.)
I think I got what you meant. Why not customize the the session_id() to be
more random. So random that someone has better luck winning the lottery.
Well, if I'm not mistaken the default session handler uses session IDs
with 128bit at least, so guessing a valid session ID is already way
harder than winning the lottery.

Anyway, it still seems to me Vernon is afraid that an attacker might use
an arbitrary session ID -- what shouldn't do any harm.
--
Christoph M. Becker
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Aziz Saleh
2014-02-19 15:04:53 UTC
Permalink
Post by Aziz Saleh
(I'm leaving the details out, because no matter what I think
a bad guy might do, chances are his goal is something else.)
I think I got what you meant. Why not customize the the session_id()
to be more random. So random that someone has better luck winning
the lottery.
In general, that is not a bad idea, but ... (see below)
Post by Aziz Saleh
As far as I can tell, the client still needs to know what session
it has been assigned, so it can keep telling the Server that it
is still participating in that session.
My way, I don't even change the session default usage (cookies).
What I do is add another layer of protection that if someone wants
to hijack the session, it would be very hard to (if not impossible).
For example, in my session handler I associate the session with the
current user's user agent and random cookie salt. This way if
someone even guesses the session id correctly, once they try to use
it and my session handler sees that there is a difference in user,
it destroys the session. Normal users do not copy sessions across
browsers, and for someone to hijack the session they would need to
know the exact user agent of the user and that cookie salt.
Aziz
It seems you are saying that you have added more data to the session
cookie, which the bad guy can inspect and copy. So, not inherently
more secure than the session ID all by itself getting sent back
and forth between browser and Server.
In a way, I'm doing some things like that, too, only not between
the browser and the Server. When a user's normal actions lead to
a normal session, the particular web-page responsible will be a
"parent" to all the other Web pages associated with that session.
Those pages all refer back to the parent page to make AJAX
requests, none can make AJAX requests by themselves. I have a
whole bunch of tests to make sure that if a child-page is opened
by a bad guy, it fails to work without the parent page existing.
By the way, one of the other messages I've received in response
to my original question concerned a php.ini file setting,
session.use_strict_mode
(available PHP 5.5.2+) which appears to at least do the ignoring
thing, if a browser sends session data to the Server which does
not happen to match an existing session-data-file. Good show!
vernnoner3voltazim
Vernon Nemitz
Glad you sorted it out. However, I don't think you understood what I meant.
My original thought is that you were worried about session hijacking
(someone finding out the session id a user uses, example and admin) and
going into your site and plugin that ID into the URL (or cookie by default)
to take control over that session, basically login in by the session id.
What I do prevents that from happening by associating the session id to not
just any user, but to that specific user that logged in.
Vernon Nemitz
2014-02-19 16:22:55 UTC
Permalink
Post by Aziz Saleh
By the way, one of the other messages I've received in response
to my original question concerned a php.ini file setting,
session.use_strict_mode
(available PHP 5.5.2+) which appears to at least do the ignoring
thing, if a browser sends session data to the Server which does
not happen to match an existing session-data-file. Good show!
vernnoner3voltazim
Vernon Nemitz
Glad you sorted it out. However, I don't think you understood
what I meant. My original thought is that you were worried
about session hijacking (someone finding out the session id
a user uses, example and admin) and going into your site and
plugin that ID into the URL (or cookie by default) to take
control over that session, basically login in by the session
id. What I do prevents that from happening by associating the
session id to not just any user, but to that specific user
that logged in.
I do understand the idea, but not the implementation as you
have so far described it. If the user has to keep identifying
self to the web server, then that is data that the bad guy
could obtain as easily as the session ID. However, it occurs
to me that the IP address of the user, and that of the bad
guy, should always be different. So, if the IP address was
saved in association with the session ID, the server could
check for a matching IP address each time a request reached
it, that began identifying itself with a session ID.

vernonner3voltazim
Vernon Nemitz
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Aziz Saleh
2014-02-19 16:34:54 UTC
Permalink
Post by Vernon Nemitz
Post by Aziz Saleh
By the way, one of the other messages I've received in response
to my original question concerned a php.ini file setting,
session.use_strict_mode
(available PHP 5.5.2+) which appears to at least do the ignoring
thing, if a browser sends session data to the Server which does
not happen to match an existing session-data-file. Good show!
vernnoner3voltazim
Vernon Nemitz
Glad you sorted it out. However, I don't think you understood
what I meant. My original thought is that you were worried
about session hijacking (someone finding out the session id
a user uses, example and admin) and going into your site and
plugin that ID into the URL (or cookie by default) to take
control over that session, basically login in by the session
id. What I do prevents that from happening by associating the
session id to not just any user, but to that specific user
that logged in.
I do understand the idea, but not the implementation as you
have so far described it. If the user has to keep identifying
self to the web server, then that is data that the bad guy
could obtain as easily as the session ID. However, it occurs
to me that the IP address of the user, and that of the bad
guy, should always be different. So, if the IP address was
saved in association with the session ID, the server could
check for a matching IP address each time a request reached
it, that began identifying itself with a session ID.
vernonner3voltazim
Vernon Nemitz
Think about the implementation this way:

function getUserSalt(){ return isset(COOKIE[salt]) ? COOKIE[salt] :
makeSalt()}

function getUniqueKey(){ return ip + user agent + salt + (other unique
factors, add as many as you want)}

function getUserSession(){
set key = getUniqueKey(), set session id = SESSION_ID (from url or
cookie)
check DB for corresponding row with those two params, if user exists,
use the corresponding user id with that session, else destroy the session
}

The only way a user can hijack someone's session is if they have the cookie
value salt + cookie/url value session_id + ip + user agent, which I
personally think is far fetched.

Aziz
Vernon Nemitz
2014-02-19 18:56:11 UTC
Permalink
Post by Aziz Saleh
If the user has to keep identifying self to the web server,
then that is data that the bad guy could obtain as easily
as the session ID.
makeSalt()}
function getUniqueKey(){ return ip + user agent + salt + (other
unique factors, add as many as you want)}
function getUserSession(){
set key = getUniqueKey(), set session id = SESSION_ID
(from url or cookie) check DB for corresponding row with
those two params, if user exists, use the corresponding
user id with that session, else destroy the session }
The only way a user can hijack someone's session is if they
have the cookie value salt + cookie/url value session_id +
ip + user agent, which I personally think is far fetched.
Aziz
OK, thank you.
vernonner3voltazim
Vernon Nemitz
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Christoph Becker
2014-02-19 20:45:15 UTC
Permalink
Post by Aziz Saleh
Post by Vernon Nemitz
Post by Aziz Saleh
By the way, one of the other messages I've received in response
to my original question concerned a php.ini file setting,
session.use_strict_mode
(available PHP 5.5.2+) which appears to at least do the ignoring
thing, if a browser sends session data to the Server which does
not happen to match an existing session-data-file. Good show!
Glad you sorted it out. However, I don't think you understood
what I meant. My original thought is that you were worried
about session hijacking (someone finding out the session id
a user uses, example and admin) and going into your site and
plugin that ID into the URL (or cookie by default) to take
control over that session, basically login in by the session
id. What I do prevents that from happening by associating the
session id to not just any user, but to that specific user
that logged in.
I do understand the idea, but not the implementation as you
have so far described it. If the user has to keep identifying
self to the web server, then that is data that the bad guy
could obtain as easily as the session ID. However, it occurs
to me that the IP address of the user, and that of the bad
guy, should always be different. So, if the IP address was
saved in association with the session ID, the server could
check for a matching IP address each time a request reached
it, that began identifying itself with a session ID.
makeSalt()}
This makes it possible for everybody to determine the salt, what might
not be the best idea.
Post by Aziz Saleh
function getUniqueKey(){ return ip + user agent + salt + (other unique
factors, add as many as you want)}
function getUserSession(){
set key = getUniqueKey(), set session id = SESSION_ID (from url or
cookie)
check DB for corresponding row with those two params, if user exists,
use the corresponding user id with that session, else destroy the session
}
The only way a user can hijack someone's session is if they have the cookie
value salt + cookie/url value session_id + ip + user agent, which I
personally think is far fetched.
No, this is not the only way somebody can hijack a session. Consider
session fixation attacks[1], where the attacker tricks someone into
using their prepared session ID. Checking additionally the IP address
and the UserAgent string makes such attacks harder, but doesn't
absolutely prevent them, as the attacker could use some indirection
(say, a PHP script on their domain, which recognizes IP address and
UserAgent string of the victim, and redirects to the appropriate URL for
the user to login).

[1] <https://www.owasp.org/index.php/Session_fixation>
--
Christoph M. Becker
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Aziz Saleh
2014-02-19 23:52:31 UTC
Permalink
Post by Christoph Becker
Post by Aziz Saleh
Post by Vernon Nemitz
Post by Aziz Saleh
By the way, one of the other messages I've received in response
to my original question concerned a php.ini file setting,
session.use_strict_mode
(available PHP 5.5.2+) which appears to at least do the ignoring
thing, if a browser sends session data to the Server which does
not happen to match an existing session-data-file. Good show!
Glad you sorted it out. However, I don't think you understood
what I meant. My original thought is that you were worried
about session hijacking (someone finding out the session id
a user uses, example and admin) and going into your site and
plugin that ID into the URL (or cookie by default) to take
control over that session, basically login in by the session
id. What I do prevents that from happening by associating the
session id to not just any user, but to that specific user
that logged in.
I do understand the idea, but not the implementation as you
have so far described it. If the user has to keep identifying
self to the web server, then that is data that the bad guy
could obtain as easily as the session ID. However, it occurs
to me that the IP address of the user, and that of the bad
guy, should always be different. So, if the IP address was
saved in association with the session ID, the server could
check for a matching IP address each time a request reached
it, that began identifying itself with a session ID.
makeSalt()}
This makes it possible for everybody to determine the salt, what might
not be the best idea.
Post by Aziz Saleh
function getUniqueKey(){ return ip + user agent + salt + (other unique
factors, add as many as you want)}
function getUserSession(){
set key = getUniqueKey(), set session id = SESSION_ID (from url or
cookie)
check DB for corresponding row with those two params, if user exists,
use the corresponding user id with that session, else destroy the session
}
The only way a user can hijack someone's session is if they have the
cookie
Post by Aziz Saleh
value salt + cookie/url value session_id + ip + user agent, which I
personally think is far fetched.
No, this is not the only way somebody can hijack a session. Consider
session fixation attacks[1], where the attacker tricks someone into
using their prepared session ID. Checking additionally the IP address
and the UserAgent string makes such attacks harder, but doesn't
absolutely prevent them, as the attacker could use some indirection
(say, a PHP script on their domain, which recognizes IP address and
UserAgent string of the victim, and redirects to the appropriate URL for
the user to login).
[1] <https://www.owasp.org/index.php/Session_fixation>
--
Christoph M. Becker
That is one of the reasons why I never encourage people to use URL based
sessions instead of cookies. Cookies on a different TLDs are harder to
read/write.

Additionally, the session fixer, will still need access to that random
cookie value from your website - even thou they have the session fixed, ip,
useragent, it won't be enough. I am not saying it is not possible to steal
cookies, but that makes it even more harder for someone to do.

Moreover, if someone is stupid enough to not check URLs for phishing, there
are much more smarter ways to get the account login/password, let alone get
their session/ip/browser. Why eat a slice when you can have the entire cake.
Stuart Dallas
2014-02-18 17:00:03 UTC
Permalink
Post by Vernon Nemitz
m developing a future web site and have basic session stuff
working OK. In thinking about what someone might do to bypass
the security tests I've associated with the $_SESSION data, it
occurred to me to experiment with a session ID that did not exist.
Could someone create their own session outside of my carefully
constructed hodgepodge? Yes....
I should mention that I'm not using the "cookie" system for
session-data propagation; I'm using the URL method with AJAX.
The user never sees the URLs being specified, unless a JavaScript
debugger is fired up, to set breakpoints and look at various
variables in the AJAX JavaScript code. With enough patience
it should be quite possible to identify a session ID, and
copy it.
This would not take any patience. It’s trivial. No more or less trivial than finding the session cookie, especially since name you use below is "SessionName" - do you really think it would take patience to find the session token when it’s called that?
Post by Vernon Nemitz
To see what might be done with that ID, first go to the "tmp"
(or other) directory where session data gets stored, and pick
any session that happens to be there. Suppose it is
"sess_pq89kf43rsmjfb75mb9bddko46"; copy the name to a note
somewhere, and now delete ALL the session data files from that
session directory.
Now create a URL to call the initial .php file that the web
site would normally call, which would start a session create a
session-data file in the session (tmp) directory. Here I'll
call that file "first.php", and I'll use a "relative" URL
address: "./first.php?SessionName=pq89kf43rsmjfb75mb9bddko46".
We make the assumption that some "bad guy" has constructed a
URL similar to this one. When the URL is invoked, so as to
cause the Web Server to run the PHP code in "first.php",
one of the first things in that file is likely to be a call
to the "session_start()" function.
NORMALLY, you want session_start() to create a new and unique
session-data-file, when no file exists in the session directory.
NORMALLY, if the URL includes a session ID, we want session_start()
to look for the previously-created session-data-file, in the
session directory, and open it. In this particular case,
however, there is no previously-created session-data-file
(because in this scenario, all such files were deleted a
couple paragraphs ago).
LOGICALLY, the session_start() function should EITHER (1) create
a new session-data file, unrelated to the ID in the URL, OR
(2) do nothing and return FALSE, because of not actually
starting a session.
But what actually happens is that session_start() creates
a brand-new session-data-file using the ID that had been
supplied in the URL. Our bad guy now has his own private
session started!
Hang on, I don’t see the difference. All that’s happening here is that "bad guy" has decided what his session will be called. Why does this matter? What does this give him over just hitting your homepage and getting a random name?
Post by Vernon Nemitz
If the above is deliberate behavior, then I need to know
what session-function can I use (and I've examined most of
them fruitlessly) to say, "Hey, the session ID in this URL
is invalid, because no such session-data-file exists!".
You can’t. There is no built-in way to check that a session ID corresponds to a valid session. I’m guessing the reason for this is that you should never need to do that.
Post by Vernon Nemitz
Yes, I know I can work around the problem by making an
effort to extract the session name from the URL and
using the file_exists() function. But that cannot be the
most efficient way, in an environment where we want PHP
code to run as fast as possible. Not to mention that
such a work-around automatically prevents session_start()
from being the first thing in the file, so the trick can't
be used with the cookie method for session propagation --and
I assume a bad guy could construct a cookie OR a URL….
The call to session_start() doesn’t need to be the first thing in the file, it just needs to be before any output. But, please don’t check that the session ID is valid before calling session_start. What would you do differently if it’s not valid? And why? I really do think you’re creating a problem that doesn’t exist.
Post by Vernon Nemitz
https://wiki.php.net/rfc/howto
It mentions some ordinary stuff about seeking out other
efforts that might coincide with one's own ideas, and,
sure enough, there exists an RFC about adding a set of
arguments to the session_start() function (currently it
takes no arguments).
In thinking about how to deal with the issue I encountered,
I could see that an easy way to handle it is to have an
argument that would trigger any of 3 different behaviors,
for the function. The default would be the existing
behavior, for compatibility. One option would cause the function
to return False if a URL contained a session ID that did not exist.
And one option would cause the function to ignore that session ID
in the URL, and just create a brand-new session-and-ID.
This particular argument would of course be "extra", relative
to the other arguments proposed in that existing RFC for the
session_start() function.
Again, the core question is why you think it’s a bad thing that a user can specify what their session is called. Try making it something potentially dangerous like "/etc/passwd" (only dangerous if you’re stupid enough to run PHP as the root user) or "." or "..". I’d put decent cash on PHP containing sufficient checks on the name to prevent those causing any issues.

-Stuart
--
Stuart Dallas
3ft9 Ltd
http://3ft9.com/
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Stuart Dallas
2014-02-19 11:34:52 UTC
Permalink
Please either include the mailing list when replying or ask me about my consultancy rates.
With enough patience it should be quite possible to identify
a session ID, and copy it.
This would not take any patience. [WINDOWS-1252?]It’s trivial.
No more or less trivial than finding the session cookie,
especially since name you use below is "SessionName" - do you
really think it would take patience to find the session token
when [WINDOWS-1252?]it’s called that?
If a different name was used (which I am actually doing), I
would not expect that to be more than a matter of patience
for the ID number to be discovered. I only used SessionName
in the example below to make it easier to describe the overall
situation.
It won’t take patience, just some very quick observation of the requests going back and forth between client and server. Anyone who needs patience to spend a few minutes observing a site’s behaviour doesn’t deserve the label "bad guy!"
[snip]
But what actually happens is that session_start() creates
a brand-new session-data-file using the ID that had been
supplied in the URL. Our bad guy now has his own private
session started!
Hang on, I [WINDOWS-1252?]don’t see the difference. All [WINDOWS-
1252?]that’s happening here is
that "bad guy" has decided what his session will be called. Why does
this matter? What does this give him over just hitting your homepage
and getting a random name?
I'm using the definition that if someone bypasses the session
handling process that I have defined for the web site, then
that someone qualifies as a bad guy, and has worse things in
mind to accomplish. I won't pretend to know exactly what he
has in mind, but I CAN in theory attempt to prevent early
success at bypassing the site's session-handling stuff.
What session handling process? What are you doing in your process that will have a problem if someone creates a new, empty session with an ID they chose? If that has any negative consequences then you need to look at how you’re using the session. The existence of a session should not be taken to indicate anything; it’s the contents of the session that should matter.
If the above is deliberate behavior, then I need to know
what session-function can I use (and I've examined most of
them fruitlessly) to say, "Hey, the session ID in this URL
is invalid, because no such session-data-file exists!".
You [WINDOWS-1252?]can’t. There is no built-in way to check
that a session ID corresponds to a valid session.
[WINDOWS-1252?]I’m guessing the reason for this is
that you should never need to do that.
"Never need to check to see if something is valid?"
Come on!
Whoa, way to change my words to make me look like an idiot. You want a gold star for that?!

I said there is never a need to validate that a session ID corresponds to a valid session, where (in this case) valid simply means exists. The validity of a session as far as your code goes should depend on its contents, not its existence!
But, please [WINDOWS-1252?]don’t check that the session ID
is valid before calling session_start. What would you do
differently if [WINDOWS-1252?]it’s not valid? And why? I
really do think [WINDOWS-1252?]you’re creating a problem
that [WINDOWS-1252?]doesn’t exist.
With respect to that "first.php" file, there should NEVER
be a session ID in the URL that calls that file. So, if
there is, that means someone is messing around where
they shouldn't. I would want to return an error message.
Two words that should never (!) be in the same sentence when describing software: should and never. Defensive programming is all about never assuming anything, so there should be no reason why first.php cannot handle being given a session ID. If it’s that important to you all you need is a chunk of code at the top of first.php that says "if there’s a session ID here, redirect to the same URL without the session ID." Do that before anything else and you’re covered without assuming anything.
https://wiki.php.net/rfc/howto
[snip]
I could see that an easy way to handle it is to have an
argument that would trigger any of 3 different behaviors,
for the function. The default would be the existing
behavior, for compatibility. One option would cause the function
to return False if a URL contained a session ID that did not exist.
And one option would cause the function to ignore that session ID
in the URL, and just create a brand-new session-and-ID.
This particular argument would of course be "extra", relative
to the other arguments proposed in that existing RFC for the
session_start() function.
Again, the core question is why you think [WINDOWS-1252?]it’s a
bad thing that a user can specify what their session is called.
Try making it something potentially dangerous like "/etc/passwd"
(only dangerous if [WINDOWS-1252?]you’re stupid enough to run
PHP as the root user) or "." or "..". [WINDOWS-1252?]I’d put
decent cash on PHP containing sufficient checks on the name
to prevent those causing any issues.
-Stuart
Perhaps it is just my control-freakiness, wanting to ensure that
users interact with my site in the way it was designed, rather
than some other way.
Your site sounds like it’s been designed with a specific user in mind; one who knows how they should be using it. That’s unrealistic and potentially quite dangerous. All users are ignorant/stupid <- develop your site with that in mind and stuff like this won’t be an issue.

-Stuart
--
Stuart Dallas
3ft9 Ltd
http://3ft9.com/
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Vernon Nemitz
2014-02-19 14:04:01 UTC
Permalink
Thank you for your feedback.
One of the other people who responded to my original message
indicated that in version 5.5.2 of PHP, a new initialization
thing was added, session.use_strict_mode
This will ignore the session ID in a URL, if the specified
session-file does not exist. Instead, a new session file
and ID will be created.
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Stuart Dallas
2014-02-19 15:21:51 UTC
Permalink
Post by Vernon Nemitz
Thank you for your feedback.
One of the other people who responded to my original message
indicated that in version 5.5.2 of PHP, a new initialization
thing was added, session.use_strict_mode
This will ignore the session ID in a URL, if the specified
session-file does not exist. Instead, a new session file
and ID will be created.
Great, fine, lovely, except that it only has one effect: it prevents "bad guy" from choosing the name of his session. He will still be able to create an empty session by specifying a non-existent session ID when he makes the request. I really don’t see what use_strict_mode gives you for the situation you described.

-Stuart
--
Stuart Dallas
3ft9 Ltd
http://3ft9.com/
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Vernon Nemitz
2014-02-19 16:26:10 UTC
Permalink
Post by Stuart Dallas
Post by Vernon Nemitz
Thank you for your feedback.
One of the other people who responded to my original message
indicated that in version 5.5.2 of PHP, a new initialization
thing was added, session.use_strict_mode
This will ignore the session ID in a URL, if the specified
session-file does not exist. Instead, a new session file
and ID will be created.
Great, fine, lovely, except that it only has one effect: it prevents
"bad guy" from choosing the name of his session. He will still be
able to create an empty session by specifying a non-existent session
ID when he makes the request. I really [WINDOWS-1252?]don’t see what
use_strict_mode gives you for the situation you described.
-Stuart
Well, it makes no sense for the bad guy to send a "desired" session
ID to the server if it will always be ignored. That is, he might
as well just go along with the normal usage that everyone else
does, to get a session ID. It seems to me that that qualifies as
a first step in not letting the bad guy get what he wants.

vernonner3voltazim
Vernon Nemitz
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Stuart Dallas
2014-02-19 19:21:06 UTC
Permalink
Post by Vernon Nemitz
Post by Stuart Dallas
Post by Vernon Nemitz
Thank you for your feedback.
One of the other people who responded to my original message
indicated that in version 5.5.2 of PHP, a new initialization
thing was added, session.use_strict_mode
This will ignore the session ID in a URL, if the specified
session-file does not exist. Instead, a new session file
and ID will be created.
Great, fine, lovely, except that it only has one effect: it prevents
"bad guy" from choosing the name of his session. He will still be
able to create an empty session by specifying a non-existent session
ID when he makes the request. I really [WINDOWS-1252?]don’t see what
use_strict_mode gives you for the situation you described.
-Stuart
Well, it makes no sense for the bad guy to send a "desired" session
ID to the server if it will always be ignored. That is, he might
as well just go along with the normal usage that everyone else
does, to get a session ID. It seems to me that that qualifies as
a first step in not letting the bad guy get what he wants.
But you still haven't answered the question. What does "bad guy" get from having his "desired" session ID used instead of one that's randomly assigned? Where's the benefit for him?

Any "bad guy" worth the name would know this doesn't give him anything, so he won't bother. Why do you think he'd bother?

-Stuart
--
Stuart Dallas
3ft9 Ltd
http://3ft9.com/
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Vernon Nemitz
2014-02-19 23:29:52 UTC
Permalink
Post by Stuart Dallas
Post by Vernon Nemitz
Post by Stuart Dallas
Post by Vernon Nemitz
Thank you for your feedback.
One of the other people who responded to my original message
indicated that in version 5.5.2 of PHP, a new initialization
thing was added, session.use_strict_mode
This will ignore the session ID in a URL, if the specified
session-file does not exist. Instead, a new session file
and ID will be created.
Great, fine, lovely, except that it only has one effect: it prevents
"bad guy" from choosing the name of his session. He will still be
able to create an empty session by specifying a non-existent session
ID when he makes the request. I really [WINDOWS-1252?][WINDOWS-
1252?]don’t see what
Post by Stuart Dallas
Post by Vernon Nemitz
Post by Stuart Dallas
use_strict_mode gives you for the situation you described.
-Stuart
Well, it makes no sense for the bad guy to send a "desired" session
ID to the server if it will always be ignored. That is, he might
as well just go along with the normal usage that everyone else
does, to get a session ID. It seems to me that that qualifies as
a first step in not letting the bad guy get what he wants.
But you still haven't answered the question. What does "bad guy" get
from having his "desired" session ID used instead of one that's
randomly assigned? Where's the benefit for him?
Any "bad guy" worth the name would know this doesn't give him
anything, so he won't bother. Why do you think he'd bother?
I don't know everything about the strengths and weaknesses of PHP.
One thing I've wondered about is the range of normal session IDs.
When a webmaster decides to use "levels" of directories for storing
the session files, the names of those directories range from 0-9
and from a-v. I don't know why "w-z" are not used. If the bad
guy can create his own session ID, then perhaps he could make the
web server burp on an ID that begins with "x". Just as a start
for other mischief. The primary assumption is that the bad guy
DOES know all the strengths and weaknesses of PHP.
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Christoph Becker
2014-02-18 17:01:02 UTC
Permalink
Post by Vernon Nemitz
But what actually happens is that session_start() creates
a brand-new session-data-file using the ID that had been
supplied in the URL. Our bad guy now has his own private
session started!
What is not a problem per se (unless your authorization check depends
solely on the fact that a session exists, what would be very bad). The
only problem with this is that it makes session fixation attacks easier.
If you don't want to deal with session_regenerate_id() (or don't
consider it safe enough), you can enable session.use_strict_mode.
--
Christoph M. Becker
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Christoph Becker
2014-02-18 22:20:00 UTC
Permalink
Post by Christoph Becker
Post by Vernon Nemitz
But what actually happens is that session_start() creates
a brand-new session-data-file using the ID that had been
supplied in the URL. Our bad guy now has his own private
session started!
What is not a problem per se (unless your authorization check depends
solely on the fact that a session exists, what would be very bad). The
only problem with this is that it makes session fixation attacks easier.
If you don't want to deal with session_regenerate_id() (or don't
consider it safe enough), you can enable session.use_strict_mode.
"session.use_strict_mode specifies whether the module will use strict session
id mode. If this mode is enabled, the module does not accept uninitialized
session ID. If uninitialized session ID is sent from browser, new session ID
is sent to browser. Applications are protected from session fixation via
session adoption with strict mode. Defaults to 0 (disabled)."
This sounds very much like what I was looking for! I need to experiment with
it to be sure, of course. Thank you!
You're welcome. But note, that this ini setting is available only since
PHP 5.5.2 (I wasn't aware of that when I replied).

And please reply to the mailing list also (CC) -- other readers might be
interested in the discussion.
--
Christoph M. Becker
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
Loading...