Headers missing from XMLHttpRequest on iOS UIWebView - ios

I'm experincing an odd situation where I have some JavaScript code running in a UIWebView. That JS code creates and fires off an XMLHttpRequest to pull some data off a server.
I listen for onreadystatechange and I have an event listener for the "progress" event.
For some reason this XMLHttpRequest returns only a subset of the Response Headers when queried using request.getAllResponseHeaders() or request.getResponseHeader('whatever'). Note that I've tried GETting any number of different of URLs and they all exhibit the same partial lack of headers.
The only headers returned are Pragma, Cache-Control, Expires & Content-Type, nothing else returns (content-length, encoding, various custom headers, etc).
The odd thing is that the same JS code executed in Mobile-Safari will show all the headers, in strike contrast to how that code behaves when inside a UIWebView.
Any idea what's going on here?

Related

How to format odd headers when adding to the TIdHTTP component via AddValue()

I am using
idhttp.Request.CustomHeaders.AddValue(x,y);
This is working fine for me, but now I have come across a different header and am not sure how to add it or what value, string to use.
In the past, I have used
'SOAPACTION','http://url/action'
But what would I need to do for the mustUnderstand part, or in the ReplyTo and Address parts?
How would I AddValue(x,y) them?
I have tried
...AddValue('SOAPACTION','http://URL/Action');
...AddValue('mustUnderstand','1');
But I am getting errors, and the host IT says that my headers are not correct.
<s:Header>
<a:Action s:mustUnderstand="1">http://URL/Action</a:Action>
<a:MessageID>A Valid GUIID</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">URL STRING</a:To>
</s:Header>
Previous simple headers have worked, but I am not sure how to add these headers.
SOAPAction is a valid HTTP header for SOAP messaging, but mustUnderstand and ReplyTo are not HTTP headers, so DO NOT add them with TIdHTTP.Request.CustomHeaders.AddValue() at all. They are components of the <Header> element inside of a SOAP <Envelope> message, so they belong inside the XML data that you post to the server via TIdHTTP (as per the example XML that you showed). You are confusing HTTP headers and SOAP headers. They are two different things.
If the webserver IT is telling you that your HTTP or SOAP headers are wrong, it should also be telling you what exactly is wrong with them so you can fix it.
This is not an Indy issue. You are simply not preparing your SOAP message the way the webserver is expecting. But we don't have those details to advise you with. The webserver IT does.

Rails caching works only if I send the If-None-Match header manually

My rails code:
def index
battles = Battle.feed(current_user, params[:category_name], params[:future_time])
#battles = paginate battles, per_page: 50
if stale?([#battles, current_user.id], template: false)
render 'index'
end
end
If I send the If-None-Match header with the last Etag manually I get 304 status code in return, If I don't send it manually (The header is sent automatically with the same If-None-Match header) I get 200 status code...
I'm checking the server using Postman rest client (Cache enabled).
I cannot comment on the Rails side of things here but this is correct behaviour if I'm following you.
When sending "If-None-Match" you get a 304 if the content has not changed (same e-tag). This is basically saying either yourself or something in between such as a proxy has the content already and so does not need to transfer the body again.
If you omit the header then you see a 200. Postman by default will send a set of a headers but it's also pretty lean in the sense that it strips a lot away. Try the same request in your browser and you'll get a 304. You'll see your browser will be set to use caching where possible.
Things may get different if you are relying upon server side caching. You may be seeing what looks like a new response yet the server is actually doing very little yet yielding a 200 response.
To summarise the header is doing the right job from your description.

'reload' vs 'reloadFromOrigin' in WKWebView

What's the difference between reload and reloadFromOrigin in WKWebView? Apple's documentation says that reloadFromOrigin:
Reloads the current page, performing end-to-end revalidation using
cache-validating conditionals if possible.
But I am not sure what that really means.
I was interested in this too. Looking at WebKit's source (Source/WebCore/loader/FrameLoader.cpp, FrameLoader::addExtraFieldsToRequest(...) around the if (loadType == FrameLoadType::Reload) conditional) it looks like the key difference is in what extra HTTP header request fields are specified.
reloadFromOrigin() sets the Cache-Control and Pragma fields to no-cache, while a simple reload() only results in in the Cache-Control header field having max-age=0 set.
To work out what this means I looked at the Header Field Definitions section of the HTTP 1.1 spec. Section 14.9.4 'Cache Revalidation and Reload Controls' states:
The client can specify these three kinds of action using Cache- Control request directives:
End-to-end reload
The request includes a "no-cache" cache-control directive or, for compatibility with HTTP/1.0 clients, "Pragma: no-cache". Field names MUST NOT be included with the no-cache directive in a request. The server MUST NOT use a cached copy when responding to such a request.
Specific end-to-end revalidation
The request includes a "max-age=0" cache-control directive, which forces each cache along the path to the origin server to revalidate its own entry, if any, with the next cache or server. The initial request includes a cache-validating conditional with the client's current validator.
Unspecified end-to-end revalidation
The request includes "max-age=0" cache-control directive, which forces each cache along the path to the origin server to revalidate its own entry, if any, with the next cache or server. The initial request does not include a cache-validating
conditional; the first cache along the path (if any) that holds a cache entry for this resource includes a cache-validating conditional with its current validator.
From my reading of the spec, it looks like reload() uses only max-age=0 so may result in you getting a cached, but validated, copy of the requested data, whereas reloadFromOrigin() will force a fresh copy to be obtained from the origin server.
(This seems to contradict Apple's header/Class Reference documentation for the two functions in WKWebView. I think the descriptions for the two should be swapped over - I have lodged Bug Report/Radar 27020398 with Apple and will update this answer either way if I hear back from them...)

What is Firebug telling me is wrong with my HTTP POST?

Im trying to figure out what is wrong with my POST data, or Ajax call.
Im using Symfony to create a form, and Ajax to collect and pass the data. Each time I do a POST request I use Firebug's Net panel to look at my POST data. My POST is breaking somewhere, but I can't tell where. The only thing I can see here is when I look at Firebug I am seeing the POST looks different there for each example (the parameters are present in one, and not present in the other), but they should be identical, right? Is this a clue? I don't know how to interpret this, I don't know enough about Firebug, and its obviously not intuitive enough here for this particular issue.
Is this telling me my data isn't encoded correctly?
Here is a non-working example. Notice, "Parameters" is missing. All I see is the "Source" serialized/encoded data:
Now, in the example below, this is what I expect to see. Notice, this one not only contains the "Source" portion and the source data looks identical (but can use a 2nd pair of eyes on this), but there is another section called "Parameters". Why is this elusively missing in the first example and what does the missing "Parameters" mean?
I'm attaching the headers here, too. Maybe this will explain the problem. And posting these here now I do see the different Content-Type, but I think most of my testing was done before I was sending that header.
broken form headers
working form headers
Either something is wrong with the POST data or might I be be missing the Ajax dataType: 'json', or something?
If you have the wrong content type set in the headers, when the data is sent back, and inspected in Firebug, it can't pull them apart as parameters, unless it knows its form encoded data. If the header declares a different type, then if the data is indeed form url encoded, then the browser doesn't parse it as such, therefore can't break it apart into its parameter elements.
So when you make your call, be sure the content type is being sent as 'application/x-www-form-urlencoded' in your Ajax call.

Burp reporting XSS vulnerability in unescaped HTML in JSON response

I have a Rails/Ember one-page app. Burp reports that
The value of the 'content_type' JSON parameter is copied into the HTML
document as plain text between tags. The payload
da80balert(1)4f31e was submitted in the content_type
JSON parameter. This input was echoed unmodified in the application's
response.
I can't quite parse this message referring to "is copied into" and "was submitted" in, but basically what is happening is:
A PUT or POST from the client contains ...<script>...</script>... in some field.
The server handles this request, and sends back the created object in JSON format, which includes the string in question
The client then displays that string, using the standard Embers/Handlebars {{content_type}}, which HTML-escapes the string and inserts it into the DOM, so the browser displays it on the screen as originally entered (and of course does NOT execute it).
So yes, the input was indeed echoed unmodified in the application's response. However, the application's response was not HTML, in which case there would indeed be a problem, but JSON, containing strings which when referred to by Handlebars will always be escaped properly for proper display in the browser.
So my question is, is this in fact a vulnerability? I have taken great care with my Ember app and can prove that no data from JSON objects is ever inserted "raw" into the DOM. Or is this a false positive given rise to by the mere fact the unescaped string may be found in the response if looked for using an unintelligent string comparison, not taking into account the fact that the JSON will be processed/escaped by the client-side framework?
To put it a different way, in a classic webapp spitting out HTML from the server, we know that user input such as the above must be escaped/sanitized properly. Unsanitized data "on the wire" in and of itself represents a vulnerability. However, in a one-page app based on JSON coming back from the server, the escaping/sanitization occurs in the client; the JSON on the "wire" may contain unsanitized data, and this is as expected. Am I missing something here?
There are subtle ways in which you can trick IE9 and older into treating JSON as HTML. So even if the server's response has a Content-Type header of application/json, IE will second guess it. This is called content type sniffing, and can be disabled by adding the X-Content-Type-Options: nosniff header.
JSON is not an executable format so your understanding is correct.
I did a demo of this exact problem in my talk on securing single page web apps at OWASP AppSec EU 2013 which someone put up on youtube here: http://m.youtube.com/watch?v=Femsrx0m9bU

Resources