
Opendocman 1.3.4: HTML Injection
Date: 2016-02-01 10:19:541. Introduction
Affected Product: | Opendocman 1.3.4 |
Fixed in: | 1.3.5 |
Fixed Version Link: | http://www.opendocman.com/free-download/ |
Vendor Website: | http://www.opendocman.com/ |
Vulnerability Type: | HTML Injection |
Remote Exploitable: | Yes |
Reported to vendor: | 11/21/2015 |
Disclosed to public: | 02/01/2016 |
Release mode: | Coordinated Release |
CVE: | n/a |
Credits | Tim Coen of Curesec GmbH |
2. Overview
CVSS
Medium 4.3 AV:N/AC:M/Au:N/C:N/I:P/A:N
Description
To defend against XSS and similar attacks, opendocman depends on a function that filters all input to remove dangerous tags and attributes.
The filter does filter out all simple approaches to XSS, but it still leaves an attacker with large control over the look and functionality of the website. This can lead to phishing attacks, privilege escalation, defacement, and may lead to XSS with older browsers.
There are likely other possibilities for attackers. It is recommended to HTML-encode user input before echoing it to mitigate these issues, instead of relying on input filtering.
These issues are present across the application and are reflected as well as persistent, for example via the profile or comments.
3. Proof of Concept
Privilege Escalation
A registered user can exploit this issue in combination with social engineering to gain admin rights:
- Change any profile field, such as last name, to: Smith"><input type="hidden" name="admin" value="1" /><input type="hidden - Contact admin, saying that one is having problems updating profile informations. Ask admin to update any field, such as the email of the user; the form will look normal to the admin, but will contain a hidden field to update the user to admin. Alternatively, ClickJacking may be used to get an admin to update the profile. - If the admin does change any field, the user will automatically gain admin rights as well.
XSS
Some payloads which may lead to XSS in older browser can bypass the filter, for example:
http://localhost/opendocman-1.3.4/search.php/"><x%20style=x:expr/**/ession(open(alert(1)))>
Phishing & Defacement
Attacker-controlled elements can be shown in places where a user would only expect application-controlled data, not user data, which can be used in phishing attacks or to deface the website.
A simple example would be:
http://localhost/opendocman-1.3.4/search.php/"><a href="http://evil.com" style="background: red; color: white">Security Alert: Please upgrade to the latest version here!</a><input type=hidden
As mentioned, these issues are not only reflected, but also persistent. For example when uploading a file, HTML code may be injected via the description or comment parameters here:http://localhost/opendocman-1.3.4/add.php
The same is possible when updating a user profile here:
http://localhost/opendocman-1.3.4//profile.php
It should be noted that by default, the registration is not open, but there is an option to open registration for anyone.
4. Code
The problem exists across the application. A quick search reveals at least these code snippets which are likely open to reflected attacks. Further parameters are likely vulnerable as well. Additionally, all user input that is persisted seems to be affected as well.
check-out.php: <input type="hidden" name="id" value="<?php echo $_GET['id']; check-out.php: <input type="hidden" name="access_right" value="<?php echo $_GET['access_right']; check-in.php:<input type="hidden" name="id" value="<?php echo $_GET['id']; signup.php: echo msg ('message_account_created') . ' ' . $_POST['username'].'<br />'; check-out.php:<form action="<?php echo $_SERVER['PHP_SELF']; check-in.php: <form action="<?php echo $_SERVER['PHP_SELF']; file_ops.php: echo PHP_EOL . '<form name="table" action="' . $_SERVER['PHP_SELF'] . '" method="POST">'; category.php:<form action="<?php echo $_SERVER['PHP_SELF']; category.php:<form action="<?php echo $_SERVER['PHP_SELF']; category.php: <form action="<?php echo $_SERVER['PHP_SELF']; profile.php: <INPUT type="hidden" name="callee" value="<?php echo $_SERVER['PHP_SELF']; ?>"> rejects.php:echo '<form name="author_note_form" action="' . $_SERVER['PHP_SELF'] . '?mode=root"' . ' method="post">'; rejects.php:echo '<form name="author_note_form" action="' . $_SERVER['PHP_SELF'] . '" method="post">'; search.php:<form action=<?php echo $_SERVER['PHP_SELF']; department.php:<form action="<?php echo $_SERVER['PHP_SELF']; department.php:<form action="<?php echo $_SERVER['PHP_SELF']; department.php: <form action="<?php echo $_SERVER['PHP_SELF'];
The function to which all user input is passed, and which is the only defense against attacks such as XSS:
function xss_clean($str) { // http://svn.bitflux.ch/repos/public/popoon/trunk/classes/externalinput.php // +----------------------------------------------------------------------+ // | Copyright (c) 2001-2006 Bitflux GmbH | [...] if (is_array($str) or is_object($str)) { foreach ($str as $k => $s) { $str[$k] = xss_clean($s); } return $str; } // Remove all NULL bytes $str = str_replace("\0", '', $str); // Fix &entity\n; $str = str_replace(array('&', '<', '>'), array('&', '<', '>'), $str); $str = preg_replace('/(*\w+)[\x00-\x20]+;/u', '$1;', $str); $str = preg_replace('/(*[0-9A-F]+);*/iu', '$1;', $str); $str = html_entity_decode($str, ENT_COMPAT); // Remove any attribute starting with "on" or xmlns $str = preg_replace('#(?:on[a-z]+|xmlns)\s*=\s*[\'"\x00-\x20]?[^\'>"]*[\'"\x00-\x20]?\s?#iu', '', $str); // Remove javascript: and vbscript: protocols $str = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $str); $str = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $str); $str = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $str); // Only works in IE: <span style="width: expression(alert('Ping!'));"></span> $str = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#is', '$1>', $str); $str = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#is', '$1>', $str); $str = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#ius', '$1>', $str); // Remove namespaced elements (we do not need them) $str = preg_replace('#</*\w+:\w[^>]*+>#i', '', $str); // Remove any attempts to pass-in a script tag obfuscated by spaces $str = preg_replace('#<\s?/?\s*[Ss]\s*[cC]\s*[rR]\s*[iI]\s*[pP]\s*[tT]#', '', $str); // Removed ;base64 data usage $str = preg_replace('#data:*[^;]+;base64,#i', 'nodatabase64', $str); do { // Remove really unwanted tags $old = $str; $str = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $str); } while ($old !== $str); return $str; }
5. Solution
To mitigate this issue please upgrade at least to version 1.3.5:
http://www.opendocman.com/free-download/
Please note that a newer version might already be available.
6. Report Timeline
11/21/2015 | Informed Vendor about Issue (no reply) |
12/10/2015 | Reminded Vendor of disclosure date |
12/19/2015 | Vendor sends fix for different issue for verification |
01/13/2016 | Confirmed fix |
01/20/2016 | Vendor requests more time to fix XSS issues |
01/31/2016 | Vendor releases fix |
02/01/2015 | Disclosed to public |