dependency injection - How do I get Jersey to call a resource method with an HttpServletResponse wrapper? -
i trying systematically address http response splitting. have developed wrapper class httpservletresponse called hardenedhttpservletresponse mitigates splitting attempts.
regrettably, cannot jersey call resource method hardenedhttpservletresponse. nulls when try.
here contrived jax-rs resource http response splitting vulnerability exploitable putting percent-encoded crlfs (%0d%0a
) in filename query parameter:
attachmentresource.java:
import javax.servlet.http.httpservletresponse; import javax.ws.rs.post; import javax.ws.rs.path; import javax.ws.rs.produces; import javax.ws.rs.queryparam; import javax.ws.rs.core.context; import javax.ws.rs.core.mediatype; @path("/attachment") @produces(mediatype.application_json) public final class attachmentresource { @get @path("/file") public streamingoutput getattachment( @context httpservletresponse response, @queryparam("filename") string filename ) throws exception { response.setheader( "content-disposition", "attachment; filename=" + filename ); return new dummystreamingoutput(); } }
here dummy implementation of streamingoutput make full example:
dummystreamingoutput.java:
import javax.ws.rs.webapplicationexception; import javax.ws.rs.core.streamingoutput; import java.io.ioexception; import java.io.outputstream; import java.nio.charset.standardcharsets; private static dummyfilestreamingoutput implements streamingoutput { @override public void write(outputstream outputstream) throws ioexception, webapplicationexception { string message = "hello, world!"; byte[] bytes = message.getbytes(standardcharsets.utf_8); outputstream.write(bytes); outputstream.flush(); outputstream.close(); } }
here httpservletresponse wrapper class mitigates http response splitting throwing exception if detects cr or lf characters in header names or values:
hardenedhttpservletresponse.java:
import javax.inject.inject; import javax.servlet.http.httpservletresponse; import javax.servlet.http.httpservletresponsewrapper; import javax.ws.rs.core.context; final class hardenedhttpservletresponse extends httpservletresponsewrapper { @inject hardenedhttpservletresponse(@context httpservletresponse response) { super(response); } @override public void setheader(string name, string value) { mitigateresponsesplitting(name); mitigateresponsesplitting(value); super.setheader(name, value); } @override public void addheader(string name, string value) { mitigateresponsesplitting(name); mitigateresponsesplitting(value); super.setheader(name, value); } @override public void setintheader(string name, int value) { mitigateresponsesplitting(name); super.setintheader(name, value); } @override public void setdateheader(string name, long date) { mitigateresponsesplitting(name); super.setdateheader(name, date); } private void mitigateresponsesplitting(string value) { if (value != null && (value.contains("\r") || value.contains("\n"))) { throw new httpresponsesplittingexception(); } } }
jersey supplies actual response object if response parameter has type @context httpservletresponse, null if response parameter has type @context hardenedhttpservletresponse.
how jersey call resource method httpservletresponse wrapper?
you can make injectable adding di system.
resourceconfig.register(new abstractbinder() { @override public void configure() { bindascontract(hardenedhttpservletresponse.class) .proxy(false) .proxyforsamescope(false) .in(requestscoped.class); } });
you need make class public
, constructor public, di system can create it. allow inject hardenedhttpservletresponse
see also:
Comments
Post a Comment