Windows.Triage.ScreenConnect

This artifact extracts useful data for triage of ConnectWise ScreenConnect CVE-2024-1709 and CVE-2024-1708 impacting versions 23.9.7 and prior.

This artifact will:

  1. Check for Webshells in /App_Extensions/**/*.{aspx,ashx} path.
    Some observed legitimate webapp strings have been excluded.
    NOTE: Use WebshellsUSN to find potential exploits that cleanup shells.

  2. Parse C:\Program Files\ScreenConnect\App_data\User.Xml file.
    Usually this file is set during first use and reset during exploit. Check for timestamp discrepancies and obviously evil usernames/email (@poc.com).

  3. Parse security.db.
    Add time filter. Results are stacked, check for unusual access patterns and malicious IPs.

  4. List and upload (optionally) all ScreenConnect files.

Collect additional artifacts as desired for support.



name: Windows.Triage.ScreenConnect
author: Matt Green - @mgreen27 - Rapid7 Labs
description: |
   This artifact extracts useful data for triage of ConnectWise ScreenConnect
   CVE-2024-1709 and CVE-2024-1708 impacting versions 23.9.7 and prior.
   
   This artifact will:   
   
   1. Check for Webshells in ```/App_Extensions/**/*.{aspx,ashx}``` path.  
   Some observed legitimate webapp strings have been excluded.   
   NOTE: Use WebshellsUSN to find potential exploits that cleanup shells.   
   
   2. Parse ```C:\Program Files\ScreenConnect\App_data\User.Xml``` file.   
   Usually this file is set during first use and reset during exploit. 
   Check for timestamp discrepancies and obviously evil usernames/email 
   (@poc.com).  
   
   3. Parse ```security.db```.   
   Add time filter. Results are stacked, check for unusual access patterns 
   and malicious IPs.
   
   4. List and upload (optionally) all ScreenConnect files.
   
   Collect additional artifacts as desired for support.

reference:
    - https://www.rapid7.com/blog/post/2024/02/20/etr-high-risk-vulnerabilities-in-connectwise-screenconnect/
   
type: CLIENT

parameters:
   - name: TargetGlob
     default: "C:/Program Files*/**/ScreenConnect/**"
     description: Glob for all files under ScreenConnect program files
   - name: ExcludedWebshellStrings
     description: Excluded webshell strings.
     default: ScreenConnect
   - name: DateAfter
     description: Search for security events after this date 
     type: timestamp
     default: "2024-02-20"
   - name: DateBefore
     description: Search for security events before this date 
     type: timestamp
   - name: UploadFiles
     description: If selected Upload all ScreenConnect files for review
     type: bool


precondition: SELECT OS From info() where OS = 'windows'
sources:
  - name: Webshells
    query: |
      LET shells = SELECT OSPath, Mtime,Atime,Ctime,Btime 
        FROM glob(globs=TargetGlob + "/App_Extensions/**/*.{aspx,ashx}")
        WHERE NOT IsDir
      
      SELECT * FROM foreach(row=shells, query={
        SELECT 
            OSPath,
            dict(
                Mtime=Mtime,
                Atime=Atime,
                Ctime=Ctime,
                Btime=Btime ) as Timestamps,
            read_file(filename=OSPath) as Contents
        FROM scope()
        WHERE NOT if(condition=ExcludedWebshellStrings,
                        then= Contents=~ExcludedWebshellStrings,
                        else= False )
      })
      
  - name: WebshellsUsn
    query: |
      SELECT Timestamp,OSPath,Reason,MFTId,Sequence,ParentMFTId,ParentSequence,Usn
      FROM Artifact.Windows.Forensics.Usn(
                        FileNameRegex='\.(aspx|ashx)$',
                        PathRegex='ScreenConnect.+App_Extensions',
                        DateAfter=DateAfter,
                        DateBefore=DateBefore )

  - name: UserXml
    query: |
      SELECT 
        OSPath, 
        dict(
            Mtime=Mtime,
            Atime=Atime,
            Ctime=Ctime,
            Btime=Btime ) as FileTimestamps,
        parse_xml(file=OSPath).Users.User as UserXml
      FROM glob(globs=TargetGlob + '/user.xml')


  - name: SecurityEvents
    query: |
      LET MaxDate <= if(condition= DateBefore, then=DateBefore, else= '2030-01-01')
      
      LET db = SELECT OSPath, Mtime,Atime,Ctime,Btime 
        FROM glob(globs=TargetGlob + '/security.db')
      
      LET sqlquery = "SELECT * FROM SecurityEvent"
      
      LET results = SELECT * FROM foreach(row=db,query= {
            SELECT * FROM sqlite(file=OSPath,query=sqlquery)
            WHERE Time > DateAfter AND Time < MaxDate
        })

      SELECT 
        EventType,
        OperationResult,
        ip(netaddr4_be=int(
            int=format(format='0x%x',args=NetworkAddress))) AS NetworkAddress,
        UserAgent,
        UserSource,
        UrlReferrer,
        UserName,
        min(item=Time) AS Earliest,
        max(item=Time) AS Latest,
        count() AS Total
      FROM results
      GROUP BY UserAgent, UserSoure, UrlReferrer, UserName

  - name: Files
    query: |
        LET TargetGlobs = (
                "C:/Windows/Temp/ScreenConnect*/**",
                "C:/Program Files/ScreenConnect*/**",
                "C:/Program Files (x86)/ScreenConnect*/**",
                "C:/ProgramData/ScreenConnect*/**",
                "C:/Users/*/Documents/ConnectWiseControl/**" )
        SELECT * 
        FROM Artifact.Windows.Search.FileFinder(
                            Upload_File=UploadFiles,
                            SearchFilesGlob=TargetGlobs )