LogCraft

LogCraft's health report generator accepts a custom title and shells out to produce the output. Double quotes are stripped — but that's not enough.

Room Description

LogCraft — figure 1

https://dashboard.webverselabs-pro.com/challenges/logcraft

Scenario

LogCraft is a log aggregation SaaS for engineering teams. One of its paid features is the Health Report generator, which produces a formatted summary of log volume, error rates, and active sources. The report is named with a custom title supplied by the user. The developer knew double quotes were dangerous inside a shell command, so they stripped them before passing the title in. The command wraps the title in double quotes — and inside double-quoted strings, backtick substitution still executes.

Objective

LogCraft's health report generator accepts a custom title and shells out to produce the output. Double quotes are stripped — but that's not the only way to inject a subshell.

Initial Analysis

LogCraft — figure 2

There is nothing hidden in a comment or anything.

We can register a new account, we don't send anything sensitive through the body.

LogCraft — figure 3

From the nav-bar we can see the following endpoints:

      <div class="tabs">
        <a href="/"           class="tab active">Streams</a>
        <a href="/search"     class="tab ">Search</a>
        <a href="/dashboards" class="tab ">Dashboards</a>
        <a href="/reports"    class="tab ">Reports</a>
        <a href="/alerts"     class="tab ">Alerts</a>
        <a href="/team"       class="tab ">Team</a>
      </div>

There are logs being generated constantly, so maybe some sort of log manipulation is in play?

LogCraft — figure 4

We see endpoints being exposed, as well as database queries.

LogCraft — figure 5

Finding the bug

There's a search parameter with suggestions on how to narrow results, we know a database is being used in the background, so we can throw a ' character out to see if an error pops out.

LogCraft — figure 6

We can filter by the different values:

LogCraft — figure 7

/dashboards

This is a well formatted dashboard that mentions the amount of events that have happened.

LogCraft — figure 8

/alerts

This is just a static list of the rules being implemented on the web app for the events.

LogCraft — figure 9

Here we can add new rules or pause old ones.

POST /alerts/new HTTP/2
Host: 7abb7e4c-3970-logcraft-4fc57.challenges.webverselabs-pro.com
Cookie: rack.session=DUoaJ38zTXT0ScR9kkNFpz8EKxj4IIWSg%2BkvPtyeRl08VyEpRjmKalCdc3SWxviluJV55XPsmoR8yVzcs0pk4UuUKiKoxvTQD%2B%2BzsVhwYTW%2BgNKr4VvtUD7Ce9y0ikHsJnryviORoGSFIB8LBSOP2UmToojdx4ljvYY%2BaFCCg30ap%2BvuT4grVZQKYr7wfcGSqVCWbzpvJdLQxoo5nIDnEJ3hmU%2BcUyqaJwIVi%2B2Kcbk4tJ23QhoihkPjpB%2FKjn8rF2p4gG2q2KVZmRWwqfDwYd%2B9RhDn4S5QZxN5l22YPfcYHDO%2BLC7btmsG1F162xt6UXczoH6Qr2JCtHG6%2FM2lv7NrIrFCdukiAB9xyayCsQ2nWXRcHVWLewZeq2IHZCtrImPQ9hWlHgQnqbdozj41EkSbnnHICInC0Ga8GKBF7LWutJbKd%2BkX5IVU3IMyEJawP0Jb5C6qd4ogwykd6w%3D%3D--4OAMs1i47dz6loGv--VBwOFEhwkTbqxL3h35YLYQ%3D%3D
Content-Length: 24
Cache-Control: max-age=0
Sec-Ch-Ua: "Google Chrome";v="147", "Not.A/Brand";v="8", "Chromium";v="147"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Origin: https://7abb7e4c-3970-logcraft-4fc57.challenges.webverselabs-pro.com
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://7abb7e4c-3970-logcraft-4fc57.challenges.webverselabs-pro.com/alerts
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=0, i

name=test&condition=test

But nothing much of value.

/team

There is a list of teammates so we have usernames, e-mails, roles and we can also add new team members.

LogCraft — figure 10

/reports

Here we have an option to create a report from a log source, add in a date range and construct a title for the report.

LogCraft — figure 11

We can add in our own reports.

LogCraft — figure 12

The POST request looks like the following:

POST /reports/generate HTTP/2
Host: 7abb7e4c-3970-logcraft-4fc57.challenges.webverselabs-pro.com
Cookie: rack.session=544Az4UEi1SNrFDQL0WmhPfJ1ZgmyWFGXX7uqwQE23PredTOD69KMt2JeMA0YFGCMDuQbibcpzwsrAOa0nj2Wwf7ZD1OGA5oKKJdOsOrUw99JSrprRV%2BMq9hEkVm9YUzisQT1xd2DvzsxQEI0l6hOhkx10RF7O4miVI3avhl3MH2BvOUAYGGfWxTN8FjmPjekx2kJty0omr0OBFdbfJ0R2Rh1eYwts9%2FkV5BBxkEdx9MclvHkgSZYaIq%2FTgYHcaH9mYxQIl5SvYTjGRaJh1MixCwqk9VQfeatEQ4PY65g53wn0nEannl7HLiUo4VGvVzSO4LohN1HQo30CIGmqYecAXzERbu8F61%2F%2FrfSp3KOajYsQOKu3YjJf%2BRnOaFl5T2l9pSbsvyEmbhxIdaR8D1mjjc1CdC4TxsqIzE31D%2B4XpQBwXiWTCgknrPJjJkneHfTdXOXHv3q71XROlFdw%3D%3D--hoq3ZBWHXfOlURc8--D0eeFLPBfCIwub2TypVu9Q%3D%3D
Content-Length: 49
Cache-Control: max-age=0
Sec-Ch-Ua: "Google Chrome";v="147", "Not.A/Brand";v="8", "Chromium";v="147"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Origin: https://7abb7e4c-3970-logcraft-4fc57.challenges.webverselabs-pro.com
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://7abb7e4c-3970-logcraft-4fc57.challenges.webverselabs-pro.com/reports
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=0, i

source=api-gateway&range=Last+24+hours&title=test

Exploitation

Alrighty, so we have our instructions from the description, we know how our Report Title field is being processed by the application.

We can try some payloads that would lead us to the hint, like things we would use in our everyday terminal syntax like:

&&
|
;
LogCraft — figure 13
LogCraft — figure 14
LogCraft — figure 15

Now we should try and see how our input is being executed, like adding quotes left and right.

LogCraft — figure 16

Maybe adding backticks or anything to see if we can add in commands if our input is among quotes to escape them?

`id`
LogCraft — figure 17

And whoop whoop, we have our command execution.

Now we have to locate the flag.

Let's list the files in the current working directory.

LogCraft — figure 18

We can extract the entire app from app.rb, but I can tell you the flag isn't located there.

What is valuable from the code for the web application is the snippet that causes the vulnerability:

# Strip double quotes — considered dangerous by the developer
  safe_title = title.tr('"', '')

  # Generate report header — backtick expansion executes inside double-quoted strings
  report_output = `echo "Health Report: #{safe_title}"`

Even if double quotes are removed, there are ways to execute commands in Bash.

  • $() -> still executes
  • `...` -> still executes

If we input `cat /proc/self/environ' then the command getting executed is:

echo "Health Report: `cat /proc/self/environ`"

Our command gets executed first, and then the echo command goes through.

The flag can easily be found by looking up /proc/self/environ .

LogCraft — figure 19

Another way to find is by using the find command, or by browsing through the directories.

`find / -name flag.txt 2>/dev/null`
LogCraft — figure 20

Let's list the root directory to see what's there.

LogCraft — figure 21

Now we know everything about the flag.