5

So i want to send a XMLHttpRequest POST request through an iFrame on page load. Reason for posting via an iFrame is to not show referrer.

Javascript:

function load() { var http = new XMLHttpRequest(); var url = "action url here"; var params = "name1=one&name2=two"; http.open("POST", url, true); http.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8"); http.send(params); } 

HTML:

<body onload="load();"> <iframe name="f1" src="about:blank" id="noreferer" width="0px" height="0px" style="border: 0px none;"> </iframe> </body> 

How can i attach the Request to the iFrame. Any help would be appreciated.



UPDATE:

For anyone asking why i added and fired load(); in the HTML body, Below is a no referrer post request code connected to the f1 iframe via innerHTML that works in all browsers because the src is 'about blank'. But not a XMLHttpRequest and doesn't give ability to add headers.

Javascript:

function load() { var postdata = '<form id=NoReferrerPost method=POST action=\'action url here\'>' + '<input type=hidden name=name1 value=one />' + '<input type=hidden name=name2 value=two />' + '</form>'; top.frames['f1'].document.body.innerHTML=postdata; top.frames['f1'].document.getElementById('NoReferrerPost').submit(); } 

So what is still needed is a way to attach a XMLHttpRequest to post in iframe f1 like my code above.


HERE ARE SOME SOLUTIONS THAT PARTIALLY WORKS:

The solution of @fedeghe HERE using src="data:text/html with no-referrer meta tag, could work on some browsers.

11
  • 1
    if you call the load function from the body onload this means that the script is defined in the same page where that body tag lives... then I have one basic question... what exactly makes you think that the iframe has something to deal with the load function? Commented Jul 17, 2018 at 12:46
  • "How can i attach the Request to the iFrame." Why would you need to attach it to the iframe? Commented Jul 17, 2018 at 13:37
  • @epascarello — Look at the first paragraph of the question. Commented Jul 17, 2018 at 13:37
  • Totally missed that and I highly doubt doing it will work.... lol Commented Jul 17, 2018 at 13:38
  • @fedeghe I just updated the question to answer your initial question on why i fired load function from the body onload. What was needed was possible a connector, hence the reason for the onload function. Commented Jul 21, 2018 at 12:55

4 Answers 4

2

If you're only intent is to not send the referer, then you can mention it using the referrer-policy. In the html of your webpage just add the meta information (source):

<meta name="referrer" content="no-referrer" /> 

Just create a the requeired html and serve it locally and test it on your machine.

$ cat untitled.html <!DOCTYPE html> <head> <meta name="referrer" content="no-referrer" /> </head> <body> <p> SOME CONTENT </p> <script> (function(){ var http = new XMLHttpRequest(); var url = "https://demo6945017.mockable.io/random/post" http.open("POST", url, true); http.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8"); http.send(); })(); </script> </body> $ python -m http.server 

On testing it, you can see the request headers with and without the referrer-policy.

(Without the meta info -> With referrer) POST /random/post HTTP/1.1 Host: demo6945017.mockable.io User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0 Referer: http://localhost:8000/untitled.html Content-type: application/x-www-form-urlencoded; charset=UTF-8 Origin: http://localhost:8000 =================================== (With the meta info -> Without referrer) POST /random/post HTTP/1.1 Host: demo6945017.mockable.io User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0 Content-type: application/x-www-form-urlencoded; charset=UTF-8 Origin: http://localhost:8000 

(I've removed a lot of the common headers like content-length and cache-control for redablilty)
But beware that the origin is still being sent on every request and that cannot be changed, it tied to the behaviour of the browser. Also browser support is limited to Chrome and Firefox.

Sign up to request clarification or add additional context in comments.

1 Comment

This solution will apply to all page request instead of the specific iFrame request. @fedeghe answer stackoverflow.com/a/51382768/1777938 is also a no-referrer meta tag workaround, but for the specific iFrame and as stated earlier, this only works in some browsers.
2
+25

Using the src="data:text/html,, you can do it but you have to take care at least about the encoding of the script

<iframe src="data:text/html,<html><head><meta name=%22referrer%22 content=%22no-referrer%22/></head><body><script>(function(){var http = new XMLHttpRequest(), url = %22http://www.yourTargetDomain.com%22, params = %22name1=one%26name2=two%22; http.open(%22POST%22, url, true); http.setRequestHeader(%22Content-type%22, %22application/x-www-form-urlencoded; charset=UTF-8%22); http.send(params);})(); </script></body></html>" width=0 height=0 style="display:none;"></iframe> 

You can read more details about it here and here

UPDATE onload

in case you really need to do it at some point, userORbrow event driven you could do something like the following (replaced also the name attribute with id for the iframe tag, but doesn't really matter):

<script> function load () { var targetDomain = "http://www.yourTargetDomain.com", params = "name1=one%26name2=two", html = '<html><head><meta name="referrer" content="no-referrer"/></head><body><script>(function(){var http = new XMLHttpRequest(), url = "' + targetDomain + '", params = "' + params + '"; http.open("POST", url, true); http.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8"); http.send(params);})(); <\/script><\/body><\/html>', src = "data:text/html;charset=utf-8,"+ escape(html); document.getElementById('f1').src= src; } </script> <body onload="load();"> <iframe id="f1" src="about:blank" width="0px" height="0px" style="border: 0px none;"> </iframe> </body> 

...at that point I suggest that Your function could easily: first create the iframe (about:blank src, hidden ...an on), second append it, then trigger the post, wait for request success (maybe also consume it), and remove finally the iframe from the dom, something similar to:

<script> function postIt (p, url, cb) { url = url || "http://www.targetdomain.org"; p = p || {}; cb && (p.cb = +new Date); var params = (function (o) { var s=[]; for (var j in o) { o.hasOwnProperty(j) && s.push(j+'='+o[j]); } return s.join('%26'); })(p), html = '<html><head><meta name="referrer" content="no-referrer"/></head><body><script>(function(){var http = new XMLHttpRequest(), url = "' + url + '", params = "' + params + '";http.onreadystatechange = function(){if (http.readyState == 4 && http.status == 200){window.parent.postMessage("posted", "*");}};http.open("POST", url, true); http.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8"); http.send(params);})(); <\/script><\/body><\/html>', src = "data:text/html;charset=utf-8,"+ escape(html), iframe = document.createElement('iframe'); iframe.style.display= 'none'; iframe.height = iframe.width = '0px'; window.addEventListener('message', function (e) { e.data == "posted" && document.body.removeChild(iframe); }, false); iframe.src = src; document.body.appendChild(iframe); } </script> <body onload="postIt({hello:'there'});"> <h1>Hello world</h1> </body> 

7 Comments

This code shows the referrer. For a referrer to not show, the logic was to make the default iframe src be about:blank. i.e src="about:blank" before the POST request.
@Julius ...strange, the origin in the request headers of the xhr request are null... at least on the brows I tested
adding <meta name="referrer" content="no-referrer" /> to the encoded iframe content in the header could solve it. I updated the answer
While no-referrer meta could solve this in some browsers, There are browsers incompatible with it that would still display referrer. Like IE and some old android browsers.
@Julius altough most likely there is no far behind in versions working solution, the caniuse link you reported highlights only opera mini...are You worried :) about that or by others bro older versions?
|
1

Using onload in <body> or in <iframe> tag doesn't change the referrer because the code is still fired from the parent window.

You should fire the ajax within the iframe. To put code in the iframe from a parent window like this example:

frames[0].window.foo = function(){ console.log ("Look at me, executed inside an iframe!", window); } 

you have to observe Same-origin policy, but in this case, since you want to change referrer, you will have the same origin and referrer, then referrer is not going to change.

Also, browsers set the referrer in ajax requests (see this and this) despite of the fact that exists a referrer header to manipulate the referrer behavior. Somethig like <meta name="referrer" content="no-referrer" /> unfortunately has some important restrictions (no Edge, IE and Safari support).

So I think a possible way to change or hide referrer is through some kind of server proxy. This is: redirecting all ajax requests to one server controlled by you, in the server you perform a POST/GET request and in this case hiding the referrer. It's really simply in fact, here an example using php (CURL) and javascript:

myproxy.php:

<?php $url = $_GET['url']; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_REFERER, "referrer you want");//<-- spoof referrer here $output = curl_exec($ch); curl_close($ch); echo $content;//content is from $_GET['url'] passed from javascript ajax ?> 

in javascript

var url = "Url we want to hide the referrer"; var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { //response from myproxy.php here } }; xhttp.open("GET", "myproxy.php?="+url , true); xhttp.send(); 

6 Comments

I have updated the question to answer your questions, with a code that POST normal request without sending referrer which works on any browser, and also added a workaround for XMLHttpRequest POST with no-referrer meta tag. And like you said, that doesn't work for all browsers.
@Julius I've updated the answer and I added an example of a little server proxy in case you could use server side code.
Seen. However, the issue with curl approach is that, it uses the server IP instead of User IP.
@Julius Yes, and unfortunately we can't spoof IP.
@Julius have you seen this jpgerek.github.io/referrer-killer/example.html ? I didn't try
|
0

Seems like a lot of answers missed the most obvious way of solving the OPs request:

In the iframe itself add the referrerPolicy there:

<iframe referrerpolicy="no-referrer" ...></iframe>

This should be all that is needed. Its specific to the iframe thus he doesn't need to do the <meta> solutions proposed above as that affects the entire page.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.