|
List Info
Thread: bug in xaraya PHP session save handler
|
|
| bug in xaraya PHP session save handler |
  United States |
2007-02-09 08:33:13 |
Hi Xaraya Development team,
We've discovered a pretty nasty bug in the xarSession.php
piece of Xaraya. As far as we can tell, this bug is still
present in the latest release (Xaraya 1.1.2). Because we
are unable to create a new bug on Xaraya Bugzilla, we
thought we would email the development list in hopes of
someone higher up adding this issue to Bugzilla. The
effects of this bug, although not common, are data loss and
possible data corruption. On our heavily used Xaraya site,
http://library.calvin.edu
a>, we've experience this bug on a daily basis, generating
mounting frustration on the part of our editors as well as
lost time and lost work. Now having invested over 16 man
hours into debugging this problem, we're hoping others can
benefit from our troubleshooting. Read on for the details.
Summary
The Xaraya session handling functions provided in
xarSession.php, namely xarSession__phpRead and
xarSession__phpWrite , do not address a fundamental feature
provided in the default file-based PHP session handler:
session locking. Without session locking code in place, it
is possible for a browser to make simultaneous requests
under the same PHP session causing a race condition between
these multiple requests, possibly resulting in overwriting
of the session data in the database ( the xar_vars BLOB
column in the xar_session_info table).
Practical Applications
We first noticed this bug manifesting itself as the stock
Xaraya error "this operation cannot be performed under
the current circumstances" when some forms were being
submitted, but usually only in FireFox (although it can be
reproduced in IE). Editors were creating content they had
composed in the WYSIWYG editor, only to submit the page and
be greeted by this fatal error message and consequentially
losing their content edits.
Technical Details
Having observed that this problem was primarily related to
FireFox, we eventually discovered that a major trigger for
this bug was FireFox's auto-fetching of RSS feeds linked to
in the requested document's rss LINK tag in its HEAD
section. IE may also eventually behave this way (if it
cannot already be configured to do so) but these two
simultaneous requests (one for RSS and one for the page)
generated a race condition which resulted in close to a 25%
chance of a data-los condition given moderate load on our
server A similar "failure" condition could be
created in FireFox or IE when an editor used tabs and/or
multiple windows to access multiple data-editing forms
across our site. Typically the two simultaneous requests
were 1) an RSS feed and 2) a page load. The RSS feed
request usually finished processing faster than the page
load, but on the occasions when a page finished processing
faster than the feed, the session data ($_SESSION)
associated with the RSS request actually overwrote the
session data just stored by the page request in the
database. Why is this session data important? The Xaraya
functions xarSecGenAuthKey() and xarSecConfirmAuthKey() rely
on session variables to ensure that create/edit/delete
operations are not committed without first going through the
proper "page" paths. If the authkey (stored in
$_SESSION) is lost by another request overwriting the
session data (as was the case), then the editor's form
submission to create/edit/delete content would be be
interpreted by Xaraya as unauthorized, and the content would
be lost. The end result for our editors was a frequent
data-loss problem, whose lacke of reproducibility was
influenced by server load, browser type, and the
"heaviness" of a particular page load.
A Solution
After researching the problem on the Internet, we found a
well-written article that addresses PHP session locking in
the context of simultaneous AJAX requests. http://thwartedefforts.org/2006
/11/11/race-conditions-with-ajax-and-php-sessions/ The
solution we came up with, per the article's suggestion, was
to implement session locking through modifying
xarSession__phpRead and xarSession__phpWrite to use the
MySQL locking features GET_LOCK() and RELEASE_LOCK() (see http://dev.mysql.com/doc/refman/4.1/en/miscel
laneous-functions.html ).
In xarSession_phpRead we added:
// Prevent simultaneous session reads
$dbconn->Execute("SELECT
GET_LOCK('XARSESSIONLOCK',60)");
In xarSession_phpWrite we added:
// Prevent simultaneous session reads
$dbconn->Execute("SELECT
RELEASE_LOCK('XARSESSIONLOCK')");
Our modified xarSession.php file is attached to this email.
Unfortunately this solution is dependent upon the locking
MySQL features mentioned above and is not database platform
independent, although it is a start. We were hoping there
would be some similar ADODB version of this locking behavior
that would make the code platform independent.
If you have any questions pertaining to this bug, please
email us. We'd be happy to help explain the problem in more
detail. We'd like to see this bug placed in Bugzilla so
that it can eventually be addressed. Please review our
improvements to xarSecGenAuthKey() and
xarSecConfirmAuthKey() in xarSecurity.php as well.
Thank you for your time,
Chris Hirt and Dan Wells
Programmers
Hekman Library - Calvin College
Grand Rapids, MI USA
_______________________________________________
Xaraya_devel mailing list
Xaraya_devel xaraya.com
http:
//xaraya.com/mailman/listinfo/xaraya_devel
|
|
| Re: bug in xaraya PHP session save
handler |
  United States |
2007-02-09 15:13:40 |
Thanks for spending the time to post this Chris.
Is this actually two different and distinct problems:
1. The authorization key being 'consumed' through an RSS
feed. The auth key
is created when a form is being presented, and is consumed
when the form is
submitted. If any further auth keys are created in the
meantime for that
session, then the submitted form will be rejected.
2. Race conditions where several pages are being delivered
to the same
browser session at the same time. I can imagine AJAX
functions could well do
that.
To fix the first problem, we need to determine why the RSS
feed is pulling
out a new auth key in the first place. Since there are no
forms in the RSS
feed, it should not do that - check the module generating
that feed to see
exactly what it is doing. In fact, I'm wondering whether the
auth key
generator should check the theme and automatically skip its
function if the
theme is RSS?
The second problem is more serious, and locking does seem to
be the only way
to solve it. Some further thought on how to make it more
portable is needed
though (my cursory glance doesn't do your analysis justice,
so perhaps
anyone who understands this better can chip in?)
-- Jason
"Chris Hirt" <chirt calvin.edu> wrote in
message
news:45CC3FD9.3405.003D.0 calvin.edu...
Hi Xaraya Development team,
We've discovered a pretty nasty bug in the xarSession.php
piece of Xaraya.
As far as we can tell, this bug is still present in the
latest release
(Xaraya 1.1.2). Because we are unable to create a new bug
on Xaraya
Bugzilla, we thought we would email the development list in
hopes of someone
higher up adding this issue to Bugzilla. The effects of
this bug, although
not common, are data loss and possible data corruption. On
our heavily used
Xaraya site, http://library.calvin.edu
a>, we've experience this bug on a daily
basis, generating mounting frustration on the part of our
editors as well as
lost time and lost work. Now having invested over 16 man
hours into
debugging this problem, we're hoping others can benefit from
our
troubleshooting. Read on for the details.
Summary
The Xaraya session handling functions provided in
xarSession.php, namely
xarSession__phpRead and xarSession__phpWrite , do not
address a fundamental
feature provided in the default file-based PHP session
handler: session
locking. Without session locking code in place, it is
possible for a
browser to make simultaneous requests under the same PHP
session causing a
race condition between these multiple requests, possibly
resulting in
overwriting of the session data in the database ( the
xar_vars BLOB column
in the xar_session_info table).
Practical Applications
We first noticed this bug manifesting itself as the stock
Xaraya error "this
operation cannot be performed under the current
circumstances" when some
forms were being submitted, but usually only in FireFox
(although it can be
reproduced in IE). Editors were creating content they had
composed in the
WYSIWYG editor, only to submit the page and be greeted by
this fatal error
message and consequentially losing their content edits.
Technical Details
Having observed that this problem was primarily related to
FireFox, we
eventually discovered that a major trigger for this bug was
FireFox's
auto-fetching of RSS feeds linked to in the requested
document's rss LINK
tag in its HEAD section. IE may also eventually behave this
way (if it
cannot already be configured to do so) but these two
simultaneous requests
(one for RSS and one for the page) generated a race
condition which resulted
in close to a 25% chance of a data-los condition given
moderate load on our
server A similar "failure" condition could be
created in FireFox or IE when
an editor used tabs and/or multiple windows to access
multiple data-editing
forms across our site. Typically the two simultaneous
requests were 1) an
RSS feed and 2) a page load. The RSS feed request usually
finished
processing faster than the page load, but on the occasions
when a page
finished processing faster than the feed, the session data
($_SESSION)
associated with the RSS request actually overwrote the
session data just
stored by the page request in the database. Why is this
session data
important? The Xaraya functions xarSecGenAuthKey() and
xarSecConfirmAuthKey() rely on session variables to ensure
that
create/edit/delete operations are not committed without
first going through
the proper "page" paths. If the authkey (stored
in $_SESSION) is lost by
another request overwriting the session data (as was the
case), then the
editor's form submission to create/edit/delete content would
be be
interpreted by Xaraya as unauthorized, and the content would
be lost. The
end result for our editors was a frequent data-loss problem,
whose lacke of
reproducibility was influenced by server load, browser type,
and the
"heaviness" of a particular page load.
A Solution
After researching the problem on the Internet, we found a
well-written
article that addresses PHP session locking in the context of
simultaneous
AJAX requests.
http://thwartedefforts.org/2006
/11/11/race-conditions-with-ajax-and-php-sessions/
The solution we came up with, per the article's suggestion,
was to implement
session locking through modifying xarSession__phpRead and
xarSession__phpWrite to use the MySQL locking features
GET_LOCK() and
RELEASE_LOCK() (see
http://dev.mysql.com/doc/refman/4.1/en/miscel
laneous-functions.html ).
In xarSession_phpRead we added:
// Prevent simultaneous session reads
$dbconn->Execute("SELECT
GET_LOCK('XARSESSIONLOCK',60)");
In xarSession_phpWrite we added:
// Prevent simultaneous session reads
$dbconn->Execute("SELECT
RELEASE_LOCK('XARSESSIONLOCK')");
Our modified xarSession.php file is attached to this email.
Unfortunately
this solution is dependent upon the locking MySQL features
mentioned above
and is not database platform independent, although it is a
start. We were
hoping there would be some similar ADODB version of this
locking behavior
that would make the code platform independent.
If you have any questions pertaining to this bug, please
email us. We'd be
happy to help explain the problem in more detail. We'd like
to see this bug
placed in Bugzilla so that it can eventually be addressed.
Please review
our improvements to xarSecGenAuthKey() and
xarSecConfirmAuthKey() in
xarSecurity.php as well.
Thank you for your time,
Chris Hirt and Dan Wells
Programmers
Hekman Library - Calvin College
Grand Rapids, MI USA
_______________________________________________
Xaraya_devel mailing list
Xaraya_devel xaraya.com
http:
//xaraya.com/mailman/listinfo/xaraya_devel
|
|
| Re: bug in xaraya PHP session save
handler |
  United States |
2007-02-10 03:31:09 |
Chris Hirt wrote:
> We've discovered a pretty nasty bug in the
xarSession.php piece of
Xaraya.
Thanks Chris and Dan, we can always count on you guys to
come up with
something interesting
I distill about the same things as Jason from your message.
Similar things i have indeed found in our own projects too.
1. auth key consuming in general
--------------------------------
As described by chris and jason, the auth key is basically
only
relevant when there are forms involved, or, more accurate,
when the
code path goes through a function which *may* involve a form
and
generated an auth key to be able to validate the sequence. I
know
there are some places in the code which need a review on
this, i.e.
where auth keys are generated unwanted.
One such path is the automaticly available 'rss link' on
every page
(stick &theme=rss at the end for one). The RSS is never
used in 99% of
the cases obviously, but the code still goes thru the same
path as if
it were the normal view, so a key may be generated during
the display
of a normal page which contains a form. This could explain
the
prefetch of firefox problem. In this particular example
(rss) it would
suffice to either suppress the rss link header generation
for that
page or change it. The bigger problem is of course the code
path going
through generating the key twice.
These things are unavoidable other than thinking carefully
where to
call genauthkey and making sure that what we generate
automatically
(for example in the meta block) actually makes sense all the
time (rss
link in admin pages does not, for example)
Every situation where we offer either automatically
generated (like
with the meta block) or manually entered, alternative views
on the
same page, the above applies and needs to be reviewed for
this problem.
Typically the improvements are trivial.
(i'm explicitly avoiding the word solution here, cos the
problem as
such is unavoidable)
2. race conditions / locking / customisations
---------------------------------------------
These problems are more fun
These typically only surface when you have a heavily used
site or are
explicitly looking for these things. The average user doesnt
get (hurt
by) these problems (hopefully)
The second reason that these situations are hard to solve in
a
generally applicable way, is that they all depend heavily on
the local
deployment choices. Backend type and configuration, proxies
and other
local optimisations.
For example, the locking solution chris described is likely
the
easiest for them, but when using persistent connections the
solution
might not work anymore and something else has to be figured
out. This
is indeed typically something that would go in the
middleware layer
(ADODB)
> happy to help explain the problem in more detail. We'd
like to see this bug
> placed in Bugzilla so that it can eventually be
addressed.
I'll make sure it gets there
Marcel
_______________________________________________
Xaraya_devel mailing list
Xaraya_devel xaraya.com
http:
//xaraya.com/mailman/listinfo/xaraya_devel
|
|
| Re: bug in Xaraya PHP session save
handler |
  United States |
2007-02-12 11:08:35 |
Hello Jason (and Marcel),
I would like to chime in here because, at least in our case,
problem #1
isn't happening. We have some custom code which allows us
to have multiple
authkeys per session, but thought it best to treat that as a
separate issue
because we are confident of the problem's cause (again, in
our case). The
RSS feed never calls xarSecGenAuthKey() or
xarSecConfirmAuthKey().
I know Chris already said it, but it was towards the end of
his quite long
message, so it may help to say it again in a different way
Here
is an
outline of the race condition we observe:
Given: You currently have stored session information with no
viable auth key
(we'll call this SessionNoAuth
Event 1: Real page request reads SessionNoAuth from DB,
creates auth key
(now we have SessionAuth in memory)
Event 2: RSS page request (or any other near simultaneous
request from same
client) reads same SessionNoAuth from DB, doesn't create or
consume auth key
(now we have SessionNoAuth2 in memory)
Event 3: Real page writes SessionAuth to DB to await the
submission of the
form.
Event 4: RSS page writes SessionNoAuth2 to DB.
Event 5: Submission of SessionAuth form fails, finding only
SessionNoAuth2
in the DB.
I think you both understood this, but I wish to stress that
this situation
does not require AJAX nor any other predictable or
especially rare
condition. For us, if Event 4 happens before Event 3, all
is well. If it
doesn't, all is lost. We actually need to be sure Event 3
comes before
event 2 to cover every situation, and hence the need for a
lock.
I like the thought of using the ADODB layer for this
problem, but I don't
know the best way to proceed. adLockPessimistic seems like
it may work, but
my understanding is that not all DBs support it and it
sometimes considered
sloppy or lazy. I think I may tinker around with
adLockOptimitic and see
how it works.
Thanks,
DW
>>> On 2/9/2007 at 4:13 PM, in message
<eqio5h$gdk$1 newton.xaraya.com>,
Jason<judgej xaraya.com> wrote:
> Thanks for spending the time to post this Chris.
>
> Is this actually two different and distinct problems:
>
> 1. The authorization key being 'consumed' through an
RSS feed. The auth
> key
> is created when a form is being presented, and is
consumed when the form
> is
> submitted. If any further auth keys are created in the
meantime for that
>
> session, then the submitted form will be rejected.
>
> 2. Race conditions where several pages are being
delivered to the same
> browser session at the same time. I can imagine AJAX
functions could
> well do
> that.
>
> To fix the first problem, we need to determine why the
RSS feed is
> pulling
> out a new auth key in the first place. Since there are
no forms in the
> RSS
> feed, it should not do that - check the module
generating that feed to
> see
> exactly what it is doing. In fact, I'm wondering
whether the auth key
> generator should check the theme and automatically skip
its function if
> the
> theme is RSS?
>
> The second problem is more serious, and locking does
seem to be the only
> way
> to solve it. Some further thought on how to make it
more portable is
> needed
> though (my cursory glance doesn't do your analysis
justice, so perhaps
> anyone who understands this better can chip in?)
>
> -- Jason
>
>
> "Chris Hirt" <chirt calvin.edu> wrote in
message
> news:45CC3FD9.3405.003D.0 calvin.edu...
> Hi Xaraya Development team,
>
> We've discovered a pretty nasty bug in the
xarSession.php piece of
> Xaraya.
> As far as we can tell, this bug is still present in the
latest release
> (Xaraya 1.1.2). Because we are unable to create a new
bug on Xaraya
> Bugzilla, we thought we would email the development
list in hopes of
> someone
> higher up adding this issue to Bugzilla. The effects
of this bug,
> although
> not common, are data loss and possible data corruption.
On our heavily
> used
> Xaraya site, http://library.calvin.edu
a>, we've experience this bug on a
> daily
> basis, generating mounting frustration on the part of
our editors as
> well as
> lost time and lost work. Now having invested over 16
man hours into
> debugging this problem, we're hoping others can benefit
from our
> troubleshooting. Read on for the details.
>
> Summary
> The Xaraya session handling functions provided in
xarSession.php, namely
>
> xarSession__phpRead and xarSession__phpWrite , do not
address a
> fundamental
> feature provided in the default file-based PHP session
handler: session
> locking. Without session locking code in place, it is
possible for a
> browser to make simultaneous requests under the same
PHP session causing
> a
> race condition between these multiple requests,
possibly resulting in
> overwriting of the session data in the database ( the
xar_vars BLOB
> column
> in the xar_session_info table).
>
> Practical Applications
> We first noticed this bug manifesting itself as the
stock Xaraya error
> "this
> operation cannot be performed under the current
circumstances" when some
>
> forms were being submitted, but usually only in FireFox
(although it can
> be
> reproduced in IE). Editors were creating content they
had composed in
> the
> WYSIWYG editor, only to submit the page and be greeted
by this fatal
> error
> message and consequentially losing their content
edits.
>
> Technical Details
> Having observed that this problem was primarily related
to FireFox, we
> eventually discovered that a major trigger for this bug
was FireFox's
> auto-fetching of RSS feeds linked to in the requested
document's rss LINK
>
> tag in its HEAD section. IE may also eventually behave
this way (if it
> cannot already be configured to do so) but these two
simultaneous
> requests
> (one for RSS and one for the page) generated a race
condition which
> resulted
> in close to a 25% chance of a data-los condition given
moderate load on
> our
> server A similar "failure" condition could
be created in FireFox or IE
> when
> an editor used tabs and/or multiple windows to access
multiple
> data-editing
> forms across our site. Typically the two simultaneous
requests were 1)
> an
> RSS feed and 2) a page load. The RSS feed request
usually finished
> processing faster than the page load, but on the
occasions when a page
> finished processing faster than the feed, the session
data ($_SESSION)
> associated with the RSS request actually overwrote the
session data just
>
> stored by the page request in the database. Why is
this session data
> important? The Xaraya functions xarSecGenAuthKey() and
> xarSecConfirmAuthKey() rely on session variables to
ensure that
> create/edit/delete operations are not committed without
first going
> through
> the proper "page" paths. If the authkey
(stored in $_SESSION) is lost
> by
> another request overwriting the session data (as was
the case), then the
>
> editor's form submission to create/edit/delete content
would be be
> interpreted by Xaraya as unauthorized, and the content
would be lost.
> The
> end result for our editors was a frequent data-loss
problem, whose lacke
> of
> reproducibility was influenced by server load, browser
type, and the
> "heaviness" of a particular page load.
>
> A Solution
> After researching the problem on the Internet, we found
a well-written
> article that addresses PHP session locking in the
context of
> simultaneous
> AJAX requests.
>
http://thwartedefforts.org/2006/11/1
1/race-conditions-with-ajax-and-php-sess
io
> ns/
> The solution we came up with, per the article's
suggestion, was to
> implement
> session locking through modifying xarSession__phpRead
and
> xarSession__phpWrite to use the MySQL locking features
GET_LOCK() and
> RELEASE_LOCK() (see
> http://dev.mysql.com/doc/refman/4.1/en/miscel
laneous-functions.html ).
>
> In xarSession_phpRead we added:
> // Prevent simultaneous session reads
> $dbconn->Execute("SELECT
GET_LOCK('XARSESSIONLOCK',60)");
>
> In xarSession_phpWrite we added:
> // Prevent simultaneous session reads
> $dbconn->Execute("SELECT
RELEASE_LOCK('XARSESSIONLOCK')");
>
> Our modified xarSession.php file is attached to this
email.
> Unfortunately
> this solution is dependent upon the locking MySQL
features mentioned
> above
> and is not database platform independent, although it
is a start. We
> were
> hoping there would be some similar ADODB version of
this locking
> behavior
> that would make the code platform independent.
>
> If you have any questions pertaining to this bug,
please email us. We'd
> be
> happy to help explain the problem in more detail. We'd
like to see this
> bug
> placed in Bugzilla so that it can eventually be
addressed. Please
> review
> our improvements to xarSecGenAuthKey() and
xarSecConfirmAuthKey() in
> xarSecurity.php as well.
>
> Thank you for your time,
>
> Chris Hirt and Dan Wells
> Programmers
> Hekman Library - Calvin College
> Grand Rapids, MI USA
_______________________________________________
Xaraya_devel mailing list
Xaraya_devel xaraya.com
http:
//xaraya.com/mailman/listinfo/xaraya_devel
|
|
[1-4]
|
|