Skip to main content
Glama
x0base

mcp-security-toolkit

by x0base

phpggc_generate

Create PHP unserialize gadget chains for security assessments. Specify a chain identifier and shell command; output raw or encoded payloads.

Instructions

Generate a single PHP unserialize gadget chain via phpggc.

Args: chain: Gadget chain identifier (e.g. Laravel/RCE9, Symfony/RCE4, Monolog/RCE1). Run phpggc -l locally to enumerate. command: Shell command to embed in the chain (e.g. id, curl ...). encoding: One of raw, base64, url, json, soft. fast_destruct: Adds --fast-destruct (triggers without await). extra_args: Extra raw arguments to pass through.

Returns: PhpggcReport with the generated payload (string). If phpggc is not installed, available is False.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
chainYes
commandYes
encodingNobase64
fast_destructNo
extra_argsNo

Implementation Reference

  • The main handler function `phpggc_generate` that wraps the phpggc CLI to generate PHP deserialization gadget chains. It checks opt-in env var, validates inputs (chain, command, encoding), locates the phpggc binary, constructs CLI args, runs subprocess, and returns a PhpggcReport dict.
    def phpggc_generate(
        chain: str,
        command: str,
        encoding: Literal["raw", "base64", "url", "json", "soft"] = "base64",
        fast_destruct: bool = False,
        extra_args: list[str] | None = None,
    ) -> dict:
        """Generate a single PHP unserialize gadget chain via `phpggc`.
    
        Args:
            chain: Gadget chain identifier (e.g. `Laravel/RCE9`, `Symfony/RCE4`,
                `Monolog/RCE1`). Run `phpggc -l` locally to enumerate.
            command: Shell command to embed in the chain (e.g. `id`, `curl ...`).
            encoding: One of `raw`, `base64`, `url`, `json`, `soft`.
            fast_destruct: Adds `--fast-destruct` (triggers without await).
            extra_args: Extra raw arguments to pass through.
    
        Returns:
            PhpggcReport with the generated payload (string). If `phpggc` is not
            installed, `available` is False.
        """
        if os.environ.get(OPT_IN_ENV, "").lower() not in {"1", "true", "yes"}:
            return {
                "error": "offensive-tool-disabled",
                "hint": (
                    f"This tool generates PHP deserialization payloads and is "
                    f"disabled by default. Set {OPT_IN_ENV}=1 in the MCP server's "
                    f"environment to enable. Only use against systems you are "
                    f"explicitly authorized to test."
                ),
            }
    
        if not isinstance(chain, str) or not chain.strip():
            return {"error": "chain must be a non-empty string"}
        if not isinstance(command, str) or not command.strip():
            return {"error": "command must be a non-empty string"}
        if encoding not in ENCODINGS:
            return {"error": f"encoding must be one of {ENCODINGS}"}
    
        bin_path = shutil.which("phpggc")
        if not bin_path:
            return PhpggcReport(
                available=False, chain=chain, encoding=encoding,
                stderr="phpggc binary not found on PATH — install from https://github.com/ambionics/phpggc",
            ).model_dump()
    
        args: list[str] = [bin_path]
        if encoding == "base64":
            args.append("-b")
        elif encoding == "url":
            args.append("-u")
        elif encoding == "json":
            args.append("-j")
        elif encoding == "soft":
            args.append("-s")
        # encoding == "raw" → no flag
        if fast_destruct:
            args.append("--fast-destruct")
        if extra_args:
            args.extend(str(a) for a in extra_args)
        # `--` separates flags from positional args: prevents a `chain` value
        # starting with `-` from being reinterpreted as a phpggc flag.
        args.append("--")
        args.extend([chain, command])
    
        try:
            result = subprocess.run(
                args, capture_output=True, text=True, timeout=30, check=False,
            )
        except (subprocess.TimeoutExpired, OSError) as e:
            return PhpggcReport(
                available=True, chain=chain, encoding=encoding,
                stderr=f"phpggc execution failed: {e}", cmd=args,
            ).model_dump()
    
        if result.returncode != 0:
            return PhpggcReport(
                available=True, chain=chain, encoding=encoding,
                stderr=result.stderr.strip() or "non-zero exit", cmd=args,
            ).model_dump()
    
        return PhpggcReport(
            available=True, chain=chain, encoding=encoding,
            payload=result.stdout.strip(), cmd=args,
        ).model_dump()
  • PhpggcReport Pydantic BaseModel schema defining the output structure: available (bool), chain, encoding, payload, stderr, cmd.
    class PhpggcReport(BaseModel):
        available: bool
        chain: str | None
        encoding: str
        payload: str | None = None
        stderr: str | None = None
        cmd: list[str] = []
  • Registration of the phpggc_generate tool with the MCP server via `mcp.tool()(phpggc_generate.phpggc_generate)`.
    mcp.tool()(phpggc_generate.phpggc_generate)
  • OPT_IN_ENV constant ('MCP_SECURITY_TOOLKIT_ENABLE_OFFENSIVE') used as an opt-in gate for this offensive tool.
    OPT_IN_ENV = "MCP_SECURITY_TOOLKIT_ENABLE_OFFENSIVE"

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.3.1

TDQS

A4/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It mentions returning a PhpggcReport and that `available` is False if phpggc is missing, but fails to disclose behavioral traits like executing shell commands, security implications, or potential side effects of generating exploit payloads.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, with a clear Args section and Returns section. Every sentence is informative, and there is no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (5 parameters, no annotations, no output schema), the description is fairly complete. It explains inputs, output structure (PhpggcReport with payload and available flag), and a note on installation. However, it could benefit from mentioning potential risks.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description compensates by explaining each parameter: chain (with example), command, encoding (listing options), fast_destruct (adding raw argument), and extra_args. It adds meaning beyond the schema's type/constraints.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with a specific verb ('Generate') and resource ('PHP unserialize gadget chain via `phpggc`'), clearly distinguishing the tool from its siblings which are unrelated security tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description lists all parameters and explains how to use them, including a hint to run `phpggc -l` locally. It implicitly covers when to use (generating gadget chains) but does not explicitly state when not to use or provide alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.