fix(back): index 页 back 校验拒绝 nested back + 调整测试断言
This commit is contained in:
@@ -34,7 +34,10 @@
|
||||
$incomingBack = (string) request()->query('back', '');
|
||||
// 为避免 & 被 Blade escape 成 & 导致回退上下文丢失,这里需要原样输出 href。
|
||||
// 安全护栏:必须为站内相对路径,并拒绝引号/尖括号,降低 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
|
||||
: '';
|
||||
@endphp
|
||||
@@ -78,7 +81,10 @@
|
||||
|
||||
// “全部”:清空筛选,但保留 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
|
||||
: '';
|
||||
$allUrl = '/admin/plans';
|
||||
|
||||
@@ -25,7 +25,10 @@
|
||||
$back = (string) request()->query('back', '');
|
||||
// 为避免 & 被 Blade escape 成 & 导致回退上下文丢失,这里需要原样输出 href。
|
||||
// 安全护栏:必须为站内相对路径,并拒绝引号/尖括号,降低 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
|
||||
: '';
|
||||
@endphp
|
||||
@@ -113,7 +116,10 @@
|
||||
|
||||
// “全部”:清空筛选,但保留 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
|
||||
: '';
|
||||
$allUrl = '/admin/platform-orders';
|
||||
|
||||
@@ -42,7 +42,10 @@
|
||||
$incomingBack = (string) request()->query('back', '');
|
||||
// 为避免 & 被 Blade escape 成 & 导致回退上下文丢失,这里需要原样输出 href。
|
||||
// 安全护栏:必须为站内相对路径,并拒绝引号/尖括号,降低 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
|
||||
: '';
|
||||
@endphp
|
||||
@@ -88,7 +91,10 @@
|
||||
|
||||
// “全部”:清空筛选,但保留 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
|
||||
: '';
|
||||
$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'))
|
||||
->assertOk()
|
||||
->assertDontSee('返回上一页(保留上下文)');
|
||||
// 页面仍会出现“返回上一页(保留上下文)”文案(其它位置也有,例如治理SOP卡提示),
|
||||
// 因此这里改为断言:不应出现该 external back 的 href。
|
||||
->assertDontSee('href="https://evil.example.com/?x=1&y=2"', false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user