В NPM-пакете node-netmask, насчитывающем около 3 млн загрузок в неделю и используемом в качестве зависимости у более 270 тысяч проектов на GitHub, выявлена уязвимость (CVE-2021-28918), позволяющая обойти проверки, в которых сетевая маска используется для определения вхождения в диапазоны адресов или для фильтрации. Проблема устранена в выпуске node-netmask 2.0.0.
Уязвимость позволяет добиться обработки внешнего IP-адреса как адреса из внутренней сети и наоборот, а при определённой логике использования модуля node-netmask в приложении совершить атаки SSRF (Server-side request forgery),RFI (Remote File Inclusion) и LFI (Local File Inclusion) для обращения к ресурсам во внутренней сети и включения в цепочку выполнения внешних или локальных файлов. Проблема заключается в том, что в соответствии со спецификацией строковые значения адресов, начинающиеся с нуля, должны интерпретироваться как восьмеричные числа, но модуль "node-netmask" не учитывает данную особенность и обрабатывает их как десятичные числа.
Например, атакующий может запросить ресурс, указав значение "0177.0.0.1", которое в десятичном представлении соответствует "127.0.0.1" (число 0177 в восьмеричной системе равно 127 в десятичной), но модуль "node-netmask" отбросит ноль, и обработает 0177.0.0.1" как "177.0.0.1". В приложении при оценке правил доступа не будет определена тождественность с "127.0.0.1" и ресурс будет загружен с "0177.0.0.1" (фактически с 127.0.0.1), несмотря на запрет обращения к адресам loopback-интерфейса.
Аналогично при обращении к приложению атакующий может указать адрес "0127.0.0.1", который тождественен "87.0.0.1", но в модуле "node-netmask" будет обработан как "127.0.0.1" (т.е. приложение разрешит доступ к операциям с 127.0.0.1, несмотря на то, что фактически указан внешний адрес). Подобным образом можно обмануть и проверку обращения к интранет адресам, указав значения подобные "012.0.0.1" (эквивалент "10.0.0.1", но при проверке в node-netmask будет обработан как 12.0.0.1).
Выявившие проблему исследователи называют проблему катастрофичной и приводят несколько сценариев атак, но большинство из них выглядят умозрительными. Например, говорится о возможности атаковать приложение на базе Node.js, устанавливающее внешние соединения для запроса ресурса на основе параметров или данных входного запроса, но конкретно приложение не называется и не детализируется. Даже если найти приложения, выполняющие загрузку ресурсов на основе введённых IP-адресов, не совсем ясно, как можно применить сценарий с отдачей фиктивного ресурса без подсоединения к локальной сети или без получения контроля за "зеркальными" IP-адресами.
Исследователи предполагают, что владельцы адресов в подсетях 87.0.0.1/8 и 177.0.0.0/8 имеют возможность обойти ограничение доступа к 127.0.0.1. Более реалистичным сценарием является использование уязвимости для обхода различных списков блокировки, реализованных на стороне приложения. Проблема также может применяться для обмена определения интранет-диапазонов в NPM-модуле "private-ip".
* - превышает 254, но не исключается сбой некоторых приложений и в этом случае
Источник статьи: https://www.opennet.ru/opennews/art.shtml?num=54857
Уязвимость позволяет добиться обработки внешнего IP-адреса как адреса из внутренней сети и наоборот, а при определённой логике использования модуля node-netmask в приложении совершить атаки SSRF (Server-side request forgery),RFI (Remote File Inclusion) и LFI (Local File Inclusion) для обращения к ресурсам во внутренней сети и включения в цепочку выполнения внешних или локальных файлов. Проблема заключается в том, что в соответствии со спецификацией строковые значения адресов, начинающиеся с нуля, должны интерпретироваться как восьмеричные числа, но модуль "node-netmask" не учитывает данную особенность и обрабатывает их как десятичные числа.
Например, атакующий может запросить ресурс, указав значение "0177.0.0.1", которое в десятичном представлении соответствует "127.0.0.1" (число 0177 в восьмеричной системе равно 127 в десятичной), но модуль "node-netmask" отбросит ноль, и обработает 0177.0.0.1" как "177.0.0.1". В приложении при оценке правил доступа не будет определена тождественность с "127.0.0.1" и ресурс будет загружен с "0177.0.0.1" (фактически с 127.0.0.1), несмотря на запрет обращения к адресам loopback-интерфейса.
Аналогично при обращении к приложению атакующий может указать адрес "0127.0.0.1", который тождественен "87.0.0.1", но в модуле "node-netmask" будет обработан как "127.0.0.1" (т.е. приложение разрешит доступ к операциям с 127.0.0.1, несмотря на то, что фактически указан внешний адрес). Подобным образом можно обмануть и проверку обращения к интранет адресам, указав значения подобные "012.0.0.1" (эквивалент "10.0.0.1", но при проверке в node-netmask будет обработан как 12.0.0.1).
Выявившие проблему исследователи называют проблему катастрофичной и приводят несколько сценариев атак, но большинство из них выглядят умозрительными. Например, говорится о возможности атаковать приложение на базе Node.js, устанавливающее внешние соединения для запроса ресурса на основе параметров или данных входного запроса, но конкретно приложение не называется и не детализируется. Даже если найти приложения, выполняющие загрузку ресурсов на основе введённых IP-адресов, не совсем ясно, как можно применить сценарий с отдачей фиктивного ресурса без подсоединения к локальной сети или без получения контроля за "зеркальными" IP-адресами.
Исследователи предполагают, что владельцы адресов в подсетях 87.0.0.1/8 и 177.0.0.0/8 имеют возможность обойти ограничение доступа к 127.0.0.1. Более реалистичным сценарием является использование уязвимости для обхода различных списков блокировки, реализованных на стороне приложения. Проблема также может применяться для обмена определения интранет-диапазонов в NPM-модуле "private-ip".
netmask sees this as –> | netmask sees this as –> | …then netmask defines the request | …or netmask allows the request (SSRF) | Notable Range |
---|---|---|---|---|
012 | 010 | 10 | 8 | 10.0.0.0/8 |
014 | 012 | 12 | 10 | 10.0.0.0/8 |
0144 | 0100 | 100 | 64 | 100.64.0.0/10 |
0220 | 0144 | 144 | 100 | 100.64.0.0/10 |
0177 | 0127 | 127 | 87 | 127.0.0.0/8 |
0261 | 0177 | 177 | 127 | 127.0.0.0/8 |
0251 | 0169 | 169 | Err:502 | 169.254.0.0/16 |
0373* | 0251 | 251 | 169 | 169.254.0.0/16 |
0254* | 0172 | 172 | 122 | 172.16.0.0/12 |
0376* | 0254 | 254 | 172 | 172.16.0.0/12 |
0300* | 0192 | 192 | Err:502 | 192.0.0.0/24 |
0306* | 0198 | 198 | Err:502 | 198.18.0.0/15 |
0313* | 0203 | 203 | 131 | 203.0.113.0/24 |
0360* | 0240 | 240 | 160 | 240.0.0.0/4 |
Источник статьи: https://www.opennet.ru/opennews/art.shtml?num=54857