Публічна форма, яка ніколи не спілкується з приватною мережею, усе одно створює дані, які приватна мережа має оцінити. Тунель змінює лише те, хто кому телефонує. Усе після завантаження — це рішення про імпорт, і воно належить приватному боку. Цей посібник простежує одне подання від браузера до зафіксованого внутрішнього запису.

Почніть з місця, куди потрапляє подання

Браузер надсилає на публічну кінцеву точку, яка записує рядок до контрольованого сховища приймання і повертає не більше ніж підтвердження. Це сховище є точкою передачі, і воно має бути єдиним, куди може писати публічний рівень. Тримайте там необроблені дані без змін, разом із часом надходження та стабільним ідентифікатором запису.

Далі приватний працівник витягує рядки в очікуванні через тунель і вирішує, що робити з кожним. Він працює під власним ідентифікатором, і це тема наступного розділу.

curl --silent --fail \
  --cert /etc/importer/client.crt --key /etc/importer/client.key \
  "https://intake.corp.internal/api/pending?limit=20" \
  -o /var/lib/importer/pending.json

Дайте імпортеру лише ті повноваження, які йому потрібні

Публічний вебпроцес і обліковий запис, який пише до внутрішнього застосунку, мають бути двома різними суб'єктами. Публічному серверу не потрібне внутрішнє адміністрування лише тому, що він має доставляти дані форми, а один спільний обліковий запис для обох боків перетворює будь-яку вебпомилку на внутрішній запис. Видайте працівникові власні облікові дані, обмежте їх однією операцією імпорту та фіксуйте, який суб'єкт виконав кожен імпорт. Саме це розділення робить межу тунелю осмисленою, а не декоративною.

Обмежте також те, з якого джерела працівник може читати. Якщо реалізація використовує чергу або службу передавання, ця служба зберігає власну автентифікацію та політику доступу, бо VPN не автентифікує нічого всередині вмісту.

Короткоживуча функція не звільняється від тієї самої перевірки. Поки вона працює, її мережеве положення та облікові дані все ще дають повноваження, а коротший термін лише звужує вікно. Термін не замінює рішення про те, які операції може виконувати суб'єкт.

Перевіряйте до того, як щось зміниться всередині

Поля публічної форми — це текст, який контролює зловмисник, доки не доведено протилежне, і настанови OWASP щодо перевірки вводу відносять серверні потоки до недовірених джерел саме з цієї причини. Зашифроване передавання означає, що байти надійшли цілими, а не що вони описують дозволений запит. Розбирайте та перевіряйте до будь-якого привілейованого кроку, щоб поганий рядок ніколи не дістався коду, здатного діяти.

Визначте дозволені поля, їхні формати, розміри та бізнес-правила, яких треба дотримуватися. Дата може бути правильно оформлена й усе одно неправильна для запитаної операції, а вміст, що називає внутрішній обліковий запис або статус затвердження, не повинен мати змоги надати собі ні того, ні іншого.

Надсилайте відхилені рядки до результату перегляду, а не вгадуйте виправлення чи передавайте їх до оболонки або сирого інтерфейсу бази даних. Записуйте ідентифікатор запису та правило, що не спрацювало, а не кожне поле, яке ввів заявник.

Зробіть точку повтору на одній операції

Якщо запис submission-1042 витягують двічі, бо перше підтвердження загубилося, працівникові потрібен стійкий спосіб розпізнати вихідний запис і його зафіксований результат. Розклад, який запускає завдання один раз, не доводить, що кожен рядок застосовано один раз. Повторне доставляння є нормальним, тож проєкт має його поглинати.

Використовуйте власну транзакцію та механізм обробки дублікатів внутрішнього застосунку й тримайте ідентифікатор джерела, результат і підтвердження в одній узгодженій послідовності. Підтверджуйте лише після того, як потрібну операцію зафіксовано або стійко призначено, і ніколи не видаляйте рядок приймання лише тому, що байти було завантажено.

Потім доведіть це трьома фікстурами: коректним рядком, неправильно оформленим рядком і тим самим контрольованим ідентифікатором джерела, доставленим двічі. Кожен із них проходить через ту саму кінцеву точку, яку використовує працівник.

for f in fixtures/valid-submission.json fixtures/bad-date.json; do
  curl --silent --fail --cert /etc/importer/client.crt \
    -X POST --data @"$f" https://intake.corp.internal/api/records
done
curl --silent --fail --cert /etc/importer/client.crt \
  -X POST --data @fixtures/valid-submission.json https://intake.corp.internal/api/records

Перші два рядки мають завершитися в різних внутрішніх станах, а третій має повернути ідентифікатор, уже зафіксований для цього вихідного запису, замість створення другого. Будь-що інше означає, що імпорт ще не є повторюваним.

Схожі статті