The lab
here is how portswigger describes it
This lab is vulnerable to server-side template injection due to the unsafe construction of an ERB template.
To solve the lab, review the ERB documentation to find out how to execute arbitrary code, then delete the morale.txt file from Carlos's home directory.
server side template injection, usually shortened to ssti. it is about what happens when user input is dropped into a server side template engine and then evaluated, and this first lab is the plain version of it, using ruby's erb templating.
What server side template injection is?#
a lot of sites build their pages from templates, skeleton pages with little placeholders that get filled in with real values before the page is sent. the template engine is the thing that reads the template, works out those placeholders, and produces the final html. erb is ruby's version of this.
the vulnerability appears when an application takes something the user controls and pastes it straight into the template text, rather than passing it in as a value for the engine to insert safely. the difference is subtle but total. if our input becomes part of the template itself, then the engine does not treat it as data, it treats it as template code and evaluates it. and template code in erb can run ruby, which can run operating system commands, so this quickly becomes full code execution on the server.
Step 1 - Find where input reaches#

on the home page the products do not reveal much, but clicking one, for example hitch a lift, shows the message that it is out of stock, and the url carries that text in a message parameter.
/?message=Unfortunately this product is out of stock
so whatever we put in message is placed onto the page. the question is whether it is placed as plain text or built into the template, and there is a simple probe for that.
Step 2 - Probe with a math expression#
in erb the syntax <%= someExpression %> means evaluate this expression and render the result on the page. so we try a tiny, distinctive calculation.
<%= 7*7 %>
the reason for 7*7 is that it is a harmless test with an unmistakable answer. if the page comes back showing the literal text 7*7, our input was treated as plain data and there is no injection. but if it comes back showing 49, then the engine evaluated our expression, which means our input is being built into the template and run as code. we choose multiplication because 49 is a value that would never appear there by chance, so it is a clear yes or no signal.
we url encode the payload and put it in the message parameter.
/?message=<%25%3d+7*7+%25>
the encoding just protects the special characters in transit, %25 is a percent sign which gives us %, %3d is =, and + is a space, so the server decodes it back to <%= 7*7 %>.

the page shows 49, so the expression was evaluated. that confirms a server side template injection.
Step 3 - Execute a command to delete the file#
now that we can run ruby, we use it to run an operating system command. erb expressions can call ruby's system method, which executes a shell command.
<%= system("rm /home/carlos/morale.txt") %>
reading it, <%= ... %> evaluates the expression inside and renders its result, and system("rm /home/carlos/morale.txt") tells ruby to run the shell command rm /home/carlos/morale.txt, which deletes the target file from carlos's home directory. we url encode this the same way and send it in the message parameter.

the page renders true, which is what ruby's system returns when the command runs successfully, so the file was deleted.

with this, we solved the lab!
