{"id":15,"date":"2026-01-15T17:20:52","date_gmt":"2026-01-15T17:20:52","guid":{"rendered":"https:\/\/zerotoghost.com\/?p=15"},"modified":"2026-01-15T23:14:55","modified_gmt":"2026-01-15T23:14:55","slug":"hackthebox-academy-web-fuzzing","status":"publish","type":"post","link":"https:\/\/zerotoghost.com\/?p=15","title":{"rendered":"HackTheBox Academy &#8211; Web Fuzzing"},"content":{"rendered":"\n<p><em>(Sections 1 and 2 coming soon)<\/em><\/p>\n\n\n\n<p><em><strong>NOTE<\/strong>: I have blurred out any secret values and flags. There are plenty of walkthroughs that chose to leave them in there, but I think half the fun is figuring it out. Hopefully this helps you get unstuck while you&#8217;re working through the module yourself.<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading is-style-text-subtitle has-medium-font-size\">3.1 Parameter and Value Fuzzing<\/h2>\n\n\n\n<p>GET Parameters : Openly Sharing Information<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;example.com\/search?query=fuzzing&amp;category=security<\/code><\/pre>\n\n\n\n<p>When you see GET parameters in the URL (following a question(?) mark, this is often a signal that you can modify the request to retrieve different information. In web application testing, I would check for tenant and user enumeration, along with information I shouldn&#8217;t be able to access with my provided permissions.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"865\" height=\"358\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_get-req-example.png\" alt=\"\" class=\"wp-image-17\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_get-req-example.png 865w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_get-req-example-300x124.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_get-req-example-768x318.png 768w\" sizes=\"auto, (max-width: 865px) 100vw, 865px\" \/><figcaption class=\"wp-element-caption\">Get request for provided IP address<\/figcaption><\/figure>\n\n\n\n<p>The tutorial instructs us to use <strong>wenum<\/strong>, but as I don&#8217;t already have that installed on my machine I&#8217;m using <strong>wfuzz<\/strong>. It&#8217;s a similar tool. Using the equivalent command and recommended wordlist, we get a successful response. <\/p>\n\n\n\n<p><em>Remember &#8211; your IP, port, and wordlist location is likely different than mine.<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>wfuzz -w \/usr\/share\/wordlists\/dirb\/common.txt --sc 200 -u http:\/\/94.237.123.85:37328\/get.php?x=FUZZ<\/code><\/pre>\n\n\n\n<p>Using <strong>cURL<\/strong>, we can retrieve the flag for question 1.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"350\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_wfuzz-get-1024x350.png\" alt=\"\" class=\"wp-image-16\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_wfuzz-get-1024x350.png 1024w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_wfuzz-get-300x103.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_wfuzz-get-768x263.png 768w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_wfuzz-get.png 1046w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Successful fuzzing response<\/figcaption><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code>curl http:\/\/94.237.123.185:37328\/get.php?x=XXXX<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"603\" height=\"107\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_get-flag-1.png\" alt=\"\" class=\"wp-image-23\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_get-flag-1.png 603w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_get-flag-1-300x53.png 300w\" sizes=\"auto, (max-width: 603px) 100vw, 603px\" \/><\/figure>\n\n\n\n<p>Next, we are given some information on POST requests. Unlike a GET request, which (like the name) retrieves information, a POST request sends data. This can be a login portal (username and password), a form, or even a blog post. The parameters are in the body of the request, unlike our example get request which had parameters in the URL portion.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"865\" height=\"302\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_post.png\" alt=\"\" class=\"wp-image-19\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_post.png 865w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_post-300x105.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_post-768x268.png 768w\" sizes=\"auto, (max-width: 865px) 100vw, 865px\" \/><figcaption class=\"wp-element-caption\">Here the response is telling us we didn&#8217;t include the expected parameters<\/figcaption><\/figure>\n\n\n\n<p>Next we use FFUF (one of my favorite tools) to fuzz the post parameter y. Note the content-type flag &#8211; it will not work without it. I tried finding a list of acceptable content-types on FFUF&#8217;s github page, but for now we just take HTB&#8217;s word for it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ffuf -u http:\/\/94.237.123.185:37328\/post.php -X POST -H \"Content-Type: application\/x-www-form-urlencoded\" -d \"y=FUZZ\" w \/usr\/share\/wordlists\/dirb\/common.txt<\/code><\/pre>\n\n\n\n<p>This results in one successful result<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"451\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_post-ffuf-1024x451.png\" alt=\"\" class=\"wp-image-21\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_post-ffuf-1024x451.png 1024w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_post-ffuf-300x132.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_post-ffuf-768x338.png 768w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_post-ffuf.png 1058w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Using FFUF to fuzz post parameters<\/figcaption><\/figure>\n\n\n\n<p>And voila! We have our second flag.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -d \"y=Sxxxxxx\" http:\/\/94.237.185:37328\/post.php<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"676\" height=\"67\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_post-curl-flag.png\" alt=\"\" class=\"wp-image-22\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_post-curl-flag.png 676w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_post-curl-flag-300x30.png 300w\" sizes=\"auto, (max-width: 676px) 100vw, 676px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\">4.1 Virtual Host and Subdomain Fuzzing<\/h2>\n\n\n\n<p>Subdomains vs virtual hosts (vhost)<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span style=\"text-decoration: underline;\">Identification<\/span>: <strong>Vhosts<\/strong> are identified in the HOST header in a HTTP request, where <strong>subdomains<\/strong> are identified by DNS records.<\/li>\n\n\n\n<li><span style=\"text-decoration: underline;\">Purpose<\/span>: <strong>Vhosts<\/strong> are used to host multiple websites on a single server, <strong>subdomains<\/strong> are used to organize sections\/services within a website.<\/li>\n\n\n\n<li><span style=\"text-decoration: underline;\">Security risks<\/span>: misconfigured <strong>vhosts<\/strong> can expose internal applications or sensitive data, <strong>subdomain<\/strong> takeover vulnerabilities can occur if DNS records are mismanaged <\/li>\n<\/ul>\n\n\n\n<p>Gobuster vhost fuzzing command<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gobuster vhost -u http:\/\/inlanefreight.htb -w \/usr\/share\/wordlists\/dirb\/common.txt --append-domain\n<\/code><\/pre>\n\n\n\n<p>For question 1, we are asked to simply fuzz vhosts for the provided target. NOTE: You will need to edit your hosts file and use the url http:\/\/inlanefreight.htb in the above command.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"611\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_vhosts-gobuster-1024x611.png\" alt=\"\" class=\"wp-image-47\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_vhosts-gobuster-1024x611.png 1024w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_vhosts-gobuster-300x180.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_vhosts-gobuster-768x459.png 768w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_vhosts-gobuster-850x508.png 850w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_vhosts-gobuster.png 1045w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Fuzzing for vhosts with gobuster<\/figcaption><\/figure>\n\n\n\n<p>For question 2, we need to repeat the process but instead of vhosts we are fuzzing for subdomains. The syntax is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gobuster dns --domain inlanefreight.com -w \/usr\/share\/wordlists\/amass\/subdomains-top1million-5000.txt<\/code><\/pre>\n\n\n\n<p><em>Note: the module uses -d, but gobuster now uses -d for delay so the correct syntax is &#8211;do or &#8211;domain<\/em>. <em><strong>ALSO &#8211; this one is .com<\/strong> not .htb<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"456\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_gobuster-subdomains-com-1024x456.png\" alt=\"\" class=\"wp-image-48\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_gobuster-subdomains-com-1024x456.png 1024w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_gobuster-subdomains-com-300x133.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_gobuster-subdomains-com-768x342.png 768w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_gobuster-subdomains-com-850x378.png 850w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_gobuster-subdomains-com.png 1045w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Successful Gobuster subdomain enumeration for inlanefreight.com<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\">5.1 Filtering Fuzzing Output<\/h2>\n\n\n\n<p>If you&#8217;ve used FFUF, Gobuster or wfuzz before you know sometimes you get an insane amount of results. I always will run the command without filters, and then typically filter by size for the default response (such as a redirect to login page with a size of 874).<\/p>\n\n\n\n<p><strong>Gobuster<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><s>-s (include) &#8211; only include responses with specific status codes (200, 301, etc)<\/s> no longer valid flag<\/li>\n\n\n\n<li><s>-b (exclude) &#8211; exclude responses with specific status codes (404, 403)<\/s> no longer valid flag<\/li>\n\n\n\n<li>&#8211;exclude-length &#8211; exclude responses with specific length (0, 874, 1290&#8230;)<\/li>\n\n\n\n<li>&#8211;exclude-status &#8211; exclude response with specific status (403)<\/li>\n<\/ul>\n\n\n\n<p>Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>gobuster dir -u http:\/\/example.com\/ -w wordlist.txt -s 200,301 --exclude-length 0<\/code><\/pre>\n\n\n\n<p><strong>FFUF<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>-mc (match code) &#8211; include only specific codes (200, 301)<\/li>\n\n\n\n<li>-fc (filter code) &#8211; exclude specific codes<\/li>\n\n\n\n<li>-fs (filter size) &#8211; exclude specific page size<\/li>\n\n\n\n<li>-ms (match size) &#8211; include only specific page size<\/li>\n\n\n\n<li>-fw (filter word count) &#8211; filter out number of words in response<\/li>\n\n\n\n<li>-mw (match word count)<\/li>\n\n\n\n<li>-fl (filter line) &#8211; exclude response with specific number of lines, or range of lines.<\/li>\n\n\n\n<li>-ml (match line)<\/li>\n\n\n\n<li>-mt (match time) &#8211; include only responses that meet a specific time-to-first-byte (TTFB) condition. Used to filter responses with unusually slow or quick responses. ( >500)<\/li>\n<\/ul>\n\n\n\n<p>Optional exercise:<\/p>\n\n\n\n<p>Fuzz the post parameter for the target. I simply reused the FFUF command from 3.1 part 2. After cURLing the target, I noticed the post parameter was again &#8220;y&#8221;.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ffuf -u http:\/\/94.237.63.174:36026\/post.php -X POST -H \"Content-Type: application\/x-www-form-urlencoded\" -d \"y=FUZZ\" -w \/usr\/share\/wordlists\/dirb\/common.txt<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"455\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_gobuster-vhosts-part2-1024x455.png\" alt=\"\" class=\"wp-image-49\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_gobuster-vhosts-part2-1024x455.png 1024w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_gobuster-vhosts-part2-300x133.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_gobuster-vhosts-part2-768x341.png 768w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_gobuster-vhosts-part2-850x377.png 850w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_gobuster-vhosts-part2.png 1045w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Fuzzing success<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"542\" height=\"64\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_success-part2.png\" alt=\"\" class=\"wp-image-50\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_success-part2.png 542w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_success-part2-300x35.png 300w\" sizes=\"auto, (max-width: 542px) 100vw, 542px\" \/><figcaption class=\"wp-element-caption\">Successful flag!<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\">6.1 Validating Findings<\/h2>\n\n\n\n<p>Fuzzing can provide potential leads, but not every result is a genuine vulnerability. It&#8217;s important to check for false positives (IE, in my job I check discovered domains in browser or with cURL). It&#8217;s important to validate any finding tooling reports, in general.<\/p>\n\n\n\n<p>Example: you discover a directory \/backup\/ while fuzzing a webserver. While this may have returned a 200 response code, you should still enumerate the directory to see if any information actually exists or if it is use.<\/p>\n\n\n\n<p>Question 1: Fuzz the target system using directory-list-2.3-medium.txt, looking for a hidden directory. Once found, responsibly determine the validity of the vulnerability by analyzing the tar.gz file.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1014\" height=\"453\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_validate-curl.png\" alt=\"\" class=\"wp-image-52\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_validate-curl.png 1014w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_validate-curl-300x134.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_validate-curl-768x343.png 768w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_validate-curl-850x380.png 850w\" sizes=\"auto, (max-width: 1014px) 100vw, 1014px\" \/><figcaption class=\"wp-element-caption\">Fuzzing target<\/figcaption><\/figure>\n\n\n\n<p>And then validate with cURL:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"606\" height=\"184\" src=\"http:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_validate-ffuf.png\" alt=\"\" class=\"wp-image-54\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_validate-ffuf.png 606w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_validate-ffuf-300x91.png 300w\" sizes=\"auto, (max-width: 606px) 100vw, 606px\" \/><figcaption class=\"wp-element-caption\">Using cURL to check content-length of discovered file<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\">7.1 Web APIs<\/h2>\n\n\n\n<p>A web API (application programming interface) is a set of rules and specifications that enable different software applications to communicate over the web. Essentially, an API is a bridge between a server and client (browser, mobile app) that wants to access or utilize the data. <\/p>\n\n\n\n<p><strong>REST APIs<\/strong><\/p>\n\n\n\n<p>Representational State Transfer (REST) APIs are popular architecture for building web services. They use a <strong>stateless<\/strong>, client-server communication module. These utilize standard HTTP methods (GET, POST, PUT, DELETE) to perform CRUD (Create, Read, Update, Delete) operations on resources. This is typically done in lightweight formats such as JSON or XML.<\/p>\n\n\n\n<p>Example query: <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>GET \/users\/123\n<\/code><\/pre>\n\n\n\n<p><strong>SOAP APIs<\/strong><\/p>\n\n\n\n<p>Simple Object Access Protocol (SOAP) APIs follow a more standardized protocol. They use XML to define messages, which are encapsulated in &#8220;SOAP envelopes&#8221; and transmitted using protocols like HTTP or SMTP. SOAP APIs often include built-in security, reliability and transaction management features.<\/p>\n\n\n\n<p>Example query:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;soapenv:Envelope xmlns:soapenv=\"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/\" xmlns:tem=\"http:\/\/tempuri.org\/\">\n   &lt;soapenv:Header\/>\n   &lt;soapenv:Body>\n      &lt;tem:GetStockPrice>\n         &lt;tem:StockName>AAPL&lt;\/tem:StockName>\n      &lt;\/tem:GetStockPrice>\n   &lt;\/soapenv:Body>\n&lt;\/soapenv:Envelope>\n<\/code><\/pre>\n\n\n\n<p><strong>GraphQL<\/strong><\/p>\n\n\n\n<p>GraphQL provides a single endpoint where clients can request data. Introspection makes it easier to evolve APIs over time without breaking exisiting clients.<\/p>\n\n\n\n<p>Example query:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>query {\n  user(id: 123) {\n    name\n    email\n  }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\">7.2 Identifying Endpoints<\/h2>\n\n\n\n<p><strong>REST APIs <\/strong>are built around the concept of resources, identified by unique URLs called endpoints.<\/p>\n\n\n\n<p>Structured as URLs representing the resource you want to access. Ex:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\/users &#8211; collection of user resources<\/li>\n\n\n\n<li>\/users\/123 &#8211; represents a specific user with ID 123<\/li>\n\n\n\n<li>\/products &#8211; collection of product resources<\/li>\n\n\n\n<li>\/users?limit=10&amp;sort=name &#8211; (query ressouce) show 10 users, sorted by name<\/li>\n\n\n\n<li>\/products\/{id}pen_spark &#8211; (path parameters) identifies a specific resource<\/li>\n\n\n\n<li>{ &#8220;name&#8221; : &#8220;New Product&#8221;, &#8220;price&#8221; : 99.00 } &#8211; sent in body of POST, PUT, PATCH requests<\/li>\n<\/ul>\n\n\n\n<p><strong>Discovering REST Endpoints and Parameters<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>API documentation<\/li>\n\n\n\n<li>Network Traffic Analysis (burp suite)<\/li>\n\n\n\n<li>Parameter Name Fuzzing (FFUF, wfuzz)<\/li>\n<\/ul>\n\n\n\n<p>SOAP APIs rely on XML-based messages and Web Services Description Language (WSDL) files to define their interfaces and operations.<\/p>\n\n\n\n<p>A WSDL file might define an operation called SearchBooks with the following parameters:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>keywords (string): The search term to use<\/li>\n\n\n\n<li>author (string): The name of the author (optional)<\/li>\n\n\n\n<li>genre (string): The genre of the book (optional)<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;soapenv:Envelope xmlns:soapenv=\"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/\" xmlns:lib=\"http:\/\/example.com\/library\">\n   &lt;soapenv:Header\/>\n   &lt;soapenv:Body>\n      &lt;lib:SearchBooks>\n         &lt;lib:keywords>cybersecurity&lt;\/lib:keywords>\n         &lt;lib:author>Dan Kaminsky&lt;\/lib:author>\n      &lt;\/lib:SearchBooks>\n   &lt;\/soapenv:Body>\n&lt;\/soapenv:Envelope>\n<\/code><\/pre>\n\n\n\n<p>Discovering SOAP endpoints and paameters<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>WSDL analysis &#8211; describes available operations (endpoints), Input parameters, output parameters, data types, location (URL) of endpoint<\/li>\n\n\n\n<li>Network traffic anaylsis<\/li>\n\n\n\n<li>Fuzzing parameter names and values<\/li>\n\n\n\n<li><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\">7.3 API Fuzzing<\/h2>\n\n\n\n<p>I love API testing. It&#8217;s an integral part of many web applications, and while it *CAN* be repetitive, there&#8217;s something beautiful about the process.<\/p>\n\n\n\n<p>API fuzzing is a specialized form of fuzzing tailored for web APIs. While the core principles of fuzzing are the same &#8211; API fuzzing focuses on unique structure and protocols used by APIs. <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Altering parameter values<\/li>\n\n\n\n<li>Modifying request headers<\/li>\n\n\n\n<li>Changing the order of parameters<\/li>\n\n\n\n<li>Introducing unexpected data types or formats<\/li>\n<\/ul>\n\n\n\n<p>Why fuzz APIs?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Uncover hidden vulnerabilities<\/li>\n\n\n\n<li>Test robustness<\/li>\n\n\n\n<li>Automate security testing<\/li>\n\n\n\n<li>Simulate real-world attacks<\/li>\n\n\n\n<li>Parameter fuzzing<\/li>\n\n\n\n<li>Data format fuzzing<\/li>\n\n\n\n<li>Sequence fuzzing<\/li>\n<\/ul>\n\n\n\n<p>PandaSt0rm<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git clone https:\/\/github.com\/PandaSt0rm\/webfuzz_api.git\ncd webfuzz_api\npip3 install -r requirements\npython3 api_fuzzer.py http:\/\/IP:PORT<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"756\" height=\"210\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-recon_api-grep.png\" alt=\"\" class=\"wp-image-59\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-recon_api-grep.png 756w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-recon_api-grep-300x83.png 300w\" sizes=\"auto, (max-width: 756px) 100vw, 756px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"220\" height=\"166\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/spongebob.gif\" alt=\"\" class=\"wp-image-58\"\/><\/figure>\n\n\n\n<p>And we got it!<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"695\" height=\"86\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-recon_api-flag.png\" alt=\"\" class=\"wp-image-60\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-recon_api-flag.png 695w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-recon_api-flag-300x37.png 300w\" sizes=\"auto, (max-width: 695px) 100vw, 695px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading has-medium-font-size\">8.1 Skills Assessment<\/h2>\n\n\n\n<p>We aren&#8217;t given much information &#8211; just follow the steps already laid out in the module and that &#8216;common.txt&#8217; will have everything we need. Starting with FFUF (I did have to re-run this and add the -e extensions flag):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ffuf -u http:\/\/IP:PORT\/FUZZ -w \/usr\/share\/wordlists\/dirb\/common.txt -recursion -recursion-depth 3 -e .html,.php<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"637\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf1-1024x637.png\" alt=\"\" class=\"wp-image-63\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf1-1024x637.png 1024w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf1-300x187.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf1-768x477.png 768w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf1-850x528.png 850w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf1.png 1052w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">FFUF output 1\/2<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"291\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf2-1024x291.png\" alt=\"\" class=\"wp-image-64\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf2-1024x291.png 1024w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf2-300x85.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf2-768x218.png 768w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf2-850x242.png 850w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf2.png 1052w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">FFUF output 2\/2<\/figcaption><\/figure>\n\n\n\n<p>We find a directory and 3 endpoints &#8211; cURLing them results in this clue, telling us an invalid parameter<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"356\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skllls-curl1-1024x356.png\" alt=\"\" class=\"wp-image-65\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skllls-curl1-1024x356.png 1024w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skllls-curl1-300x104.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skllls-curl1-768x267.png 768w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skllls-curl1-850x296.png 850w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skllls-curl1.png 1052w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Run FFUF again, fuzzing the directory\/page.php?{parameter}=FUZZ gives us a valid parameter to use.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"954\" height=\"226\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf-getaccess.png\" alt=\"\" class=\"wp-image-66\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf-getaccess.png 954w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf-getaccess-300x71.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf-getaccess-768x182.png 768w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_skills-ffuf-getaccess-850x201.png 850w\" sizes=\"auto, (max-width: 954px) 100vw, 954px\" \/><\/figure>\n\n\n\n<p>And using cURL we have a hint on where to go next. cURLing the newly discovered endpoint gives us a new hint (not pictured, you get the idea).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"969\" height=\"344\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_curl2-fuzzing_fun.png\" alt=\"\" class=\"wp-image-67\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_curl2-fuzzing_fun.png 969w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_curl2-fuzzing_fun-300x107.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_curl2-fuzzing_fun-768x273.png 768w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/htb-academy_web-fuzzing_curl2-fuzzing_fun-850x302.png 850w\" sizes=\"auto, (max-width: 969px) 100vw, 969px\" \/><\/figure>\n\n\n\n<p>We use gobuster to fuzz for vhosts and discover a new endpoint (and add to \/etc\/hosts).<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"379\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.10.15-PM-1-1024x379.png\" alt=\"\" class=\"wp-image-69\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.10.15-PM-1-1024x379.png 1024w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.10.15-PM-1-300x111.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.10.15-PM-1-768x284.png 768w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.10.15-PM-1-850x314.png 850w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.10.15-PM-1.png 1055w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Inspect this in the web browser for a hint, and then another hint \ud83d\ude42<\/p>\n\n\n\n<p>After using recrusion with our discovered vhost &#8211; use at least 3 levels &#8211; you will find the page you&#8217;re looking for. Inspecting it gives you the flag, and final piece needed to finish the module.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ffuf -u http:\/\/vhost.discoveredHost.hth\/PORT\/directory\/FUZZ -w common.txt -recursion -recursion-depth 5 -fc 403,404<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"591\" data-id=\"70\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.49.16-PM-1024x591.png\" alt=\"\" class=\"wp-image-70\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.49.16-PM-1024x591.png 1024w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.49.16-PM-300x173.png 300w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.49.16-PM-768x443.png 768w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.49.16-PM-850x491.png 850w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.49.16-PM.png 1055w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"766\" height=\"151\" src=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.51.32-PM-1.png\" alt=\"\" class=\"wp-image-72\" srcset=\"https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.51.32-PM-1.png 766w, https:\/\/zerotoghost.com\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-15-at-5.51.32-PM-1-300x59.png 300w\" sizes=\"auto, (max-width: 766px) 100vw, 766px\" \/><\/figure>\n\n\n\n<p>And there you have it! If you finished this module, leave a comment with any tips or hang-ups you experienced.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>(Sections 1 and 2 coming soon) NOTE: I have blurred out any secret values and flags. There are plenty of walkthroughs that chose to leave them in there, but I think half the fun is figuring it out. Hopefully this helps you get unstuck while you&#8217;re working through the module&#8230;<\/p>\n","protected":false},"author":1,"featured_media":49,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[6,7,5],"class_list":["post-15","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-htb-academy","tag-ffuf","tag-fuzzing","tag-wfuzz"],"_links":{"self":[{"href":"https:\/\/zerotoghost.com\/index.php?rest_route=\/wp\/v2\/posts\/15","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zerotoghost.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zerotoghost.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zerotoghost.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zerotoghost.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=15"}],"version-history":[{"count":9,"href":"https:\/\/zerotoghost.com\/index.php?rest_route=\/wp\/v2\/posts\/15\/revisions"}],"predecessor-version":[{"id":73,"href":"https:\/\/zerotoghost.com\/index.php?rest_route=\/wp\/v2\/posts\/15\/revisions\/73"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/zerotoghost.com\/index.php?rest_route=\/wp\/v2\/media\/49"}],"wp:attachment":[{"href":"https:\/\/zerotoghost.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=15"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zerotoghost.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=15"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zerotoghost.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=15"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}