Share
## https://sploitus.com/exploit?id=40E319BF-0986-50B5-BDEF-7FE2757BA74E
# WebSec SQL Injection

Учебный backend-проект по безопасности веб-приложений: небольшое приложение на **Node.js + Express + SQLite**, которое показывает SQL Injection и способы защиты от неё.

Проект содержит два варианта поиска пользователей:

- уязвимый endpoint, где SQL-запрос собирается через конкатенацию строк;
- защищённый endpoint, где используются параметризованные запросы, валидация входных данных и фильтрация ответа.

> Проект является учебным security lab и предназначен для портфолио. Это не production-ready приложение и не инструкция для атаки на реальные системы.

## Что демонстрирует проект

В проекте реализованы:

- REST API на Express;
- SQLite database in memory;
- разделение приложения на `app`, `server`, `routes`, `middleware`, `services`, `data`, `utils`;
- уязвимый поиск пользователей через string concatenation;
- демонстрация SQL Injection через `OR 1=1`;
- демонстрация UNION-based data exposure;
- защищённый поиск через parameterized query;
- allowlist-валидация `username`;
- фильтрация ответа: API не отдаёт поле `password` в защищённом endpoint;
- логирование подозрительных поисковых запросов;
- единый JSON-формат ошибок;
- OpenAPI-спецификация;
- Postman-коллекция;
- автотесты на встроенном `node:test`;
- GitHub Actions CI.

## Стек технологий

- Node.js
- Express
- SQLite
- JavaScript
- Node.js Test Runner
- OpenAPI
- Postman
- GitHub Actions

## Структура проекта

```text
websec-sql-injection-lab/
├── src/
│   ├── app.js
│   ├── server.js
│   ├── data/
│   │   ├── database.js
│   │   └── security-log.js
│   ├── middleware/
│   │   └── errors.js
│   ├── routes/
│   │   ├── search.js
│   │   └── security-events.js
│   ├── services/
│   │   └── users.js
│   └── utils/
│       └── sql-signals.js
├── tests/
│   └── sql-injection.test.js
├── docs/
│   ├── manual-checks.md
│   ├── openapi.yaml
│   ├── security-model.md
│   └── test-plan.md
├── postman/
│   ├── websec-sql-injection-lab.postman_collection.json
│   └── websec-sql-injection-lab.local.postman_environment.json
├── .github/workflows/ci.yml
├── .env.example
├── .editorconfig
├── .gitignore
├── LICENSE
├── package.json
└── README.md
```

## Установка и запуск

### 1. Клонировать репозиторий

```bash
git clone https://github.com/kindarufy/websec-sql-injection-lab.git
cd websec-sql-injection-lab
```

### 2. Установить зависимости

```bash
npm install
```

### 3. Запустить приложение

```bash
npm start
```

По умолчанию API будет доступно по адресу:

```text
http://localhost:3000
```

## Переменные окружения

Пример переменных находится в файле `.env.example`:

```env
PORT=3000
```

Если переменная окружения не задана, приложение использует порт `3000`.

## API endpoints

### Health check

```http
GET /health
```

Пример ответа:

```json
{
  "status": "ok",
  "service": "websec-sql-injection-lab"
}
```

### Уязвимый поиск пользователей

```http
GET /search/vulnerable?username=admin
```

Пример ответа:

```json
{
  "mode": "vulnerable",
  "warning": "This endpoint intentionally uses string concatenation and is vulnerable to SQL injection.",
  "executedSql": "SELECT id, username, email, is_admin AS isAdmin FROM users WHERE username = 'admin'",
  "users": [
    {
      "id": 1,
      "username": "admin",
      "email": "admin@example.com",
      "isAdmin": 1
    }
  ]
}
```

### Защищённый поиск пользователей

```http
GET /search/secure?username=admin
```

Пример ответа:

```json
{
  "mode": "secure",
  "protection": "Parameterized query with input validation.",
  "users": [
    {
      "id": 1,
      "username": "admin",
      "email": "admin@example.com",
      "isAdmin": 1
    }
  ]
}
```

### Журнал security events

```http
GET /security-events
```

Endpoint возвращает последние поисковые события, включая подозрительные и заблокированные запросы.

## Демонстрация SQL Injection

### Нормальный запрос

```bash
curl "http://localhost:3000/search/vulnerable?username=admin"
```

Ожидаемый результат: возвращается только пользователь `admin`.

### SQL Injection через OR 1=1

```bash
curl "http://localhost:3000/search/vulnerable?username=' OR 1=1 --"
```

Ожидаемый результат: уязвимый endpoint возвращает всех пользователей.

### UNION-based data exposure

```bash
curl "http://localhost:3000/search/vulnerable?username=' UNION SELECT id, username, password, is_admin FROM users --"
```

Ожидаемый результат: через уязвимый endpoint можно получить значения из колонки `password`.

## Защита

Защищённый endpoint использует два основных механизма:

| Проблема | Как исправлено |
|---|---|
| Конкатенация пользовательского ввода в SQL | Используется параметризованный запрос `WHERE username = ?` |
| SQL-like payload в query parameter | Добавлена allowlist-валидация `username` |
| Риск утечки чувствительных колонок | В ответ выбираются только публичные поля |
| Невидимость подозрительных запросов | Добавлено in-memory логирование security events |

Пример безопасного запроса:

```js
database.all(
  'SELECT id, username, email, is_admin AS isAdmin FROM users WHERE username = ?',
  [username]
);
```

Попытка повторить атаку на защищённый endpoint:

```bash
curl "http://localhost:3000/search/secure?username=' OR 1=1 --"
```

Пример ответа:

```json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid username query parameter.",
    "details": [
      "username may contain only latin letters, numbers and underscore."
    ]
  }
}
```

Подробнее: [`docs/security-model.md`](docs/security-model.md)

## Ручная проверка

Все команды для ручной проверки находятся в файле:

```text
docs/manual-checks.md
```

## Автотесты

Запуск тестов:

```bash
npm test
```

Проверка синтаксиса основных файлов:

```bash
npm run check
```

В тестах проверяется:

- доступность `/health`;
- нормальный поиск в уязвимом endpoint;
- успешная SQL Injection через `OR 1=1` в уязвимом endpoint;
- успешная UNION-based data exposure в уязвимом endpoint;
- нормальный поиск в защищённом endpoint;
- отсутствие поля `password` в защищённом ответе;
- блокировка SQL Injection payload в защищённом endpoint;
- блокировка UNION payload в защищённом endpoint;
- логирование подозрительных запросов.

## OpenAPI

Спецификация API находится в файле:

```text
docs/openapi.yaml
```

Её можно открыть в Swagger Editor или использовать как документацию к API.

## Postman

Postman-коллекция и environment находятся в папке:

```text
postman/
```

Импортировать в Postman:

- `websec-sql-injection-lab.postman_collection.json`
- `websec-sql-injection-lab.local.postman_environment.json`

## CI

В проекте настроен GitHub Actions workflow:

```text
.github/workflows/ci.yml
```

CI устанавливает зависимости, проверяет синтаксис и запускает автотесты.

## Статус проекта

Проект выполнен как учебная работа по безопасности веб-приложений и оформлен как портфолио-проект. Он показывает понимание SQL Injection, параметризованных запросов, валидации входных данных и безопасной фильтрации ответов API.