View Issue Details

IDProjectCategoryView StatusLast Update
0009744mantisbtsecuritypublic2011-02-15 08:46
Reporterseiji Assigned Tojreese  
PrioritynormalSeveritymajorReproducibilityhave not tried
Status closedResolutionfixed 
Target Version1.2.0rc1Fixed in Version1.2.0rc1 
Summary0009744: Users behind proxy will get 'ERROR_SESSION_NOT_VALID'
Description

BRANCH_1_1_0 0005706
TRUNK 0005707

"session_validate()" validates users IP.
But users behind some proxies will get 'ERROR_SESSION_NOT_VALID' because $_SERVER['REMOTE_ADDR'] will return proxy's IP which changes each connection.

See http://en.wikipedia.org/wiki/Session_fixation#Verify_that_additional_information_is_consistent_throughout_session

Additional Information

1) Replace
function session_validate( $p_session ) {
$t_user_ip = '';
if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
$t_user_ip = trim( $_SERVER['REMOTE_ADDR'] );
}
with
function session_validate( $p_session ) {
$t_user_ip = '';
if ( isset( $_SERVER["HTTP_X_FORWARDED_FOR"] ) ) {
$t_user_ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
} else if ( isset( $_SERVER["HTTP_CLIENT_IP"] ) ) {
$t_user_ip = $_SERVER["HTTP_CLIENT_IP"];
} else if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
$t_user_ip = trim( $_SERVER['REMOTE_ADDR'] );
}

OR

  1. Use "User-Agent" insted of IP.
    "User-Agent" will not normally change during use.
Tagspatch
Attached Files
0001-Fix-9744-Properly-handle-sessions-for-proxied-user.patch (2,606 bytes)   
From 095f04d578145963bf5fd986ea780cdf3001e130 Mon Sep 17 00:00:00 2001
From: John Reese <jreese@leetcode.net>
Date: Mon, 27 Oct 2008 15:49:42 -0400
Subject: [PATCH] Fix #9744: Properly handle sessions for proxied users.
 Add User-Agent checks when validating sessions.

---
 mantisbt/core/constant_inc.php |    5 +++++
 mantisbt/core/session_api.php  |   30 ++++++++++++++++++++++++++----
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/mantisbt/core/constant_inc.php b/mantisbt/core/constant_inc.php
index 7e8444a..e24b856 100644
--- a/mantisbt/core/constant_inc.php
+++ b/mantisbt/core/constant_inc.php
@@ -142,6 +142,11 @@ define( 'ALL_USERS', 0 );
 # no user
 define( 'NO_USER', 0 );
 
+# session constants
+define( 'SESSION_NEW', 0 );
+define( 'SESSION_DIRECT', 1 );
+define( 'SESSION_PROXIED', 2 );
+
 # history constants
 define( 'NORMAL_TYPE', 0 );
 define( 'NEW_BUG', 1 );
diff --git a/mantisbt/core/session_api.php b/mantisbt/core/session_api.php
index 7049b21..bef2124 100644
--- a/mantisbt/core/session_api.php
+++ b/mantisbt/core/session_api.php
@@ -136,18 +136,40 @@ function session_init( $p_session_id=null ) {
  * @param object Session object
  */
 function session_validate( $p_session ) {
+	$t_last_type = $p_session->get( 'session_type', SESSION_NEW );
+	$t_last_ip = $p_session->get( 'session_ip', '' );
+	$t_last_agent = $p_session->get( 'session_agent', '' );
+
+	$t_user_type = SESSION_DIRECT;
 	$t_user_ip = '';
-	if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
+	if ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
+		$t_user_type = SESSION_PROXIED;
+		$t_user_ip = trim( $_SERVER['HTTP_X_FORWARDED_FOR'] );
+
+	} else if ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) {
+		$t_user_type = SESSION_PROXIED;
+		$t_user_ip = trim( $_SERVER['HTTP_CLIENT_IP'] );
+
+	} else if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
+		$t_user_type = SESSION_DIRECT;
 		$t_user_ip = trim( $_SERVER['REMOTE_ADDR'] );
 	}
 
-	if ( is_null( $t_last_ip = $p_session->get( 'last_ip', null ) ) ) {
+	$t_user_agent = $_SERVER['HTTP_USER_AGENT'];
+
+	if ( SESSION_NEW == $t_last_type ) {
 		# First session usage
-		$p_session->set( 'last_ip', $t_user_ip );
+		$p_session->set( 'session_type', $t_user_type );
+		$p_session->set( 'session_ip', $t_user_ip );
+		$p_session->set( 'session_agent', $t_user_agent );
 
 	} else {
 		# Check a continued session request
-		if ( $t_user_ip != $t_last_ip ) {
+
+		if ( $t_last_type != $t_user_type ||
+			$t_last_ip != $t_user_ip ||
+			$t_last_agent != $t_user_agent ) {
+
 			session_clean();
 
 			trigger_error( ERROR_SESSION_NOT_VALID, WARNING );
-- 
1.6.0.2

server_dump.txt (8,200 bytes)   
No.1
===========================================================================
$t_last_type: 1, 
$t_user_type: 1 
$t_last_ip: 221.249.178.190, 
$t_user_ip: 58.157.44.142 
$t_last_agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17, 
$t_user_agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17

array(32) {
  ["UNIQUE_ID"]=>
  string(24) "j@nxa38AAAEAAEhXEmoAAAAH"
  ["HTTP_X_ICAP_VERSION"]=>
  string(3) "1.0"
  ["HTTP_HOST"]=>
  string(13) "bacons.ddo.jp"
  ["HTTP_CONNECTION"]=>
  string(10) "keep-alive"
  ["HTTP_COOKIE"]=>
  string(363) "PHPSESSID=e59c5d01cbefb2c7acdb700a923edfe2726722c6; MANTIS_STRING_COOKIE=e64242c1dbb3f6b0cdd0ad500723be57dcd9a0c8091b27bbf1a8714ac259273e; MANTIS_PROJECT_COOKIE=1; __utma=254938395.990757942.1162292416.1224491211.1224579813.287; __utmz=254938395.1224579813.287.137.utmccn=(referral)|utmcsr=google.com|utmcct=/reader/view/|utmcmd=referral; MANTIS_VIEW_ALL_COOKIE=3"
  ["HTTP_USER_AGENT"]=>
  string(89) "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17"
  ["HTTP_ACCEPT"]=>
  string(99) "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
  ["HTTP_ACCEPT_LANGUAGE"]=>
  string(23) "ja,en-us;q=0.7,en;q=0.3"
  ["HTTP_ACCEPT_ENCODING"]=>
  string(12) "gzip,deflate"
  ["HTTP_ACCEPT_CHARSET"]=>
  string(29) "Shift_JIS,utf-8;q=0.7,*;q=0.7"
  ["HTTP_REFERER"]=>
  string(61) "http://bacons.ddo.jp/~sogabe/mantis120/view_all_bug_page.php?"
  ["PATH"]=>
  string(121) "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/sbin:/usr/sbin"
  ["SERVER_SIGNATURE"]=>
  string(0) ""
  ["SERVER_SOFTWARE"]=>
  string(6) "Apache"
  ["SERVER_NAME"]=>
  string(13) "bacons.ddo.jp"
  ["SERVER_ADDR"]=>
  string(13) "192.168.10.20"
  ["SERVER_PORT"]=>
  string(2) "80"
  ["REMOTE_ADDR"]=>
  string(13) "58.157.44.142"
  ["DOCUMENT_ROOT"]=>
  string(25) "/var/www/localhost/htdocs"
  ["SERVER_ADMIN"]=>
  string(20) "XXXXXXXXXXX" // masked
  ["SCRIPT_FILENAME"]=>
  string(51) "/home/sogabe/public_html/mantis120/my_view_page.php"
  ["REMOTE_PORT"]=>
  string(5) "29149"
  ["GATEWAY_INTERFACE"]=>
  string(7) "CGI/1.1"
  ["SERVER_PROTOCOL"]=>
  string(8) "HTTP/1.1"
  ["REQUEST_METHOD"]=>
  string(3) "GET"
  ["QUERY_STRING"]=>
  string(0) ""
  ["REQUEST_URI"]=>
  string(35) "/~sogabe/mantis120/my_view_page.php"
  ["SCRIPT_NAME"]=>
  string(35) "/~sogabe/mantis120/my_view_page.php"
  ["PHP_SELF"]=>
  string(35) "/~sogabe/mantis120/my_view_page.php"
  ["REQUEST_TIME"]=>
  int(1225240619)
  ["argv"]=>
  array(0) {
  }
  ["argc"]=>
  int(0)
}


No.2
===========================================================================

$t_last_type: 1, 
$t_user_type: 1 
$t_last_ip: 58.157.44.142, 
$t_user_ip: 220.96.46.29 
$t_last_agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17, 
$t_user_agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17

array(33) {
  ["UNIQUE_ID"]=>
  string(24) "wMT@EH8AAAEAAAzNbssAAAAF"
  ["HTTP_X_ICAP_VERSION"]=>
  string(3) "1.0"
  ["HTTP_HOST"]=>
  string(13) "bacons.ddo.jp"
  ["HTTP_CONNECTION"]=>
  string(10) "keep-alive"
  ["HTTP_COOKIE"]=>
  string(276) "PHPSESSID=19f6d450d501e6dd2f45d2a8e366ba3f2c5efd91; MANTIS_PROJECT_COOKIE=1; MANTIS_VIEW_ALL_COOKIE=3; __utma=254938395.990757942.1162292416.1224491211.1224579813.287; __utmz=254938395.1224579813.287.137.utmccn=(referral)|utmcsr=google.com|utmcct=/reader/view/|utmcmd=referral"
  ["HTTP_USER_AGENT"]=>
  string(89) "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17"
  ["HTTP_ACCEPT"]=>
  string(99) "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
  ["HTTP_ACCEPT_LANGUAGE"]=>
  string(23) "ja,en-us;q=0.7,en;q=0.3"
  ["HTTP_ACCEPT_ENCODING"]=>
  string(12) "gzip,deflate"
  ["HTTP_ACCEPT_CHARSET"]=>
  string(29) "Shift_JIS,utf-8;q=0.7,*;q=0.7"
  ["HTTP_REFERER"]=>
  string(30) "http://d.hatena.ne.jp/ssogabe/"
  ["HTTP_CACHE_CONTROL"]=>
  string(9) "max-age=0"
  ["PATH"]=>
  string(121) "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/sbin:/usr/sbin"
  ["SERVER_SIGNATURE"]=>
  string(0) ""
  ["SERVER_SOFTWARE"]=>
  string(6) "Apache"
  ["SERVER_NAME"]=>
  string(13) "bacons.ddo.jp"
  ["SERVER_ADDR"]=>
  string(13) "192.168.10.20"
  ["SERVER_PORT"]=>
  string(2) "80"
  ["REMOTE_ADDR"]=>
  string(12) "220.96.46.29"
  ["DOCUMENT_ROOT"]=>
  string(25) "/var/www/localhost/htdocs"
  ["SERVER_ADMIN"]=>
  string(20) "XXXXXXXXXXX" // masked
  ["SCRIPT_FILENAME"]=>
  string(48) "/home/sogabe/public_html/mantis120/main_page.php"
  ["REMOTE_PORT"]=>
  string(5) "24456"
  ["GATEWAY_INTERFACE"]=>
  string(7) "CGI/1.1"
  ["SERVER_PROTOCOL"]=>
  string(8) "HTTP/1.1"
  ["REQUEST_METHOD"]=>
  string(3) "GET"
  ["QUERY_STRING"]=>
  string(0) ""
  ["REQUEST_URI"]=>
  string(32) "/~sogabe/mantis120/main_page.php"
  ["SCRIPT_NAME"]=>
  string(32) "/~sogabe/mantis120/main_page.php"
  ["PHP_SELF"]=>
  string(32) "/~sogabe/mantis120/main_page.php"
  ["REQUEST_TIME"]=>
  int(1225241439)
  ["argv"]=>
  array(0) {
  }
  ["argc"]=>
  int(0)
}

No.3
===========================================================================
$t_last_type: 1, 
$t_user_type: 1 
$t_last_ip: 60.45.60.157, 
$t_user_ip: 221.249.178.190 
$t_last_agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17, 
$t_user_agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17

array(32) {
  ["UNIQUE_ID"]=>
  string(24) "xGcVIX8AAAEAAA0xc9kAAAAH"
  ["HTTP_X_ICAP_VERSION"]=>
  string(3) "1.0"
  ["HTTP_HOST"]=>
  string(13) "bacons.ddo.jp"
  ["HTTP_CONNECTION"]=>
  string(10) "keep-alive"
  ["HTTP_COOKIE"]=>
  string(276) "PHPSESSID=85c2625d39bd78aa8d17b5bf87184799013ec75c; MANTIS_PROJECT_COOKIE=1; MANTIS_VIEW_ALL_COOKIE=3; __utma=254938395.990757942.1162292416.1224491211.1224579813.287; __utmz=254938395.1224579813.287.137.utmccn=(referral)|utmcsr=google.com|utmcct=/reader/view/|utmcmd=referral"
  ["HTTP_USER_AGENT"]=>
  string(89) "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17"
  ["HTTP_ACCEPT"]=>
  string(99) "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
  ["HTTP_ACCEPT_LANGUAGE"]=>
  string(23) "ja,en-us;q=0.7,en;q=0.3"
  ["HTTP_ACCEPT_ENCODING"]=>
  string(12) "gzip,deflate"
  ["HTTP_ACCEPT_CHARSET"]=>
  string(29) "Shift_JIS,utf-8;q=0.7,*;q=0.7"
  ["HTTP_REFERER"]=>
  string(52) "http://bacons.ddo.jp/~sogabe/mantis120/main_page.php"
  ["PATH"]=>
  string(121) "/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/sbin:/usr/sbin"
  ["SERVER_SIGNATURE"]=>
  string(0) ""
  ["SERVER_SOFTWARE"]=>
  string(6) "Apache"
  ["SERVER_NAME"]=>
  string(13) "bacons.ddo.jp"
  ["SERVER_ADDR"]=>
  string(13) "192.168.10.20"
  ["SERVER_PORT"]=>
  string(2) "80"
  ["REMOTE_ADDR"]=>
  string(15) "221.249.178.190"
  ["DOCUMENT_ROOT"]=>
  string(25) "/var/www/localhost/htdocs"
  ["SERVER_ADMIN"]=>
  string(20) "XXXXXXXXXXX" // masked
  ["SCRIPT_FILENAME"]=>
  string(56) "/home/sogabe/public_html/mantis120/view_all_bug_page.php"
  ["REMOTE_PORT"]=>
  string(5) "29360"
  ["GATEWAY_INTERFACE"]=>
  string(7) "CGI/1.1"
  ["SERVER_PROTOCOL"]=>
  string(8) "HTTP/1.1"
  ["REQUEST_METHOD"]=>
  string(3) "GET"
  ["QUERY_STRING"]=>
  string(0) ""
  ["REQUEST_URI"]=>
  string(40) "/~sogabe/mantis120/view_all_bug_page.php"
  ["SCRIPT_NAME"]=>
  string(40) "/~sogabe/mantis120/view_all_bug_page.php"
  ["PHP_SELF"]=>
  string(40) "/~sogabe/mantis120/view_all_bug_page.php"
  ["REQUEST_TIME"]=>
  int(1225241500)
  ["argv"]=>
  array(0) {
  }
  ["argc"]=>
  int(0)
}

server_dump.txt (8,200 bytes)   
patch.txt (Attachment missing)

Activities

jreese

jreese

2008-10-27 15:53

reporter   ~0019705

Seiji, I've taken what you posted and adapted it a bit; mind looking over this patch to make sure I've done things correctly?

seiji

seiji

2008-10-27 23:50

reporter   ~0019706

I've tested this patch from my office behind proxy.
Unfortunately, I got error message. Maybe IP address check caused this error.

I think that it's enough for validating session to check User-Agent.
See following articles.

http://phpsec.org/projects/guide/4.html
http://shiflett.org/articles/session-hijacking

jreese

jreese

2008-10-28 09:32

reporter   ~0019710

I'm hesitant to rely on only the user agent when validating sessions, because the large majority of users pick from a very small selection of browsers, meaning that the attack space is rather limited. I'd much prefer to be able to figure out what is causing issues with proxy/IP detection, and solve that problem as it is.

Could you possibly assist me by logging some var_dump( $_SERVER ) calls to see how your REMOTE_ADDR and FORWARDED_FOR headers change. Perhaps we can figure out why it's not working as it currently is, and then go from there. Also, what is the proxy server/setup that you are using?

Thanks.

seiji

seiji

2008-10-28 21:02

reporter   ~0019721

Could you possibly assist me by logging some var_dump( $_SERVER ) calls to see how your REMOTE_ADDR and FORWARDED_FOR headers change.

I attached server_dump.txt.

what is the proxy server/setup that you are using?

Via: 1.1 proxy4 (NetCache NetApp/6.0.3P2), Version 1.1-Build_SOL_1139 $Date: 04/19/2006 18:57:0012$(IWSS), 1.1 proxy4 (NetCache NetApp/6.0.3P2)
(HTTP Response Header)

jreese

jreese

2008-10-28 21:26

reporter   ~0019723

So now I'm completely confused... You use a proxy server that has an unpredictable remote address, yet it doesn't pass through your own IP via HTTP_CLIENT_IP or HTTP_X_FORWARDED_FOR? How else is the app supposed to track individual users behind the proxy, especially at businesses where most users will all share the same browser/user-agent?

Is this something that you can configure the proxy server to start using those headers, or is that not an option?

If not, perhaps the patch I made could be further changed to allow a configurable set of validation checks, which default to using both IP and agent tracking?

I'm torn between offering as much session security as possible and proxy servers which prevent proper client tracking...

olegos

olegos

2008-10-29 01:23

reporter   ~0019724

Session cookie?

jreese

jreese

2008-10-29 10:29

reporter   ~0019725

Olegos: The cookie by itself is not secure enough, because anyone could forge someone else's session ID into their own session cookie, and steal/hijack the other user's session. That's why this whole thread has come up, because we are trying to validate that the cookie is coming from the correct client, by tracking the client's last IP address and user agent. But apparently some proxy servers make it impossible to track the user's real IP address....

olegos

olegos

2008-10-29 12:44

reporter   ~0019727

Sorry, I didn't realize that this was in addition to a cookie. In this case, using User-Agent is useless: if someone can intercept/steal a cookie, they definitely can intercept & forge User-Agent.

My opinion is that using just a session cookie is sufficient (as long as the cookie contains some large hash, not just a small number for a session id, so that it can't be guessed). Those worried about cookies getting intercepted should run Mantis over https (as we do).

A config option to also add IP check would be good, but not required, IMHO.

seiji

seiji

2008-10-29 13:24

reporter   ~0019729

Last edited: 2008-10-29 13:32

Hi jreese,

How else is the app supposed to track individual users behind the proxy, especially at businesses where most users will all share the same browser/user-agent?

There is no perfect way that tracks users behind the proxy (expect cookie). because end user's networks are complicated such as proxy, NAT..., and server-side may use reverse-proxy.
Therefore we should have application secure as much as possible so that session hijack, session fixation and XSS do not happen.

"Token" is maybe useful for detecting session hijack if all forms and links support it. but it is...

Sorry for bothering you.

Note: I've attached patch.txt. this patch supports tracking users with only USER_AGENT, session fixation and some bug fixes. I think that it still needs to do...

jreese

jreese

2009-03-30 10:08

reporter   ~0021288

seiji, sorry it took so long to get to this, but would you mind reattaching your patch for me? thanks.

jreese

jreese

2009-06-08 15:46

reporter   ~0022060

Retargeting for 1.2.x with a different approach allowing the user to selectively disable validation at login time.

jreese

jreese

2009-06-09 13:04

reporter   ~0022066

Proposal branch available at http://git.mantisforge.org/w/mantisbt/jreese.git?a=shortlog;h=refs/heads/proxy-login

jreese

jreese

2009-06-12 11:37

reporter   ~0022116

Fix committed to master branch. Mantis now allows users to selectively disable session validation at login time.

Related Changesets

MantisBT: master-1.1.x b8fe196a

2008-10-29 11:55

jreese


Details Diff
Disable session validation from r5706 until issue 0009744 is resolved.

git-svn-id: http://mantisbt.svn.sourceforge.net/svnroot/mantisbt/branches/BRANCH_1_1_0@5745 <a class="text" href="/?p=mantisbt.git;a=object;h=f5dc347c">f5dc347c</a>-c33d-0410-90a0-b07cc1902cb9
Affected Issues
0009744
mod - core/session_api.php Diff File