I have the following URL:
example.com/?redirect=some-url-encoded
I need to redirect it to the URL specified in the query string (redirect
parameter).
I have tried:
RewriteCond %{QUERY_STRING} redirect=(.+)
RewriteRule ^(.*)$ %1 [R=302,L,QSA]
But I got redirected to the URL:
example.com/some-url-encoded?redirect=some-url-decoded
So:
- my URL is not decoded
- old query string is applied.
- URL is started from example.com
How to handle it properly?
Best Answer
The
QUERY_STRING
server variable is not URL decoded, and mod_rewrite will also URL encode the substitution, so you are likely ending up with a doubly encoded URL? You probably need theNE
(NOESCAPE
) flag.However, if colons and slashes (as in
http://
) are URL encoded (ie.http:%3A%2F%2F
) in the query string parameter then these will be passed through to the substitution already encoded, negating their normal meaning in a URL. Whilst most URL encoding functions will encode these characters, they don't strictly need to be encoded in the URL parameter value (although this can depend on your server config - if you are changing what the server considers URL delimiters - but this is rare). So, encode all other characters, except:
and/
in the URL param value. For example, instead of:Leave the
:
(colon) and/
(slash) chars unencoded:An alternative, instead of using a URL parameter is to use additional
PATH_INFO
at the end of the URL, since this should be automatically URL decoded. However, this depends on theAcceptPathInfo
directive and you will also need to enableAllowEncodedSlashes
(in the server config), but this comes with its own security concerns. See the Apache docs: http://httpd.apache.org/docs/current/mod/core.html#allowencodedslashesYou are explicitly telling mod_rewrite to apply the original query string with the
QSA
(Query String Append) flag. But it will do this by default anyway. You need to explicity remove it with either theQSD
(Query String Discard) flag on Apache 2.4+, or append a?
to theRewriteRule
substitution.You need to include an absolute URL (ie. complete with scheme
http://
) in the URL param (or explicitly hard code this in the substitution?). Note that if the colon and/or slashes inhttp://
are URL encoded then Apache will not see this as an absolute URL and it will be treated as relative (to the current directory) to which Apache will prefix the directory-prefix and then try to make it absolute (because of theR
flag - an external redirect) by prefixing the protocol and current domain ie.http://example.com
. Not only does this wholly corrupt the redirect, it will also expose your internal directory structure.Bringing this all together, try the following:
This is assuming that the protocol/scheme is passed in the query string parameter. eg.
http://example.com/?redirect=http://www.google.pl/
A parenthesized subpattern in the
RewriteRule
pattern (ie.(.*)
) would seem to be unnecessary here.A word on Security
Note that allowing any absolute URL to be used as the target in a simple redirect script like this is a security risk. If hackers were to discover this then it's likely to be abused and used as part of a redirect chain directing users to download malicious software and the like.
See also:
https://webmasters.stackexchange.com/questions/99749/301-redirect-script-being-abused-for-what-purpose