Политика безопасности контента (CSP) — это дополнительный уровень безопасности, используемый для обнаружения и смягчения определенных типов атак, включая межсайтовые сценарии (XSS) и атаки с внедрением данных. Будь то кража данных, загрязнение содержимого веб-сайта или распространение вредоносных программ, эти атаки являются основными средствами.
причина
когда я случайно твиттер страницыview source
Позже обнаружил сюрприз.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Twitter</title>
<style>
body {
background-color: #ffffff;
font-family: sans-serif;
}
a {
color: #1da1f2;
}
svg {
color: #1da1f2;
display: block;
fill: currentcolor;
height: 21px;
margin: 13px auto;
width: 24px;
}
</style>
</head>
<body>
<noscript>
<center>If you’re not redirected soon, please <a href="/">use this link</a>.</center>
</noscript>
<script nonce="SG0bV9rOanQfzG0ccU8WQw==">
document.cookie = "app_shell_visited=1;path=/;max-age=5";
location.replace(location.href.split("#")[0]);
</script>
</body>
</html>
Можно сказать, что это очень освежает по сравнению с исходным кодом других сайтов, которые обычно видят. Там нет грязной этикетки, функции как много. Особенно смущается, думая, что это весь исходный код страницы, но легко понять, что это не настоящий HTML-код, после просмотра панели Source DevTools. Но что такое исходный код страницы, учитывая такую освежающую версию, это не исследование в первую очередь.
nonce
Атрибуты.它以及它后面的神秘字符串成功引起了我的好奇。再去看 Google 首页的源码,也有好些nonce
Оно использует.是时候去了解一下这里的nonce
что это такое.
! <script nonce="SG0bV9rOanQfzG0ccU8WQw==">
document.cookie = "app_shell_visited=1;path=/;max-age=5";
location.replace(location.href.split("#")[0]);
</script>
Content Security Policy (CSP)
чтобы понятьnonce
, сначала поймиContent-Security-Policy(CSP).
Мы все знаем, что браузеры имеют политику одного и того же происхождения (same-origin policy) ограничения безопасности, то есть каждому сайту разрешено загружать данные только из того же источника, что и он сам,https://a.com
невозможно изhttps://b.com
загружается в ресурс. Каждый сайт строго ограничен своим островом, и это песочница, поэтому очень безопасно, и вся сеть не будет захламлена. В основном, это решает большинство проблем безопасности. При отсутствии политики одинакового происхождения вредоносный код может легко выполниться на стороне браузера и получить различную личную информацию: номера банковских счетов, социальные данные и т. д.
Конечно, есть способ обмена данными между веб-сайтами.Подробнее.CORS.
На самом деле проблема в том, что политика одного и того же источника не является надежной, а междоменные атакиCross-site scripting (XSS)Он включает в себя различные средства для обхода ограничений, в виде внедрения вредоносного кода на страницу для завершения кражи или атаки информации. Например, сайты типа UGC, поскольку контент зависит от создания пользователем, это открывает большую дыру, позволяя контенту, введенному пользователем, работать на странице. Конечно, поскольку мы все знаем, что будут атаки путем внедрения, анти-XSS-фильтрация пользовательского ввода также стала стандартной.
Content-Security-Policy, с другой стороны, добавляет уровень защиты в браузер, что может значительно снизить вероятность таких атак.
принцип
Сообщая браузеру ряд правил, CSP строго определяет, какие ресурсы разрешены на странице и какие источники разрешены, а все те, которые не входят в указанный диапазон, отклоняются. Можно сказать, что по сравнению с политикой одного и того же происхождения CSP очень строгая.
Есть два способа его реализации:
- добавить сервер
Content-Security-Policy
Респондент для обозначения правил - Добавьте теги в HTML, чтобы указать
Content-Security-Policy
правило
Правила CSP в шапке mobile.twitter.com
Для удобства тестирования использованы следующие примеры<meta>
тег, чтобы включить правила CSP. но<meta>
Некоторые из команд нельзя использовать, которые будут изучены позже. Все директивы ограничения можно использовать только в заголовках ответа.
Простой пример
Создайте HTML-файл со следующим содержимым:
csp_test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' https://unpkg.com">
<title>CSP Test</title>
</head>
<body>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
</body>
</html>
Откройте локальный сервер в каталоге, где тестовый файл для доступа, здесь приходит использование Python Server:
python -m SimpleHTTPServer 8000
Затем посетите localhost:8000, чтобы увидеть результат:
Обычный доступ в соответствии с правилами CSP
Тогда мы будемContent-Security-Policy
Измените его, чтобы запретить использование каких-либо ресурсов, и повторите попытку:
csp_test.html
<!DOCTYPE html>
<html lang="en">
<head>
- <meta http-equiv="Content-Security-Policy" content="script-src 'self' https://unpkg.com">
+ <meta http-equiv="Content-Security-Policy" content="script-src ‘none’">
<title>CSP Test</title>
</head>
<body>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
</body>
</html>
Инициировать блокировку ресурсов правила CSP
Давайте объясним установленные здесь правила CSP и поймем, почему загрузка ресурсов не удалась.
Правила CSP
либо в шапке, либо<meta>
Формат значения, указанного в теге, является единым, который состоит из ряда директив CSP (директив).
Пример:
Content-Security-Policy: <policy-directive>; <policy-directive>…
Здесь директива, то есть директива, — это указанный в спецификации CSP источник для детализации определенного ресурса, такого как тот, что использовался в предыдущем примере.script-src
, указав, какие легитимные источники могут быть у скрипта,img-src
Затем укажите изображение, обычно используются следующие команды:
-
base-uri
На странице могут появиться ограничения<base>
ссылка в этикетке. -
child-src
Список ссылок, доступных для работника и встроенных в виде фрейма. Например:child-src https://youtube.com
Указывает, что видеоресурсы могут быть встроены только с Youtube. -
connect-src
Адрес, с которого может быть инициировано соединение (через XHR, WebSockets или EventSource). -
font-src
Источник шрифта. Например, чтобы использовать Google Web-шрифты, которые вам нужно добавитьfont-src https://themes.googleusercontent.com
-
form-action
<form>
-
frame-ancestors
child-src
ровно наоборот). Действующий на<frame>
,<iframe>
,<embed>
а также<applet>
.该指令不能通过<meta>
Назначен и работает только с документами, отличными от HTML. -
frame-src
Эта директива устарела на уровне 2, но будет восстановлена на уровне 3. резервный вариант, если не указаноtochild-src
инструкция. -
img-src
Укажите источник изображения. -
media-src
Ограничьте источники аудио- и видеоресурсов. -
object-src
Источник для Flash и других плагинов. -
plugin-types
Ограничьте типы плагинов, которые могут быть загружены на странице. -
report-uri
指定一个可接收 CSP 报告的地址,浏览器会在相应指令不通过时发送报告。 не могу пройти<meta>
Теги указаны. -
style-src
Ограничьте источник файлов стилей. -
upgrade-insecure-requests
Поручите клиенту переписать адрес страницы с HTTP на HTTPS. Полезно, когда на сайте много старых адресов, которые нужно перенаправить. -
worker-src
Директива в CSP уровня 3, указывающая адреса, которые можно использовать в рабочем, совместно используемом или сервисном работнике.
child-src
а такжеframe-ancestors
Похоже. Первый указывает, какие фреймы могут быть загружены на страницу, а второй указывает, кто может загружать страницу в фреймах. Например, две веб-страницы A и B с разных сайтов, B и B имеют фреймы iframe, которые загружают A. Так
- Необходимость включения фреймов-предков B
- Child-src B должен содержать A
По умолчанию эти инструкции открыты до максимального состояния, что можно понимать как их значение по умолчанию.*
. Напримерimg-src
, если не указано явно, ресурс изображения может быть загружен отовсюду.
default-src
img-src
Если не указано, значение по умолчанию равно*
, может загружать изображения из всех источников, но установитьdefault-src
После этого по умолчаниюdefault-src
указанное значение.
Обычная практика установитdefault-src ‘self’
, чтобы все ресурсы были ограничены тем же доменом, что и страница. Если вы хотите загружать изображения из CDN в это время, вы можете добавить источник изображения отдельно.
Content-Security-Policy: default-src ‘self’; img-src https://cdn.example.com
Теперь посмотрите на пример в начале, может быть, вы видите его сейчас. Поскольку странице необходимо загрузить библиотеку React из CDN, мы<meta>
Тег определяет следующие правила CSP:
script-src 'self' https://unpkg.com
здесьself
а позже изменился наnone
Это значение по умолчанию и должно быть заключено в кавычки, иначе оно будет проанализировано как URI. Правило CSP здесь означает, что доступ к сценарию на странице возможен только из того же домена иhttps://unpkg.com
нагрузка. Если мы удалим последний, библиотека React также не сможет загрузиться, как показано на снимке экрана выше, и в консоли появится журнал неудачной загрузки и сработавшие правила.
изменить наnone
После этого это означает, что страница не загружает никаких скриптов, даже скрипты на вашем собственном сайте не могут быть загружены и выполнены. Попробуйте здесьcsp_test.html
создать файл сценария вместеtest.js
:
test.js
alert(‘来自 test.js 的问候!’)
В то же время обратитесь к нему на странице:
csp_test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Security-Policy" content="script-src 'none'">
<title>CSP Test</title>
</head>
<body>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
+ <script src="./test.js"></script>
</body>
</html>
Результат выполнения страницы:
Страница не будет загружать никаких скриптов, если script-src не указан
Да, даже ваши собственные скрипты не могут быть загружены и выполнены. CSP настолько строг и ясен, что в нем нет двусмысленности. Поэтому при указании источника нам нужно подтвердить правильность URI.
допустимые значения для инструкции
Есть два способа записать исходный код, за которым следует команда
- значение по умолчанию
- подстановочный знак URI
значение по умолчанию
Значения по умолчанию следующие:
- никто ничему не соответствует.
- unsafe-inline позволяет использовать встроенные скрипты и стили. Да, вы правильно прочитали, существуют соответствующие ограничения на встроенный в страницу контент.
- unsafe-eval позволяет выполнять скрипты, динамически созданные из строк, такие как eval, setTimeout и т. д.
В частности, под строгим контролем CSP также затрагиваются встроенные скрипты и стили на странице, и они не могут быть выполнены браузером без явного указания.
Рассмотрим следующий код:
csp_test.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>CSP Test</title>
<style>
body{
color:red;
}
</style>
</head>
<body>
<h1>Hello, World!</h1>
<script>
window.onload=function(){
alert('hi jack!')
}
</script>
</body>
</html>
CSP неуказанные обстоятельства
По описанию на MDN, если на сайте не указан CSP, браузер по умолчанию не откроет соответствующую проверку, так что все вышеперечисленное работает нормально, только ограничивается нормальным тем же доменом.
Если сайт не предлагает заголовок CSP, браузеры также используют стандартную политику того же источника.
— через MDN оОписание политики безопасности контента (CSP)
Добавляем лимит CSP:
csp_test.html
<!DOCTYPE html>
<html lang="en">
<head>
+ <meta http-equiv="Content-Security-Policy" content="default-src 'self'">
<title>CSP Test</title>
<style>
body{
color:red;
}
</style>
</head>
<body>
<h1>Hello, World!</h1>
<script>
window.onload=function(){
alert('hi jack!')
}
</script>
</body>
</html>
Конфигурация по умолчанию сайта только с информационным ресурсом домена, но обратите внимание, что этот набор не содержит ситуации в Union, поэтому результат будет таким, как показано ниже.
Встроенный код запрещен
Как это исправить. Если мы хотим разрешить встроенные скрипты или стили на странице, нам нужно явно указать это через script-src и style-src.
csp_test.html
<!DOCTYPE html>
<html lang="en">
<head>
! <meta http-equiv="Content-Security-Policy" content="default-src 'self' ‘unsave-inline’">
<title>CSP Test</title>
<style>
body{
color:red;
}
</style>
</head>
<body>
<h1>Hello, World!</h1>
<script>
window.onload=function(){
alert('hi jack!')
}
</script>
</body>
</html>
здесьdefault-src 'self' ‘unsave-inline’
В конфигурации по умолчанию заслуживают доверия эти источники: те же страницы и домены, а также встроенные.
unsafe-inline
unsafe-eval
), потому что встроенные сценарии и стили неудобно поддерживать и они не используют преимущества хорошо организованного кода. Лучше всего извлекать стили в файлы стилей, а скрипты загружать в отдельные файлы js. Рекомендуется сохранять HTML-файлы чистыми. даже еслиonclick=“myHandler”
илиhref=“javascript:;”
Этот распространенный метод записи также является встроенным сценарием и нуждается в модификации.
Если страница должна использовать встроенное письмо, есть другой способ. То есть этим встроенным сценариям или тегам стиля на странице назначается зашифрованная строка, зашифрованная строка генерируется сервером, и зашифрованная строка добавляется в заголовок ответа страницы.
<script nonce=EDNnf03nceIOfn39fn3e9h3sdfa>
// 这里放置内联在 HTML 中的代码
</script>
заголовки ответа HTTP страницыContent-Security-Policy
Эта же зашифрованная строка включена в конфигурацию:
Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'
Обратите внимание здесьnonce-
приставка.
Это то, что мы видели в начале статьи, и я понимаю это здесь.
<style>
Метки обрабатываются аналогично.
Зашифрованная строка здесь должна быть случайной и непредсказуемой, иначе эффект безопасности не будет достигнут, и она будет перегенерироваться каждый раз при доступе к странице.
Помимо использованияnoce
Укажите зашифрованную строку, чего также можно добиться путем запутывания хеш-значения. Эту практику не нужно добавлять на этикеткуnonce
Вместо этого код, который необходимо внедрить, использует алгоритм шифрования для генерации хэша и помещения его в инструкцию CSP в качестве значения.Алгоритм шифрования здесь поддерживает sha256, sha384 и sha512. В настоящее время префикс, используемый в CSP, является соответствующим именем алгоритма.
Пример хеш-метода:
<script>alert('Hello, world.');</script>
Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='
eval
Кое-где в js код может динамически создаваться и выполняться в строковом режиме, что считается небезопасным, поэтому его использовать не рекомендуется, и он будет упомянут в общих рекомендациях.
- setTimeout/setInterval может получить строку для выполнения в виде кода. setTimout('предупреждение(1)', 1000).
- оценить . eval('предупреждение(1)').
- Конструктор функций. новая функция («предупреждение (1)»).
И встроенный такой же, есть специальные инструкцииunsafe-eval
eval
а такжеFunction
Конструктор, исключите использование иsetTimeout/setInterval
Может быть преобразован в нестроковую форму.
setTimout(function(){
alert(1);
}, 1000)
URI
В дополнение к указанным выше предустановкам можно указать полный URI или с подстановочными знаками.*
адрес, чтобы соответствовать уточнению законного происхождения ресурса. Правила URI здесь такие же, как заголовки отклика в перекрестных доменах сервера конфигурации, см.Same-origin policy.
-
*://*.example.com:*
будет соответствовать всемexample.com
поддомены , но не включаяexample.com
. -
http://example.com
а такжеhttp://www.example.com
два разных URI. -
http://example.com:80
а такжеhttp://example.com
Это также два разных URI, хотя порт веб-сайта по умолчанию — 80.
Согласно ВикипедииUniform Resource IdentifierКак поясняется на странице, полный URI состоит из следующих частей:
URI = scheme:[//authority]path[?query][#fragment]
в
authority
Также включает:authority = [userinfo@]host[:port]
Таким образом, вы можете подумать, что один из них отличается, это оба URI. Это важно понимать, как и в первом примере, указанном выше.
*.example.com
, легко предположить, что раз разрешены все поддомены домена, то должно бытьexample.com
также является законным.
Поскольку URI сопоставляются динамически, это объясняет, почему вышеупомянутые пресеты взяты в кавычки. Потому что без кавычекself
сказал быhost
даself
Адрес ресурса и не выражает первоначальный смысл.
Content-Security-Policy
Производительность CSP в этих условиях мы посмотрим.
- Для случаев, когда задано несколько заголовков ответа, применяется самое строгое правило. Например, в следующих двух заголовках ответа, хотя второй установлен
connect-src
разрешатьhttp://example.com/
, но первый установленconnect-src
дляnone
, тем строжеnone
вступит в силу. видетьMultiple content security policies.
Content-Security-Policy: default-src 'self' http://example.com;
connect-src 'none';
Content-Security-Policy: connect-src http://example.com/;
script-src http://example.com/
- Если одна и та же инструкция указана несколько раз, приоритет будет иметь первая, а последующие будут игнорироваться.
csp_test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'self';default-src 'unsafe-inline';">
<title>CSP Test</title>
<style>
body{
color:red;
}
</style>
</head>
<body>
<h1>Hello, World!</h1>
<script>
window.onload=function(){
alert('hi jack!')
}
</script>
</body>
</html>
Эффект отображается, когда одна и та же команда настроена повторно
Очень разумно браузер не только распечатает ресурсы и команды, которые не могут быть обнаружены, но и подскажет команды, которые игнорируются при повторной настройке.
- уточнить
default-src
Fetch
类指令 的默认值。 которыйdefault-src
Недействительно для всех команд, значение по умолчанию для других команд по-прежнему*
.
Отправить жалобу
Content-Security-Policy
report-uri
Content-Security-Policy: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
JSON основан на сервере для получения данных из формы.
{
"csp-report": {
"document-uri": "http://example.org/page.html",
"referrer": "http://evil.example.com/",
"blocked-uri": "http://evil.example.com/evil.js",
"violated-directive": "script-src 'self' https://apis.google.com",
"original-policy": "script-src 'self' https://apis.google.com; report-uri http://example.org/my_amazing_csp_report_parser"
}
}
режим отчета
CSP предоставляет режим отчетов, в котором загрузка ресурсов на самом деле не ограничивается, а только сообщается об обнаруженных проблемах.JSON
данные отправляются наreport-uri
назначенное место.
УказавContent-Security-Policy-Report-Only
вместоContent-Security-Policy
, режим отчета включен.
Content-Security-Policy-Report-Only: default-src 'self'; ...; report-uri /my_amazing_csp_report_parser;
Конечно, вы также можете указать два заголовка ответа одновременно, и правила в каждом будут выполняться нормально и не будут влиять друг на друга. Например:
Content-Security-Policy: img-src *;
Content-Security-Policy-Report-Only: img-src ‘none’; report-uri http://reportcollector.example.com/collector.cgi
Изображение здесь по-прежнему загружается нормально, ноimg-src ‘none’
также обнаружит и отправит отчет.
Режим отчета очень удобен для тестирования. Перед запуском CSP обязательно необходимо провести всестороннее тестирование всего сайта, и вовремя исправить обнаруженные проблемы перед его запуском, такие как преобразование инлайн-кода, о котором говорилось выше.
Рекомендуемая практика
Такие меры безопасности, конечно, включаются как можно скорее. Ниже приведены рекомендуемые практики:
- Во-первых, откройте только режим отчета, посмотрите масштаб влияния и измените проблему.
- При добавлении инструкций из
default-src ‘none’
Запускайте, проверяйте на ошибки и постепенно добавляйте правила, пока требования не будут выполнены. - Наблюдайте в течение определенного периода времени после подключения к сети, а затем после стабилизации переключитесь из режима отчетности в режим обязательного выполнения.
Совместимость с браузером
Текущий выпускLevel 3Can I UseImplementation Report for Content Security Policy Level 2.
Если вы не поддерживаете браузер, не беспокойтесь, вы вернетесь к ограничениям на гомологичные стратегии.
Ссылаться на
оригинал:блог woo woo woo.cn на.com/WA have/afraid/int…
Автор: Лю Вэйонг