Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XMLHttpRequest POST in iFrame on Page Load

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.

like image 863
Julius Avatar asked Nov 21 '17 13:11

Julius


2 Answers

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.

like image 115
TheChetan Avatar answered Sep 28 '22 03:09

TheChetan


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>
like image 44
fedeghe Avatar answered Sep 28 '22 03:09

fedeghe