Back to Articles

Joro: The Web Exploitation Framework That Finally Bridges Proxy, C2, and Team Collaboration

[ View on GitHub ]

Joro: The Web Exploitation Framework That Finally Bridges Proxy, C2, and Team Collaboration

Hook

Most penetration testers juggle three separate tools for web exploitation: a proxy for traffic interception, a C2 framework for post-exploitation, and collaborative infrastructure for team coordination. Joro collapses all three into a single Go binary.

Context

The modern web penetration testing workflow is fragmented by design. You start with Burp Suite or mitmproxy to intercept traffic, manually extract credentials or session tokens, pivot to a C2 framework like Cobalt Strike or Sliver for persistent access, and coordinate findings through Slack or shared spreadsheets. Each tool boundary introduces friction—copying payloads between terminals, screenshotting results for teammates, manually correlating blind XSS callbacks with injection points.

BishopFox's Joro emerged from this operational pain point. Built in Go and released as open-source, it integrates intercepting proxy functionality, fuzzing capabilities, web shell generation, out-of-band detection infrastructure, and bidirectional Sliver C2 integration. The collaborative team server adds real-time multiplayer capabilities, letting multiple operators share proxy history, findings, and chat without expensive enterprise licenses. For red teams already invested in Sliver, Joro represents the missing web exploitation layer that turns initial access into implant deployment without context switching between tools.

Technical Insight

At its core, Joro implements Go's net/http.RoundTripper interface for HTTP interception, wrapping the default transport with custom logic that captures requests and responses before forwarding them. The proxy engine uses goproxy for MITM TLS, dynamically generating certificates from a CA root that clients must trust. WebSocket traffic gets special treatment—the proxy hijacks the underlying TCP connection using http.Hijacker, then copies bytes bidirectionally while logging frames.

Here's how the proxy chain works conceptually:

type ProxyTransport struct {
    base http.RoundTripper
    storage *sqlite.DB
    plugins []PluginHook
}

func (t *ProxyTransport) RoundTrip(req *http.Request) (*http.Response, error) {
    // Clone request for logging
    reqCopy := cloneRequest(req)
    
    // Execute plugin chain (pre-request hooks)
    for _, plugin := range t.plugins {
        req = plugin.OnRequest(req)
    }
    
    // Forward to actual server
    resp, err := t.base.RoundTrip(req)
    
    // Execute plugin chain (post-response hooks)
    for _, plugin := range t.plugins {
        resp = plugin.OnResponse(req, resp)
    }
    
    // Persist to SQLite in goroutine to avoid blocking
    go t.storage.SaveTransaction(reqCopy, resp)
    
    // Broadcast to team server WebSocket clients
    go t.teamServer.BroadcastTransaction(reqCopy, resp)
    
    return resp, err
}

The fuzzer implements position-based payload injection similar to Burp Intruder's attack types. You mark injection points with §param§ delimiters, select an attack mode (sniper, battering ram, cluster bomb), and the fuzzer spawns a goroutine pool to parallelize requests. Unlike Python-based fuzzers that spawn processes or use threading with GIL constraints, Go's goroutines provide lightweight concurrency—you can run hundreds of concurrent requests without significant overhead.

The team server architecture uses WebSocket connections for real-time collaboration. When a client connects, the server registers it in an in-memory map and broadcasts events (new proxy traffic, chat messages, shared notes) to all connected clients. SQLite serves as the persistence layer, storing proxy history, findings, and metadata. This works well for small teams (2-5 operators) but hits SQLite's write concurrency limits under heavy traffic—the database locks on writes, creating contention when multiple operators generate traffic simultaneously.

Web shell generation leverages template-based obfuscation with AST-level transformations. Instead of simple string substitution, Joro parses the target language (PHP, JSP, ASPX, etc.) into an abstract syntax tree, randomizes variable names, reorders function definitions, and injects benign code to increase entropy. The generated artifacts evade signature-based detection better than static templates but still produce recognizable patterns with repeated use.

The Sliver C2 integration is Joro's most distinctive feature. It uses gRPC to communicate with external Sliver teamservers, presenting implant sessions alongside web shells in a unified interface. You can pivot from a web shell to a full implant by generating a stager payload through the Joro UI, executing it via the web shell, and receiving the callback in Sliver—all without leaving the tool. However, the integration is unidirectional from Sliver's perspective: Joro can send commands but can't receive new sessions that originated outside its context.

The listener mode runs concurrent DNS and HTTP servers to catch out-of-band callbacks, similar to Burp Collaborator or Canarytokens. When you inject a payload with a unique identifier, Joro correlates incoming DNS queries or HTTP requests with the original injection point. The XSS Hunter integration extends this further—when a blind XSS payload fires, Joro captures screenshots, DOM snapshots, and cookies, turning blind vulnerabilities into actionable findings without requiring separate infrastructure.

The entire UI is embedded using Go 1.16's //go:embed directive, bundling HTML, JavaScript, and CSS directly into the binary. This eliminates Node.js dependencies and produces a single ~20MB executable that runs on Linux and macOS without installation. The plugin system uses Go's plugin package to load .so files at runtime, registering hooks into the proxy chain and adding UI tabs. Unfortunately, Go's plugin support is completely absent on Windows, making Joro non-extensible for Windows-based pentesters.

Gotcha

The Windows plugin limitation is a dealbreaker for many pentesters. Go's plugin system relies on dynamic linking features unavailable in Windows PE executables, so the entire extensibility model simply doesn't work on the platform where most security practitioners operate. You get the core functionality but can't write custom hooks or integrations.

SQLite persistence creates a scalability ceiling. High-traffic engagements or large team servers will hit write contention—SQLite locks the database file on writes, so concurrent operators generating traffic simultaneously will experience latency. The project shows no evidence of sharding, replication, or migration to PostgreSQL/MySQL for horizontal scaling. The team server also lacks explicit mention of TLS or authentication in the collaborative mode, raising serious questions about operational security. Broadcasting proxy traffic over unencrypted WebSockets on untrusted networks could leak sensitive engagement data. The Sliver integration being read-only from the C2 perspective limits its usefulness as a full alternative—you can't use Joro as your primary C2 interface since it won't receive sessions generated by other operators or automated deployment pipelines.

Verdict

Use Joro if: You're running red team engagements with Sliver as your primary C2 and need seamless web-to-implant pivoting without manually bridging tools. The collaborative team server makes it ideal for multi-operator penetration tests where shared context matters more than individual feature depth. The single-binary deployment shines in air-gapped environments or time-constrained assessments where spinning up separate proxy, OOB detection, and collaboration infrastructure isn't feasible. Skip it if: You're on Windows and require plugin extensibility, need enterprise-grade scalability for high-traffic engagements, or have mature Burp Suite workflows with irreplaceable extensions. The project's minimal GitHub traction (12 stars) signals a small community—expect to debug issues by reading source code rather than finding community support. If you're not already invested in Sliver, the C2 integration loses most of its value, and you're better served by mature alternatives like Burp Suite Pro or Caido for pure proxy functionality.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/cybersecurity/bishopfox-joro.svg)](https://starlog.is/api/badge-click/cybersecurity/bishopfox-joro)