В этой статье я рас­ска­жу о ска­ниро­вании API веб‑при­ложе­ний с помощью ути­литы Nuclei. Для демонс­тра­ции мы будем ата­ковать заведо­мо уяз­вимое при­ложе­ние, исполь­зующее OpenAPI. По дороге научим­ся писать кас­томные шаб­лоны для Nuclei, которые помогут искать уяз­вимос­ти на авто­мате.
 

Эффективность DAST

Ди­нами­чес­кое ска­ниро­вание (DAST) — один из важ­ных эта­пов ана­лиза защищен­ности при­ложе­ния. Будь то пен­тест или про­цес­сы application security, в любом слу­чае мы запус­каем ска­нер уяз­вимос­тей, который отправ­ляет к при­ложе­нию мно­жес­тво зап­росов и пыта­ется выявить проб­лемы безопас­ности.

Од­нако DAST не лишен недос­татков.

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

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

В‑треть­их, это отчет, в котором может быть отме­чено мно­жес­тво нез­начитель­ных недос­татков безопас­ности, что меша­ет заметить реаль­но важ­ные уяз­вимос­ти и уде­лить им вре­мя.

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

  1. Раз­гла­шение информа­ции.
  2. Error based SQL-инъ­екции.
  3. Broken Object Level Authorization.

В качес­тве подопыт­ного возь­мем VAmPI — спе­циаль­ное уяз­вимое при­ложе­ние для тес­тирова­ния защищен­ности API. У него есть под­дер­жка OpenAPI и показа­тель­ные при­меры небезо­пас­ной реали­зации. Что­бы его уста­новить, дос­таточ­но кло­ниро­вать репози­торий и запус­тить docker compose:

git clone https://github.com/erev0s/VAmPI
cd VAmPI
docker compose up

Так­же необ­ходимо ини­циали­зиро­вать базу дан­ных, отпра­вив GET-зап­рос:

curl http://127.0.0.1:5002/createdb
{ "message": "Database populated." }

Для начала запус­тим Nuclei с нас­трой­ками по умол­чанию (дос­таточ­но передать цель для ска­ниро­вания):

nuclei -u http://127.0.0.1:5002

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

На­ша цель — най­ти ре­аль­ные проб­лемы, поэто­му мы напишем кас­томные шаб­лоны для ска­ниро­вания извес­тно­го REST API на уяз­вимос­ти, наличие которых мы можем пред­полагать из понима­ния реали­зации. В этом нам помогут воз­можнос­ти, которые появи­лись в Nuclei вер­сии 3.2.

 

Фаззинг с Nuclei

Ес­ли у при­ложе­ния мно­го эндпо­интов HTTP, каж­дый из которых может обра­баты­вать мно­жес­тво парамет­ров, про­вер­ка ста­новит­ся уто­митель­ной.

Ав­томати­зиро­вать ана­лиз защищен­ности круп­ных API помога­ет фаз­зинг — тех­ника, которая пос­ледова­тель­но при­меня­ет набор про­верок ко всем воз­можным вари­ациям зап­росов к при­ложе­нию.

Мы можем передать реаль­ные зап­росы из дам­па тра­фика дру­гих инс­тру­мен­тов, логов или спе­цифи­кации OpenAPI в Nuclei. Оста­новим­ся на OpenAPI, так как ее под­дер­жка есть у мно­гих сов­ремен­ных веб‑при­ложе­ний и в отли­чие от сбо­ра тра­фика такой метод не тре­бует активных дей­ствий.

Пе­редать OpenAPI в Nuclei мож­но сле­дующим обра­зом:

nuclei -l openapi.json -im openapi -t templates

При­мер шаб­лона для фаз­зинга:

http:
# filter checks if the template should be executed on a given request
- pre-condition:
- type: dsl
dsl:
- method == POST
- len(body) > 0
condition: and
# payloads that will be used in fuzzing
payloads:
injection: # Variable name for payload
- "'"
- "\""
- ";"
# fuzzing rules
fuzzing:
- part: body # This rule will be applied to the Body
type: postfix # postfix type of rule (i.e., payload will be added at the end of exiting value)
mode: single # single mode (i.e., existing values will be replaced one at a time)
fuzz: # format of payload to be injected
- '{{injection}}' # here, we are directly using the value of the injection variable

В шаб­лоне выше сек­ция pre-condition филь­тру­ет и запус­кает про­вер­ку толь­ко POST-зап­росов с непус­тым телом.

- pre-condition:
- type: dsl
dsl:
- method == POST
- len(body) > 0
condition: and

Вот какие час­ти HTTP-зап­роса может фаз­зить Nuclei:

  • part: query — парамет­ры зап­роса;
  • part: path — путь;
  • part: header — заголо­вок;
  • part: cookie — cookie;
  • part: body — тело зап­роса.

Это далеко не все нас­трой­ки фаз­зинга Nuclei, но для наших целей дос­таточ­но.

 

Сканирование с аутентификацией

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

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии