---
title: 'Заобикаляне на WAF чрез объркване на кодирането: Историята на CVE-2026-21876 | DevSense'
description: 'Научете как уязвимостта CVE-2026-21876 позволява на атакуващите да заобикалят OWASP ModSecurity Core Rule Set (CRS) чрез объркване на кодирането в multipart заявки и презаписване на променливи в правило 922110.'
faq:
    - { question: 'Каква е основната причина за уязвимостта CVE-2026-21876?', answer: 'Основната причина е проблем с презаписването на променливи в правило 922110 на OWASP CRS. По време на парсването на multipart заявка, WAF записва Content-Type и кодирането (charset) на всяка част в една и съща глобална променлива на трансакцията. Тъй като валидацията спрямо белия списък се извършва едва след обработката на всички части, се проверява само типът на последната част, а предходните остават непроверени.' }
    - { question: 'Защо объркването на кодирането с IBM037 или UTF-7 води до заобикаляне на WAF?', answer: 'Атакуващите кодират зловредния си товар в нестандартни кодировки (като IBM037 на базата на EBCDIC или UTF-7). WAF не декодира или проверява тези части, тъй като проверката на техния Content-Type се заобикаля поради презаписването на променливите, а сигнатурите му са написани за ASCII/UTF-8. Въпреки това, бекенд сървърите (като Undertow или ASP.NET Core) автоматично поддържат и декодират тези кодировки, възстановявайки чистия текст на бекенда.' }
    - { question: 'Как OWASP Core Rule Set коригира тази уязвимост?', answer: 'Уязвимостта беше коригирана чрез пренаписване на набора от правила. Вместо да се презаписва една променлива, новата логика инициализира брояч, записва Content-Type на всяка част от multipart заявката в отделна променлива с уникално име, и след това обхожда всички записани променливи, за да провери всяка една от тях спрямо белия списък.' }
published: '2026-07-09'
---
# Заобикаляне на WAF чрез объркване на кодирането: Историята на CVE-2026-21876

Защитните стени за уеб приложения (WAF) са критични компоненти на модерната уеб сигурност. Те стоят между клиентите и бекенд сървърите, анализирайки входящия трафик с цел откриване и блокиране на зловредни заявки като SQL инжекции (SQLi) и междусайтов скриптинг (XSS). Но един WAF е толкова силен, колкото са силни неговите правила.

В тази статия анализираме **CVE-2026-21876** – уязвимост с висока степен на сериозност в **OWASP ModSecurity Core Rule Set (CRS)**. Този пропуск позволява на атакуващите напълно да заобиколят проверките за сигурност, като експлоатират грешка при презаписване на променливи, комбинирана с автоматично декодиране на кодирането на символите (charset) в съвременните бекенд приложения.

---

## ModSecurity и OWASP Core Rule Set (CRS)

**ModSecurity** е популярен WAF двигател с отворен код, базиран на сигнатури, който се интегрира с уеб сървъри като Nginx, Apache и IIS. Тъй като ModSecurity е само двигател, той разчита на правила за откриване на атаки.

**OWASP ModSecurity Core Rule Set (CRS)** е индустриалният стандарт за общи правила за откриване на атаки. Той се внедрява широко от големи облачни доставчици и CDN мрежи, включително Azure WAF, конфигурации на AWS WAF, Cloudflare, Fastly и Google Cloud Armor. С милиони активни инсталации по целия свят, уязвимост в CRS правилата има каскаден ефект, излагайки на риск огромен брой уеб инфраструктури.

---

## Механика на уязвимостта CVE-2026-21876

Уязвимостта се намира в правило **922110**, което е създадено да налага строга валидация на заглавните части `Content-Type` на multipart заявките. По-конкретно, то гарантира, че всяка част в `multipart/form-data` заявка използва одобрен (whitelisted) тип съдържание и кодировка.

### Проблемът с презаписването на променливи

Когато клиент изпрати multipart заявка, ModSecurity обхожда всяка част от нейното съдържание. По време на този процес правило 922110 извлича `Content-Type` на съответната част и го съхранява в глобална променлива на трансакцията (например `TX:content_type`).

Грешката е проста, но критична:
1. **Цикълът:** ModSecurity обхожда всички части, като извлича и записва Content-Type на текущата част в същата променлива, презаписвайки предишната стойност.
2. **Валидацията:** Проверката за съответствие с белия списък се извършва едва **след** приключване на цикъла, а не в самия цикъл за всяка отделна част.
3. **Последствието:** Само стойността на Content-Type на **последната част** от multipart заявката се проверява спрямо белия списък. Всички предходни части се игнорират от правило 922110.

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

```python
# Уязвима логика (CVE-2026-21876)
content_type_var = None

# Извличане на типове съдържание в цикъл
for part in request.multipart_parts:
    content_type_var = part.headers.get("Content-Type")  # Презаписва глобалната променлива

# Валидацията се извършва извън цикъла
if not is_whitelisted(content_type_var):
    block_request()
```

Чрез добавяне на фиктивен параметър с одобрен Content-Type в края на заявката, атакуващият може да презапише глобалната променлива с „безопасна“ стойност, заобикаляйки проверката изцяло.

---

## Вектор на атака: Объркване на кодирането (Charset Confusion)

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

Сигнатурните правила на WAF (например тези, които търсят `UNION SELECT` или `<script>`) са проектирани да анализират данни, кодирани в стандартни кодировки като UTF-8 или ASCII. Ако атакуващият изпрати полезен товар, кодиран в нестандартно кодиране, WAF няма да открие съвпадение със сигнатурите, тъй като суровите байтови последователности не приличат на зловредни ключови думи.

При нормални обстоятелства правило 922110 би блокирало всяка заявка с неодобрена кодировка. Поради грешката с презаписването обаче, WAF допуска неодобрени кодировки в първоначалните части, стига последната част да е легитимна.

### Конструиране на заявката за заобикаляне

Атакуващият структурира `multipart/form-data` заявка с две части:
1. **Част 1 (Зловреден товар):** Използва нестандартна кодировка като `IBM037` (кодиране на базата на EBCDIC). WAF пропуска проверката на Content-Type (поради презаписването) и не успява да провери съдържанието, защото е кодирано в EBCDIC.
2. **Част 2 (Фиктивна част):** Използва стандартна кодировка като `utf-8`. Това презаписва променливата на WAF с валидна стойност и позволява на цялата заявка да премине.

### Пример за сурова HTTP заявка за заобикаляне

```http
POST /vulnerable-endpoint HTTP/1.1
Host: target-app.com
Content-Length: 432
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarySafeAndBypass

------WebKitFormBoundarySafeAndBypass
Content-Disposition: form-data; name="id"
Content-Type: text/plain; charset=ibm037

K@ñ%ÈÊÈÀñKñ
------WebKitFormBoundarySafeAndBypass
Content-Disposition: form-data; name="legitimate_param"
Content-Type: text/plain; charset=utf-8

safe-value
------WebKitFormBoundarySafeAndBypass--
```

> [!NOTE]
> В горния пример стойността `K@ñ%ÈÊÈÀñKñ` представлява SQL инжекцията `' OR 1=1 --`, кодирана в IBM037 (EBCDIC). За WAF тези байтове изглеждат като произволни символи и не съвпадат с нито една сигнатура за атака.

---

## Декодиране от страна на бекенда

Заобикалянето на WAF е опасно само ако бекенд приложението действително обработва зловредния товар.

Много съвременни бекенд сървъри и фреймворци автоматично парсват `multipart/form-data` заявките. Когато срещнат част със специфичен параметър `charset` в заглавната част `Content-Type`, те автоматично декодират байтовете на тази част, използвайки посоченото кодиране.

Някои известни платформи, показващи това поведение от самото начало, включват:
- **Spring Boot под Undertow:** Undertow автоматично разчита и декодира multipart стойностите въз основа на кодирането, посочено в Content-Type на всяка част.
- **ASP.NET Core:** Вграденият multipart парсер спазва параметъра charset, като автоматично превежда низове в IBM037 или UTF-7 обратно в стандартни UTF-8/Unicode низове, преди да достигнат до контролерите на приложението.

Когато заявката достигне до бекенда:
1. Бекендът парсва Част 1, вижда `charset=ibm037` и декодира EBCDIC байтовете обратно в чист текст: `' OR 1=1 --`.
2. Приложението изпълнява параметъра, активирайки SQL инжекцията или XSS уязвимостта.
3. WAF остава напълно сляп за атаката, защото е проверил само `charset=utf-8` на Част 2 и е видял само неразбираеми EBCDIC данни в Част 1.

---

## Коригиране на уязвимостта в Core Rule Set

След разкриването на уязвимостта, екипът на OWASP CRS пусна корекция (patch), която промени начина на валидиране на multipart заявките в правило 922110. Вместо единична глобална променлива, проверката вече е разделена на три фази:

1. **Инициализиране на брояч:** Инициализира се уникален брояч за следене на отделните части в multipart заявката.
2. **Разделно съхранение:** Извлича се и се записва Content-Type и charset на *всяка* част в отделна променлива, обвързана с нейния индекс (например `TX:multipart_content_type_0`, `TX:multipart_content_type_1` и т.н.).
3. **Цялостна валидация:** Обхождат се всички записани променливи и всяка се проверява индивидуално спрямо белия списък. Ако дори една част се окаже с неодобрен Content-Type, WAF блокира заявката.

Коригираната логика функционира подобно на следния псевдокод:

```python
# Коригирана логика
content_types = []

# Събиране на всички Content-Type в списък
for part in request.multipart_parts:
    content_types.append(part.headers.get("Content-Type"))

# Валидация на абсолютно всяка част
for ct in content_types:
    if not is_whitelisted(ct):
        block_request()
        break
```

Тази корекция напълно елиминира презаписването на променливи, гарантирайки, че атаките чрез объркване на кодирането се засичат и блокират успешно на ниво WAF.