---
title: 'Разширени атаки чрез качване на файлове: методи за заобикаляне и защита'
description: 'Подробно ръководство за разработчици относно уязвимости при качване на файлове, включително MIME заобикаляне, полиглоти, Zip Slip, SVG XSS, PDF SSRF и сигурна имплементация в Laravel.'
faq:
    - { question: 'Защо клиентската проверка на MIME-type е несигурна?', answer: "Проверките на MIME-type от страна на клиента и HTTP заглавката Content-Type се контролират изцяло от клиента. Атакуващите могат да прихванат заявката с прокси (като Burp Suite) и да променят заглавката (например от 'application/x-php' на 'image/png'), за да заобиколят простите бекенд филтри." }
    - { question: 'Какво представлява файл-полиглот и как изпълнява код?', answer: 'Файлът-полиглот е валиден в няколко формата едновременно (например валидно изображение и работещ PHP скрипт). Кодът се вгражда в метаданните или коментарите на изображението. Ако сървърът го запише в уеб директорията с разширение .php, кодът ще се изпълни.' }
    - { question: 'Как да предотвратя XSS атаки от качени SVG файлове?', answer: "SVG файловете са XML документи и могат да съдържат вграден JavaScript. За да се предотврати XSS, трябва да почистите SVG файла (премахвайки скриптове и събития), да го конвертирате в растерен формат (като PNG/JPEG) при качването или да го доставяте със заглавка 'Content-Disposition: attachment'." }
published: '2026-07-09'
---
# Разширени атаки чрез качване на файлове: методи за заобикаляне и защита

Функционалността за качване на файлове е стандартна характеристика в съвременните уеб приложения. Тя обаче е и един от най-критичните вектори за атака. Ако не бъде защитена правилно, тя може да доведе до отдалечено изпълнение на код (RCE), разкриване на локални файлове (LFD), фалшифициране на заявки от страна на сървъра (SSRF) и междусайтов скриптинг (XSS).

Това ръководство разглежда съвременните техники за заобикаляне на проверките при качване на файлове и обяснява как да се внедрят надеждни методи за защита на ниво бекенд в PHP и Laravel.

---

## 1. Заобикаляне на проверка за MIME-тип (MIME-Type Check Bypass)

### Уязвимостта
Уеб приложенията често проверяват заглавката `Content-Type`, изпратена от браузъра на клиента, за да определят дали даден файл е безопасен. Например, ако качите изображение, браузърът автоматично изпраща:

```http
Content-Type: image/png
```

Ако бекендът на приложението валидира само тази заглавка, се създава сериозна уязвимост в сигурността.

### Атаката
Атакуващият прихваща заявката за качване с прокси инструмент като Burp Suite. Той качва зловреден PHP уеб шел (`shell.php`), но модифицира заглавката `Content-Type`:

```http
POST /upload HTTP/1.1
Host: vulnerable-app.com
Content-Disposition: form-data; name="file"; filename="shell.php"
Content-Type: image/png

<?php system($_GET['cmd']); ?>
```

Тъй като бекендът чете модифицираната заглавка и смята, че файлът е безопасно PNG изображение, той разрешава качването. След като бъде записан в достъпна през уеб директория, атакуващият достъпва `http://vulnerable-app.com/uploads/shell.php?cmd=id`, за да изпълнява команди в операционната система.

---

## 2. Манипулиране на Magic Bytes и файлови сигнатури

### Уязвимостта
За да се справят с обикновеното заобикаляне на MIME-типовете, разработчиците често внедряват анализ на сигнатурата на файла. Всеки файлов формат има уникален набор от начални байтове, известни като \"вълшебни байтове\" (magic bytes). Например:
- **GIF**: `GIF89a` (`47 49 46 38 39 61`)
- **PNG**: `\x89PNG\r\n\x1a\n` (`89 50 4E 47 0D 0A 1A 0A`)
- **JPEG**: `\xFF\xD8\xFF` (`FF D8 FF`)

Ако сървърът проверява само тези начални байтове в началото на файла, той остава уязвим.

### Атаката
Атакуващият добавя валидната сигнатура на файла в началото на своя зловреден код. Например създава текстов файл, който започва с `GIF89a;`, последван от PHP код:

```http
POST /upload HTTP/1.1
Host: vulnerable-app.com
Content-Disposition: form-data; name="file"; filename="shell.gif.php"
Content-Type: image/gif

GIF89a;
<?php system($_GET['cmd']); ?>
```

Когато бекендът прочете първите няколко байта, той открива сигнатурата `GIF89a` и валидира файла като изображение. Ако файлът се запази с разширение `.php`, уеб сървърът ще изпълни зловредния код.

---

## 3. EXIF инжектиране на метаданни и файлове-полиглоти

### Уязвимостта
Файл-полиглот е файл, който е валиден в няколко различни формата едновременно (например едновременно валидно изображение и валиден скрипт). Съвременните валидатори използват задълбочена проверка на файловата структура (чрез библиотеки като GD или ImageMagick). Въпреки това, форматите на изображенията позволяват текстови коментари или структури от метаданни (като EXIF тагове в JPEG или текстови блокове в PNG).

### Атаката
Чрез инструменти като `exiftool`, атакуващите могат да инжектират PHP код в коментара на изображението или в поле за метаданни, без да повредят структурата му:

```bash
exiftool -Comment="<?php system($_GET['cmd']); ?>" exploit.jpg
```

Ако бекендът само проверява дали изображението е валидно (например чрез `getimagesize()` в PHP) и запазва файла с разширение `.php` (или разчита на двойно разширение / нулев байт), PHP интерпретаторът ще изпълни кода, скрит в метаданните.

> [!WARNING]
> **Оцеляване при преоразмеряване и компресия**: Преоразмеряването на изображението на сървъра не гарантира сигурност. Атакуващите са разработили специални \"GD-proof\" полиглоти (особено за PNG и JPEG), при които зловредният код се поставя в части от данните на изображението (като PLTE блок или таблици за квантуване), които остават непроменени след компресия и преоразмеряване.

---

## 4. Заобикаляне на пътя чрез името на файла (Path Traversal)

### Уязвимостта
При качване на файлове браузърът изпраща заглавка `Content-Disposition`, съдържаща оригиналното име на файла. Ако бекендът се доверява на това име и го добавя директно към пътя за качване, възниква уязвимост за заобикаляне на пътя (Path Traversal).

### Атаката
Атакуващият променя параметъра `filename`, за да включи символи за връщане назад в директориите (`../`):

```http
POST /upload HTTP/1.1
Host: vulnerable-app.com
Content-Disposition: form-data; name="file"; filename="../../../../var/www/html/shell.php"
Content-Type: image/png

<?php system($_GET['cmd']); ?>
```

Ако директорията за качване е `/var/www/html/storage/uploads/` и приложението динамично резолва пътя без филтриране, файлът ще бъде записан директно в `/var/www/html/shell.php` вместо в ограничената папка. Това позволява на атакуващия да изпълни шела директно от основния уеб корен.

---

## 5. Zip Slip (Path Traversal вътре в архиви)

### Уязвимостта
Когато уеб приложенията приемат компресирани архиви (например `.zip` или `.tar`), бекендът трябва да ги разопакова. Ако рутината за декомпресиране не проверява имената на файловете в архива, приложението е уязвимо на атаката \"Zip Slip\".

### Атаката
Атакуващият създава архив, в който името на някой файл съдържа символи за преминаване през директориите:

```text
Malicious Archive:
└── ../../../../var/www/html/shell.php
```

Ако бекендът използва стандартни библиотеки за разархивиране, без да проверява каноничния път на всеки елемент, уеб шелът ще се запише директно в уеб корена на сървъра.

---

## 6. Клиентски XSS чрез качване на SVG файлове

### Уязвимостта
Форматът SVG (Scalable Vector Graphics) е базиран на XML. Тъй като SVG файловете са XML документи, те могат да съдържат вградени скриптове (`<script>` тагове) и HTML манипулатори на събития.

### Атаката
Ако приложението позволява на потребителите да качват SVG файлове (например за профилни снимки) и ги обслужва със заглавка `Content-Type: image/svg+xml`, браузърът ги третира като активни HTML документи.

```xml
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="40" fill="red" />
  <script type="text/javascript">
    alert(document.domain);
  </script>
</svg>
```

При директно отваряне на SVG файла, вграденият JavaScript ще се изпълни в контекста на домейна на приложението, което води до кражба на сесии или потребителски сесийни данни.

---

## 7. SSRF и LFD чрез обработка на PDF файлове

### Уязвимостта
Много сайтове обработват качени PDF файлове, за да генерират визуализации/минимизирани изображения (thumbnails) или да анализират текстово съдържание. Често се използват инструменти като Ghostscript, `pdftoppm` или конвертори от PDF към HTML. Повечето от тези инструменти имат дълга история на критични уязвимости (като уязвимости при изпълнение на команди в Ghostscript).

### Атаката
1. **Разкриване на локални файлове (LFD)**: Атакуващият качва PDF файл, съдържащ препратки към локални ресурси (например `/etc/passwd` или `C:\Windows\win.ini`). При рендериране на прегледа сървърът чете тези файлове и ги вгражда директно в изображението на прегледа.
2. **Фалшифициране на заявки от страна на сървъра (SSRF)**: Атакуващият добавя вътрешни URL адреси (например `http://169.254.169.254/` или вътрешни административни панели) в структурата на PDF файла. При опит за обработка сървърът ще изпрати заявки към тези изолирани вътрешни мрежи.

---

## 8. Пример за сигурна имплементация в PHP/Laravel (Многослойна защита)

За сигурно качване на файлове е необходимо внедряване на многослойна защита. Простото валидиране на разширението не е достатъчно.

### Сигурен контролер за качване в Laravel

По-долу е показан готов за производствена среда сигурен контролер в Laravel.

```php
<?php

namespace App\Http\Controllers;

use App\Http\Requests\SecureUploadRequest;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Facades\Image;
use Symfony\Component\HttpFoundation\File\Exception\FileException;

class SecureUploadController extends Controller
{
    /**
     * Обработва сигурното качване, валидирането и обработката на изображения.
     */
    public function upload(SecureUploadRequest $request)
    {
        if (!$request->hasFile('uploaded_file')) {
            return response()->json(['error' => 'Няма качен файл.'], 400);
        }

        $file = $request->file('uploaded_file');

        // 1. Строг бял списък с разширения
        $extension = strtolower($file->getClientOriginalExtension());
        $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'svg'];
        
        if (!in_array($extension, $allowedExtensions)) {
            return response()->json(['error' => 'Невалидно файлово разширение.'], 400);
        }

        // 2. Определяне на реалния MIME-тип на сървъра (чрез fileinfo)
        $realMime = $file->getMimeType();
        $mimeToExtensionMap = [
            'image/jpeg'    => ['jpg', 'jpeg'],
            'image/png'     => ['png'],
            'image/gif'     => ['gif'],
            'image/svg+xml' => ['svg'],
        ];

        if (!isset($mimeToExtensionMap[$realMime]) || !in_array($extension, $mimeToExtensionMap[$realMime])) {
            return response()->json(['error' => 'Несъответствие в MIME-типа.'], 400);
        }

        // 3. Генериране на случайно име (UUID) за предотвратяване на Path Traversal и изтичане на метаданни
        $uuid = Str::uuid()->toString();
        $secureFilename = "{$uuid}.{$extension}";

        // 4. Специална обработка за SVG файлове (почистване против XScript и XXE)
        if ($realMime === 'image/svg+xml') {
            try {
                $sanitizedSvg = $this->sanitizeSvg($file->getRealPath());
                
                // Запазване в изолирано хранилище (напр. AWS S3) извън публичната уеб директория
                Storage::disk('s3')->put("uploads/{$secureFilename}", $sanitizedSvg, [
                    'visibility' => 'private',
                    'ContentType' => 'image/svg+xml',
                    'ContentDisposition' => 'attachment; filename="' . $secureFilename . '"' // Принудително изтегляне за спиране на XSS
                ]);
            } catch (\Exception $e) {
                return response()->json(['error' => 'Неуспешно почистване на SVG.'], 400);
            }
        } else {
            // 5. Прекодиране на растерни изображения (JPEG/PNG/GIF) за изтриване на EXIF метаданни и унищожаване на полиглоти
            try {
                // Използване на Intervention Image (на базата на GD или ImageMagick)
                $img = Image::make($file->getRealPath());

                // Реконструирането на изображението изчиства EXIF данните и премахва вградените PHP кодове
                $stream = $img->stream($extension, 85); // прекодиране с 85% качество

                // Запазване в защитено частно хранилище
                Storage::disk('s3')->put("uploads/{$secureFilename}", $stream->__toString(), [
                    'visibility' => 'private',
                    'ContentType' => $realMime,
                ]);
            } catch (\Exception $e) {
                return response()->json(['error' => 'Грешка при обработка на изображението.'], 500);
            }
        }

        return response()->json([
            'message' => 'Файлът е качен сигурно.',
            'file_id' => $uuid,
            'filename' => $secureFilename
        ], 200);
    }

    /**
     * Почиства SVG съдържанието чрез премахване на скриптове и inline събития.
     */
    private function sanitizeSvg(string $filePath): string
    {
        $xml = file_get_contents($filePath);
        if ($xml === false) {
            throw new \Exception('Неуспешно четене на SVG файл.');
        }

        $dom = new \DOMDocument();
        
        // Деактивиране на външни обекти (предотвратяване на XXE)
        libxml_use_internal_errors(true);
        libxml_disable_entity_loader(true);

        if (!$dom->loadXML($xml, LIBXML_NONET | LIBXML_NOENT | LIBXML_DTDLOAD)) {
            libxml_clear_errors();
            throw new \Exception('Невалидна XML структура.');
        }

        // 1. Премахване на всички <script> тагове
        $scripts = $dom->getElementsByTagName('script');
        while ($scripts->length > 0) {
            $script = $scripts->item(0);
            $script->parentNode->removeChild($script);
        }

        // 2. Премахване на всички вградени събития (onload, onclick и т.н.)
        $xpath = new \DOMXPath($dom);
        $nodes = $xpath->query('//@*[starts-with(name(), "on")]');
        foreach ($nodes as $node) {
            $node->ownerElement->removeAttributeNode($node);
        }

        $sanitizedXml = $dom->saveXML();
        libxml_clear_errors();

        return $sanitizedXml;
    }
}
```

### Защита на ниво уеб сървър
В допълнение към сигурния код на приложението, вашият уеб сървър трябва да бъде конфигуриран така, че да предотвратява изпълнението на файлове в папките за качване.

#### За Nginx
Спиране на PHP изпълнението в папката с качванията:
```nginx
location ~* ^/storage/uploads/.*\.php$ {
    deny all;
    return 404;
}
```

#### За Apache
Спиране на директния достъп и изпълнението на скриптове чрез `.htaccess`:
```apache
Options -Indexes
RemoveHandler .php .phtml .php3 .php4 .php5 .php7 .php8
RemoveType .php .phtml .php3 .php4 .php5 .php7 .php8
php_flag engine off
```