forked from dsh/panel-auth
fix: treat Origin: null as absent instead of rejecting login
The audit diagnostics showed the real browser posting the login form with Origin: null (opaque context — sandboxed iframe, privacy proxy, or browser isolation product), which is not an attack signal. Skip the origin check for the literal "null" value; real cross-site posts with a concrete foreign origin are still rejected. Tests: Origin:null POST tolerated, foreign origin still 403.
This commit is contained in:
@@ -451,11 +451,19 @@ export function installGuard(server, guard, { audit, loginPath, logoutPath }) {
|
|||||||
// Cross-origin form posts are rejected: the login form must come from this host.
|
// Cross-origin form posts are rejected: the login form must come from this host.
|
||||||
// Hostname-level comparison tolerates port/case differences that proxies
|
// Hostname-level comparison tolerates port/case differences that proxies
|
||||||
// or alternate listeners introduce, while still blocking foreign sites.
|
// or alternate listeners introduce, while still blocking foreign sites.
|
||||||
|
// `Origin: null` (opaque contexts: sandboxed iframes, privacy proxies,
|
||||||
|
// browser isolation) carries no usable origin information — treat it like
|
||||||
|
// an absent header instead of rejecting real users.
|
||||||
const origin = req.headers.origin
|
const origin = req.headers.origin
|
||||||
const host = req.headers.host
|
const host = req.headers.host
|
||||||
const ip = clientIp(req)
|
const ip = clientIp(req)
|
||||||
const ua = req.headers['user-agent'] ?? ''
|
const ua = req.headers['user-agent'] ?? ''
|
||||||
if (typeof origin === 'string' && typeof host === 'string' && !sameHost(origin, host)) {
|
if (
|
||||||
|
typeof origin === 'string' &&
|
||||||
|
origin !== 'null' &&
|
||||||
|
typeof host === 'string' &&
|
||||||
|
!sameHost(origin, host)
|
||||||
|
) {
|
||||||
audit.write({
|
audit.write({
|
||||||
event: 'login-fail',
|
event: 'login-fail',
|
||||||
username: '',
|
username: '',
|
||||||
|
|||||||
@@ -94,6 +94,10 @@ assert.match(await r.text(), /非法请求来源/)
|
|||||||
r = await post('/panel-auth/login', 'username=admin&password=s3cret-pass&next=%2F', { Origin: 'http://127.0.0.1:9999' })
|
r = await post('/panel-auth/login', 'username=admin&password=s3cret-pass&next=%2F', { Origin: 'http://127.0.0.1:9999' })
|
||||||
assert.equal(r.status, 303)
|
assert.equal(r.status, 303)
|
||||||
|
|
||||||
|
// 5d. `Origin: null` (opaque context: privacy proxy / sandboxed iframe) → tolerated
|
||||||
|
r = await post('/panel-auth/login', 'username=admin&password=s3cret-pass&next=%2F', { Origin: 'null' })
|
||||||
|
assert.equal(r.status, 303)
|
||||||
|
|
||||||
// 6. POST login with correct credentials → 303 + cookie + next
|
// 6. POST login with correct credentials → 303 + cookie + next
|
||||||
r = await post('/panel-auth/login', 'username=admin&password=s3cret-pass&next=%2Fsome%2Fpage')
|
r = await post('/panel-auth/login', 'username=admin&password=s3cret-pass&next=%2Fsome%2Fpage')
|
||||||
assert.equal(r.status, 303)
|
assert.equal(r.status, 303)
|
||||||
|
|||||||
Reference in New Issue
Block a user