Category:OWASP Proxy

Welcome to the OWASP Proxy

The OWASP Proxy aims to provide a high quality intercepting proxy library which can be used by developers who require this functionality in their own programs, rather than having to develop it all from scratch.

The library is developed in Java, making it most attractive to Java developers obviously, but also accessible to Python (Jython) and Ruby (JRuby) developers as well.

Overview
One of the priorities of this project is to allow developers to do whatever they choose, without enforcing RFC compliance. This is important for a security testing library, as often the most interesting behavior manifests outside the RFCs! Keep in mind that a lot of the safety nets that exist in libraries that enforce RFC compliance do not exist in this library, and that as the developer, you need to be prepared to deal with the consequences!

Another priority is to accurately deliver whatever is specified by the client, and similarly, to accurately reflect whatever is returned by the server, rather than coloured by the parsing and normalisation performed by the library.

Download
At the moment there is no packaged version of this library. Development is done in a git repository, located here.

Interested parties can download a snapshot of the code at any point using the snapshot link next to each revision, or clone the repository:

$ git clone http://dawes.za.net/rogan/owasp-proxy/owasp-proxy.git/

Implementation details
In order to achieve byte for byte accuracy with what was sent by the client, and received from the server, OWASP Proxy does the bare minimum of message parsing. The basic storage of an HTTP message is as an array of byte (a byte for byte copy of what was read from the network), rather than parsed out into convenient pieces. The library does provide convenience methods for accessing interesting parts of the message, such as headers, content, etc, but the message itself is always stored as a large byte[].

The Request and Response objects that you may deal with also do not decode the message bodies for you. If the message was sent using chunked encoding, the message body will show the individual chunks that were sent. Of course, again, there are also classes which allow you to obtain the actual entity body, with appropriate decoding.

Future development
As mentioned above, one objective is correctness. By this I mean correctly handling whatever the major browsers send to it, and successfully retrieving whichever resource was requested. Failure to do so will be addressed as soon as possible.

Other than that, there is no intention to add major new features to the library above those required to fulfill its purpose as a Lstener and a HTTP client implementation.

One feature which is under serious consideration is the ability to proxy upstream requests via a SOCKS proxy, for example, as implemented by OpenSSH.

Extensibility
The library attempts to provide the necessary extension points to allow developers access to the major lifecycle events of a request and a response. Here are the major methods that can be overridden:

/**        * Override this method to control SSL support. * Return null to disable SSL CONNECT support *         * @param host *           the host that the client wishes to CONNECT to         * @param port *           the port that the client wishes to CONNECT to         * @return an SSLSocketFactory generated from the relevant server key *        material, or null to disable CONNECT support */       protected SSLSocketFactory getSocketFactory(String host, int port) { return null; }

/**        * Override this method to configure your HttpClient. * For example, configure it to use an upstream proxy *         * @return a preconfigured HttpClient */       protected HttpClient createHttpClient { return new HttpClient; }

A developer wishing to implement an in-browser interface to their application can override this method. If the request refers to your UI, simply return an appropriate Response here, and that Response will be returned to the client. Returning null will allow the (possibly modified) Request to be sent on to the server.

/**        * Called when a request is received by the proxy. Changes can be made to        * the Request object to alter what will be sent to the server. *         * @param request *           the Request received from the client * @return a custom Response to be sent directly back to the client without *        making any request to a server, or null to forward the Request * @throws MessageFormatException *            if the request cannot be parsed */       protected Response requestReceived(Request request) throws MessageFormatException { return null; }

/**        * Called when an error is encountered while reading the request from the * client. *         * @param request * @param e        * @return a customized Response to be sent to the browser, or null to send *        the default error message * @throws MessageFormatException *            if the request couldn't be parsed */       protected Response errorReadingRequest(Request request, Exception e)                        throws MessageFormatException { return null; }

/**        * Called when the Response headers have been read from the server. The * response content (if any) will not yet have been read. Analysis can be        * performed based on the headers to determine whether to intercept the * complete response at a later stage. If you wish to intercept the complete * response message at a later stage, return false from this method to        * disable streaming of the response content, otherwise the response would * already have been written to the browser when responseContentReceived is        * called. *         * Note: If you modify the response headers in this method, be very careful * not to affect the retrieval of the response content. For example, * deleting a "Transfer-Encoding: chunked" header would be a bad idea! *         * @param conversation * @return true to stream the response to the client as it is being read *        from the server, or false to delay writing the response to the *        client until after responseContentReceived is called * @throws MessageFormatException *            if either the request or response couldn't be parsed */       protected boolean responseHeaderReceived(Conversation conversation) throws MessageFormatException { return true; }

/**        * Called after the Response content has been received from the server. If        * streamed is false, the response can be modified here, and the modified * version will be written to the client. *         * @param conversation * @param streamed *           true if the response has already been written to the client * @throws MessageFormatException *            if either the request or response couldn't be parsed */       protected void responseContentReceived(Conversation conversation,                        boolean streamed) throws MessageFormatException { }

/**        * Called in the event of an error occurring while reading the response * header from the client *         * @param request * @param e        * @return a custom Response to be sent to the client, or null to use the *        default * @throws MessageFormatException *            if either the request or response couldn't be parsed */       protected Response errorFetchingResponseHeader(Request request, Exception e)                        throws MessageFormatException { return null; }

/**        * Called in the event of an error occurring while reading the response * content from the client *         * @param conversation * @param e        * @return a custom Response to be sent to the client, or null to use the *        default * @throws MessageFormatException *            if either the request or response couldn't be parsed */       protected Response errorFetchingResponseContent(Conversation conversation,                        Exception e) throws MessageFormatException { return null; }

protected void wroteResponseToBrowser(Conversation conversation) throws MessageFormatException { }

protected void errorWritingResponseToBrowser(Conversation conversation,                       Exception e) throws MessageFormatException { }

Project Contributors
The OWASP Proxy project is run by Rogan Dawes of Corsaire Security. He can be contacted at rogan AT dawes.za.net