نوشتن CSP برای سایت (حل شد)

csp
browser
xss

#1

سلام

من خواستم برای سایتی که درست کردیم قوانین csp رو اعمال کنم تا جلوی حملات xss تا حدی گرفته بشه

در nginx هدرهای زیر فعال هست

	add_header X-Frame-Options SAMEORIGIN;
	add_header X-Content-Type-Options nosniff;
	add_header X-XSS-Protection "1; mode=block";

برای اینکه ببینم هر صفحه از سایت به چه قوانینی نیاز داره به این صورت عمل کردم:

پلاگین csp mitigator رو برای مرورگر کروم نصب کردم . این پلاگین قوانین ‌csp که شما به اون میدین رو داخل header صفحه مورد نظر شما تزریق میکنه تا مرورگر در زمان لود کردن صفحه اونا رو چک بکنه.

در حالتی که فقط گزارش میده سایت رو بررسی کردم و خطاهای زیاد رو به من نشون داد

[Report Only] Refused to load the script 'https://www.googletagmanager.com/gtag/js?id=UA-105589342-1' because it violates the following Content Security Policy directive: "script-src 'report-sample' 'unsafe-inline' 'nonce-DONT+TOUCH+TOOL+WILL+AUTOFILL+BASED+ON+SERVED+NONCE'".

17:16:10.532 login:1 [Report Only] Refused to load the script 'https://www.googletagmanager.com/gtag/js?id=UA-105589342-1' because it violates the following Content Security Policy directive: "script-src 'strict-dynamic' 'report-sample' 'unsafe-inline' 'unsafe-eval' 'nonce-DONT+TOUCH+TOOL+WILL+AUTOFILL+BASED+ON+SERVED+NONCE'". 'strict-dynamic' is present, so host-based whitelisting is disabled.

17:16:10.534 login:1 [Report Only] Refused to load the script 'https://www.googletagmanager.com/gtag/js?id=UA-105589342-1' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.

17:16:10.536 login:6 [Report Only] Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'report-sample' 'unsafe-inline' 'nonce-DONT+TOUCH+TOOL+WILL+AUTOFILL+BASED+ON+SERVED+NONCE'". Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.

17:16:10.538 login:6 [Report Only] Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'strict-dynamic' 'report-sample' 'unsafe-inline' 'unsafe-eval' 'nonce-DONT+TOUCH+TOOL+WILL+AUTOFILL+BASED+ON+SERVED+NONCE'". Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.

17:16:10.542 login:17 [Report Only] Refused to load the image 'https://example.com/images/smal-example-logo.png' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.

17:16:10.546 login:30 [Report Only] Refused to load the stylesheet 'https://example.com/css/app-3499f2a6f0ad5cf05889004b72983568.css?vsn=d' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'style-src' was not explicitly set, so 'default-src' is used as a fallback.

17:16:10.705 login:94 [Report Only] Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'report-sample' 'unsafe-inline' 'nonce-DONT+TOUCH+TOOL+WILL+AUTOFILL+BASED+ON+SERVED+NONCE'". Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.

17:16:10.707 login:94 [Report Only] Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'strict-dynamic' 'report-sample' 'unsafe-inline' 'unsafe-eval' 'nonce-DONT+TOUCH+TOOL+WILL+AUTOFILL+BASED+ON+SERVED+NONCE'". Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.

17:16:10.711 login:114 [Report Only] Refused to load the image 'https://example.com/images/smal-example-logo-354df0f2f90aa2b0d28da7916c607781.png?vsn=d' because it violates the following Content Security Policy directive: "img-src 'unsafe-inline' https://ssl.gstatic.com/ https://example.com/images/smal-example-logo.png https://stats.g.doubleclick.net https://www.google-analytics.com/ ".

17:16:10.712 login:114 [Report Only] Refused to load the image 'https://example.com/images/smal-example-logo-354df0f2f90aa2b0d28da7916c607781.png?vsn=d' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.

17:16:10.781 login:1 [Report Only] Refused to load the font 'https://example.com/fonts/fontawesome-webfont.woff2?v=4.7.0' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'font-src' was not explicitly set, so 'default-src' is used as a fallback.

17:16:10.786 login:1 [Report Only] Refused to load the font 'https://example.com/fonts/fontawesome-webfont.woff?v=4.7.0' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'font-src' was not explicitly set, so 'default-src' is used as a fallback.

17:16:10.802 login:1 [Report Only] Refused to load the font 'https://example.com/fonts/fontawesome-webfont.ttf?v=4.7.0' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'font-src' was not explicitly set, so 'default-src' is used as a fallback.

17:16:10.810 login:1 [Report Only] Refused to load the font 'https://example.com/fonts/vazir/Vazir-Light-b509835797d20934db7c6bc07b87fbe1.woff2?vsn=d' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'font-src' was not explicitly set, so 'default-src' is used as a fallback.

17:16:10.816 login:1 [Report Only] Refused to load the font 'https://example.com/fonts/vazir/Vazir-Light-e6ae621e1cac3c725c2d92e79bdd002b.woff?vsn=d' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'font-src' was not explicitly set, so 'default-src' is used as a fallback.

17:16:10.824 login:1 [Report Only] Refused to load the font 'https://example.com/fonts/vazir/Vazir-Light-9127936b3852796d3a579028ff77a293.ttf?vsn=d' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'font-src' was not explicitly set, so 'default-src' is used as a fallback.

17:16:10.832 login:1 [Report Only] Refused to load the image 'https://example.com/images/login-bg.jpg' because it violates the following Content Security Policy directive: "img-src 'unsafe-inline' https://ssl.gstatic.com/ https://example.com/images/smal-example-logo.png https://stats.g.doubleclick.net https://www.google-analytics.com/ ".

17:16:10.889 login:1 [Report Only] Refused to load the image 'https://example.com/images/login-bg.jpg' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.

17:16:11.006 js?id=UA-105589342-1:62 [Report Only] Refused to load the script 'https://www.google-analytics.com/analytics.js' because it violates the following Content Security Policy directive: "script-src 'report-sample' 'unsafe-inline' 'nonce-DONT+TOUCH+TOOL+WILL+AUTOFILL+BASED+ON+SERVED+NONCE'".

17:16:11.027 login:1 [Report Only] Refused to load the script 'https://example.com/js/app-a81037d0ffa5bd95b8e2a38a2daca0cb.js?vsn=d' because it violates the following Content Security Policy directive: "script-src 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com/ https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/".

17:16:11.028 login:1 [Report Only] Refused to load the script 'https://example.com/js/app-a81037d0ffa5bd95b8e2a38a2daca0cb.js?vsn=d' because it violates the following Content Security Policy directive: "script-src 'report-sample' 'unsafe-inline' 'nonce-DONT+TOUCH+TOOL+WILL+AUTOFILL+BASED+ON+SERVED+NONCE'".

17:16:11.029 login:1 [Report Only] Refused to load the script 'https://example.com/js/app-a81037d0ffa5bd95b8e2a38a2daca0cb.js?vsn=d' because it violates the following Content Security Policy directive: "script-src 'strict-dynamic' 'report-sample' 'unsafe-inline' 'unsafe-eval' 'nonce-DONT+TOUCH+TOOL+WILL+AUTOFILL+BASED+ON+SERVED+NONCE'". 'strict-dynamic' is present, so host-based whitelisting is disabled.

17:16:11.032 login:1 [Report Only] Refused to load the script 'https://example.com/js/app-a81037d0ffa5bd95b8e2a38a2daca0cb.js?vsn=d' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.

17:16:11.329 login:1 [Report Only] Refused to load the script 'https://www.google.com/recaptcha/api.js?hl=fa' because it violates the following Content Security Policy directive: "script-src 'report-sample' 'unsafe-inline' 'nonce-DONT+TOUCH+TOOL+WILL+AUTOFILL+BASED+ON+SERVED+NONCE'".

17:16:11.333 login:1 [Report Only] Refused to load the script 'https://www.google.com/recaptcha/api.js?hl=fa' because it violates the following Content Security Policy directive: "script-src 'strict-dynamic' 'report-sample' 'unsafe-inline' 'unsafe-eval' 'nonce-DONT+TOUCH+TOOL+WILL+AUTOFILL+BASED+ON+SERVED+NONCE'". 'strict-dynamic' is present, so host-based whitelisting is disabled.

17:16:11.336 login:1 [Report Only] Refused to load the script 'https://www.google.com/recaptcha/api.js?hl=fa' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.

17:16:11.345 api.js?hl=fa:1 [Report Only] Refused to load the script 'https://www.gstatic.com/recaptcha/api2/v1543818755456/recaptcha__fa.js' because it violates the following Content Security Policy directive: "script-src 'report-sample' 'unsafe-inline' 'nonce-DONT+TOUCH+TOOL+WILL+AUTOFILL+BASED+ON+SERVED+NONCE'".

17:16:11.875 login:1 [Report Only] Refused to load the image 'https://www.google-analytics.com/r/collect?v=1&_v=j72&a=684254911&t=pageview&_s=1&dl=https%3A%2F%2Fexample.com%2Flogin&ul=en-us&de=UTF-8&dt=%D9%88%D8%B1%D9%88%D8%AF%20%D8%A8%D9%87%20%D8%B3%D8%A7%DB%8C%D8%AA%20-%20%D8%AA%D8%B1%D8%A7%D9%86%DA%AF%D9%84&sd=24-bit&sr=1366x768&vp=1351x235&je=0&_u=AACAAUAB~&jid=176315361&gjid=838732702&cid=973804971.1544859172&tid=UA-105589342-1&_gid=1912575447.1545081086&_r=1&gtm=2oubc0&z=280935752' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.

و در هر بار تست ، میشه قانونی رو به اون پلاگین اضافه کرد تا بررسی بکنه

قوانینی که تا الان نوشتم به این صورت هست(هنوز کامل نشده)

base-uri 
'self';

default-src 
'self'
'unsafe-inline'
https://www.google-analytics.com ;


script-src 
'unsafe-inline' 
https://www.googletagmanager.com 
https://www.google-analytics.com/
https://www.google.com/recaptcha/ 
https://www.gstatic.com/recaptcha/;

style-src 
'self' 
'unsafe-inline'
'sha256-JplxS3ZsBrP3aZQRQfTgHGXQ3qI60A+11PWJSWLulVA=' 
https://www.googletagmanager.com  
https://fonts.googleapis.com/ 
https://www.google.com/recaptcha/;

img-src 'unsafe-inline' 
https://ssl.gstatic.com/   
https://example.com/images/smal-example-logo.png  
https://stats.g.doubleclick.net 
https://www.google-analytics.com/ ;

frame-src 
https://www.gstatic.com/ 
https://www.google.com/ 
https://www.googletagmanager.com/ns.html;

font-src 
'self'
https://example.com/fonts/  
https://fonts.gstatic.com;

connect-src 
www.google-analytics.com 
https://www.google-analytics.com 
https://stats.g.doubleclick.net ;

object-src 
'none';

report-uri 
https://my_code.report-uri.com/r/d/csp/reportOnly
;

برای بررسی قوانین از این سایت استفاده میکنم
https://csp-evaluator.withgoogle.com

بیشترین خطاهایی که من برای csp دارم مربوط به google recaptcha و google analytics هست که برای حلشون از csp هایی که در داکیومنت گوگل هم بوده استفاده کردم ولی بازم مشکل داره

آیا روندی که دارم جلو میرم درسته ؟
راه بهتری برای درست کردنش وجود داره ؟
در اکثر خطوط بالا نگاه کنید اینو نوشته

'strict-dynamic' is present, so host-based whitelisting is disabled

در صورتیکه در قوانینی که من نوشتم اصلا از اون مورد استفاده نکردم به نظرتون چرا این گفته؟ آیا یکی از اون هدرهای nginx باعث اون شده ؟

در مورد عنصر nonce خونده بودم. یک کدی هست ، که باید توی هدر csp باشه به این صورت

'nonce-rAnd0m123'

و هم داخل هر تگ که به صورت inline

 <script type="text/javascript" nonce="rAnd0m123">alert('123');</script>

. و بر اساس هر بار رفرش شدن صفحه باید تغییر بکنه . حالا آیا این کد برای همه عناصر باید یکی باشه ؟‌یا اینکه برای هر عنصر باید متفاوت باشه؟


انتقال مقادیر بین صفحات در الکسیر
#2

من با آموزش هایی که در سایت های مختلف بود چندتا مشکل رو حل کردم ولی بعضی موارد رو انجام دادم اما خطا رفع نشده ،‌ یک csp generator پیدا کردم در این سایت

اونم تست کردم با اینکه قوانین رو خودش میسازه بازم اون یه سری موارد رو حل نمیکنه و اون موارد رو منم نتونستم حل بکنم :disappointed_relieved:

مثلا چند تا عکس من توی این مسیر دارم

https://example.com/images
https://example.com/images/pic1.png
https://example.com/images/pic2.png
https://example.com/images/pic3.png

و من چندین حالت رو تست کردم:

img-src  
'self' 
https://example.com/images/pic1.png
https://example.com/images
https://example.com/images/
https://example.com/images/*;

یا

img-src * 'self' data: https:;

یا

img-src  'self' data: filesystem: blob: ws: wss: https:;

ولی هیچ کدوم جواب نداده و بازم این خطا رو دارم :expressionless:

[Report Only] Refused to load the image 'https://example.com/images/smal-example-logo-354df0f2f90aa2b0s28da7416c107761.png?vsn=d' because it violates the following Content Security Policy directive: "default-src * 'unsafe-inline' 'strict-dynamic' data: filesystem: blob: ws: wss: ". 'strict-dynamic' is present, so host-based whitelisting is disabled. Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.

#3

سلام
مشکل با کمک دوست عزیز @shahryarjb حل شد . علتی که باعث شد با csp های مختلف و روش های دیگه همچنان خطا داشته باشم ، حتی با قوانین درست این بود که همه این موارد روی https برروی لوکال و افزونه مرورگر انجام شده بود و من فکر کرده بودم که حالا که https رو روی لوکال پیاده کرده یه محیطی نزدیک به محیط سرور روی اینترنت دارم ولی اینطور نبود . البته منطیقش این بود که با csp مشکل نداشته باشم چون csp سمت کاربر و با مرورگر چک میشه . همه قوانینی که نوشته بودم اکثرا درست بودن ولی روی لوکال عمل نمیکردن . همه رو روی یک کانتینر دیگه در سرور با یک دامنه جدا از دامنه اصلی اعمال کردم بیشتر ارورهایی که توی لوکال به من نشون داده میشد اونجا نبود ، من ۳۵ خطا روی لوکال داشتم وقتی بردم روی سرور رسید به ۵ تا . روی سرور نیاز به حالت report هم نبود در همون حالتی که csp روی مرورگر اعمال میشه ،‌کنسول هر عنصری که بلاک شده باشه رو نشون میده
مثلا

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self' 
'unsafe-inline'
https://www.googletagmanager.com  
https://fonts.googleapis.com/ 
https://www.google.com/recaptcha/
'strict-dynamic'
". Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.

از خطای بالا متوجه میشیم که style-src مشکل داره . بعد قانونش رو اصلاح و نتیجه رو بررسی کردم . فعلا که مشکلی ندارم .

قوانین نهایی

base-uri 'self';
default-src 'self' 'unsafe-inline' https://www.google-analytics.com ;
script-src 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com/ https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ 'strict-dynamic' 'nonce-hZwUTOrpRghioqmODf631g==';
style-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://fonts.googleapis.com/ https://www.google.com/recaptcha/ 'strict-dynamic' 'nonce-hZwUTOrpRghioqmODf631g==';
img-src 'unsafe-inline' https://ssl.gstatic.com/ example.com/images/ https://stats.g.doubleclick.net https://www.google-analytics.com/ ;
frame-src https://example.com/* example.com/https://example.com/ example.com https://www.gstatic.com/ https://www.google.com/ https://www.googletagmanager.com/ns.html;
font-src 'self' https://example.com/fonts/  https://fonts.gstatic.com;
connect-src www.google-analytics.com https://www.google-analytics.com https://stats.g.doubleclick.net ;
object-src 'none';

در خطوط بالا یه جایی nonce و یک رشته بلند نوشته شده اون رشته باید در هر درخواست صفحه تغییر بکنه یعنی به صورت رندوم باشه و غیر قابل حدس زدن و در تگ های زیر به این صورت اعمال بشه

<script nonce="hZwUTOrpRghioqmODf631g==">  </script>
<style nonce="hZwUTOrpRghioqmODf631g==">  </style>

جاهایی که css رو به صورت inline هم زدین سعی کنید مثل بالا داخل تگ style باشه تا بتونید بهش اون کد رندوم رو بدین تا مشکلی ایجاد نشه

در آینده قوانین csp که نشوتم باز نیاز به تغییرات داره و اینکه برای هر صفحه یه چیزهایی کم و زیاد میشه . البته علاوه بر اینکه شما این قوانین رو در کد html خودتون قرار دادین . باید در سرور nginx یا apache هم قرار بدین .

به این صورت

add_header Content-Security-Policy "base-uri 'self'; default-src 'self' 'unsafe-inline' https://www.google-analytics.com ; script-src 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com/ https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ 'strict-dynamic' 'nonce-hZwUTOrpRdsdlZmODf631g=='; style-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://fonts.googleapis.com/ https://www.google.com/recaptcha/ 'strict-dynamic' 'nonce-hZwUTOrpRdsdlZmODf631g=='; img-src 'unsafe-inline' https://ssl.gstatic.com/ example.com/images/ https://stats.g.doubleclick.net https://www.google-analytics.com/ ; frame-src https://example.com/* example.com/https://example.com/ example.com https://www.gstatic.com/ https://www.google.com/ https://www.googletagmanager.com/ns.html; font-src 'self' https://example.com/fonts/  https://fonts.gstatic.com; connect-src www.google-analytics.com https://www.google-analytics.com https://stats.g.doubleclick.net ; object-src 'none';";

برای اینکه چک کنید csp و هدرهای دیگه روی سایت و سرور اعمال شده میتونید از لینک زیر استفاده کنید

اطلاعات بیشتر در لینک
https://content-security-policy.com