FlawOpen

flawopen.com/XSS в Swift/loadHTMLString

Безопасен ли WKWebView.loadHTMLString в iOS для недоверенного содержимого?

Справочная страница
Краткий ответ

Не автоматически: WKWebView разбирает переданную строку как HTML, поэтому теги и разметка, способная запускать скрипты, остаются активными, пока содержимое не является доверенным или не обработано для нужного контекста. Для обычного текста и пользовательского HTML нужны разные меры.

Безопасное использование

RISKY
let html = "

\(untrustedText)

" webView.loadHTMLString(html, baseURL: nil)
SAFER
func escapeHTMLText(_ value: String) -> String {
    value
        .replacingOccurrences(of: "&", with: "&")
        .replacingOccurrences(of: "<", with: "<")
        .replacingOccurrences(of: ">", with: ">")
        .replacingOccurrences(of: "\"", with: """)
        .replacingOccurrences(of: "'", with: "'")
}

let html = "

\(escapeHTMLText(untrustedText))

" webView.loadHTMLString(html, baseURL: nil)

Дополнительный риск для проверки

Обработчик сообщений в мире страницы даёт её скриптам путь к коду приложения. `WKContentWorld` может разделять среды JavaScript, но скрипты страницы и приложения по-прежнему используют общий DOM. Если вместе используются недоверенный HTML и мост, предоставляйте только минимальные возможности, проверяйте сообщение и его frame и отдельно авторизуйте каждое действие; не путайте разделение миров с авторизацией.

Что контролирует baseURL

Apple описывает `baseURL` как базовый адрес для разрешения относительных URL в переданном HTML. Этот параметр не очищает разметку и не отключает JavaScript страницы. Значение `nil` не защищает от XSS и не включает sandbox; политику ресурсов и навигации задавайте отдельно.

Выбирайте защиту для каждой границы

Для обычного текста в HTML-текстовом узле используйте кодирование именно для этого контекста, как ниже; не применяйте его повторно к атрибутам, URL, CSS или JavaScript. Для пользовательского HTML с разметкой используйте поддерживаемый санитайзер с явными списками разрешённых элементов, атрибутов и схем URL. Передавайте значения JavaScript приложения через аргументы `callAsyncJavaScript`, не подставляя их в исходный код. Если JavaScript страницы не нужен, `allowsContentJavaScript` может отключить его как дополнительную меру; это не заменяет корректную обработку вывода.

Вопросы и ответы

Устаревший UIWebView отличается?

Нет: риск тот же, и дополнительной встроенной очистки там тоже нет. Переход на WKWebView обновляет технологию, но сам по себе не устраняет проблему безопасности.

Защищает ли `baseURL: nil` от XSS?

Нет. Apple документирует `baseURL` для разрешения относительных URL. Это не HTML-санитайзер, не переключатель скриптов и не гарантия sandbox.

Изолирует ли `WKContentWorld` DOM страницы?

Нет. Он разделяет среды JavaScript, но они используют общий DOM. Считайте данные DOM и сообщения недоверенными и отдельно авторизуйте каждое нативное действие.

Источники

См. также XSS (межсайтовый скриптинг, CWE-79): как он работает и как его предотвратить в любом языке — flawopen.com Отражённый, хранимый и DOM-based XSS: в чём разница? Риски безопасности addJavascriptInterface в Android Защита Angular от XSS: безопасные значения и обходные API XSS из-за MIME sniffing: Content-Type и nosniff CSP и экранирование вывода: нужны ли оба? Безопасен ли dangerouslySetInnerHTML в React?