nuclei icon indicating copy to clipboard operation
nuclei copied to clipboard

[BUG] JARM function bypasses SOCKS5 proxy and reveals real IP

Open Zcentury opened this issue 5 months ago • 1 comments

Is there an existing issue for this?

  • [x] I have searched the existing issues.

Current Behavior

When performing a scan on my cloud server using Nuclei with a SOCKS5 proxy configured via the -p flag, my real IP address is observed in the server logs. Upon investigation, it was determined that the jarm function, specifically when used with the cobalt-strike-c2-jarm.yaml template, is the cause of this issue. Additionally, no network traffic appears to be routed through the configured proxy.

Command used: nuclei.exe -u https://myserverip/ -p socks5://127.0.0.1:7890 -pi=true -vv -ts -duc -t \templates\network\jarm\c2\cobalt-strike-c2-jarm.yaml

Expected Behavior

The expected behavior is for all network traffic, including that generated by the jarm function, to be routed through the configured SOCKS5 proxy. Consequently, the scanned server's logs should show the proxy's IP address, not my real IP address.

Steps To Reproduce

  1. Set up a SOCKS5 proxy (e.g., on 127.0.0.1:7890).
  2. Run the following Nuclei command targeting a personal cloud server (replace https://myserverip/ with your server's actual IP/URL):
    nuclei.exe -u https://myserverip/ -p socks5://127.0.0.1:7890 -pi=true -vv -ts -duc -t \templates\network\jarm\c2\cobalt-strike-c2-jarm.yaml
    
  3. Monitor the access logs on myserverip.

Environment

- OS: Windows 11
- Nuclei: v3.4.7
- Go: go1.24.1

Anything else?

The issue seems to stem from the jarm function's implementation not utilizing the globally configured SOCKS5 proxy. A potential solution involves modifying the github.com/projectdiscovery/utils/crypto/jarm/jarm.go and github.com/projectdiscovery/dsl/dsl.go packages to explicitly handle SOCKS5 proxy connections for JARM hashing when the -pi flag is used, leveraging the HTTP_PROXY environment variable.

Proposed code changes:

  1. Add Socks5WrapperDialer and CreateSOCKS5Dialer to github.com/projectdiscovery/utils/crypto/jarm/jarm.go:

    type Socks5WrapperDialer struct {
        dialer proxy.Dialer
    }
    
    func (s *Socks5WrapperDialer) Dial(ctx context.Context, network, address string) (net.Conn, error) {
        conn, err := s.dialer.Dial(network, address)
        if err != nil {
            return nil, fmt.Errorf("failed to connect via SOCKS5 proxy: %w", err)
        }
        return conn, nil
    }
    
    func CreateSOCKS5Dialer(socks5ProxyURLStr string) (connpool.Dialer, error) {
        proxyURL, err := url.Parse(socks5ProxyURLStr)
        if err != nil {
            return nil, fmt.Errorf("failed to parse proxy URL: %v", err)
        }
    
        if proxyURL.Scheme != "socks5" {
            return nil, fmt.Errorf("unsupported proxy scheme: %s, only socks5 is supported", proxyURL.Scheme)
        }
    
        var auth *proxy.Auth
        // Extract authentication information (if present)
        if proxyURL.User != nil {
            username := proxyURL.User.Username()
            password, hasPassword := proxyURL.User.Password()
            if hasPassword {
                auth = &proxy.Auth{User: username, Password: password}
            } else {
                auth = &proxy.Auth{User: username}
            }
        }
    
        // Create the SOCKS5 dialer
        socks5ProxyDialer, err := proxy.SOCKS5("tcp", proxyURL.Host, auth, proxy.Direct)
        if err != nil {
            return nil, fmt.Errorf("failed to create SOCKS5 proxy dialer: %w", err)
        }
    
        return &Socks5WrapperDialer{dialer: socks5ProxyDialer}, nil
    }
    
  2. Modify jarm function in github.com/projectdiscovery/dsl/dsl.go:

    MustAddFunction(NewWithPositionalArgs("jarm", 1, true, func(args ...interface{}) (interface{}, error) {
        host, ok := args[0].(string)
        if !ok {
            return nil, errors.New("invalid target")
        }
        hostname, portRaw, err := net.SplitHostPort(host)
        if err != nil {
            return nil, err
        }
        port, err := strconv.Atoi(portRaw)
        if err != nil {
            return nil, err
        }
    
        proxy := os.Getenv("HTTP_PROXY")
        if proxy == "" {
            proxy = os.Getenv("http_proxy")
        }
        if proxy != "" {
            socks5Dialer, err := jarm.CreateSOCKS5Dialer(proxy)
            if err != nil {
                return "", err
            }
            return jarm.HashWithDialer(socks5Dialer, hostname, port, 10)
        }
    
        return jarm.HashWithDialer(nil, hostname, port, 10)
    }))
    

Zcentury avatar Jul 30 '25 06:07 Zcentury

@Zcentury Thanks for reporting the issue, this will be indirectly fixed upon new https://github.com/projectdiscovery/dsl release

Mzack9999 avatar Oct 30 '25 18:10 Mzack9999