3

I'm using a bookmarklet to inject javascript into a webpage. I am trying to login into my gmail account(that part works) and in my gmail account automatically click Sent folder as the page loads. This is the starting page: enter image description here

This is the code I am using in bookmarklet:

javascript:
document.getElementById('Email').value='myEmail@gmail.com';
document.getElementById('next').click();
setTimeout(function(){
document.getElementById('Passwd').value='myPassword';
document.getElementById('signIn').click();},1000);

setTimeout(function(){
document.getElementsByClassName("J-Ke n0 aBU")[0].click();
},6000);

J-Ke n0 aBU is the class of Sent folder. This code logins into my account, but it doesn't click Sent folder.

I noticed similar behavior on other websites; whenever a new page loads or refreshes, the bookmarklet stops working.
Why is that and what is the correct way of using the same bookmarklet on different page than it was originally clicked.

GitaarLAB
  • 14,536
  • 11
  • 60
  • 80
potato
  • 4,479
  • 7
  • 42
  • 99
  • The javascript is executed on the current page only. Whenever a new page is loaded, all JS of the last page get's lost. If the JS still would be executed, any attacker could forward you to e.g. Gmail and read your mails there. – Reeno Nov 02 '15 at 16:21
  • hmm. is is possible to chain my scripts so that one gets executed on the login page and the second one in the next page? it isn't a necessity that bookmarklets are involved. – potato Nov 02 '15 at 16:25
  • You could try to use http://www.seleniumhq.org/ – Reeno Nov 02 '15 at 16:27
  • @Reeno "The bad news: from Firefox 55 onwards, Selenium IDE will no longer work." so... perhaps something else – twobob Mar 09 '18 at 12:34

2 Answers2

2

Disclaimer: I don't have gmail, so I didn't test this for gmail specifically.
This answer exists to address your comment:

What about iframes. Is theoretically possible to use gmail login in an iframe and therefore when the iframe changes to another page this doesnt have effect on the bookmarklet?

Yes, it is technically possible to have a persistent bookmarklet using iframes (or, deity forbid, a frameset).
As long as your parent window (and it's containing iframe) remain on the same domain, it should work according to cross-domain spec.
It is however possible (depending on used method) to (un-)intentionally 'counter-act' this (which, depending on used counter-action, can still be circumvented, etc..).

Navigate to website, then execute bookmarklet which:

  • Creates iframe.
  • Sets onload-handler to iframe.
  • Replaces current web-page content with iframe (to window's full width and height).
  • Set iframe's source to current url (reloading the currently open page in your injected iframe).

Then the iframe's onload-handler's job is to detect (using url/title/page-content) what page is loaded and which (if any) actions should be taken.

Example (minify (strip comments and unneeded whitespace) using Dean Edward's Packer v3):

javascript:(function(P){
  var D=document
  ,   B=D.createElement('body')
  ,   F=D.createElement('iframe')
  ; //end vars
  F.onload=function(){
    var w=this.contentWindow     //frame window
    ,   d=w.document             //frame window document
    ; //end vars
    //BONUS: update address-bar and title. 
    //Use location.href instead of document.URL to include hash in FF, see https://stackoverflow.com/questions/1034621/get-current-url-in-web-browser
    history.replaceState({}, D.title=d.title, w.location.href ); 
    P(w, d);        //execute handler
  };
  D.body.parentNode.replaceChild(B, D.body);   //replace body with empty body
  B.parentNode.style.cssText= B.style.cssText= (
   F.style.cssText= 'width:100%;height:100%;margin:0;padding:0;border:0;'
  ) + 'overflow:hidden;' ;           //set styles for html, body and iframe
  //B.appendChild(F).src=D.URL; //doesn't work in FF if parent url === iframe url
  //B.appendChild(F).setAttribute('src', D.URL); //doesn't work in FF if parent url === iframe url
  B.appendChild(F).contentWindow.location.replace(D.URL); //works in FF
}(function(W, D){   //payload function. W=frame window, D=frame window document
  alert('loaded');
  // perform tests on D.title, W.location.href, page content, etc.
  //   and perform tasks accordingly
}));

Note: one of the obvious methods to minify further is to utilize bracket-access with string-variables for things like createElement, contentWindow, etc.

Here is an example function-body for the payload-function (from above bookmarklet) to be used on http://www.w3schools.com (sorry, I couldn't quickly think of another target):

var tmp;
if(D.title==='W3Schools Online Web Tutorials'){
  //scroll colorpicker into view and click it after 1 sec
  tmp=D.getElementById('main').getElementsByTagName('img')[0].parentNode;
  tmp.focus();
  tmp.scrollIntoView();
  W.setTimeout(function(){tmp.click()},1000);
  return;
}
if(D.title==='HTML Color Picker'){
  //type color in input and click update color button 'ok'
  tmp=D.getElementById('entercolorDIV');
  tmp.scrollIntoView();
  tmp.querySelector('input').value='yellow';
  tmp.querySelector('button').click();

  //click 5 colors with 3 sec interval
  tmp=D.getElementsByTagName('area');
  tmp[0].parentNode.parentNode.scrollIntoView();
  W.setTimeout(function(){tmp[120].click()},3000);
  W.setTimeout(function(){tmp[48].click()},6000);
  W.setTimeout(function(){tmp[92].click()},9000);
  W.setTimeout(function(){tmp[31].click()},12000);
  W.setTimeout(function(){tmp[126].click()},15000);
  return;
}

above example (inside bookmarklet) minified:

javascript:(function(P){var D=document,B=D.createElement('body'),F=D.createElement('iframe');F.onload=function(){var w=this.contentWindow,d=w.document;history.replaceState({},D.title=d.title,w.location.href);P(w,d)};D.body.parentNode.replaceChild(B,D.body);B.parentNode.style.cssText=B.style.cssText=(F.style.cssText='width:100%;height:100%;margin:0;padding:0;border:0;')+'overflow:hidden;';B.appendChild(F).contentWindow.location.replace(D.URL)}(function(W,D){var tmp;if(D.title==='W3Schools Online Web Tutorials'){tmp=D.getElementById('main').getElementsByTagName('img')[0].parentNode;tmp.focus();tmp.scrollIntoView();W.setTimeout(function(){tmp.click()},1000);return}if(D.title==='HTML Color Picker'){tmp=D.getElementById('entercolorDIV');tmp.scrollIntoView();tmp.querySelector('input').value='yellow';tmp.querySelector('button').click();tmp=D.getElementsByTagName('area');tmp[0].parentNode.parentNode.scrollIntoView();W.setTimeout(function(){tmp[120].click()},3000);W.setTimeout(function(){tmp[48].click()},6000);W.setTimeout(function(){tmp[92].click()},9000);W.setTimeout(function(){tmp[31].click()},12000);W.setTimeout(function(){tmp[126].click()},15000);return}}));

Hope this helps (you get started)!

Community
  • 1
  • 1
GitaarLAB
  • 14,536
  • 11
  • 60
  • 80
1

As JavaScript is executed in the context of the current page only, it's not possible to execute JavaScript which spans over more than one page. So whenever a second page is loaded, execution of the JavaScript of the first page get's halted.

If it would be possible to execute JavaScript on two pages, an attacker could send you to another page, read your personal information there and send it to another server in his control with AJAX (e.g. your mails).

A solution for your issue would be to use Selenium IDE for Firefox (direct link to the extension). Originally designed for automated testing, it can also be used to automate your browser.

Reeno
  • 5,720
  • 11
  • 37
  • 50
  • 1
    What about iframes. Is teoretically possible to use gmail login in an iframe and therefore when the iframe changes to another page this doesnt have effect on the bookmarklet? – potato Nov 02 '15 at 18:20
  • 1
    Not possible. The reason is my second paragraph. You can read more about all this here: http://javascript.info/tutorial/same-origin-security-policy – Reeno Nov 02 '15 at 18:34
  • 1
    It *is theoretically possible* to have a persistent bookmarklet using an iframe (see my answer) on the *same domain*. However, if gmail's code will let you do this is a different thing. The 'attacker' in this case is the one who executes the bookmarklet (the user himself, which, in the case of a bookmarklet from the user, is a *good* thing). – GitaarLAB Nov 29 '15 at 05:10