Displaying cache headers - php

Symfony 2 is displaying cache headers, i was wondering how i could hide those
examples
HTTP/1.0 200 OK Cache-Control: no-cache Content-Type: text/html Date: Fri, 18 Jan 2013 19:07:08 GMT HTTP/1.0 200 OK Cache-Control: no-cache Date: Fri, 18 Jan 2013 19:07:08 GMT X-Debug-Token: 50f99d5cba4da
i am using this in my code
return new Response($this->renderView('Shout/view/default.html.twig'));
which gets called by
$httpKernel = $this->container->get('http_kernel');
$response = new Response;
$response->SetContent($httpKernel->forward('MyBundle:Module/'.$module.'/'.$module.':index'));
$response->headers->set('Content-Type', 'text/html');
return $response;
in a twig extension

Add ->getContent() to end.
http://api.symfony.com/2.0/Symfony/Component/HttpFoundation/Response.html
$response = $this->forward("MyBundle:Module:$module", array(
'customer_id' => $customer_id
))->getContent();
return $response;

Headers are part of the Response class inside HttpFoundation. You can manage them using the headers attribute, the same one you used in your code. That attribute is an instance of the ResponseHaderBag class, which has a remove function.
The header you want to remove is named 'Cache-Control', so if you write:
$response->headers->remove('Cache-Control');
It will remove that header. But if you check the source of Response, you will see that some of it's functionality depends on this header, so I'm not sure that removing this is really a good idea.
By default this header does nothing wrong, just returns 'no-cache', which means the browser won't cache your page. But you won't be able to cache a page without this header.
If your goal is to manually send the cache-control header yourself, consider using Symfony2's built in functionality instead.

For everyone that is looking for an answer, i continued on the above post and tried to use the render function from twig but with my custom module
this is was i got and it works fine :)
return $this->container->get('templating.helper.actions')->render('MyBundle:Module/'.$module.'/'.$module.':index', $attributes, $options);

Related

How to prevent CRLF injection (Http response splitting) in php

I did R&D on prevention of CRLF injection in php, but i didn't find any solution in mycase, as I'm using a burp suite tool to inject some headers using CRLF characters like the below.
// Using my tool i put CRLF characters at the start of my request url
GET /%0d%0a%20HackedHeader:By_Hacker controller/action
//This generates an header for me like below
HackedHeader:By_Hacker
So i can modify all headers by doing just like above
This tool is just like a proxy server so it catches the request and gives the response and we can modify the response in the way we want.
So i'm just modifying the response by injecting some headers using CRLF characters. Now the Server responds to this request by injecting the CRLF characters in the response.
I'm just worried as header fields like Pragma, Cache-Control, Last-Modified can lead to cache poisoning attacks.
header and setcookie contain mitigations against response/header splitting, But these can't support me in fixing the above issue
Edit
When i request to mysite.com contact us page like below This is the request I captured in my tool like below
Request headers:
GET /contactus HTTP/1.1
Host: mysite.com
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
And i get the Response HTML for the above request
Now for the same request using the tool i'm adding custom headers just like below
Request Headers:
GET /%0d%0a%20Hacked_header:By_Hacker/contactus HTTP/1.1
Host: mysite.com
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Response Headers:
HTTP/1.1 302 Found
Date: Fri, 10 Jul 2015 11:51:22 GMT
Server: Apache/2.2.22 (Ubuntu)
Last-Modified: Fri, 10 Jul 2015 11:51:22 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Location: mysite.com
Hacked_header:By_Hacker/..
Vary: Accept-Encoding
Content-Length: 2
Keep-Alive: timeout=5, max=120
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
You can see the injected header Hacked_header:By_Hacker/.. in the above response
Is there anyway in php or apache server configuration to prevent such kind of headers' hack?
Not sure why all the down votes - infact, it is an interesting question :)
I can see that you have tagged CakePHP - which means your app is using Cake Framework... Excellent! If you are using Cake 3 , it is automatically strip off : %0d%0a
Alternatively, where you receive the response header, just strip off %0d%0a and you are good!
Where things like these could be applied - a 3rd party API response or say.... a Webhook response! or a badly sanitized way to handle intl.. example : lang=en to lang=fr where the GET param is directly set as response header... That would not be a wise move!
Ideally, the responses will be as GET and not in the header but either way just strip the %0d%0a and you are good.
Answering your edit.
You can see the injected header Hacked_header:By_Hacker/.. in the above response
That injected header cannot be controlled or stopped, mate. We do not have control over what the other server does.
The question is.. What do you do with the response header?
The answer is... You sanitize it, as ndm said you need to sanitize the input.. What you get as a response IS an input. As soon as you detect %0d%0a, discard the response.
Need code work?
<?php
$cr = '/\%0d/';
$lf = '/\%0a/';
$response = // whatever your response is generated in;
$cr_check = preg_match($cr , $response);
$lf_check = preg_match($lf , $response);
if (($cr_check > 0) || ($lf_check > 0)){
throw new \Exception('CRLF detected');
}

get_headers() not returning Content-Length element

Function get_headers() does not give an array with the same indexes when I make a change in domain. When and why does this occur?
I want Content-Length value for hundreds of domains. What changes do I need to make?
<?php
$url = 'http://www.ecomexpomelbourne.com.au/sponsors/';
echo "<pre>";
$domain_data[] = array();
$domain_data = get_headers( $url, 1 );
print_r($domain_data);
echo $domain_data['Last-Modified'];
?>
When used for current page url I get Content-Length index
Sometimes the server just does not send the Content-length header, and you should expect and treat properly such cases, as there are such provisions described in RFC2616.
In some situations, when the page is dynamically generated (with PHP or other language), the length of the body is not known yet at the stage of the sending of headers, so there is no way for the server to generate proper Content-length header in advance. But there are also cases when the Content-length header is explicitly forbidden to be sent.
PWS is hopelessly outdated, use IIS instead. I'm not sure that PWS allows to configure response headers and I can't find any docs. This is what it sends now:
Cache-Control:private
Connection:keep-alive
Content-Encoding:gzip
Content-Type:text/html; charset=utf-8
Date:Tue, 09 Dec 2014 09:46:13 GMT
Expires:Mon, 08 Dec 2014 09:46:13 GMT
Server:PWS/8.1.20.5
Set-Cookie:www.ecomexpomelbourne.com.au_trackingData=; path=/
Transfer-Encoding:chunked
Vary:Accept-Encoding
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
X-Px:nc h0-s4.p1-hyd ( h0-s2.p6-lhr), nc h0-s2.p6-lhr ( origin)
there is no Content-length

Response::json() sending html instead of json

Using Laravel 4, return Response::json(array('foo' => 'bar')) used in one controller will return actual application/json, whereas in another controller, for another action, it will return text/html. Both actions are called via Ajax.
In the faulty controller, I tried to force the content-type with this snippet:
[...]
$response = Response::json($data);
$response->header('Content-Type', 'application/json');
$response->header('Content-Foo', 'Bar'); // test if additional headers are really set
Log::info($response);
return $response;
... while working controller returns correct Json response with:
return Response::json($data);
In both, $data is an array (tested).
Logged response from the faulty controller is:
HTTP/1.0 200 OK
Cache-Control: no-cache
Content-Foo: Bar
Content-Type: application/json
Date: Wed, 17 Sep 2014 10:55:03 GMT
But received response (in Firebug / DevTools) is:
Connection Keep-Alive
Content-Type text/html
Date Wed, 17 Sep 2014 10:55:03 GMT
Keep-Alive timeout=5, max=93
Server Apache/2.2.25 (Unix) mod_ssl/2.2.25 OpenSSL/0.9.8y DAV/2 PHP/5.5.3
Transfer-Encoding chunked
X-Powered-By PHP/5.5.3
I tried to directly return Response::json(array('foo' => 'bar')) at the beginning of the faulty controller action but it still sends the response as text/html.
I would like to know why would the content-type switch from application/json to text/html for no reason? And why the mock header isn't in the received response?
-- EDIT --
The problem seems to be located around the validator.
public function faultyAction()
{
if(!Request::ajax()) App::abort(405);
$validator = Validator::make(
array('trackfile' => Input::file('trackfile')),
array('trackfile' => 'required|audio')); // audio is a custom validator
if($validator->fails())
{
Log::info('validation failed!');
return Response::json(array('code' => 1, 'message' => 'File validation has failed.'));
}
else
{
Log::info('validation passed!');
return Response::json(array('code' => 0, 'filename' => 'test'));
}
}
... returns text/html response while validation passed.
public function faultyAction()
{
if(!Request::ajax()) App::abort(405);
$validator = Validator::make(
array('trackfile' => Input::file('trackfile')),
array('trackfile' => 'required|audio')); // audio is a custom validator
return Response::json(array('code' => 0, 'filename' => 'test'));
}
... returns application/json.
How comes the same response is returned with different content-type depending on where it is called in the code?
May it come from $validator->fails() (even if nothing seems to alter the headers or to print something in the Laravel's Validator.php code)?
Hi basically using Response::json() with an array of data as parameter is enough.
Defining again the Content-type header is useless, Response::json is supposed to set it right by default.
I'm creating json responses on my project right now and so far it went fine.
Just to be clear the faulty controller returns the good value with a wrong content-type header, right ?
Can you try again using just Response::json and can you tell which exact laravel version are you using ?
Hi again i'm editing my first answer based on your replies :
you should test something like this :
$json = json_encode($yourArray);
// first check the $json variable with var_dump() oro Log::info() to see if you have the space problem. Then you can create the response.
$response = Response::make($json, 200);
$response->header('Content-Type', 'application/json');
return $response;
Hope it helps...
It may not be the case for OP, but this is a best search result for json response sent as text/html. I just spent considerable amount of time debugging this issue in Laravel 9 with php 8.2
One possible reason for wrong content type is hidden somewhere in php magic goo. In another words, how it handles sending response headers.
If you have whitespace anywhere before or after php opening or closing tag, respectively, the headers will be sent and you cant modify them anymore. This is why it is recommended to not use php closing tag in multi file applications, but this does not help for whitespace before opening tag:
<?php
Now if your framework, like Laravel, checks with headers_sent(), before modifying headers for you, the result is, drumm roll: text/html, with no errors anywhere.
To identify the problem, try setting headers yourself, with header(), somewhere at the end of call stack. It should then fail and tell you in which file the headers are already sent. For me the culprit was hidden in one of the lang files.

How to tell ZF2's JsonModel to return text/plain instead of application/json?

Using PHP Zend Framework 2.0.2, I return JSON data after an AJAX call. Obviously, Internet Explorer 9 wants to download the data instead of returning it to the calling Javascript method.
Posts like this one and this one say to use Content-Type: text/plain instead of Content-Type: application/json, but how do I do this with ZF2's JsonModel? I'm new to it...
I imagine I have to set something in the setOptions() array, but what?
public function testJsonAction()
{
$jsonResponse = new JsonModel(array('success' => false));
$jsonResponse->setOptions(array(
// ** Should I put something here? What? **
));
return $jsonResponse;
}
I tried using these:
$this->getResponse()->getHeaders()->addHeaderLine('Content-Type', 'text/plain');
$this->getResponse()->getHeaders()->addHeaderLine('Content-Disposition', 'inline; filename="textdata.json"');
but it doesn't change the HTTP Content-Type in the response headers:
Key Value
Response HTTP/1.1 200 OK
Content-Type application/json
Server Microsoft-IIS/7.5
X-Powered-By PHP/5.3.13
Set-Cookie ZDEDebuggerPresent=php,phtml,php3; path=/
Content-Disposition inline; filename="textdata.json"
X-Powered-By ASP.NET
Date Wed, 10 Oct 2012 13:19:42 GMT
Content-Length 17
Thanks for your help!
Because when \Zend\Mvc\MvcEvent::EVENT_RENDER event happen, the JsonStrategy will change content-type again. Source code is in
Zend\View\Strategy\JsonStrategy->injectResponse();
So in order to replace content-type into yours, you need to use EventManager to inject your custom header after JsonStrategy injected.
try below codes in your controller:
$this->getServiceLocator()->get('Application')->getEventManager()->attach(\Zend\Mvc\MvcEvent::EVENT_RENDER, function($event){
$event->getResponse()->getHeaders()->addHeaderLine('Content-Type', 'text/plain');
}, -10000);

Error 404 with jQuery Autocomplete JSON referencing external PHP file

I'm been stuck on this problem for a while and I'm pretty sure it must be something quite simple that hopefully someone out there can shed some light on.
So, I'm currently using jQuery UI's Autocomplete plugin to reference and external PHP which gets information from a database (in an array) and sends it to a JSON output.
From my PHP file (search.php) when I do this:
echo json_encode($items);
My output (when looking at the search.php file) is this:
["Example 1","Example 2","Example 3","Example 4","Example 5"]
Which is valid JSON according to jsonlint.com
The problem is that when I use jQuery UI's Autocomplete script to reference the external search.php file, Chrome just gives me the following error:
GET http://www.example.com/search.php?term=my+search+term 404 (Not Found)
I have tried inputting the JSON code straight into the 'Source:' declaration in my jQuery, and this works fine, but it will not read the JSON from the external PHP file.
Please can someone help?
Here's my code:
HMTL
<p class="my-input">
<label for="input">Enter your input</label>
<textarea id="input" name="input"
class="validate[required]"
placeholder="Enter your input here.">
</textarea>
</p>
jQuery
$(function() {
$( "#input" ).autocomplete({
source: "http://www.example.com/search.php",
minLength: 2
});
});
PHP
header("Content-type: application/json");
// no term passed - just exit early with no response
if (empty($_GET['term'])) exit ;
$q = strtolower($_GET["term"]);
// remove slashes if they were magically added
if (get_magic_quotes_gpc()) $q = stripslashes($q);
include '../../../my-include.php';
global $globalvariable;
$items = array();
// Get info from WordPress Database and put into array
$items = $wpdb->get_col("SELECT column FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY column ASC");
// echo out the items array in JSON format to be read by my jQuery Autocomplete plugin
echo json_encode($items);
Result
In browser, when information is typed into #input
GET http://www.example.com/search.php?term=Example+1 404 (Not Found)
Update: the real PHP url is here: http://www.qwota.co.uk/wp/wp-content/themes/qwota/list-comments.php?term=Your
Please help!
UPDATE: ANSWER
The answer to my problem has been pointed out by Majid Fouladpour
The problem wasn't with my code but rather with trying to use WordPress' $wpdb global variable as (as far as I understand) it includes it's own headers, and anything outside of it's usual layout will result in a 404 error, even if the file is actually there.
I'm currently trying to get around the problem by creating my own MySQL requests and not using WordPress's global variables / headers.
PS. Majid, I'll come back and give you a 'helpful tick' once StackOverflow lets me! (I'm still a n00b.)
Are you sure the path source: "http://www.example.com/search.php" is correct?
You have to make sure that the target URL exists. If you are really using http://www.example.com/search.php then, wk, it simply does not exist, so this is why it does not work.
Update
Since you have a real URL that's working (I tested it!), here are a few steps you can take:
Make sure there's no typo. If there's one, fix it.
Make sure you can open that URL from your browser. If you cannot, then you might be having network access problems (firewall, proxy, server permission issues, etc.)
Try redirecting to another know URL, just to make sure. The 404 error is really a "not found" error. It cannot be anything else.
I think the include is the issue. As Majid pointed out... use the below include instead.
include("../../../wp-load.php");
Good luck!
Your apache server is sending wrong headers. Here is a pair of request and response:
Request
GET /wp/wp-content/themes/qwota/list-comments.php?term=this HTTP/1.1
Host: www.qwota.co.uk
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
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
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Cookie: __utma=142729525.1341149814.1305551961.1305551961.1305551961.1; __utmb=142729525.3.10.1305551961; __utmc=142729525; __utmz=142729525.1305551961.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Response headers
HTTP/1.1 404 Not Found
Date: Mon, 16 May 2011 13:28:31 GMT
Server: Apache
X-Powered-By: PHP/5.2.14
X-Pingback: http://www.qwota.co.uk/wp/xmlrpc.php
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Cache-Control: no-cache, must-revalidate, max-age=0
Pragma: no-cache
Last-Modified: Mon, 16 May 2011 13:28:31 GMT
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
Response body
["Bake 'em away... toys.","Content precedes design. Design in the absence of content is not design, it\u2019s decoration.","Hanging on in quiet desperation is the English way.","I'm a reasonable man, get off my case.","Look at me, Damien! It's all for you!","Never get out of the boat... absolutely god damn right.","That gum you like is going to come back in style.","The secret to creativity is knowing how to hide your sources.","Things could be different... but they're not.","Your eyes... they turn me."]
So, even though you receive back response from the server, it has HTTP/1.1 404 Not Found in the headers. Someone may be able to investigate this and provide a potential reason and solution.

Categories