Commit 8fbdc0d4ddc18ce405cf50944702c26c42885bce
Restrict private requests by Host and Referer
cel committed on 4/10/2020, 8:12:43 PMParent: d0d23d8d9e03d38b5f6a89d3ab680cd659544746
Files changed
index.js | changed |
index.js | ||
---|---|---|
@@ -38,11 +38,11 @@ | ||
38 | 38 … | |
39 | 39 … | function parseAddr(str, def) { |
40 | 40 … | if (!str) return def |
41 | 41 … | var i = str.lastIndexOf(':') |
42 | - if (~i) return {host: str.substr(0, i), port: str.substr(i+1)} | |
42 … | + if (~i) return {host: str.substr(0, i), port: Number(str.substr(i+1))} | |
43 | 43 … | if (isNaN(str)) return {host: str, port: def.port} |
44 | - return {host: def.host, port: str} | |
44 … | + return {host: def.host, port: Number(str)} | |
45 | 45 … | } |
46 | 46 … | |
47 | 47 … | function tryDecodeURIComponent(str) { |
48 | 48 … | if (!str || (str[0] == '%' && ref.isBlobId(str))) |
@@ -138,10 +138,12 @@ | ||
138 | 138 … | this.serveAcmeChallenge = require('./lib/acme-challenge')(ssb) |
139 | 139 … | |
140 | 140 … | var addr = parseAddr(config.listenAddr, { |
141 | 141 … | host: webConfig.host || 'localhost', |
142 | - port: webConfig.port || 7718 | |
142 … | + port: Number(webConfig.port) || 7718 | |
143 | 143 … | }) |
144 … | + this.listenHost = addr.host | |
145 … | + this.listenPort = addr.port | |
144 | 146 … | this.listen(addr.host, addr.port) |
145 | 147 … | |
146 | 148 … | this.monitorSsbClient() |
147 | 149 … | } |
@@ -213,8 +215,14 @@ | ||
213 | 215 … | if (req.url.startsWith('/.well-known/acme-challenge')) |
214 | 216 … | return this.serveAcmeChallenge(req, res) |
215 | 217 … | |
216 | 218 … | req._u = url.parse(req.url, true) |
219 … | + | |
220 … | + if (!this.isHostAllowed(req.headers.host)) { | |
221 … | + res.writeHead(403) | |
222 … | + return res.end('403 Forbidden') | |
223 … | + } | |
224 … | + | |
217 | 225 … | var locale = req._u.query.locale || |
218 | 226 … | (/locale=([^;]*)/.exec(req.headers.cookie) || [])[1] |
219 | 227 … | var reqLocales = req.headers['accept-language'] |
220 | 228 … | var locales = reqLocales ? reqLocales.split(/, */).map(function (item) { |
@@ -228,8 +236,35 @@ | ||
228 | 236 … | pull(this.handleRequest(req), serve(req, res)) |
229 | 237 … | }.bind(this)) |
230 | 238 … | } |
231 | 239 … | |
240 … | +G.isHostAllowed = function (hostname) { | |
241 … | + if (this.isPublic) return true | |
242 … | + if (!hostname) return false | |
243 … | + var addr = parseAddr(hostname, {port: 80}) | |
244 … | + if (addr.port !== this.listenPort) return false | |
245 … | + var host = addr.host | |
246 … | + return host === 'localhost' || | |
247 … | + host === '[::1]' || | |
248 … | + host === '127.0.0.1' || | |
249 … | + host === this.listenHost | |
250 … | +} | |
251 … | + | |
252 … | +var unsafePathRegex = /^\/(?:&|%26)|^%[^\/]+\/raw\// | |
253 … | + | |
254 … | +G.isRefererAllowed = function (referer) { | |
255 … | + if (this.isPublic) return true | |
256 … | + if (!referer) return false | |
257 … | + var u = url.parse(referer) | |
258 … | + return u.protocol === 'http:' | |
259 … | + && (Number(u.port) || 80) === this.listenPort | |
260 … | + && (u.hostname === this.listenHost | |
261 … | + || u.hostname === 'localhost' | |
262 … | + || u.hostname === '::1' | |
263 … | + || u.hostname === '127.0.0.1') | |
264 … | + && u.pathname && !unsafePathRegex.test(u.pathname) | |
265 … | +} | |
266 … | + | |
232 | 267 … | G.handleRequest = function (req) { |
233 | 268 … | var path = req._u.pathname.slice(1) |
234 | 269 … | var dirs = ref.isLink(path) ? [path] : |
235 | 270 … | path.split(/\/+/).map(tryDecodeURIComponent) |
@@ -263,8 +298,13 @@ | ||
263 | 298 … | G.handlePOST = function (req, dir) { |
264 | 299 … | var self = this |
265 | 300 … | if (self.isPublic) |
266 | 301 … | return self.serveBuffer(405, req._t('error.POSTNotAllowed')) |
302 … | + | |
303 … | + if (!self.isRefererAllowed(req.headers.referer)) { | |
304 … | + return this.serveBuffer(403, 'Referer not allowed') | |
305 … | + } | |
306 … | + | |
267 | 307 … | return u.readNext(function (cb) { |
268 | 308 … | readReqForm(req, function (err, data) { |
269 | 309 … | if (err) return cb(null, self.serveError(req, err, 400)) |
270 | 310 … | if (!data) return cb(null, self.serveError(req, |
Built with git-ssb-web