0x00 background
In this article, the Browser Security-same-origin policy and pseudo-URL domain mentioned the same-origin policy of the Browser, which mentioned that XMLHttpRequest strictly abides by the same-origin policy and cannot be requested from different sources. However, in practice, cross-origin resource requests are often required. For example, a subdomain name requests user information from a subdomain name that is responsible for user verification.
In the past, one solution was to use JSONP for cross-origin resource requests. However, this solution has several defects:
1) only GET requests are allowed. 2) There is no effective error capture mechanism. Therefore, in the XMLHttpRequest v2 standard, a CORS (Cross Origin Resourse-Sharing) model is proposed to ensure the security of Cross-Origin requests.
Currently, major browsers support CORS models. for IE 8 and IE 9, XDomainRequest is required for cross-origin requests.
0x01 Basic Model
Although cross-origin requests of XMLHttpRequest are allowed, such permits are not unconditional.
When making a request, the browser will also determine the validity of the request. The verification is carried out through the server's return header. In this case, the specific request type is involved, therefore, simple cross-origin requests are defined in the standard.
A simple cross-origin request is a request that meets the following conditions:
The request header (except Accept, Accept-Language, Content-Language, and Content-Type) is not set in the Request Method of GET or POST. If the Content-Type header is set, the value is application/x-www-form-urlencoded, multipart/form-data or text/plain.
The difference between verifying the validity of a simple cross-origin request and a non-simple cross-origin request is that before verifying a non-simple cross-origin request, the browser sends an OPTIONS method pre-check request to the server to determine whether the pre-check fails, the actual request is discarded. The browser will normally send a simple cross-origin request, and then judge the return header to check the validity of the request. When the check fails, the browser will prevent the script from accessing the returned content.
LZ sets the X-Forward-For header. Therefore, the browser first sends a pre-check request and discards the actual header after the check fails. This causes LZ misunderstanding.
0x02 HTTP header sent during a request
Simple cross-origin requests do not contain the following HTTP headers. The pre-check request will send the following HTTP Header
Origin: a common HTTP Request also carries the Origin information. In CORS, the Origin information is used by the backend to compare Access-Control-Request-Method: the Method of the next Request, such as PUT, DELETE and so on. Access-Control-Request-Headers: Custom Headers. All Headers set using the setRequestHeader method will be included in this header by commas.
Other headers, such as the actual request header, and Cookie headers are not included in the pre-check request.
0x03 returned HTTP Header
The browser mainly checks whether the request is valid by returning these HTTP headers. It is worth noting that the pass of the pre-check request does not necessarily mean that the request will succeed. If the HTTP header returned by the server during the pre-check request makes the browser judge that the request is valid, the actual request is sent, however, when the access control header contained in the return header of the actual request shows that the request is invalid, the browser still determines that the request is invalid, thus hiding the returned details from the script.
Access-Control-Allow-Origin: the domain that allows cross-Origin Access. It can be a list of domains or a wildcard "*". Note that the Origin rule is valid only for the domain name and not for the subdirectory. That is, http://foo.example/subdir/is invalid. However, different subdomain names need to be set separately. The rules here can refer to the same-source policy Access-Control-Allow-Credentials: whether to Allow requests with verification information, this part will be explained in detail below: Access-Control-Expose-Headers: The Return header that allows the script to Access. After the request is successful, the script can Access the header information in XMLHttpRequest (it seems that webkit has not implemented this) Access-Control-Max-Age: the number of seconds to cache this request. In this time range, all requests of the same type no longer send pre-check requests, but directly use the returned header as the judgment basis, which is very useful, greatly optimize the number of requests Access-Control-Allow-Methods: allowed request Methods, separated by commas (,) Access-Control-Allow-Headers: Allow custom Headers, separated by commas, case Insensitive
Whether it is a pre-check request or an actual request, ifAccess-Control-Allow-Origin, Access-Control-Allow-Credentials, Access-Control-Allow-Methods, Access-Control-Allow-Headers
Will be considered as a request failure.
0x04 talk about Credentials separately
By default, HTTP Authentication information, Cookie header, and your SSL certificate will not be sent in the pre-check request or in the actual request.
However, the authentication information mechanism is enabled by setting the credentials of XMLHttpRequest to true.
Although a simple request still does not need to send a pre-check request, in this case, to determine whether the request is successful, you need to determine the Access-Control-Allow-Credentials. If Access-Control-Allow-Credentials is false, request failed.
One thing to note is that Access-Control-Allow-Origin cannot be a wildcard "*" at this time (it is really cheap for a bunch of lazy programmers ), if Access-Control-Allow-Origin is a wildcard "*", the request still fails.
Even for failed requests, if the returned header contains the Set-Cookie header, the browser will Set the Cookie as usual.
0x05 security risks in CORS
The biggest risk is that some slack programmers set Access-Control-Allow-Origin to "*", which basically invalidates the CORS model. However, due to the protection of the Credentials model, many online articles believe that information leakage does not actually exist. The risk here is that DDoS attacks can be constructed.
In addition, we will find that although the return value cannot be obtained, simple requests are actually sent, so POST requests can be sent. At this time, it is actually the same as the common CSRF, so it does not mean that the domain defined by the cross-origin request can be prevented by CSRF.