The way to debug this is to try it in a browser (where you get a 403) and in your code (where you get a 200), compare the request headers, and bisect on the differences.
--
I did this using the "Network" panel in Chrome's devtools, and using requests
so I can just print(page.request.headers)
.
From Chrome:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Cookie: __test=9eea7a0d55374cb5b0673e2058581017
Host: switch-check.cf
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
From requests:
User-Agent python-requests/2.18.4
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Before even getting to those headers: Chrome requested index.php?i=1
instead of just index.php
. So apparently there was a redirect while I wasn't paying attention. And that redirect isn't happening in requests
, which implies that it's likely scripted.
And meanwhile, I know I said to bisect, but the fact that there's a cookie there is immediately suspicious.
So, let's look at the actual 200 response, run through a pretty-printer:
<html>
<body>
<script type="text/javascript" src="/aes.js"></script>
<script>
function toNumbers(d) {
var e = [];
d.replace(/(..)/g, function(d) {
e.push(parseInt(d, 16))
});
return e
}
function toHex() {
for (var d = [], d = 1 == arguments.length && arguments[0].constructor == Array ? arguments[0] : arguments, e = "", f = 0; f < d.length; f++) e += (16 > d[f] ? "0" : "") + d[f].toString(16);
return e.toLowerCase()
}
var a = toNumbers("f655ba9d09a112d4968c63579db590b4"),
b = toNumbers("98344c2eee86c3994890592585b49f80"),
c = toNumbers("c4ba932dbf1d8d33ca88410be4f79eb0");
document.cookie = "__test=" + toHex(slowAES.decrypt(c, 2, a, b)) + "; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/";
location.href = "http://switch-check.cf/index.php?i=1";
</script>
<noscript>This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support</noscript>
</body>
</html>
Well, there's your problem. You're not actually rejecting access to index.php
at all; you're returning a 200 with some JavaScript that adds a randomized cookie and then redirects to index.php?i=1
. And that's where you reject them.
Is it the cookie, or the redirect, that triggers the 403? Let's try both with Requests:
>>> r = requests.get('http://switch-check.cf/index.php', headers={'Cookie': '__test=9eea7a0d55374cb5b0673e2058581017'})
>>> r.status_code
403
>>> r = requests.get('http://switch-check.cf/index.php?i=1')
>>> r.status_code
200
So, you're only forbidding access based on a cookie that's generated by JavaScript.
What if we just send a nonsense cookie?
>>> r = requests.get('http://switch-check.cf/index.php', headers={'Cookie': '__test=' + '0'*32})
>>> r.status_code
403
>>> r = requests.get('http://switch-check.cf/index.php', headers={'Cookie': '__test=' + str(uuid.uuid4().hex})
>>> r.status_code
403
Wow. It actually has to be the right cookie, the one the server was expecting, or you don't get rejected? That's the opposite of the logic you'd normally want.
You could write some urllib
or requests
code to cooperate the way a browser does—either run a JS interpreter, or parse out the three numbers and AES them and build a cookie yourself. But that seems like a silly thing to do.
The right thing to do is to change the server to actually forbid access to index.php
, instead of returning JS code that generates a special cookie that will allow you to get forbidden if you want.
How do you do that?
Well, you say:
with the help of .htaccess and php I tried my best for that all .php files are forbidden access
First, as far as I can tell, you think you're using Apache, and are following some guide somewhere to how to forbid access in Apache, but you're actually using nginx. (Look at the Server
header in the responses.)
And meanwhile, I don't know what you're doing in PHP, but you probably got some code that's intended to require a valid cookie from a valid JS-running browser that's (a) wrong and gets it backward, (b) overly complicated, and (c) not what you wanted in the first place.
I don't know whether you have a PHP question here, or an nginx question on Server Fault, or something else. But that's the side you need to fix.