HTTP 403 Forbidden Message Format - http

What is the correct format for sending an HTTP 403 forbidden message?
I'm writing a proxy in c for a homework project that has a content filtering system built in. When my proxy detects that a server's response has certain keywords that are contained in the content blacklist, I would like to send a HTTP 403 Forbidden message.
Currently, I am sending the message as: "HTTP/1.1 403 Forbidden\r\n\r\n" (without the quotes) as per this standard: https://www.rfc-editor.org/rfc/rfc7231#section-6.5.3
When I send this message, the browser doesn't display an error and looks like it's still trying to load the page.
Are there any required header fields for this http message that I missed? Also, is this the correct usage for the 403 error? I couldn't find anything else that would be more fitting, so I chose 403 because the client won't automatically re-request the data.
Thanks in advance for any help!

For those struggling with this issue as I did, you need to make sure to close the socket or set Connection: Close as Sami noted in the comments. I assumed that you could keep it open so they could send another request with http persistent connections, but they will need to open a new connection.
As for the html displayed, you can send a body with the response (make sure you set Content-Length) that contains the html you want displayed.
Finally, here are two references, one to the HTTP response spec, and the other to the Amazon Restful response spec:
https://www.rfc-editor.org/rfc/rfc7231#section-6.5.3
https://developer.amazon.com/docs/amazon-drive/ad-restful-api-response-codes.html

Related

Is it possible for an HTTP server to interrupt and replace a response in progress?

Supposing I was to stream a large response to a browser, or other HTTP client; is there a way for the server to return an HTTP 500 error page mid-way through the download?
For example, I may be serving a very large HTML page, or perhaps displaying a large JPEG file in its own tab, and the data-source is terminated prematurely. At this point I want to show my standard HTTP 500 error page.
If it helps, I can use Content-Transfer-Encoding: chunked, or even other hackish HTTP headers to make this work.
Is it possible to override a download result on the HTTP level?
I know one could add a JavaScript alert if the response were in HTML format, but I'm just wondering if I can override / restart the response on the HTTP level instead?

Is it suitable to use 200 HTTP status code for a forbidden web page?

What is the difference when we use 200 response status code for a forbidden page with an error message saying 'Access Denied' instead of using 403 response status code?
Are there any security implications?
The HTTP Response codes convey information about how the server has processed your request. So, if the server responds with 200, it means: "OK, I have received your request and processed it successfully". If it returns 403, it would mean: "I received your request successfully, but you don't have access to this resource".
However, technically they are both returned in the same format, in the same way in the response HTTP header like this:
HTTP/1.1 200 OK
HTTP/1.1 403 Forbidden
The difference is in the meaning. And the meanings are defined in the standard.
So, when you are responding with code 200, you are telling the client that it is all good and dandy. If you are responding to client with 403, you are saying that the client doesn't have permission to this resource. Remember, there can be different clients: web browsers, crawlers, ajax requests from javascript, etc.
So, if you are sending a login form with 200 code:
Users who are using a web browser would understand that they need to login.
Google crawler will index your members/quality-content URL with the login form and will not understand that actually, the original content is different and it should not index this page with the login form.
Javascript with ajax callback will run success callback, when it should be running error callback function.
So, basically, make us all a favour and follow the standards! :)
Answering your second question, no it does not make your application any less secure.
The reason for this decision might be that error message was not visiable using Internet explorer like described here: How do I suppress "friendly error messages" in Internet Explorer?
Actually the correct way is to use the right HTTP error code and make the error message longer than 512 bytes as described here:
https://support.microsoft.com/en-us/kb/294807
Response status codes are intended to help the client to understand the result of the request. Whenever possible, you should use the proper status codes.
The semantics of the status codes are defined in the RFC 7231, the current reference for HTTP/1.1.
While the 200 status code indicates that the request has succeeded, the 403 status code indicates that the server understood the request but refuses to authorize it:
6.3.1. 200 OK
The 200 (OK) status code indicates that the request has succeeded. The payload sent in a 200 response depends on the request method. [...]
6.5.3. 403 Forbidden
The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it. A server that wishes to make public why the request has been forbidden can describe that reason in the response payload (if any). [...]
Returning 200 will work, for sure. But why would you return 200 if you can return a much more meaningful status code? If is there any good reason, this should be added to your question.

What HTTP status code use when the required header is not specified?

If the user sends request to the server and the link requires specific custom headers to be set in order to work. In this case the error code should be 400, 403 or 422 ?
The HTTP specification requires any client to treat the response as 400 by default if it does not understand the specific meaning of the final two digits. So you must always design with the assumption that some clients will treat the response as 400.
If you can find a 4xx status code whose special extra handling works better for your application, then use it. When the client understands enough to do that extra handling you are slightly better off than if you had sent the default status.
The currently registered status codes which seem to match your servers meaning are:
403 Forbidden - this is about server refusing the request until it is somehow changed. Preferrably with the reason stated in the response body.
406 Not Acceptible - this is more specifically about values in the request headers not being right. Most commonly used for the Accept: header values.
412 Precondition Failed - this is about the problems with headers involved with negotiating which response body would be sent. Most commonly used for the If-* header values.
The 403 seems to be most accurate for when a server refused to deliver anything unless the custom headers is sent.

jetty BadMessage: 400 No Host for HttpChannelOverHttp

I have seen previous posts about Jetty BadMessage: 400 No Host for HttpChannelOverHttp and I can confirm that I am able to repeat the problem.
I have a Jetty route in Camel Blueprint, which creates another request and forwards on to a Dropwizard service via Camel HTTP.
.process(new Processor() {
//Creates Object for request
}
.marshal(jsonFormat)
.convertBodyTo(String.class)
.setHeader(Exchange.HTTP_URI, simple(serviceEndpoint))
.setHeader(Exchange.HTTP_METHOD, constant(HttpMethod.POST))
.to(userviceEndpoint)
When this request executes, I see the following error on Dropwizard
WARN [2014-11-12 23:15:35,333] org.eclipse.jetty.http.HttpParser: BadMessage: 400 No Host for HttpChannelOverHttp#3aa99dd2{r=0,a=IDLE,uri=-}
This happens constantly, and this problem does not occur when I send a request to the DW service using SOAP-UI (using the serviceEndpoint URL).
Please if anyone has solved this problem, I would like to know how. Thank you.
Capture your network traffic, and post the HTTP request headers you are sending to Jetty.
Odds are that your HTTP client is not sending the Host: header (which is required on HTTP/1.1)
In my case, I was setting header with null value. After removing header having null value from request solved the issue.
Jetty Version: 9.3.8
I got this error when I was making a request with incorrectly formatted headers. So instead of having the header as "X_S_ID: ABC" I had "X_S_ID: ["X_S_ID":BLAH]". So the error sometimes may not literally mean you need to pass a Host header.
Fixing the headers fixed this. Print the exact request you are making and make sure all headers are correctly formatted.

Does sending POST data to a server that doesn't accept post data recieve the data?

I am setting up a back end API in a script of mine that contacts one of my sites by sending XML to my web server in the form of POST data. This script will be used by many and I want to limit the bandwidth waste for people that accidentally turn the feature on without a proper access key.
I will be denying requests that do not have the correct access key by maybe generating a 403 access code.
Lets say the POST data is ~500kb of data. Does the server receive all 500kb of data when this attempt is made regardless of the status code?
How about if I made the url contain the key mydomain/api/123456789 and generate 403 status on all bad access keys.
Does the POST data still get sent/received regardless or is it negotiated before the data is finally sent.
Thanks in advance!
Generally speaking, the entire request will be sent, including post data. There is often no way for the application layer to return a response like a 403 until it has received the entire request.
In reality, it will depend on the language/framework used and how closely it is linked to the HTTP server. Section 8.2.2 of RFC2616 HTTP/1.1 specification has this to say
An HTTP/1.1 (or later) client sending
a message-body SHOULD monitor the
network connection for an error status
while it is transmitting the request.
If the client sees an error status, it
SHOULD immediately cease transmitting
the body. If the body is being sent
using a "chunked" encoding (section
3.6), a zero length chunk and empty trailer MAY be used to prematurely
mark the end of the message. If the
body was preceded by a Content-Length
header, the client MUST close the
connection.
So, if you can find a language environemnt closely linked with the HTTP server (for example, mod_perl), you could do this in a way which does comply with standards.
An alternative approach you could take is to make an initial, smaller request to obtain a URL to use for the larger POST. The application can then deny providing the URL to clients without an appropriate key.
Here is great book about RESTful Web Services, where it's explained how HTTP works: http://oreilly.com/catalog/9780596529260
You can consider any request as envelope, where on top of it it's written address (URL), some properties (HTTP Headers) and inside it there's some data (if request is initiated by post method). So as you might guess you can't receive envelope partially.
Oh I forgot, it's when you are using HTTP Post with standard HTTP header "application/x-www-form-urlencoded" but if you are uploading files (correspondingly using ""multipart/form-data") Django gives you control over streamed chunks of files using Middleware classes: http://docs.djangoproject.com/en/dev/topics/http/middleware/

Resources