From 1bccbae725d6584ddabaa39c195bd227ab3e1722 Mon Sep 17 00:00:00 2001 From: Robert Landers Date: Mon, 4 Nov 2024 20:02:17 +0100 Subject: [PATCH 1/2] ensure php-self is normalized --- cgi.go | 3 ++- frankenphp_test.go | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/cgi.go b/cgi.go index e9bb736ad..9deafb4e0 100644 --- a/cgi.go +++ b/cgi.go @@ -7,6 +7,7 @@ import ( "crypto/tls" "net" "net/http" + "path" "path/filepath" "strings" ) @@ -80,7 +81,7 @@ func addKnownVariablesToServer(thread *phpThread, request *http.Request, fc *Fra registerTrustedVar(keys["REMOTE_PORT\x00"], port, trackVarsArray, thread) registerTrustedVar(keys["DOCUMENT_ROOT\x00"], fc.documentRoot, trackVarsArray, thread) registerTrustedVar(keys["PATH_INFO\x00"], fc.pathInfo, trackVarsArray, thread) - registerTrustedVar(keys["PHP_SELF\x00"], request.URL.Path, trackVarsArray, thread) + registerTrustedVar(keys["PHP_SELF\x00"], path.Clean(request.URL.Path), trackVarsArray, thread) registerTrustedVar(keys["DOCUMENT_URI\x00"], fc.docURI, trackVarsArray, thread) registerTrustedVar(keys["SCRIPT_FILENAME\x00"], fc.scriptFilename, trackVarsArray, thread) registerTrustedVar(keys["SCRIPT_NAME\x00"], fc.scriptName, trackVarsArray, thread) diff --git a/frankenphp_test.go b/frankenphp_test.go index 370c1b6ca..0b0870baa 100644 --- a/frankenphp_test.go +++ b/frankenphp_test.go @@ -176,6 +176,53 @@ func testServerVariable(t *testing.T, opts *testOptions) { }, opts) } +func TestUnusualServerVariable_module(t *testing.T) { + testUnusualServerVariable(t, nil) +} +func TestUnusualServerVariable_worker(t *testing.T) { + testUnusualServerVariable(t, &testOptions{workerScript: "server-variable.php"}) +} +func testUnusualServerVariable(t *testing.T, opts *testOptions) { + runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) { + req := httptest.NewRequest("POST", fmt.Sprintf("http://example.com//%%2f///server-variable.php%%2fbaz/bat?foo=a&bar=b&i=%d#hash", i), strings.NewReader("foo")) + req.SetBasicAuth(strings.Clone("kevin"), strings.Clone("password")) + req.Header.Add(strings.Clone("Content-Type"), strings.Clone("text/plain")) + w := httptest.NewRecorder() + handler(w, req) + + resp := w.Result() + body, _ := io.ReadAll(resp.Body) + + strBody := string(body) + + assert.Contains(t, strBody, "[REMOTE_HOST]") + assert.Contains(t, strBody, "[REMOTE_USER] => kevin") + assert.Contains(t, strBody, "[PHP_AUTH_USER] => kevin") + assert.Contains(t, strBody, "[PHP_AUTH_PW] => password") + assert.Contains(t, strBody, "[HTTP_AUTHORIZATION] => Basic a2V2aW46cGFzc3dvcmQ=") + assert.Contains(t, strBody, "[DOCUMENT_ROOT]") + assert.Contains(t, strBody, "[PHP_SELF] => /server-variable.php/baz/bat") + assert.Contains(t, strBody, "[CONTENT_TYPE] => text/plain") + assert.Contains(t, strBody, fmt.Sprintf("[QUERY_STRING] => foo=a&bar=b&i=%d#hash", i)) + assert.Contains(t, strBody, fmt.Sprintf("[REQUEST_URI] => //%%2f///server-variable.php%%2fbaz/bat?foo=a&bar=b&i=%d#hash", i)) + assert.Contains(t, strBody, "[CONTENT_LENGTH]") + assert.Contains(t, strBody, "[REMOTE_ADDR]") + assert.Contains(t, strBody, "[REMOTE_PORT]") + assert.Contains(t, strBody, "[REQUEST_SCHEME] => http") + assert.Contains(t, strBody, "[DOCUMENT_URI]") + assert.Contains(t, strBody, "[AUTH_TYPE]") + assert.Contains(t, strBody, "[REMOTE_IDENT]") + assert.Contains(t, strBody, "[REQUEST_METHOD] => POST") + assert.Contains(t, strBody, "[SERVER_NAME] => example.com") + assert.Contains(t, strBody, "[SERVER_PROTOCOL] => HTTP/1.1") + assert.Contains(t, strBody, "[SCRIPT_FILENAME]") + assert.Contains(t, strBody, "[SERVER_SOFTWARE] => FrankenPHP") + assert.Contains(t, strBody, "[REQUEST_TIME_FLOAT]") + assert.Contains(t, strBody, "[REQUEST_TIME]") + assert.Contains(t, strBody, "[SERVER_PORT] => 80") + }, opts) +} + func TestPathInfo_module(t *testing.T) { testPathInfo(t, nil) } func TestPathInfo_worker(t *testing.T) { testPathInfo(t, &testOptions{workerScript: "server-variable.php"}) From 1b20a86d0ebce70aa3a926dd4eb2dc377a3ffd25 Mon Sep 17 00:00:00 2001 From: Robert Landers Date: Mon, 4 Nov 2024 20:28:38 +0100 Subject: [PATCH 2/2] be even more strange --- frankenphp_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frankenphp_test.go b/frankenphp_test.go index 0b0870baa..8e925dbff 100644 --- a/frankenphp_test.go +++ b/frankenphp_test.go @@ -184,7 +184,7 @@ func TestUnusualServerVariable_worker(t *testing.T) { } func testUnusualServerVariable(t *testing.T, opts *testOptions) { runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) { - req := httptest.NewRequest("POST", fmt.Sprintf("http://example.com//%%2f///server-variable.php%%2fbaz/bat?foo=a&bar=b&i=%d#hash", i), strings.NewReader("foo")) + req := httptest.NewRequest("POST", fmt.Sprintf("http://example.com//%%2f///server-variable.php%%2fbaz///////bat?foo=a&bar=b&i=%d#hash", i), strings.NewReader("foo")) req.SetBasicAuth(strings.Clone("kevin"), strings.Clone("password")) req.Header.Add(strings.Clone("Content-Type"), strings.Clone("text/plain")) w := httptest.NewRecorder() @@ -204,7 +204,7 @@ func testUnusualServerVariable(t *testing.T, opts *testOptions) { assert.Contains(t, strBody, "[PHP_SELF] => /server-variable.php/baz/bat") assert.Contains(t, strBody, "[CONTENT_TYPE] => text/plain") assert.Contains(t, strBody, fmt.Sprintf("[QUERY_STRING] => foo=a&bar=b&i=%d#hash", i)) - assert.Contains(t, strBody, fmt.Sprintf("[REQUEST_URI] => //%%2f///server-variable.php%%2fbaz/bat?foo=a&bar=b&i=%d#hash", i)) + assert.Contains(t, strBody, fmt.Sprintf("[REQUEST_URI] => //%%2f///server-variable.php%%2fbaz///////bat?foo=a&bar=b&i=%d#hash", i)) assert.Contains(t, strBody, "[CONTENT_LENGTH]") assert.Contains(t, strBody, "[REMOTE_ADDR]") assert.Contains(t, strBody, "[REMOTE_PORT]")