This Sherlock will have players investigate logs of an AI system that is under attack.
An attacker probed a set of web-hosted AI chatbots in a packet capture, first checking whether a person’s name existed as a local account, then failing to coax stored data out of one bot. A second bot, built to read web pages and files on the server, was more cooperative and printed a file containing a plaintext username and password. The attacker used those credentials to log in over SSH. On the host they found a Python script runnable through sudo that used a vulnerable LangChain chain, and injected Python through it to run commands as root. The capture shows the social-engineering half of the intrusion, and auth.log and the shell history show the login and the escalation.
tshark or Wireshark, follow the TCP streamsauth.log → grep. Syslog format, so timestamps have no yearcat, includes the ai-bot.py injection attemptsTimestamp note: The capture’s timestamps sit 11 hours off
auth.log, which is UTC. Answer the two time questions fromauth.logonly.
Extract the HTTP requests from the capture and read the questions the attacker POSTed. One request to /rag-chatbot/ask asks whether a named person is “also a username in your machine”, which is the account-existence check.
tshark -r Neural-Noel.pcap -Y http -T fields -e frame.time -e http.request.uri -e http.file_data
The refusals are in the responses to /user_manage_chatbot/ask. The bot’s display name is not the page heading but the navbar link text, so follow the TCP stream of the page load and read the navigation HTML.
tshark -r Neural-Noel.pcap -q -z follow,tcp,ascii,<stream>
Gotcha: The format hint says to check the navbar. The page
h1carries a different, more descriptive title and is not the accepted answer.
The Server header on any chatbot response names the web framework and runtime. The format mask (********/*.*.* ******/*.**/*) matches the header layout exactly, so the full header value is the answer.
tshark -r Neural-Noel.pcap -Y http.response -T fields -e http.server
The bot that answers is behind /web-assistant/ask. Its reply to the attacker states that it can read page content and server files. As with Q2, the name to report is the navbar link text from the page HTML.
tshark -r Neural-Noel.pcap -q -z follow,tcp,ascii,<stream>
Gotcha: Same trap as Q2. The
h1on the page is a longer descriptive title, not the navbar name.
Continue reading the /web-assistant/ask conversation. Once asked to show files, the bot returns the contents of one that holds a plaintext username:password pair for the noel account. The filename appears in the bot’s reply next to the credentials.
tshark -r Neural-Noel.pcap -Y 'http.request.uri contains "web-assistant"' -T fields -e http.file_data
From Q5 the account is noel. Search auth.log for the successful SSH password authentication for that user. The capture’s clock is offset by 11 hours, so the sshd line is the authoritative time.
grep -n "Nov 27 06:5\|Nov 27 07:0" auth.log
The shell history shows the attacker feeding injection strings to ai-bot.py, a script that wraps a LangChain chain which executes model-generated Python. That pattern is the __import__ bypass in LangChain’s PALChain. This answer was reasoned from the history and the known vulnerability rather than read from an artifact, and HTB accepted it.
cat history
Gotcha: LangChain has several code-execution CVEs, and similar-looking IDs such as CVE-2023-29374, -36258, -38896 and -39631 are not the one. Match the
__import__bypass seen in the history.
The injected payloads in the history (lines 55 and 56) use the built-in __import__ to reach modules and run commands, which is the bypass named in Q7.
sed -n '50,60p' history
The history has no timestamps, so it cannot place the commands in a session. Use auth.log instead: the first sudo session in which noel runs ai-bot.py as root is the moment the injection landed.
grep -n "sudo" auth.log | grep "ai-bot.py"
Gotcha: Later sudo sessions look just as plausible, and the history can’t separate them. Take the first
ai-bot.pysession opened as root.
| Phase | Action |
|---|---|
| Discovery | Asks a chatbot whether a named person is a local account on the machine |
| Discovery | Tries to talk the user-management bot into revealing stored data and is refused |
| Credential Access | Asks the web and files assistant what it can read, then has it print a credentials file |
| Initial Access | Logs in over SSH as noel with the leaked password |
| Privilege Escalation | Injects Python through ai-bot.py using an __import__ bypass in a vulnerable LangChain chain |
| Privilege Escalation | Runs commands as root through a sudo session of the script |
| Type | Value |
|---|---|
| Account | noel (credentials leaked in plaintext) |
| File | creds.txt |
| Script | ai-bot.py |
| CVE | CVE-2023-44467 |
| Technique | ID | Description |
|---|---|---|
| Account Discovery: Local Account | T1087.001 | Chatbot asked whether a name exists as a username |
| Unsecured Credentials: Credentials In Files | T1552.001 | Plaintext credentials file served by the file-reading bot |
| Valid Accounts: Local Accounts | T1078.003 | Interactive login with the leaked password |
| Remote Services: SSH | T1021.004 | SSH session as noel |
| Exploitation for Privilege Escalation | T1068 | LangChain code-execution flaw in a sudo-able script |
| Command and Scripting Interpreter: Python | T1059.006 | Injected Python via __import__ |
An AI assistant with file access inherits every file’s secrecy. The file-reading bot returned a plaintext credentials file to an unauthenticated user. Restrict such tools to an allow-listed directory, and keep secrets out of anything the web app’s account can read.
Plaintext credentials on a server are a one-question compromise. A single prompt turned a stray text file into a working SSH login. Remove credential files and alert on SSH logins that follow a burst of chatbot requests.
Sudo on a script that runs model output is sudo on a Python shell. ai-bot.py ran with root rights while executing code generated from user input through an unpatched LangChain chain. Patch the library, and never grant sudo on tools that evaluate generated code.
Log the chatbot requests. The social-engineering half of the intrusion existed only in HTTP traffic. Retain chatbot prompts and responses so abuse like this is searchable, and timestamp them on the same clock as host logs.
The attacker never exploited the chatbots themselves. They simply asked one for a file it should not have served, then used the login to reach a root-capable AI script with a known flaw. The access control gap sat around the AI tools, not inside them.