How to match requests containing greater-than symbol (<) in nginx? - nginx

I'm trying to harden a back end server, for which nginx is acting as a reverse proxy, against XSS and HTML injection attacks. I want to be able to simply respond with a 400 error to any request containing a '<' or a '>', either as part of the request or the query string (e.g., /LookupPrice?name=<"haarsy%0A>). I tried the following (for query_string) but the requests are still getting through:
if ($query_string ~* <){
return 400;
}
What do I need to do?

The request URI is percent encoded, so <> are often encoded as %3C and %3E (although they are not listed as reserved characters in RFC3986). Nginx will decode the characters to URI part when constructing the normalised URI variable $uri. But the query string remains percent encoded.
To match either < or > in the query string, whether percent encoded or not, use:
if ($query_string ~* (%3[CE]|[<>])) { return 400; }

Related

Nginx location blocks syntax

I'm trying to return 400 status if someone includes this character '<' anywhere in the url request, for example the request might look like
https://example.com/adfg<script
I tried the following in Nginx location block, but obviously this is not how it works,
location /*<* {
return 400;
}
What's the right syntax that i need to write please.
"<" characters is not allowed in a url. Therefore you can't use it, maybe you want to use the url encoded version: "%3C".
Check: Characters allowed in a URL

Redirect URI on NGINX

I have a page on my site (only accessible to logged in users), that looks like the following:
https://www.example.com/forum/new
However, sometimes when users click or refresh they get the page as follows:
https://www.example.com/forum%252fnew
Now %25 decodes to the % symbol, and %2f decodes to the "/", so it seems the URI is getting double-encoded.
I'm not sure how this encoding is happening, but I thought a workaround would be to have Nginx redirect back to the correct URL, with something like the following:
location ~ /forum%252Fnew {
return 301 https://www.example.com/forum/new;
}
I have tried escaping the % in the location with \, but neither seem to be working.
What am I missing?
The URI has been decoded and normalized before being processed by the location and rewrite directives, so the %25 looks like a single %.
The example in your question shows a regular expression location statement. The ~ operator is for case-dependent matching, whereas the ~* operator is for case-independent matching.
To make the example in your question work, you will need to change it to:
location ~* /forum%2Fnew
Or:
location ~ /forum%2fnew
See this document for details.

Ningx : How to filter request with a particular query parameter value?

To securize my Wordpress site which is always under attacks, I try fo filter (ie. return 404) to all request that tries to upload the wp-config.php.
The requests are :
GET /wp-content/plugins/recent-backups/download-file.php?file_link=../../../wp-config.php
GET /wp-content/themes/parallelus-mingle/framework/utilities/download/getfile.php?file=../../../../../../wp-config.php
GET /wp-content/plugins/imdb-widget/pic.php?url=../../../wp-config.php
So I want to return 404 to every request that have a wp-config.php in one request parameter.
Do you think it is possible ?
Thank's in advance
You can test $request_uri for the entire URI including query string, or $args (aka $query_string) for the entire query string.
An if statement near the top of the server block should screen out all of the requests you want to ban.
For example:
if ($request_uri ~* wp-config\.php) { return 404; }
See this caution on the use of if.

How to determine if a URI is escaped?

I am using apache commons HTTPClient to download web resources. The URI for these resources come from third parties, I do not generate them.
The commons httpclient requires a URI object to be given to the GetMethod object.
The URI constructor takes a string (for the uri) and a boolean specifying if it is escaped or not.
Currently, I am doing the following to determine if the original url I am given is already escaped...
boolean isEscaped = URIUtil.getPathQuery(originalUrl).contains("%");
m.setURI(new URI(originalUrl, isEscaped));
Is this the correct way to determine if a uri is already escaped?
Update...
according to wikipedia ( Well, according to wikipedia ( http://en.wikipedia.org/wiki/Percent-encoding ) it says that percent is a reserved character and should always be encoded... I am quoting verbatim here...
Percent-encoding the percent character[edit] Because the percent ("%")
character serves as the indicator for percent-encoded octets, it must
be percent-encoded as "%25" for that octet to be used as data within a
URI.
Doesnt this mean that you can never have a naked '%' character in a valid uri?
Also, the uri(s) come from various sources so I cannot be sure if they are escaped or unescaped.
This wouldn't work. It's possible the un-encoded string has a % in it already.
ex:
https://www.google.com/#q=like%25&safe=off
is the url for a google search for like%. In unescaped form it would be https://www.google.com/#q=like%&safe=off
Your consumers should let you know if the URI is escaped or not.

Is a URL with // in the path-section valid?

I have a question regarding URLs:
I've read the RFC 3986 and still have a question about one URL:
If a URI contains an authority component, then the path component
must either be empty or begin with a slash ("/") character. If a URI
does not contain an authority component, then the path cannot begin
with two slash characters ("//"). In addition, a URI reference
(Section 4.1) may be a relative-path reference, in which case the
first path segment cannot contain a colon (":") character. The ABNF
requires five separate rules to disambiguate these cases, only one of
which will match the path substring within a given URI reference. We
use the generic term "path component" to describe the URI substring
matched by the parser to one of these rules.
I know, that //server.com:80/path/info is valid (it is a schema relative URL)
I also know that http://server.com:80/path//info is valid.
But I am not sure whether the following one is valid:
http://server.com:80//path/info
The problem behind my question is, that a cookie is not sent to http://server.com:80//path/info, when created by the URI http://server.com:80/path/info with restriction to /path
See url with multiple forward slashes, does it break anything?, Are there any downsides to using double-slashes in URLs?, What does the double slash mean in URLs? and RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax.
Consensus: browsers will do the request as-is, they will not alter the request. The / character is the path separator, but as path segments are defined as:
path-abempty = *( "/" segment )
segment = *pchar
Means the slash after http://example.com/ can directly be followed by another slash, ad infinitum. Servers might ignore it, but browsers don't, as you have figured out.
The phrase:
If a URI does not contain an authority component, then the path cannot begin
with two slash characters ("//").
Allows for protocol-relative URLs, but specifically states in that case no authority (server.com:80 in your example) may be present.
So: yes, it is valid, no, don't use it.

Resources