---
# System prepended metadata

title: OWASP TOP 10 DAY 3

---

---
title: OWASP TOP 10 Day 3
tags: OWASP TOP 10
slideOptions:
  transition: fade
  center: true
  parallaxBackgroundImage: 'https://hackmd.io/_uploads/SJhktzri2.png'
---

# OWASP TOP 10 DAY 3


# A03: 2021 - A01: 2017 Injection 

## OS injection

### Что такое инъекции команд?

Инъекция команд ОС (также известная как shell инъекция) является уязвимостью веб-приложений, которая позволяет злоумышленнику выполнять произвольные команды операционной системы (ОС) на сервере, на котором запущено приложение, и, как правило, дает возможность полностью скомпрометировать приложение и все его данные. Очень часто злоумышленник может использовать уязвимость внедрения команд ОС для компрометации других частей инфраструктуры, используя доверительные отношения для перенаправления атаки на другие системы в организации.



### Как возникают инъекции команд?

Пример уязвимости инъекции команд:

```
$command = 'convert -pointsize 72 label:Hello  ' . $_FILES['userfile']['name'];
system($command);
```

Пример эксплуатации для уязвимости выше:

```
------WebKitFormBoundaryePkpFF7tjBAqx29L
Content-Disposition: form-data; name="userfile"; filename="check | ls -la;"
Content-Type: application/x-object

... contents of file goes here ...
```


### Code examples


[VulnPlanet - a03 injection code example](https://github.com/yevh/VulnPlanet/blob/main/web2/owasp/A03-Injection.md)
[VulnPlanet - command injection](https://github.com/yevh/VulnPlanet/blob/main/web2/type/Command_Injection.md)


#### PHP  CVE-2019-16663
[Two unpatched RCE flaws in rConfig software expose servers to hack](https://securityaffairs.com/93391/hacking/rconfig-rce-flaws.html)
```php!
<?php
$rootUname = $_GET['rootUname'];
$array = array();
/* check PHP Safe_Mode is off */
if (ini_get('safe_mode')) {
    $array['phpSafeMode'] = '<strong><font class="bad">Fail - php safe mode is on - turn it off before you proceed with the installation</strong></font>br/>';
} else {
    $array['phpSafeMode'] = '<strong><font class="Good">Pass - php safe mode is off</strong></font><br/>';
}
/* Test root account details */
$rootTestCmd1 = 'sudo -S -u ' . $rootUname . ' chmod 0777 /home 2>&1';
exec($rootTestCmd1, $cmdOutput, $err);
$homeDirPerms = substr(sprintf('%o', fileperms('/home')), -4);
if ($homeDirPerms == '0777') {
    $array['rootDetails'] = '<strong><font class="Good">Pass - root account details are good </strong></font><br/>';
} else {
    $array['rootDetails'] = '<strong><font class="bad">The root details provided have not passed: ' . $cmdOutput[0] . '</strong></font><br/>';
}
// reset /home dir permissions
$rootTestCmd2 = 'sudo -S -u ' . $rootUname . ' chmod 0755 /home 2>&1';
exec($rootTestCmd2, $cmdOutput, $err);
echo json_encode($array);
```

#### C#

```c#

using Microsoft.AspNetCore.Mvc;
using System;
using System.Diagnostics;

namespace WebFox.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class OsInjection : ControllerBase
    {
        [HttpGet("{binFile}")]
        public string os(string binFile)
        {
            Process p = new Process();
            p.StartInfo.FileName = binFile; // Noncompliant
            p.StartInfo.RedirectStandardOutput = true;
            p.Start();
            string output = p.StandardOutput.ReadToEnd();
            p.Dispose();
            return output;
        }
    }
}
```

#### nodeJS

```javascript!
const express = require('express');
const router = express.Router()

const { exec, spawn }  = require('child_process');


router.post('/ping', (req,res) => {
    exec(`${req.body.url}`, (error) => {
        if (error) {
            return res.send('error');
        }
        res.send('pong')
    })
    
})

router.post('/gzip', (req,res) => {
    exec(
        'gzip ' + req.query.file_path,
        function (err, data) {
          console.log('err: ', err)
          console.log('data: ', data);
          res.send('done');
    });
})

router.get('/run', (req,res) => {
   let cmd = req.params.cmd;
   runMe(cmd,res)
});

function runMe(cmd,res){
//    return spawn(cmd);

    const cmdRunning = spawn(cmd, []);
    cmdRunning.on('close', (code) => {
        res.send(`child process exited with code ${code}`);
    });
}

module.exports = router

# curl -X POST -H "Content-Type: application/json" -d '{"url": "touch /tmp/test"}' http://server/ping
# curl -X POST 'http://server/gzip?file_path=touch%20/tmp/test'
# curl -X GET 'http://server/run?cmd=touch%20/tmp/test'
```

#### Java

```java!
import testcasesupport.*;

import javax.servlet.http.*;


public class CWE78_OS_Command_Injection__getParameter_Servlet_10 extends AbstractTestCaseServlet
{
    /* uses badsource and badsink */
    public void bad(HttpServletRequest request, HttpServletResponse response) throws Throwable
    {
        String data;
        if (IO.staticTrue)
        {
            /* POTENTIAL FLAW: Read data from a querystring using getParameter */
            data = request.getParameter("name");
        }
        else
        {
            /* INCIDENTAL: CWE 561 Dead Code, the code below will never run
             * but ensure data is inititialized before the Sink to avoid compiler errors */
            data = null;
        }

        String osCommand;
        if(System.getProperty("os.name").toLowerCase().indexOf("win") >= 0)
        {
            /* running on Windows */
            osCommand = "c:\\WINDOWS\\SYSTEM32\\cmd.exe /c dir ";
        }
        else
        {
            /* running on non-Windows */
            osCommand = "/bin/ls ";
        }

        /* POTENTIAL FLAW: command injection */
        Process process = Runtime.getRuntime().exec(osCommand + data);
        process.waitFor();

    }

    /* goodG2B1() - use goodsource and badsink by changing IO.staticTrue to IO.staticFalse */
    private void goodG2B1(HttpServletRequest request, HttpServletResponse response) throws Throwable
    {
        String data;
        if (IO.staticFalse)
        {
            /* INCIDENTAL: CWE 561 Dead Code, the code below will never run
             * but ensure data is inititialized before the Sink to avoid compiler errors */
            data = null;
        }
        else
        {

            /* FIX: Use a hardcoded string */
            data = "foo";

        }

        String osCommand;
        if(System.getProperty("os.name").toLowerCase().indexOf("win") >= 0)
        {
            /* running on Windows */
            osCommand = "c:\\WINDOWS\\SYSTEM32\\cmd.exe /c dir ";
        }
        else
        {
            /* running on non-Windows */
            osCommand = "/bin/ls ";
        }

        /* POTENTIAL FLAW: command injection */
        Process process = Runtime.getRuntime().exec(osCommand + data);
        process.waitFor();

    }

    /* goodG2B2() - use goodsource and badsink by reversing statements in if */
    private void goodG2B2(HttpServletRequest request, HttpServletResponse response) throws Throwable
    {
        String data;
        if (IO.staticTrue)
        {
            /* FIX: Use a hardcoded string */
            data = "foo";
        }
        else
        {
            /* INCIDENTAL: CWE 561 Dead Code, the code below will never run
             * but ensure data is inititialized before the Sink to avoid compiler errors */
            data = null;
        }

        String osCommand;
        if(System.getProperty("os.name").toLowerCase().indexOf("win") >= 0)
        {
            /* running on Windows */
            osCommand = "c:\\WINDOWS\\SYSTEM32\\cmd.exe /c dir ";
        }
        else
        {
            /* running on non-Windows */
            osCommand = "/bin/ls ";
        }

        /* POTENTIAL FLAW: command injection */
        Process process = Runtime.getRuntime().exec(osCommand + data);
        process.waitFor();

    }

    public void good(HttpServletRequest request, HttpServletResponse response) throws Throwable
    {
        goodG2B1(request, response);
        goodG2B2(request, response);
    }

    /* Below is the main(). It is only used when building this testcase on
     * its own for testing or for building a binary to use in testing binary
     * analysis tools. It is not used when compiling all the testcases as one
     * application, which is how source code analysis tools are tested.
     */
    public static void main(String[] args) throws ClassNotFoundException,
           InstantiationException, IllegalAccessException
    {
        mainFromParent(args);
    }
}
```


[Code Security Advent Calendar 2022 | Can you Spot the Vulnerability? | Sonar](https://www.sonarsource.com/knowledge/code-challenges/advent-calendar-2022/) - day 10 - java
[Real attack - PHP Supply Chain Attack on Composer](https://www.sonarsource.com/blog/php-supply-chain-attack-on-composer/)

```java!
@WebServlet(name = "MercurialImporterServlet", urlPatterns = {"/check"})

public class MercurialImporterServlet extends HttpServlet {
    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse res) throws IOException {
        res.setContentType("text/plain");
        var out = res.getOutputStream();
        if (req.getParameter("repository") == null 
            || req.getParameter("repository").indexOf("$(") != -1 
            || req.getParameter("repository").indexOf("`") != -1) {
            res.setStatus(405);
            return;
        }
        var cmd = new String[] {
            "hg",
            "identify",
            req.getParameter("repository")
        };
        var p = Runtime.getRuntime().exec(cmd);
        var br = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String l;

        while ((l = br.readLine()) != null) {
            out.write(l.getBytes("ascii"));
        }
        br.close();
    }
}
```

`repository=--config=alias.identify=!id`


### Мета - символы

| Injection Operator | Injection Character | URL-Encoded Character | Executed Command |
|-|-|-|-|
|Semicolon| ;|%3b|Both|
|New Line| \n|%0a|Both|
|Background| &|%26|Both (second output generally shown first)|
|Pipe| \||%7c|Both (only second output is shown)|
|AND| &&|%26%26|Both (only if first succeeds)|
|OR| \|\||%7c%7c|Second (only if first fails)|
|Sub-Shell|  `` |%60%60|Both (Linux-only)|
|Sub-Shell| $()|%24%28%29|Both (Linux-only)|

### Как предотвратить инъекции команд?

На сегодняшний день наиболее эффективным способом предотвращения уязвимостей инъекции команд ОС является никогда не вызывать команды ОС из кода прикладного уровня. Практически в каждом случае существуют альтернативные способы реализации требуемой функциональности с использованием более безопасных платформенных API.

1. **Избегать прямого выполнения команд ОС**. Для огромного количества различных функций реализованы библиотеки.
2. Использовать функции языка для **вызова других программ без обращения к оболочке ОС** (proc_open в PHP)
3. **Не передавать пользовательский ввод** в командную оболочку.
4. В крайнем случае **используйте специальные функции для экранирования** (escapeshellargs в PHP)
5. [https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview](https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview) (для .Net)

Если считается неизбежным вызывать команды ОС с пользовательским вводом, то должна быть выполнена серьезная проверка вводимых данных:

1. Соответствие типу данных
2. Корректность формата
3. Регулярные выражения
4. Разрешенный набор символов

Валидация Laravel
```php!
public function createUser(Request $request)
{
	$this->validate($request, [
		'login' => 'required|max:255', (required - обязятельные данные)
		'age' => 'required|integer', (integer целое число )
		'email' => 'required|email',
		'body' => 'required',
	]);
	...
}

```


[Security Code Review 101](https://owasp.org/SecureCodingDojo/codereview101/ "title")


### Еще примеры

https://hackerone.com/reports/212696
https://hackerone.com/reports/1360208
https://hackerone.com/reports/389561
https://hackerone.com/reports/303061
https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41293
https://www.wallarm.com/what/command-injection-definition

### Упражнения
- BWAPP OS Command injection  
- BWAPP OS Command injection (Blind)
- [https://portswigger.net/web-security/os-command-injection/lab-simple](https://portswigger.net/web-security/os-command-injection/lab-simple)


### Отстуки

https://requestinspector.com/

## Code injection

Контролируемые атакующим данные подставляются в программный код, после чего он исполняется веб-приложением.


### Упражнения
- bWAPP: PHP Code Injection  
- root-me PHP Command Injection  


## SQL Injection (Инъекции управляющих конструкций SQL)

**SQL** - Structured Query Language Структурированный язык запросов
https://sqliteonline.com/


### Что такое SQL инъекция?

SQL-инъекция - Уязвимость, при которой контролируемые атакующим данные внедряются в формируемый SQL-запрос. В результате внедрения атакующий может нарушить логику работы запроса и/или заставить СУБД выполнить полезные для атакующего действия.

```php
$query  = "SELECT username, email, phone FROM users
           WHERE username = '" . $_REQUEST['username'] . "'";
$result = mysql_query($conn, $query);
```



### Какой ущерб несут уязвимости к инъекции SQL?

Успешная атака SQL-инъекции может привести к несанкционированному доступу к конфиденциальным данным, таким как пароли, данные кредитной карты или личная информация пользователя. Многие громкие утечки данных в последние годы стали результатом атак SQL-инъекции, что привело к репутационному ущербу и штрафам со стороны регулирующих органов. В некоторых случаях злоумышленник может получить постоянный черный ход в системы организации, что приводит к долгосрочному закреплению злоумышленника в инфраструктуре, которое может оставаться незамеченным длительный период времени.

В частности, уязвимости SQL-инъекций могут приводить к:

- Чтение информации из доступных баз данных
- Получение информации о сервере, текущем пользователе, настройках
- Получение информации из файловой системы
- Возможность модификации информации в базе данных
- Возможность записи в файлы
- Возможность выполнения произвольного кода


### Примеры SQL инъекций

**Сценарий №1** Приложение использует недоверенные данные при создании следующего уязвимого SQL-вызова:

```php!
String query = "SELECT * FROM accounts WHERE custID='" + request.getParameter("id") + "'";
```

**Сценарий №2** Безоговорочное доверие приложений к фреймворкам может привести к появлению уязвимых запросов (например, в языке запросов HQL):

```php!
Query HQLQuery = session.createQuery("FROM accounts WHERE custID='" + request.getParameter("id") + "'");
```

В обоих случаях злоумышленник изменяет в своем браузере значение параметра “id” для отправки `' or '1'='1`.

Например:  
`http://example.com/app/accountView?id='+or+'1'='1`

Изменение обоих запросов позволяет получить все записи из таблицы учетных данных. Более серьезные атаки позволяют изменить или удалить.

**Сценарий №3** Использование фреймворков, кажущееся безопасным, может быть обманчивым (Пример использования фреймворка Ruby On Rails и Active Records):

```
User.order("#{params[:sortby]} ASC")
```

Кажущийся безопасным вызов `.order()` на самом деле не экранирует управляющих конструкций получаемых от приложения, что приводит к возможности проведения атак на базу данных, через такой вектор как:

```
(CASE SUBSTR(password, 1, 1) WHEN 's' THEN 0 else 1 END)
```

[SQL Injection ruby on rails](https://www.stackhawk.com/blog/sql-injection-prevention-rails/)


### О техниках атак

Существует широкий спектр уязвимостей, атак и методов SQL инъекции, которые возникают в различных ситуациях. К числу наиболее распространенных примеров SQL-инъекций относятся:

- Stacked queries
- Union-based
- Error-based
- Boolean blind
- Time-base
- Out of band

![](https://www.researchgate.net/publication/292997018/figure/fig1/AS:694192334450690@1542519758561/SQL-Injection-Categories-and-Types-proached-through-various-techniques-which-are-broadly.jpg)


### Как найти SQL 

- Ввод символа одиночной кавычки ' и поиск ошибок или других аномалий.
- Ввод некоторого синтаксиса, специфичного для SQL и поиск систематических различий в результирующих ответах приложения.
- Ввод булевых условий, таких как OR 1=1 и OR 1=2, и поиск различий в ответах приложения.
- Отправка полезных нагрузок (прим. Временная задержка)




##### Union-based
Классический вариант внедрения SQL-кода, когда в уязвимый параметр (или несколько параметров) передаётся выражение (фактически новый запрос), начинающееся с "UNION SELECT" или "UNION ALL SELECT". Этот способ работает тогда, когда веб-приложения напрямую возвращают результат вывода команды SELECT на страницу. Важно определить количество столбцов 


##### Error-based

Внедрение в уязвимый параметр синтаксически неправильного выражения, после чего веб-сайт раскрывает ошибки DBMS (обычно это делается в целях отладки).
![](https://miro.medium.com/v2/resize:fit:4800/format:webp/1*C02Rfg_EwWHfio7VnJtcFQ.png)


##### Boolean blind
"Слепая" инъекции: данные из базы данных в чистом виде никогда не возвращаются. Пользователь может предоставить строку или регулярное выражение для определения "true"-страниц (отсюда и название атаки), и используя бинарный поиск выявлять за 7 запросов любой ASCII символ


##### Time-base
Полностью слепая инъекция, но в отличии от предыдущей - true/false можно определить по времени ответа сервера

##### Out of band

Слепая с выводом на подконтрольный злоумышленнику сервер


##### Stacked Quieries
Иногда бывает можно в одном запросе от приложения к базе данных передать несколько SQL-запросов через `;`. В этом случае SQL injection позволяет сделать уже вообще любой SQL-запрос. Доступность stacked queries зависит от БД и используемого драйвера, к примеру c базами sqlite3 и MySQL обычно нельзя, с базой PostgreSQL и стандартным питоновским драйвером psycopg2 - можно. 





### Как предотвращать SQL инъекции?

Большинство случаев SQL-инъекции можно предотвратить, используя параметризованные запросы (также известные как “prepared statements”) вместо конкатенации строк внутри запроса.

Также, от SQL-инъекций спасает концепция ORM (Object-Relational Mapping), но не следует ей слепо доверять.


[Security Code Review 101](https://owasp.org/SecureCodingDojo/codereview101/ "title")


### Дополнительные материалы

- [PayloadsAllTheThings - SQL injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
- [PayloadsAllTheThings - NoSQL injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection)
- [OWASP NoSQL injection slides](https://owasp.org/www-pdf-archive/GOD16-NOSQL.pdf)
- [PortSwigger - SQL injection cheat sheet](https://portswigger.net/web-security/sql-injection/cheat-sheet)
- [SQLMap - Инструмент автоматизации](https://xakep.ru/2011/12/06/57950/)
- [https://en.wikipedia.org/wiki/List_of_object–relational_mapping_software](https://en.wikipedia.org/wiki/List_of_object%E2%80%93relational_mapping_software)



### Примеры из Тинькофф Банка

- [https://jira.tcsbank.ru/browse/IBUL-5866](https://jira.tcsbank.ru/browse/IBUL-5866)
- [https://jira.tcsbank.ru/browse/INFDEV-3156](https://jira.tcsbank.ru/browse/INFDEV-3156)
- [https://jira.tcsbank.ru/browse/IBUL-6509](https://jira.tcsbank.ru/browse/IBUL-6509)
- [https://jira.tcsbank.ru/browse/FOCRM-164](https://jira.tcsbank.ru/browse/FOCRM-164)



### Упражнения


#### Упражнение 1

UNION-based атака SQL инъекции, на извлечение данных из других таблиц - [https://portswigger.net/web-security/sql-injection/union-attacks/lab-retrieve-data-from-other-tables](https://portswigger.net/web-security/sql-injection/union-attacks/lab-retrieve-data-from-other-tables) (Сложность: Низкая)



#### Упражнение 2
https://www.root-me.org/en/Challenges/Web-Server/SQL-injection-String

#### Упражнение 3
https://www.root-me.org/en/Challenges/Web-Server/SQL-injection-File-reading

#### Упражнение 4
https://portswigger.net/web-security/sql-injection/blind/lab-sql-injection-visible-error-based


## Инъекции шаблонов (Server-side template injection)


### Что такое внедрение шаблона на стороне сервера?

Инъекция шаблонов на стороне сервера - это атака, при которой злоумышленник может использовать собственный синтаксис шаблона для введения вредоносной полезной нагрузки в шаблон, который затем выполняется на стороне сервера.

Движки шаблонов предназначены для генерации веб-страниц путем объединения фиксированных шаблонов с изменчивыми данными. Атаки с инъекцией шаблонов на стороне сервера могут происходить, когда вводимые пользователем данные не передаются в виде данных, а непосредственно вставляются в шаблон. Это позволяет злоумышленникам вводить произвольные директивы шаблонов для манипулирования движком шаблонов, часто позволяя им получить полный контроль над сервером.

**Twig example**
https://github.com/marvin/php-twig-example/blob/master/views/index.html
https://github.com/marvin/php-twig-example/blob/master/index.php



### Какой ущерб несут уязвимости к инъекции шаблонов?

Уязвимости инъекции шаблонов на стороне сервера могут подвергать веб-сайты различным атакам в зависимости от движка шаблонов и того, как именно приложение его использует. В некоторых редких случаях эти уязвимости не представляют реального риска для безопасности. Однако, в большинстве случаев, воздействие инъекции шаблона на стороне сервера может быть катастрофическим.

В самом крайнем случае злоумышленник потенциально может добиться удаленного выполнения кода, получив полный контроль над внутренним сервером и используя его для других атак на внутреннюю инфраструктуру.

Даже в тех случаях, когда полное удаленное выполнение кода невозможно, злоумышленник часто все равно может использовать внедрение шаблонов на стороне сервера в качестве основы для множества других атак, потенциально получая доступ на чтение к конфиденциальным данным и произвольным файлам на сервере.


### Как появляются уязвимости инъекции шаблонов?

Рассмотрим несколько примеров кода:

Пример НЕ уязвимый к SSTI:

```
<?php

require_once('lib/Twig/Autoloader.php');
Twig_Autoloader::register();

$loader = new Twig_Loader_Filesystem('views');

$twig = new Twig_Environment($loader, array(
  'cache' => 'cache',
));

echo $twig->render('index.html', array('name' => '', 'title' => 'Startpage'));

?>
```

Пример уязвимый к SSTI:

```
<?php

require_once('lib/Twig/Autoloader.php');
Twig_Autoloader::register();

$twig = new \Twig_Environment(new \Twig_Loader_String());

echo $twig->render("Error message: ".$_GET['error']);

?>
```


### Проведение атаки инъекции шаблонов


#### Сценарий №1 Пример для кода шаблонизатора PHP Twig

Код:

```
echo $twig->render("Error message: ".$_GET['error']);
```

Эксплоит:

```
{{['cat\x20/etc/passwd']|filter('system')}}
```


#### Сценарий №2 Пример для кода шаблонизатора [ASP.NET](http://ASP.NET) Razor

Код:

```
[HttpPost]
[ValidateInput(false)]
public ActionResult Index(string razorTpl)
{
	ViewBag.RenderedTemplate = Razor.Parse(razorTpl);
	ViewBag.Template = razorTpl;
	return View();
}
```

Эксплоит:

```
@{
  // C# code
}
```


#### Сценарий №3 Пример для кода шаблонизатора Java Velocity

Код:

```
// Set up the context data
VelocityContext context = new VelocityContext();
context.put( "name", user.name );

// Load the template
String template = getUserTemplateFromRequestBody(request);
RuntimeServices runtimeServices = RuntimeSingleton.getRuntimeServices();
StringReader reader = new StringReader(template);
SimpleNode node = runtimeServices.parse(reader, "myTemplate");
template = new Template();
template.setRuntimeServices(runtimeServices);
template.setData(node);
template.initDocument();

// Render the template with the context data
StringWriter sw = new StringWriter();
template.merge( context, sw );
```

Эксплоит:

```
$name.getClass().forName("java.lang.Runtime").getRuntime().exec(<COMMAND>)
```


### Как защищаться от инъекции шаблонов?

Лучший способ предотвратить инъекцию шаблонов на стороне сервера - **не позволять никаким пользователям изменять или отправлять новые шаблоны**. Однако иногда это неизбежно из-за требований бизнеса.

Один из простейших способов избежать внедрения уязвимостей инъектирования шаблонов на стороне сервера - **всегда использовать “logic-less” шаблонный движок**, такой как Mustache, если в этом нет абсолютной необходимости. Максимально возможное отделение логики от представления может значительно уменьшить вашу подверженность наиболее опасным атакам на основе шаблонов.

Другой мерой является **выполнение пользовательских шаблонов только в песочнице**, где потенциально опасные модули и функции были полностью удалены. К сожалению, недоверенный код в песочнице по своей природе сложен и склонен к обходу.

Наконец, еще одним дополнительным подходом является признание того, что произвольное выполнение кода практически неизбежно, и **применение собственной “песочницы” путем развертывания среды шаблонов**, например, в изолированном контейнере Docker.


### Дополнительные материалы

- [PayloadsAllTheThings - Templates Injections](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection)
- [TPLMap: инструмент автоматизации](https://github.com/epinna/tplmap)


### Упражнения

#### Упражнение 1


Основы инъеции шаблонов на стороне сервера - [https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-basic](https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-basic) (Сложность: низкая)


#### Упражнение 2

Основы инъекции шаблонов на стороне сервера (контекст кода) - [https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-basic-code-context](https://portswigger.net/web-security/server-side-template-injection/exploiting/lab-server-side-template-injection-basic-code-context) (Сложность: низкая)


