Validating Referer in Laravel - php

My organization is testing my laravel app with IBM AppScan and it reveled the following issue. I'm not sure the best way I should be verifying the referer. Details of the scan
The following changes were applied to the original request:
- Set header to 'http://bogus.referer.ibm.com'
Reasoning:
The test result seems to indicate a vulnerability because the Test
Response is identical to the Original Response, indicating that the
Cross-Site Request Forgery attempt was successful, even
though it included a fictive 'Referer' header.
Request/Response:
GET /data/1?page=3 HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 9.0; Win32) Referer:
http://bogus.referer.ibm.com
Host: xxxx.xxx.xxx.xxx
Accept: text/html,application/

Laravel relies on CSRF token to prevent the application from CSRF. Validating the header only adds an extra layer of security, however, this can be forged.

Related

XSRF-Token in Laravel

I implement login in laravel on login request there is two token generate one in body and another one is in header cookie.
When i remove value of body token it's show page expired error but when I remove value of xsrf-token it's not shows any error and login getting succesfull
POST /login HTTP/1.1
Host: <host>
Content-Length: 513
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: <Origin Address>
Content-Type: application/x-www-form-urlencoded
User-Agent:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Cookie: XSRF-TOKEN=<token>; laravel_session=<session token>
Connection: close
_token=<token>&userName=<userName>&password=<Password>
Anyone help me to explain this both token. and why page is not getting expired on remove value of xsrf-token value using burpusite tool.
as mentioned in laravel document:
Laravel makes it easy to protect your application from cross-site
request forgery (CSRF) attacks. Cross-site request forgeries are a
type of malicious exploit whereby unauthorized commands are performed
on behalf of an authenticated user.
also:
Laravel stores the current CSRF token in an encrypted XSRF-TOKEN
cookie that is included with each response generated by the framework.
You can use the cookie value to set the X-XSRF-TOKEN request header.
This cookie is primarily sent as a convenience since some JavaScript frameworks and libraries, like Angular and Axios, automatically place its value in the X-XSRF-TOKEN header on same-origin requests.

How to retrieve attempted $_SERVER['REMOTE_USER'] from URL when no authentication is required

Normally when a publicly-accessible directory requires basic HTTP authentication, the value of $_SERVER['HTTP_AUTHORIZATION'] and/or $_SERVER['REMOTE_USER'] (or $_SERVER['PHP_AUTH_USER'], etc) will be set and accessible to PHP once a valid username/password combination have been provided to the server.
For example, if http://www.example.com/members requires basic authentication, and a user successfully authenticates using the credentials myusername and mypassword by manually typing http://myusername:mypassword#www.example.com/members into their browser, the value of $_SERVER['HTTP_AUTHORIZATION'] would be something like:
Basic bXl1c2VybmFtZTpteXBhc3N3b3Jk
... and the value of $_SERVER['REMOTE_USER'] would simply be:
myusername
However if authentication is not required in the same directory, but the URL is still visited with the username/password inside of it, the values of the username/password don't seem to be set anywhere (running PHP 5.3.10 as CGI/FastCGI on Apache/2.2.22).
From within PHP (and/or .htaccess if necessary), when no authentication is required, is there a way to retrieve the values of the username (and/or password) that have been provided by a visitor who manually added them to the URL?
TLDR; As far as I can see that information is never sent to server so I claim it's not possible.
The way http authentication works if you have it set is that server sends a request for user/pass if it's not already set, and browser then adds that information in encoded form to a Authorization header and sends it to the server along with the request.
As specified in RFC 2617, describing Basic and Digest authentication mechanisms For basic authentication, server sends HTTP 401 Not Authorized status and WWW-Authenticate header fields to request this information. (RFC 2617, Access Authentication Framework)
With tests one can see that if authentication is never configured on the server to be required, server won't request authentication information from browser, and browser won't add user/pass information into the request. RFC does not mandate browser (user agent) to not pass that information, but says instead
A user agent that wishes to authenticate itself with an origin
server--usually, but not necessarily, after receiving a 401
(Unauthorized)--MAY do so by including an Authorization header field
with the request.
In practice, if you watch the sent headers you can see that if this information is requested by the server, it's sent in encoded form using Authorization header like specified by the RFC. However, if you're not using any authentication the request you send just doesn't seem to contain that information in any form. I've confirmed this with IE, Firefox and Chrome browsers myself.
If you want to test this yourself for your setup, this can be done for example using netcat like this:
First, run netcat on your server:
nc -l 8888
Then issue a request from your browser to http://testvalue:testvalue#yourdomain:8888/
As a result, observe from netcat output all the information that get sent to server, something like this:
GET / HTTP/1.1
Host: yourdomain:8888
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
There is no information about user or password anywhere. I claim that unless the server requests it, it won't be there.
The addition of user and password in a url using http(s)://user:pass#site.com has been disabled by at least Internet Explorer for several years now, as far as i know.
https://support.microsoft.com/en-us/kb/834489
So I am not sure if what you are trying to reach is even usefull. I think the browsers dont even pass that part of the url on anymore.

Use session data on websocket handshake

If a logged in user navigates to a certain area of the site which is to use WebSockets, How can I grab that session Id so I can identify him on the server?
My server is basically an endless while loop which holds information about all connected users and stuff, so in order to grab that id I figured the only suitable moment is at the handshake, but unfortunately the handshake's request headers contain no cookie data:
Request Headers
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5
Cache-Control: no-cache
Connection: keep-alive, Upgrade
DNT: 1
Host: 192.168.1.2:9300
Origin: http://localhost
Pragma: no-cache
Sec-WebSocket-Key: 5C7zarsxeh1kdcAIdjQezg==
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64;
rv:27.0) Gecko/20100101 Firefox/27.0
So how can I really grab that id? I thought I could somehow force javascript to send cookie data along with that request but any self-respecting website in 2014 will have httpOnly session cookies so that wont work out. Any help is greatly appreciated!
Here's a link for the server I'm using: https://github.com/Flynsarmy/PHPWebSocket-Chat/blob/master/class.PHPWebSocket.php (thanks to accepted answer)
http only cookies as well as secure cookies work fine with websocket.
Some websocket modules have chosen to ignore cookies in the request, so you need to read the specs of the module.
Try: websocket node: https://github.com/Worlize/WebSocket-Node.
Make sure to use the secure websocket protocol as wss://xyz.com
Update:
Also, chrome will not show the cookies in the "inspect element" Network tab.
In node try dumping the request, something like:
wsServer.on('request', function(request) {
console.log(request);
console.log(request.cookies); // works in websocket node
}
If you see the cookies somewhere in the log...you've got it.
If you're using secure-only cookies, you need to be in secure web sockets: wss://
Update2:
The cookies are passed in the initial request. Chrome does not show it (all the time) as sometimes it shows provisional headers which omits cookie information.
It is up to the websocket server to do 'something' with the cookies and attach them to each request.
Looking at the code of your server: https://github.com/Flynsarmy/PHPWebSocket-Chat/blob/master/class.PHPWebSocket.php I do not see the word "cookie" anywhere, so it is not being nicely packaged and attached to each websocket connection. I could be wrong, that's why you might want to contact the developer and see if the whole header is being attached to each connection and how to access it.
This I can say for certain: If you're using secure cookies then cookies will not be transmitted unless you use the secure websocket wss://mysite.com. Plain ws://mysite.com will not work.
Also, cookies will only be transmitted in the request if the domain is the same as the webpage.

SQL Injection accept-language php

I'm working through a security assessment report on a php app generated by Accunetix.
The report is claiming a SQL Injection vulnerability. The app is PHP with MySQL. Here's the headers it says are making the attack (specifically the accept-language header):
GET /user_login.php HTTP/1.1
user-agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
accept-language: 1;select pg_sleep(1); --
X-Requested-With: XMLHttpRequest
Cookie: PHPSESSID=35kno6h8kmkbin973q02gojp82; uniqueuser=1382404387
Host: xxx.xxx.com
Connection: Keep-alive
Accept-Encoding: gzip,deflate
I haven't found "accept-language" or "accept_language" anywhere in the app. Also, pg_sleep() isn't a MySQL function.
I searched for a known vulnerability in PHP and didn't find anything. Is this a false positive, or am I missing something?
Accept-Language is the request header sent by client's browser.
Accunetix were trying to manipulate these headers by injecting malicious code to find security wholes (imitating hackers) to test if you application is vulnerable to them.
If you haven't used accept-language header, or request headers in your DB queries, then probably it is a false positive. To make sure, see the response of that request, if the response is normal, then it is all OK.
The code will probably treat that header as a source for selecting the language, an that is done via a database query. And when generating the query, the contents of the HTTP header are improperly parsed.
The reason for you not seeing this might be because the fetching of the HTTP headers is done indirectly (like in $_SERVER[$language_header]).

Can a cURL based HTTP request imitate a browser based request completely?

This is a two part question.
Q1: Can cURL based request 100% imitate a browser based request?
Q2: If yes, what all options should be set. If not what extra does the browser do that cannot bee imitated by cURL?
I have a website and I see thousands of request being made from a single IP in a very short time. These requests harvest all my data. When looked at the log to identify the agent used, it looks like a request from browser. So was curious to know if its a bot and not a user.
Thanks in advance
This page has all the answers to your questions. You can imitate the things mostly.
R1 : I suppose, if you set all the correct headers, that, yes, a curl-based request can imitate a browser-based one : after all, both send an HTTP request, which is just a couple of lines of text following a specific convention (namely, the HTTP RFC)
R2 : The best way to answer that question is to take a look at what your browser is sending ; with Firefox, for instance, you can use either Firebug or LiveHTTPHeaders to get that.
For instance, to get this page, Firefox sent those request headers :
GET /questions/1926876/can-a-curl-based-http-request-imitate-a-browser-based-request-completely HTTP/1.1
Host: stackoverflow.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2b4) Gecko/20091124 Firefox/3.6b4
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://stackoverflow.com/questions/1926876/can-a-curl-based-http-request-imitate-a-browser-based-request-completely/1926889
Cookie: .......
Cache-Control: max-age=0
(I Just removed a couple of informations -- but you get the idea ;-) )
Using curl, you can work with curl_setopt to set the HTTP headers ; here, you'd probably have to use a combination of CURLOPT_HTTPHEADER, CURLOPT_COOKIE, CURLOPT_USERAGENT, ...

Categories