From cbc05e59b7f601d833e99cd4c3ad0dbd87c7531c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=9D=E5=8D=9C?= Date: Sun, 15 Mar 2026 04:17:10 +0000 Subject: [PATCH] =?UTF-8?q?BackUrl::sanitizeForLinks=20=E5=A2=9E=E5=BC=BA?= =?UTF-8?q?=EF=BC=9A=E6=8B=92=E7=BB=9D=E6=8E=A7=E5=88=B6=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=8E=20CRLF=20=E6=B3=A8=E5=85=A5=20=E5=B9=B6=E8=A1=A5?= =?UTF-8?q?=E5=8D=95=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Support/BackUrl.php | 8 ++++++++ tests/Unit/BackUrlSanitizeForLinksTest.php | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/app/Support/BackUrl.php b/app/Support/BackUrl.php index 5e92a3e..0b76f1f 100644 --- a/app/Support/BackUrl.php +++ b/app/Support/BackUrl.php @@ -26,6 +26,14 @@ class BackUrl return ''; } + // 拒绝控制字符/CRLF 注入(包括明文与常见 URL 编码形式) + if (preg_match('/[\r\n\t]/', $incomingBack)) { + return ''; + } + if (preg_match('/%0d|%0a|%09/i', $incomingBack)) { + return ''; + } + // 拒绝 back 自身再包含 back=(避免无限嵌套导致 URL 膨胀,且容易绕过页面侧护栏) // 同时拒绝“二次编码”的 back%3D(例如 %2526back%253D 经过一次 urldecode 后变成 %26back%3D, // 在浏览器点击后会再次被解码为 &back=,形成绕过)。 diff --git a/tests/Unit/BackUrlSanitizeForLinksTest.php b/tests/Unit/BackUrlSanitizeForLinksTest.php index df6c182..f35cf2b 100644 --- a/tests/Unit/BackUrlSanitizeForLinksTest.php +++ b/tests/Unit/BackUrlSanitizeForLinksTest.php @@ -24,6 +24,10 @@ class BackUrlSanitizeForLinksTest extends TestCase $this->assertSame('', BackUrl::sanitizeForLinks("/admin/x?keyword='a'")); $this->assertSame('', BackUrl::sanitizeForLinks('/admin/x?a=')); $this->assertSame('', BackUrl::sanitizeForLinks('/admin/x?a=>')); + + // 控制字符/CRLF 注入 + $this->assertSame('', BackUrl::sanitizeForLinks("/admin/x?x=1\nSet-Cookie:evil=1")); + $this->assertSame('', BackUrl::sanitizeForLinks('/admin/x?x=1%0aSet-Cookie:evil=1')); } public function test_sanitize_for_links_should_reject_nested_back_param(): void