fix(back): index 页 back 校验拒绝 nested back + 调整测试断言
This commit is contained in:
@@ -34,7 +34,10 @@
|
|||||||
$incomingBack = (string) request()->query('back', '');
|
$incomingBack = (string) request()->query('back', '');
|
||||||
// 为避免 & 被 Blade escape 成 & 导致回退上下文丢失,这里需要原样输出 href。
|
// 为避免 & 被 Blade escape 成 & 导致回退上下文丢失,这里需要原样输出 href。
|
||||||
// 安全护栏:必须为站内相对路径,并拒绝引号/尖括号,降低 XSS 风险。
|
// 安全护栏:必须为站内相对路径,并拒绝引号/尖括号,降低 XSS 风险。
|
||||||
$safeBack = (str_starts_with($incomingBack, '/') && !preg_match('/["\'<>]/', $incomingBack))
|
$safeBack = (str_starts_with($incomingBack, '/')
|
||||||
|
&& !preg_match('/["\'<>]/', $incomingBack)
|
||||||
|
// back 本身不应再包含 back(避免无限嵌套导致 URL 膨胀)
|
||||||
|
&& !preg_match('/(?:^|[?&])back=/', $incomingBack))
|
||||||
? $incomingBack
|
? $incomingBack
|
||||||
: '';
|
: '';
|
||||||
@endphp
|
@endphp
|
||||||
@@ -78,7 +81,10 @@
|
|||||||
|
|
||||||
// “全部”:清空筛选,但保留 back(用于返回来源页)
|
// “全部”:清空筛选,但保留 back(用于返回来源页)
|
||||||
$incomingBack = (string) request()->query('back', '');
|
$incomingBack = (string) request()->query('back', '');
|
||||||
$safeBack2 = (str_starts_with($incomingBack, '/') && !preg_match('/["\'<>]/', $incomingBack))
|
$safeBack2 = (str_starts_with($incomingBack, '/')
|
||||||
|
&& !preg_match('/["\'<>]/', $incomingBack)
|
||||||
|
// back 本身不应再包含 back(避免无限嵌套导致 URL 膨胀)
|
||||||
|
&& !preg_match('/(?:^|[?&])back=/', $incomingBack))
|
||||||
? $incomingBack
|
? $incomingBack
|
||||||
: '';
|
: '';
|
||||||
$allUrl = '/admin/plans';
|
$allUrl = '/admin/plans';
|
||||||
|
|||||||
@@ -25,7 +25,10 @@
|
|||||||
$back = (string) request()->query('back', '');
|
$back = (string) request()->query('back', '');
|
||||||
// 为避免 & 被 Blade escape 成 & 导致回退上下文丢失,这里需要原样输出 href。
|
// 为避免 & 被 Blade escape 成 & 导致回退上下文丢失,这里需要原样输出 href。
|
||||||
// 安全护栏:必须为站内相对路径,并拒绝引号/尖括号,降低 XSS 风险。
|
// 安全护栏:必须为站内相对路径,并拒绝引号/尖括号,降低 XSS 风险。
|
||||||
$safeBack = (str_starts_with($back, '/') && !preg_match('/["\'<>]/', $back))
|
$safeBack = (str_starts_with($back, '/')
|
||||||
|
&& !preg_match('/["\'<>]/', $back)
|
||||||
|
// back 本身不应再包含 back(避免无限嵌套导致 URL 膨胀)
|
||||||
|
&& !preg_match('/(?:^|[?&])back=/', $back))
|
||||||
? $back
|
? $back
|
||||||
: '';
|
: '';
|
||||||
@endphp
|
@endphp
|
||||||
@@ -113,7 +116,10 @@
|
|||||||
|
|
||||||
// “全部”:清空筛选,但保留 back(用于返回来源页)
|
// “全部”:清空筛选,但保留 back(用于返回来源页)
|
||||||
$incomingBack = (string) request()->query('back', '');
|
$incomingBack = (string) request()->query('back', '');
|
||||||
$safeBack = (str_starts_with($incomingBack, '/') && !preg_match('/["\'<>]/', $incomingBack))
|
$safeBack = (str_starts_with($incomingBack, '/')
|
||||||
|
&& !preg_match('/["\'<>]/', $incomingBack)
|
||||||
|
// back 本身不应再包含 back(避免无限嵌套导致 URL 膨胀)
|
||||||
|
&& !preg_match('/(?:^|[?&])back=/', $incomingBack))
|
||||||
? $incomingBack
|
? $incomingBack
|
||||||
: '';
|
: '';
|
||||||
$allUrl = '/admin/platform-orders';
|
$allUrl = '/admin/platform-orders';
|
||||||
|
|||||||
@@ -42,7 +42,10 @@
|
|||||||
$incomingBack = (string) request()->query('back', '');
|
$incomingBack = (string) request()->query('back', '');
|
||||||
// 为避免 & 被 Blade escape 成 & 导致回退上下文丢失,这里需要原样输出 href。
|
// 为避免 & 被 Blade escape 成 & 导致回退上下文丢失,这里需要原样输出 href。
|
||||||
// 安全护栏:必须为站内相对路径,并拒绝引号/尖括号,降低 XSS 风险。
|
// 安全护栏:必须为站内相对路径,并拒绝引号/尖括号,降低 XSS 风险。
|
||||||
$safeBack = (str_starts_with($incomingBack, '/') && !preg_match('/["\'<>]/', $incomingBack))
|
$safeBack = (str_starts_with($incomingBack, '/')
|
||||||
|
&& !preg_match('/["\'<>]/', $incomingBack)
|
||||||
|
// back 本身不应再包含 back(避免无限嵌套导致 URL 膨胀)
|
||||||
|
&& !preg_match('/(?:^|[?&])back=/', $incomingBack))
|
||||||
? $incomingBack
|
? $incomingBack
|
||||||
: '';
|
: '';
|
||||||
@endphp
|
@endphp
|
||||||
@@ -88,7 +91,10 @@
|
|||||||
|
|
||||||
// “全部”:清空筛选,但保留 back(用于返回来源页)
|
// “全部”:清空筛选,但保留 back(用于返回来源页)
|
||||||
$incomingBack = (string) request()->query('back', '');
|
$incomingBack = (string) request()->query('back', '');
|
||||||
$safeBack = (str_starts_with($incomingBack, '/') && !preg_match('/["\'<>]/', $incomingBack))
|
$safeBack = (str_starts_with($incomingBack, '/')
|
||||||
|
&& !preg_match('/["\'<>]/', $incomingBack)
|
||||||
|
// back 本身不应再包含 back(避免无限嵌套导致 URL 膨胀)
|
||||||
|
&& !preg_match('/(?:^|[?&])back=/', $incomingBack))
|
||||||
? $incomingBack
|
? $incomingBack
|
||||||
: '';
|
: '';
|
||||||
$allUrl = '/admin/site-subscriptions';
|
$allUrl = '/admin/site-subscriptions';
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ class AdminPlatformOrderIndexBackLinkNotEscapedTest extends TestCase
|
|||||||
|
|
||||||
$this->get('/admin/platform-orders?back=' . urlencode('https://evil.example.com/?x=1&y=2'))
|
$this->get('/admin/platform-orders?back=' . urlencode('https://evil.example.com/?x=1&y=2'))
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertDontSee('返回上一页(保留上下文)');
|
// 页面仍会出现“返回上一页(保留上下文)”文案(其它位置也有,例如治理SOP卡提示),
|
||||||
|
// 因此这里改为断言:不应出现该 external back 的 href。
|
||||||
|
->assertDontSee('href="https://evil.example.com/?x=1&y=2"', false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user