https://kotlinlang.org logo
#http4k
Title
# http4k
a

Andrew O'Hara

03/21/2024, 4:02 PM
My team had a pentest done, and they managed to get a Jetty stacktrace in a response by using an invalid URL. They see this is a vulnerability, even though my actual application guards against leaking stacktraces. Is this something that http4k's server wrapper should be guarding against? Or should I just ignore the result? Because all it says is that the server is using Jetty, which is already advertised in the Jetty response headers.
d

dave

03/21/2024, 4:05 PM
where did the stacktrace originate?
We generally use a CatchAll filter to catch any unhandled exceptions that originate inside the http4k layers
Generally the app writer is responsible for decorating their http handlers
just out of interest - what was the URL?
it's better to never return a stack to a public call TBH
a

Andrew O'Hara

03/21/2024, 4:47 PM
It seems to have been caused by a
//
. The stacktrace was from Jetty itself. Never hit my application. Not sure if this is Jetty's fault, or if there was something the http4k wrapper for Jetty could have configured to avoid it.
d

dave

03/21/2024, 4:47 PM
can you see http4k anywhere in the stack?
if you can then there's something we can do about it
a

Andrew O'Hara

03/21/2024, 4:49 PM
Ok so I just reproduced it myself and got this. Http4k isn't in the stacktrace, but http4k is the one that configures the jetty server during init. I figure if there's a way we can compensate for it, it would be there.
Copy code
org.eclipse.jetty.http.BadMessageException: 400: Ambiguous URI empty segment
	at org.eclipse.jetty.server.internal.HttpConnection$HttpStreamOverHTTP1.headerComplete(HttpConnection.java:1189)
	at org.eclipse.jetty.server.internal.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:959)
	at org.eclipse.jetty.http.HttpParser.parseFields(HttpParser.java:1251)
	at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:1543)
	at org.eclipse.jetty.server.internal.HttpConnection.parseRequestBuffer(HttpConnection.java:580)
	at org.eclipse.jetty.server.internal.HttpConnection.onFillable(HttpConnection.java:404)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:322)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:99)
	at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
	at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:478)
	at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:441)
	at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:293)
	at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run(AdaptiveExecutionStrategy.java:201)
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:410)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:971)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1201)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1156)
	at java.base/java.lang.Thread.run(Unknown Source)
d

dave

03/21/2024, 4:50 PM
well regardless - I think this should be a jetty thing - they shouldn't be leaking a stacktrace.. maybe open an issue in jetty?
a

Andrew O'Hara

03/21/2024, 4:51 PM
Yeah, probably Jetty's responsibility 🤷 . I'll see about posting an issue.
d

dave

03/21/2024, 4:54 PM
@Andrew O'Hara I wrote a quick test in the server contract... looks like just Jetty 12 affected
TFFT 😉
a

Andrew O'Hara

03/21/2024, 5:02 PM
Not sure what TFFT means 😛
d

dave

03/21/2024, 5:03 PM
Thank Flip For Tests!
🙃 1
a

Andrew O'Hara

03/21/2024, 5:03 PM
I see even the latest Jetty 12 version exhibits the issue too
d

dave

03/21/2024, 5:03 PM
or something equivalent..
😁 1
a

Andrew O'Hara

03/21/2024, 5:04 PM
Jetty will probably want a way to reproduce the issue with pure Jetty, so I'll see about that later. Thanks for confirming it's only Jetty 12
d

dave

03/21/2024, 5:04 PM
The test I wrote was just in the ServerContract
Copy code
@Test
    fun `illegal url`() {
        assertThat(client(Request(GET, "$baseUrl/v1/foo//bar")).bodyString().lowercase(), !containsSubstring("exception"))
    }
a

Andrew O'Hara

03/21/2024, 5:05 PM
What does Jetty 11 return?
d

dave

03/21/2024, 5:06 PM
Copy code
<h1>Bad Message 400</h1><pre>reason: Ambiguous URI empty segment</pre>
a

Andrew O'Hara

03/21/2024, 5:07 PM
Yeah, that's better
Security report away!
a

andyg

03/21/2024, 6:27 PM
exposing the stacktrace appears to be a long-running issue: https://stackoverflow.com/questions/62331132/disable-the-default-stacktrace-error-response-in-jetty you could of course create a custom error page, or use your reverse proxy to sanitize/reject similar URLs
a

Andrew O'Hara

03/22/2024, 1:30 PM
So after talking to the Jetty security team about it. They don't see this as a security issue, and point out that you can even disable stacktraces by configuring the default error handler. So http4k could override this if it wanted. However, they admit it might be more appropriate to make suppression the default action, and appear to be making a PR to change it.
d

dave

03/22/2024, 1:48 PM
I'm hesitant to make the ServerConfigs more complicated than absolutely necessary. Let's see what they come back with.
a

Andrew O'Hara

03/22/2024, 2:58 PM
They're changing the default in 12.0.8
🎉 2
d

dave

03/22/2024, 2:58 PM
👍