Sending Post Data to remote site and displaying the results - javascript

I've read quite a few posts here asking roughly the same thing, but usually the person asking has access to the remote site and can use the methods available to achieve this. My situation is a bit different, and I just wanted to see if it was possible before spending time and effort trying to get it to work.
The site that I am trying to access is remote, I have no access to it in anyway, and it's only accessible from a computer logged into OpenVPN.
The tool that I am writing is trying to get the results of a form submit from the remote site. I don't want to parse the results or modify it in anyway. I just want to display the page with the Post Data sent. The remote site uses AJAX for the form submit.
It's code is as such:
<form name="MyForm" action="response_normal.php" method="post" onsubmit="xmlhttpPost('response_ajax_v2.php', 'MyForm', 'response', '<img src=\'pleasewait.gif\'>'); return false;">
Upon submitting on that page, three values are sent:
site : radio1
search : 000000000000
submit : Search Site
Is it possible at all for me to simply send that post data to the page and display it? I am hoping to do this in an iframe - since I can't do it server side due to VPN restrictions.

Since the computer you're accessing your offsite server from is on the VPN that has access to the remote system (and assuming this remote system is under your control), you could have the offsite server return some JavaScript that AJAX-pulls the data–in this case, a full HTML page–it needs from the remote system using a JSONP-like strategy.
I have used this technique for some small projects in the past.
From there, you are free to do with the data what you will–modify it, return it as is, or otherwise.
Personally, I would avoid the use of frames if possible. Of course, when strapped for time, nothing is off limits ;)
However, if the remote system IS NOT under your control (and they don't have a kickass CORS cross-access policy), your only option is, as you said in the body of your question, frames. Here is an example:
<!-- If the remote system is NOT under your control, it CANNOT respond with the X-Frame-Options header set to SAMEORIGIN or DENY! -->
<iframe id="inlineframe" src="http://www.randomwebsite.com" frameborder="0" scrolling="auto" width="800" height="300" marginwidth="5" marginheight="5" ></iframe>
//Depending on the JS you put here, you may get some "unsafe Javascript" warnings from certain browsers
~function()
{
var frame = document.getElementById('inlineframe'),
ref = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument;
// ref is now a reference to the document of the content within the iframe
// You can now do your getElementById/getElementByTagName etc. and otherwise
// manipulate the response as you please.
console.log(ref);
}();
A working example can be found here: http://jsfiddle.net/FTudJ/
The contents of the iframe should be the submitted results of the remote page, or whatever the remote server responds with. If you're not looking to modify anything, then you don't even need the Javascript component.
The key will be the URL you specify as the source of the iframe. Now, if the remote system doesn't support GET requests for form submissions (in your example code I see a "POST" method), coupled with the fact that you have no control over it and your offsite system can't access it in any way, your only other options are:
Instead of supplying the form's submission URL directly, simply supply the form's typical access URL to the iframe. From there, use JavaScript to populate the form with the necessary values, and then submit the form within the iframe as if you were the user. From there, you can scrape the results back into JavaScript or simply display them as is.
Find a way to get your offsite server into the VPN network so that it may communicate with the remote system on your behalf. Of course, if that were easy, I guess you would have done that first!
Redirect your users to the remote site–possibly using a frameset + banner frame like Google used to do, let them do what they need to do there, and then tell them to come back when they're finished.
--
I see that you're using PHP. As long as the server that is executing the PHP has access to the VPN that has access to this remote system–all over traditional HTTP–a simple curl call from the server-side should suffice, as you can use AJAX to pass through the results to the client.
These links may be of some assistance:
http://php.net/manual/en/book.curl.php
What is cURL in PHP?
http://php.net/manual/en/curl.examples-basic.php
Post data and retrieve the response using PHP Curl?

Related

Why do I need CORS header to request a downloadable link?

I have a link that allows me to download a file when I click on it. Instead of downloading, I am trying to access it with a simple request however I am having CORS problems. I do not have any access to the server side, and therefore everything I have tried so far have failed. If I understand correctly, all suggestions I have found so far needs me to have control over the server (I might be mistaken, but as far as I see server side needs to have a CORS header including my domain or have a jsonp function to be envoked).
Does that mean I am unable to read and parse a file that is already downloadable? If yes, how does it make sense since the file is public and already downloadable when I click the link. Since I am manually able to get the file, shouldn't it be possible to access it with code? Could you suggest me any solution or give something that I can work on? Why the code below do not work as a manual click on the browser would?
var urlString = "http://abc.def.com/download?fileid=123&entity_id=123&sid=123";
$.get(urlString, function(data, status){
alert("Data: " + data + "\nStatus: " + status);});
You are able to download the external script by manually clicking on a link to it because, well, you manually clicked it on it! The browser knows that you authorized access to that URL because you clicked a link that pointed to it. But if a bit of JavaScript accesses that URL in the background, the browser can't be so sure the user is okay with that.
You're thinking "I'm just trying to download an innocent file, why does the browser not trust me??" But let's consider a scarier scenario. Let's say, instead of trying to access http://innocentsite.com/download, your JavaScript was trying to access https://bankofamerica.com/initiateMoneyTransfer?recipient=OE1&amount=10000. Without even knowing it, the user has just let you send $10,000 to yourself since they were logged in on bankofamerica.com.
Now, obviously Bank of America (or any other respectable bank) doesn't allow $10,000 transfers to be initiated like that. But hopefully the example gets the idea across -- it would be very dangerous for webpages to be able to make HTTP requests to other domains. That's why CORS headers are required.
Footnote: If you are hosting your own web server, you might look into setting up a proxy. You could have a URL on your website that automatically retrieves the file from the other website, and serves it on your domain. That way, you can retrieve the file without needing the other website to set CORS headers.

Sending client data to another computer

I'm a newbie in web programming.
I'm now kind of stuck and lost.
Lets say that I have a content server (video). A client request a video from the server and a html page display the video on the client's web browser. At the same time, some data from the client have to be send to ANOTHER computer, which act as network monitor - lets say it has a database where the data will be stored into.
My questions are:
1.Let say that i'm using javascript to grab the data (i.e IP address), how do I send that data to the network monitor ? Or if it is not possible, is there any other method?
2.How do I build the network monitor?
I really need some hints and tips to kick start and to make sure that I learn the correct things. Any useful links will also be appreciated.
Thanks! =D
You can send data to any server you want using a form and submit it to the url you set with action.
<html>
<head></head>
<body>
<form action="http://the-other-server.com" method="post" target="theIframe">
<input type="hidden" name="data" value="{your:'data_here'}" />
</form>
<iframe name="theIframe" style="display:none"></iframe>
<script>
document.getElementsByTagName('FORM')[0].submit();
</script>
</body>
</html>
But the SOP prevents you to read the information from another server(with a different protocol, sub-domain, domain or port). For instance get the response of your POST above.
To read the content of another domain you need to use a technique called JSONP
EDIT: Or if you target modern browsers (> IE8), you can use parent.postMessage from an iframe of another origin to exchange string data with the main page.
And finally if you have to support older browsers, you can still use the window.name Transport hack passing data through the window.name property of an iframe

Cross domain javascript form filling, reverse proxy

I need a javascript form filler that can bypass the 'same origin policy' most modern browsers implement.
I made a script that opens the desired website/form in a new browser. With the handler, returned by the window.open method, I want to retrieve the inputs with theWindowHandler.document.getElementById('inputx') and fill them (access denied).
Is it possible to solve this problem by using Isapi Rewrite (official site) in IIS 6 acting like a reverse proxy?
If so, how would I configure the reverse proxy?
This is how far I got:
RewriteEngine on
RewriteLogLevel 9
LogLevel debug
RewriteRule CarChecker https://the.actualcarchecker.com/CheckCar.aspx$1 [NC,P]
The rewrite works, http://ourcompany.com/ourapplication/CarChecker, as evident in the logging. From within our companysite I can run the carchecker as if it was in our own domain. Except, the 'same origin policy' is still in force.
Update,
I stopped using Isapi Rewrite as the free version does not include a proxy component. I started to use the url rewriter from Managed Fusion.
My current working rewriterule:
RewriteRule /MySecuredSite/CarChecker https://the.actualcarchecker.com [NC,P]
Now I get the error: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
I think this occurs because our ssl-certificate is passed on to the carchecker site. How can I configure the reverse proxy so that the certificate of the carchecker site is passed on?
Regards,
Michel
Without knowing a few more details I decided that it might just be helpful to list some of the restrictions you face and some of the tricks you could take advantage of:
I'm not an ASP developer but I'm aware that, as you mentioned, there is some kind of viewstate variable that must be submitted along with a ASP form. I assume that this viewstate can be validated using only the form fields that are to be resubmitted. That's all that I'd expect (unless it's super complex) since the form the browser receives is all it sends back (along with values). So the point is that you'll need a valid viewstate when you submit to the aspx page, but maybe you can grab any viewstate you want from the server so long as the form fields you submit are identical.
You can write a webpage that acts just like your browser does. It can grab the aspx page (thus establishing a valid viewstate), then you can create all of the fields necessary to POST to the aspx page, including the viewstate, and do so. Whatever the results are can be returned from your webpage to the browser. Unless you have the ability to modify the other server I really don't see another option at this point, but maybe someone else can be more helpful.
If you can modify the other server then you have a few other options. One of them involves a trick for passing data between iframes. If you're using a hidden iframe to get the aspx page then you won't be able to get the result back to the parent page due to the cross-domain restriction. But since you can modify the other server (running on the.actualcarchecker.com), you can get around this. To do so just make that server provide JavaScript to submit the form asynchronously and then set the result (serialized to a string) to window.name.
Now to get access to window.name from your domain, you set the iframe's window.location to a page on your domain that will simply call a function you wrote in the JavaScript loaded in the parent window. Like window.parent.process(window.name). Since the iframe loaded a page on your domain it will have access to window.name which will not have been changed even though you changed window locations. Then the process() function in the parent window can deserialize the string, remove the hidden iframe, show the results, do whatever you want, etc.
You won't be able to populate the aspx form that's loaded in the hidden iframe unless you do a similar trick on the other domain's server. That server's JavaScript will need to read from window.name to receive the inputs to populate the form with. However, if both servers are in on the trick then you don't have to write a proxy, you can just pass data via window.name.
Which server side language are you using? Using it you can create a proxy which should easily bypass the one domain policy...
PHP
<?php
$handle = fopen("https://the.actualcarchecker.com/CheckCar.aspx", "r");
$contents = '';
while (!feof($handle)) {
$contents .= fread($handle, 8192);
}
fclose($handle);
echo $contents;
?>
I'd imagine it would be a similar process with other languages.
Why don't you use JSONP approach instead? I.e. use JavaScript to read the values entered into your form and sent it to the server-side handler via a dynamically generated <script> element (<script> and img elements can refer to resources from external domains).
var e = document.createElement("script");
e.setAttribute("type", "text/javascript");
e.setAttribute("src", "https://the.actualcarchecker.com/CheckCar.aspx?input1=value1&input2=value2");
document.getElementsByTagName('head')[0].appendChild(e);
Likely, you will not need any serious URL rewriting at all if you use this approach - just make sure that CheckCar.aspx returns valid JSON.
JQuery even has several convenience functions for this: AFAIK $.getJSON will transparently switch from XHR to dynamic script insertion method if the request is cross-domain. Also, it supports specifying callbacks. See jQuery docs and this IBM article for more info.
Will this method work for you?

How to get javascript in an iframe to modify the parent document?

So I have two documents dA and dB hosted on two different servers sA and sB respectively.
Document dA has some JS which opens up an iframe src'ing document dB, with a form on it. when the form in document dB is submitted to a form-handler on server sB, I want the iframe on page dA to close.
I hope that was clear enough. Is there a way to do this?
Thanks!
-Mala
UPDATE: I have no control over dA or sA except via inserted javascript
This isn't supposed to be possible due to browser/JavaScript security sandbox policy. That being said, it is possible to step outside of those limitations with a bit of hackery. There are a variety of methods, some involving Flash.
I would recommend against doing this if possible, but if you must, I'd recommend the DNS approach referred to here:
http://www.alexpooley.com/2007/08/07/how-to-cross-domain-javascript/
Key Excerpt:
Say domain D wants to
connect to domain E. In a nutshell,
the trick is to use DNS to point a
sub-domain of D, D_s, to E’s server.
In doing so, D_s takes on the
characteristics of E, while also being
accessible to D.
Assume that I create page A, that lies withing a frame that covers the entire page.
Let A link to yourbank.com, and you click on that link. Now if I could use javascript that modifies the content of the frame (banking site), I would be able to quite easily read the password you are using and store it in a cookie, send it to my server, etc.
That is the reason you cannot modify the content in another frame, whose content is NOT from the same domain. However, if they ARE from the same domain, you should be able to modify it as you see fit (both pages must be on your server).
You should be able to access the iframe with this code:
window["iframe_name"].document.body
If you just want the top-level to close, you can just call something like this:
window.top.location = "http://www.example.com/dC.html";
This will close out dA and sent the user to dC.html instead. dC.html can have the JS you want to run (for example, to close the window) in the onload handler.
Other people explained security implications. But the question is legitimate, there are use cases for that, and it is possible in some scenarios to do what you want.
W3C defines a property on document called domain, which is used to check security permissions. This property can be manipulated cooperatively by both documents, so they can access each other in some cases.
The governing document is DOM Level 1 Spec. Look at the description of document. As you can see this property is defined there and … it is read-only. In reality all browsers allow to modify it:
Mozilla's document.domain description.
Microsoft's domain property description.
Modifications cannot be arbitrary. Usually only super-domains are allowed. It means that you can make two documents served by different server to access each other, as long as they have a common super-domain.
So if you want two pages to communicate, you need to add a small one-liner, which should be run on page load. Something like that should do the trick:
document.domain = "yourdomain.com";
Now you can serve them from different subdomains without losing their accessibility.
Obviously you should watch for timing issues. They can be avoided if you establish a notification protocol of some sort. For example, one page (the master) sets its domain, and loads another page (the server). When the server is operational, it changes its domain and accesses the master triggering some function.
A mechanism to do so would be capable of a cross-site scripting attack (since you could do more than just remove a benign bit of page content).
A safe approach would limit to just the iframe document emptying/hiding itself, but if the iframe containing it is fixed size, you will just end up with a blank spot on the page.
If you don't have control over dA or Sa this isn't possible because of browser security restrictions. Even the Flash methods require access to both servers.
This is a bit convoluted but may be more legitimate than a straight XSS solution:
You have no control over server A other than writing javascript to document A. But you are opening an iframe within document A, which suggests that you only have write-access to document A. This a bit confusing. Are you writing the js to document A or injecting it somehow?
Either way, here is what I dreamed up. It won't work if you have no access to the server which hosts the page which has the iframe.
The user hits submit on the form within the iframe. The form, once completed, most likely changes something on the server hosting that form. So you have an AJAX function on Document A which asks a server-side script to check if the form has been submitted yet. If it has, the script returns a "submitted" value to the AJAX function, which triggers another js function to close the iframe.
The above requires a few things:
The iframe needs to be on a page hosted on a server where you can write an additional server-side script (this avoids the cross-domain issue, since the AJAX is pointing to the same directory, in theory).
The server within the iframe must have some url that can be requested which will return some kind of confirmation that the form has been submitted.
The "check-for-submitted" script needs to know both the above-mentioned URL and what to look for upon loading said URL.
If you have all of the above, the ajax function calls the server-script, the server-script uses cURL to go the URL that reflects if the form is done, the server-script looks for the "form has been submitted" indicators, and, depending on what it finds, returns an answer of "not submitted" or "submitted" to the ajax function.
For example, maybe the form is for user registration. If your outer document knows what username will be entered into the form, the server-side script can go to http://example.org/username and if it comes up with "user not found" you know the form has yet to be submitted.
Anything that goes beyond what is possible in the above example is probably outside of what is safe and secure anyway. While it would be very convenient to have the iframe close automatically when the user has submitted it, consider the possibility that I have sent you an email saying your bank account needs looking at. The email has a link to a page I have made which has an iframe of your bank's site set to fill the entire viewable part of my page. You log in as normal, because you are very trusting. If I had access to the fact that you hit submit on the page, that would imply I also had access to what you submitted or at the very least the URL that the iframe redirected to (which could have a session ID in or all sorts of other data the bank shouldn't include in a URL).
I don't mean to sound preachy at all. You should just consider that in order to know about one event, you often are given access to other data that you ought not have.
I think a slightly less elegant solution to your problem would be to have a link above the iframe that says "Finished" or "Close" that kills the iframe when the user is done with the form. This would not only close the iframe when the user has submitted the form, but also give them a chance to to say "oops! I don't want to fill out this form anyway. Nevermind!" Right now with your desired automatic solution, there is no way to get rid of the iframe unless the user hits submit.
Thank you everybody for your answers. I found a solution that works:
On my server, I tell the form to redirect to the url that created the iframe.
On the site containing the iframe, I add a setInterval function to poll for the current location of the iframe.
Due to JS sandboxing, this poll does not work while the url is foreign (i.e. before my form is submitted). However, once the url is local (i.e. identical to that of the calling page), the url is readable, and the function closes the iframe. This works as soon as the iframe is redirected, I don't even need to wait for the additional pageload.
Thank you very much Greg for helping me :)

JavaScript/Greasemonkey: Avoiding FireFox Security Warning when Submitting a Form from a Secure Page

I'm writing a Greasemonkey script to connect two company-internal webpages. One is SSL, and the other is insecure and can only be accessed via a POST request. If I create a hidden form on the secure page and submit it via an onclick() in an <a>, it works fine, but FF gives a warning:
Although this page is encrypted, the information you have entered is to be sent over an unencrypted connection and could easily be read by a third party.
Are you sure you want to continue sending this information?"
The insecure page can't be accessed via SSL and the other one can't be accessed w/o it, and I can't modify either server =\ Is there any way to avoid this warning by doing some kind of JavaScript/Greasemonkey redirect magic? Thanks!
EDIT: The warning can't be disabled (for rather good reasons, since it's hard to tell if what you're about to send is secure, otherwise). I'm mostly wondering if there's a way to POST in JavaScript without looking like you're submitting a form.
This may be possible by doing a GM_xmlhttpRequest. e.g.,
GM_xmlhttpRequest({
method: 'POST',
url: 'http://your.insecure.site.here',
onload: function(details) {
// look in the JavaScript console
GM_log(details.responseText);
/* This function will be called when the page (url)
has been loaded. Do whatever you need to do with the remote page here.*/
}
});
API/more info here: GM_xmlhttpRequest wiki
You could set up a new SSL site as a proxy that just passes data back to the insecure site. Or just have all your users turn off that particular security warning. (Sorry FF team, but that's not a terribly useful message to start with.)
That's a browser configuration setting, which can't (or shouldn't) be changable by Javascript.
Unless the script needs to be used by more than one user, Tools -> Options -> Security. You can click on settings to display which warning messages are displayed. Note that this currently affects all sites rather then just your internal system.

Categories

Resources