{"id":56098,"date":"2024-04-05T23:30:23","date_gmt":"2024-04-05T19:30:23","guid":{"rendered":"https:\/\/packetstormsecurity.com\/files\/177959\/SCHUTZWERK-SA-2023-003.txt"},"modified":"2024-04-05T23:30:23","modified_gmt":"2024-04-05T19:30:23","slug":"visual-planning-rest-api-2-0-authentication-bypass","status":"publish","type":"post","link":"https:\/\/afaghhosting.net\/blog\/visual-planning-rest-api-2-0-authentication-bypass\/","title":{"rendered":"Visual Planning REST API 2.0 Authentication Bypass"},"content":{"rendered":"<p>&#8212;&#8211;BEGIN PGP SIGNED MESSAGE&#8212;&#8211;<br \/>Hash: SHA512<\/p>\n<p>Title<br \/>=====<\/p>\n<p>SCHUTZWERK-SA-2023-003: Authentication Bypass in Visual Planning REST API<\/p>\n<p>Status<br \/>======<\/p>\n<p>PUBLISHED<\/p>\n<p>Version<br \/>=======<\/p>\n<p>1.0<\/p>\n<p>CVE reference<br \/>=============<\/p>\n<p>CVE-2023-49231<\/p>\n<p>Link<br \/>====<\/p>\n<p>https:\/\/www.schutzwerk.com\/advisories\/schutzwerk-sa-2023-003\/<\/p>\n<p>Text-only version:<br \/>https:\/\/www.schutzwerk.com\/advisories\/SCHUTZWERK-SA-2023-003.txt<\/p>\n<p>Affected products\/vendor<br \/>========================<\/p>\n<p>All versions prior to Visual Planning 8 (Build 240207) by STILOG I.S.T.<\/p>\n<p>Summary<br \/>=======<\/p>\n<p>A wildcard injection inside a prepared SQL statement was found in an <br \/>undocumented Visual Planning[0] 8 REST API route. The combination of <br \/>fuzzy matching (via LIKE operator) and user-controlled input allows <br \/>exfiltrating the REST API key based on distinguishable server responses. <br \/>If exploited, attackers are able to gain administrative access to the <br \/>REST API v2.0.<\/p>\n<p>Risk<br \/>====<\/p>\n<p>The vulnerability allows attackers to obtain a valid API key for the <br \/>Visual Planning REST API v2.0. With such a key, attackers can use <br \/>corresponding endpoints to exfiltrate company data or upload\/download <br \/>files. If no external user management (e.g. LDAP) is configured, the API <br \/>key can also be used for user management tasks including the creation of <br \/>administrative users. Since administrators are allowed to upload modules <br \/>using the Visual Planning Admin Center, a compromise of the underlying <br \/>server is likely.<\/p>\n<p>Description<br \/>===========<\/p>\n<p>During a recent red teaming assessment, Visual Planning was identified <br \/>as part of the customers internet-facing assets. The software is <br \/>developed by STILOG I.S.T. and provides resource management and <br \/>scheduling features. A security assessment conducted by SCHUTZWERK found <br \/>an authentication bypass in Visual Planning&#8217;s administrative REST API <br \/>v2.0.[1]\n<p>Corresponding API routes are implemented in the PlanningWSRestV2.java <br \/>file. A comparison between the documentation and implemented routes <br \/>revealed an undocumented route (documentation accessed on 2024-03-05), <br \/>which is externally reachable via a GET request to the \/session endpoint.<\/p>\n<p>The following code snippet shows the corresponding undocumented route, <br \/>which takes the value of the apikey header as an argument:<\/p>\n<p>vp.jar.src\/com\/visualplanning\/webservice\/PlanningWSRestV2.java<br \/>\/* *\/ @GET<br \/>\/* *\/ @Path(&#8220;\/session&#8221;)<br \/>\/* *\/ public Response openSession(@HeaderParam(&#8220;apikey&#8221;) String <br \/>apikey, @HeaderParam(&#8220;keepalive&#8221;) String keepalive) {<br \/>\/* 123 *\/ if (apikey == null || apikey.trim().isEmpty()) {<br \/>\/* 124 *\/ return <br \/>WSResponse.instance().errorApikey((Response.StatusType)Response.Status.FORBIDDEN, <br \/>apikey);<br \/>\/* *\/ }<br \/>\/* *\/<br \/>\/* 127 *\/ WSSession session = WSSession.existsSession(apikey);<br \/>\/* 128 *\/ if (session != null) {<br \/>\/* 129 *\/ return <br \/>WSResponse.instance().error((Response.StatusType)Response.Status.FORBIDDEN, <br \/>&#8220;Already opened session for apikey : &#8220;, apikey);<br \/>\/* *\/ }<br \/>\/* *\/<br \/>\/* 132 *\/ if (WSSession.getSession(apikey, (keepalive != null &amp;&amp; <br \/>Boolean.parseBoolean(keepalive) == true)) == null) {<br \/>\/* 133 *\/ return <br \/>WSResponse.instance().errorApikey((Response.StatusType)Response.Status.FORBIDDEN, <br \/>apikey);<br \/>\/* *\/ }<br \/>\/* 135 *\/ return WSResponse.instance().success(&#8220;WSSession created <br \/>for apikey : &#8221; + apikey);<br \/>\/* *\/ }<\/p>\n<p>Line 132 shows a call to the getSession(apikey, &#8230;) method of the <br \/>WSSession class. Subsequently, the getSession(..) method will call the <br \/>makeSession(apikey, ..) method of the same class.<\/p>\n<p>The following code snippet shows the makeSession(..) method. Line 646 <br \/>contains the vulnerable prepared SQL statement, which is prone to <br \/>wildcard injections[2] due to the usage of the LIKE operator in <br \/>combination with user-controlled input:<\/p>\n<p>vp.jar.src\/com\/visualplanning\/webservice\/WSSession.java<br \/>\/* *\/ private static WSSession makeSession(String apiKey, <br \/>WSSessionType type) {<br \/>\/* 634 *\/ WSSession wsSession = new WSSession();<br \/>\/* 635 *\/ WebApplicationContext applicationContext = <br \/>WebApplicationContext.getDefaultApplication();<br \/>\/* 636 *\/ UserSession userSession = <br \/>applicationContext.createUserSession();<br \/>\/* *\/<br \/>\/* 638 *\/ DBConnection connection = <br \/>applicationContext.createUserSession().getDBConnection();<br \/>\/* 639 *\/ String databaseName = <br \/>applicationContext.getProperty(&#8220;Application&#8221;, &#8220;Databasename&#8221;, <br \/>&#8220;VisualPlanning7&#8221;);<br \/>\/* *\/<br \/>\/* 641 *\/ connection.setPoolMode(false);<br \/>\/* 642 *\/ connection.setDatabase(databaseName);<br \/>\/* *\/<br \/>\/* *\/ try {<br \/>\/* 645 *\/ if (type == WSSessionType.CLIENT) {<br \/>\/* 646 *\/ String planningQuery = &#8220;SELECT XMLContent FROM <br \/>Planning WHERE XMLContent LIKE ?&#8221;;<br \/>\/* 647 *\/ PreparedStatement stmt = <br \/>connection.createPreparedStatement(planningQuery);<br \/>\/* 648 *\/ stmt.setString(1, &#8220;%&lt;APIKey&gt;&#8221; + apiKey + &#8220;&lt;\/APIKey&gt;%&#8221;);<br \/>\/* 649 *\/ ResultSet rs = stmt.executeQuery();<br \/>\/* *\/<br \/>\/* 651 *\/ if (!rs.next()) {<br \/>\/* 652 *\/ return null;<br \/>\/* *\/ }<\/p>\n<p>The following GET request demonstrates the behavior of injecting a <br \/>percent sign as wildcard character:<\/p>\n<p>GET \/vplanning\/api\/v2\/session HTTP\/1.1<br \/>Host: vp-host<br \/>apikey: %<br \/>[..]\n<p>The server will respond with a success message, indicating that a <br \/>session was created for the used API key:<\/p>\n<p>HTTP\/1.1 200<br \/>[..]\n<p>WSSession created for apikey : %<\/p>\n<p>Further tests showed that an apikey header payload of &#8216;1%&#8217; will result <br \/>in a similar success response, if the api key starts with the character <br \/>&#8216;1&#8217;. A payload with a different non-matching first apikey character like <br \/>&#8216;2%&#8217; will result in a status code 403 and the error message &#8216;Invalid API <br \/>key (2%)&#8217;.<\/p>\n<p>The proof-of-concept script brute_vp_apikey.py[3] was developed in order <br \/>to automate the process of exfiltrating the full apikey. The script can <br \/>be executed as follows against a vulnerable Visual Planning instance and <br \/>to extract the administrative api key:<\/p>\n<p>$ python3 brute_vp_apikey.py &#8211;url http:\/\/127.0.0.1:8080<br \/>Visual Planning API Key: 79d4add3-6995-8cae-976b-4aaaddd90616<\/p>\n<p>Solution\/Mitigation<br \/>===================<\/p>\n<p>The vendor suggests to update to Visual Planning 8 (Build 240207)<\/p>\n<p>Disclosure timeline<br \/>===================<\/p>\n<p>2023-11-01: Vulnerability discovered<br \/>2023-11-09: Contact vendor in order to determine security contact<br \/>2023-11-10: Received generic sales response from vendor<br \/>2023-11-14: Contacted CTO of vendor directly<br \/>2023-11-16: Vulnerabilities demonstrated in call with contact at vendor<br \/>2023-11-24: CVE assigned by Mitre<br \/>2023-11-24: Additional technical details provided to vendor<br \/>2023-12-19: Vendor informed SCHUTZWERK that work on fixing the findings <br \/>is in progress<br \/>2024-01-30: Inquired about mitigation status regarding the reported <br \/>vulnerabilities<br \/>2024-01-30: Vendor informed SCHUTZWERK that some of the issues were <br \/>already fixed<br \/>2024-03-08: Sent advisory drafts to vendor<br \/>2024-03-28: Received patch information and release of advisory<\/p>\n<p>Contact\/Credits<br \/>===============<\/p>\n<p>The vulnerability was discovered by Lennert Preuth of SCHUTZWERK GmbH.<\/p>\n<p>References<br \/>==========<\/p>\n[0] https:\/\/www.visual-planning.com\/en\/<br \/>[1] <br \/>https:\/\/app.swaggerhub.com\/apis-docs\/VisualPlanning\/visual-planning_api_rest_v_2_0_us\/2.0-oas3<br \/>[2] <br \/>https:\/\/owasp.org\/www-project-web-security-testing-guide\/latest\/4-Web_Application_Security_Testing\/07-Input_Validation_Testing\/05-Testing_for_SQL_Injection#sql-wildcard-injection<br \/>[3] https:\/\/www.schutzwerk.com\/en\/43\/assets\/advisories\/brute_vp_apikey.py<\/p>\n<p>Disclaimer<br \/>==========<\/p>\n<p>The information provided in this security advisory is provided &#8220;as is&#8221; <br \/>and without warranty of any kind. Details of this security advisory may <br \/>be updated in order to provide as accurate information as possible. The <br \/>most recent version of this security advisory can be found at SCHUTZWERK <br \/>GmbH&#8217;s website ( https:\/\/www.schutzwerk.com ).<\/p>\n<p>Additional information<br \/>======================<\/p>\n<p>SCHUTZWERK Advisories: https:\/\/www.schutzwerk.com\/blog\/tags\/advisories\/<\/p>\n<p>SCHUTZWERK Advisory Policy: https:\/\/www.schutzwerk.com\/en\/advisories\/<br \/>&#8212;&#8211;BEGIN PGP SIGNATURE&#8212;&#8211;<\/p>\n<p>iQJOBAEBCgA4FiEEgLsg7Oj\/wY3LSF87GrXfkTIXLrsFAmYF0QkaHGFkdmlzb3Jp<br \/>ZXNAc2NodXR6d2Vyay5jb20ACgkQGrXfkTIXLrvAZhAArh5MI5kM1lTjcIPPMiDS<br \/>VXJ51Z39qgcXySyrqrKslnP\/2a\/pfpakD8g161oOTSK\/tt9Yd6L\/6O5Vywe7Kx5V<br \/>lkVw7bs9J0WCY8aYzJ9RxdALt7HexAG+USgbjFWFajdSNNJ8giBu3P3ZCE8\/GbHJ<br \/>0bKd8AN88NKL954olnI6qGbbnOr\/QXWuIOWAYF9wXLgEk992hszYgt7SJIrFHuX6<br \/>2TC4iWOv4+72HQiQ8QYXCAZZVBDr3mUPQRBSJ9AZ3x7mxtJtMg8DyW0OATNe9Qlq<br \/>IUO7HFqrPwTQmFKf9whk8QD7\/Y9dKTpAjlVzvXe49COqbjOzxmIe7muxwyVlOrqO<br \/>J9ZqreOr\/ENLUgYDBaTLSTAHdEFNeqRGPK3dG0yiRSi3dtavJwr8PN1L52qTqLzT<br \/>C+Yrruu6Ac6pSin1Ea9WaXF+YS1ErRcbZxkRD5pS4s6V4NMkV4bDWlDtraQ0rDfL<br \/>AA+TxtA25p34S2MV\/b3qAiA66UjrXEb6IJVNx4Rx7X3+gcLgI2w7t3DQEVuPaB3k<br \/>ltT1oV6ei7tqeQpn7usHzlfa6lq7Q3PIRpxYAo0g4kp4cVVblLRNWDpZMK+cBj1N<br \/>MrGP2f50gbpYej\/yYHsXNU2pMfbUPoSq3X8uwVCoLvaBSBWx7I3TM1hl0\/3wBi\/w<br \/>phO+Bauh2QYGX2mFw\/mduZM=<br \/>=ycwQ<br \/>&#8212;&#8211;END PGP SIGNATURE&#8212;&#8211;<\/p>\n<p>&#8212; <br \/>SCHUTZWERK GmbH, Pfarrer-Wei\u00df-Weg 12, 89077 Ulm, Germany<br \/>Zertifiziert \/ Certified ISO 27001, 9001 and TISAX<\/p>\n<p>Phone +49 731 977 191 0<\/p>\n<p>advisories@schutzwerk.com \/ www.schutzwerk.com<\/p>\n<p>Gesch\u00e4ftsf\u00fchrer \/ Managing Directors:<br \/>Jakob Pietzka, Michael Sch\u00e4fer<\/p>\n<p>Amtsgericht Ulm \/ HRB 727391<br \/>Datenschutz \/ Data Protection www.schutzwerk.com\/datenschutz<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8212;&#8211;BEGIN PGP SIGNED MESSAGE&#8212;&#8211;Hash: SHA512 Title===== SCHUTZWERK-SA-2023-003: Authentication Bypass in Visual Planning REST API Status====== PUBLISHED Version======= 1.0 CVE reference============= CVE-2023-49231 Link==== https:\/\/www.schutzwerk.com\/advisories\/schutzwerk-sa-2023-003\/ Text-only version:https:\/\/www.schutzwerk.com\/advisories\/SCHUTZWERK-SA-2023-003.txt Affected products\/vendor======================== All versions prior to Visual Planning 8 (Build 240207) by STILOG I.S.T. Summary======= A wildcard injection inside a prepared SQL statement was found in an undocumented Visual Planning[0] &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-56098","post","type-post","status-publish","format-standard","hentry","category-vulnerability"],"_links":{"self":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/56098","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/comments?post=56098"}],"version-history":[{"count":0,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/posts\/56098\/revisions"}],"wp:attachment":[{"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/media?parent=56098"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/categories?post=56098"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/afaghhosting.net\/blog\/wp-json\/wp\/v2\/tags?post=56098"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}