Skip to content

Commit 1a41c3d

Browse files
committed
feat: Add identity risk classification service and related utilities
- Implemented `identity_risk_service.py` for user segmentation and risk classification based on group memberships and privileges. - Introduced `weakpass_service.py` for querying Weakpass API with TLS fallback behavior. - Added `winrm_access_probe_service.py` for concurrent probing of WinRM service access with Kerberos support. - Created `session_summary.py` for generating end-of-session summary metrics related to attack paths.
1 parent c909c0b commit 1a41c3d

66 files changed

Lines changed: 9587 additions & 1793 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Dockerfile.runtime

Lines changed: 100 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,19 @@ ARG LIGOLO_NG_VERSION=0.8.3
8484
ARG MEDUSA_COMMIT=fef1e1f0ee91f6108a5a48d3b3c11dc4df40b122
8585
ARG FREERDP_VERSION=3.24.1
8686
ARG FREERDP_COMMIT=b6e770ccba87c58ffd0a55366fef33361798e39c
87+
ARG ADSCAN_RUNTIME_CONTRACT_VERSION="1"
8788
SHELL ["/bin/bash", "-euo", "pipefail", "-c"]
8889

8990
ENV ADSCAN_HOME=/opt/adscan \
9091
HOME=/opt/adscan \
92+
ADSCAN_RUNTIME_CONTRACT_VERSION=${ADSCAN_RUNTIME_CONTRACT_VERSION} \
9193
XDG_CONFIG_HOME=/opt/adscan/.config \
9294
NPM_CONFIG_UPDATE_NOTIFIER=false \
95+
PLAYWRIGHT_BROWSERS_PATH=/opt/adscan/ms-playwright \
9396
PATH="/opt/adscan/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
9497

98+
RUN mkdir -p /opt/adscan
99+
95100
RUN apt-get update -y && apt-get install -y --no-install-recommends \
96101
ca-certificates \
97102
curl \
@@ -213,6 +218,33 @@ RUN apt-get update -y && apt-get install -y --no-install-recommends \
213218
&& printf '%s\n' 'libnvidia-opencl.so.1' > /etc/OpenCL/vendors/nvidia.icd \
214219
&& rm -rf /var/lib/apt/lists/*
215220

221+
RUN printf '%s\n' \
222+
'#!/usr/bin/env bash' \
223+
'set -euo pipefail' \
224+
'if curl "$@"; then' \
225+
' exit 0' \
226+
'else' \
227+
' status=$?' \
228+
'fi' \
229+
'if [[ "$status" -ne 60 ]]; then' \
230+
' exit "$status"' \
231+
'fi' \
232+
'echo "warning: curl TLS verification failed; retrying with insecure fallback (-k)" >&2' \
233+
'exec curl -k "$@"' \
234+
> /usr/local/bin/adscan-curl \
235+
&& chmod +x /usr/local/bin/adscan-curl
236+
237+
# Install the browser revision expected by the Python Playwright package bundled
238+
# into the PRO binary. The Debian chromium package remains installed as a
239+
# fallback and for workflows that call Chromium directly.
240+
RUN set -eux; \
241+
python3 -m venv /tmp/playwright-installer; \
242+
/tmp/playwright-installer/bin/python -m pip install --no-cache-dir --upgrade pip; \
243+
/tmp/playwright-installer/bin/python -m pip install --no-cache-dir playwright==1.57.0; \
244+
PLAYWRIGHT_BROWSERS_PATH=/opt/adscan/ms-playwright \
245+
/tmp/playwright-installer/bin/python -m playwright install chromium; \
246+
rm -rf /tmp/playwright-installer
247+
216248
# Codex CLI (official ChatGPT plan sign-in path for Plus/Pro subscriptions).
217249
# Installed globally so `ask login codex` and `ask` can use `codex` directly.
218250
RUN set -eux; \
@@ -224,6 +256,8 @@ RUN mkdir -p /opt/adscan/{bin,tools,tool_venvs,wordlists,logs,fonts} /workspaces
224256
&& fc-cache -f \
225257
&& chmod -R 0777 /opt/adscan /workspaces
226258

259+
COPY wordlists/ /opt/adscan/wordlists/
260+
227261
COPY --from=john_builder /opt/adscan/tools/john/run /opt/adscan/tools/john/run
228262

229263
# Install Python tool environments (mirrors `PipToolsConfig` from adscan.py)
@@ -248,7 +282,7 @@ RUN set -eux; \
248282
\
249283
python3 -m venv /opt/adscan/tool_venvs/netexec/venv; \
250284
pip_retry /opt/adscan/tool_venvs/netexec/venv/bin/python -U pip; \
251-
pip_retry /opt/adscan/tool_venvs/netexec/venv/bin/python "git+https://github.com/Pennyw0rth/NetExec.git@f187717"; \
285+
pip_retry /opt/adscan/tool_venvs/netexec/venv/bin/python "git+https://github.com/Pennyw0rth/NetExec.git@73ccf0d"; \
252286
\
253287
python3 -m venv /opt/adscan/tool_venvs/certipy/venv; \
254288
pip_retry /opt/adscan/tool_venvs/certipy/venv/bin/python -U pip; \
@@ -262,10 +296,6 @@ RUN set -eux; \
262296
pip_retry /opt/adscan/tool_venvs/bloodhound-ce-py/venv/bin/python -U pip; \
263297
pip_retry /opt/adscan/tool_venvs/bloodhound-ce-py/venv/bin/python "bloodhound-ce==1.9.1"; \
264298
\
265-
python3 -m venv /opt/adscan/tool_venvs/weakpass/venv; \
266-
pip_retry /opt/adscan/tool_venvs/weakpass/venv/bin/python -U pip; \
267-
pip_retry /opt/adscan/tool_venvs/weakpass/venv/bin/python "weakpass-lookup"; \
268-
\
269299
python3 -m venv /opt/adscan/tool_venvs/enum-trusts/venv; \
270300
pip_retry /opt/adscan/tool_venvs/enum-trusts/venv/bin/python -U pip; \
271301
pip_retry /opt/adscan/tool_venvs/enum-trusts/venv/bin/python "git+https://github.com/ADScanPro/enum-trusts.git@f7eae14"; \
@@ -291,7 +321,11 @@ RUN set -eux; \
291321
# External tools (git/curl)
292322
RUN set -eux; \
293323
mkdir -p /opt/adscan/tools; \
294-
curl -fsSL "https://hashcat.net/files/hashcat-${HASHCAT_VERSION}.7z" -o /tmp/hashcat.7z; \
324+
if ! adscan-curl -fsSL "https://hashcat.net/files/hashcat-${HASHCAT_VERSION}.7z" -o /tmp/hashcat.7z; then \
325+
echo "warning: official hashcat download failed; falling back to SourceForge mirror" >&2; \
326+
wget --max-redirect=10 --no-check-certificate -O /tmp/hashcat.7z \
327+
"https://sourceforge.net/projects/hashcat.mirror/files/v${HASHCAT_VERSION}/hashcat-${HASHCAT_VERSION}.7z/download"; \
328+
fi; \
295329
7z x /tmp/hashcat.7z -o/opt/adscan/tools >/dev/null; \
296330
test -x "/opt/adscan/tools/hashcat-${HASHCAT_VERSION}/hashcat.bin"; \
297331
ln -sf "/opt/adscan/tools/hashcat-${HASHCAT_VERSION}/hashcat.bin" /opt/adscan/bin/hashcat; \
@@ -300,8 +334,8 @@ RUN set -eux; \
300334
\
301335
git clone --depth 1 https://github.com/Greenwolf/ntlm_theft.git /opt/adscan/tools/ntlm_theft; \
302336
mkdir -p /opt/adscan/tools/firepwd; \
303-
curl -fsSL https://raw.githubusercontent.com/lclevy/firepwd/refs/heads/master/firepwd.py -o /opt/adscan/tools/firepwd/firepwd.py; \
304-
curl -fsSL https://raw.githubusercontent.com/lclevy/firepwd/refs/heads/master/requirements.txt -o /opt/adscan/tools/firepwd/requirements.txt; \
337+
adscan-curl -fsSL https://raw.githubusercontent.com/lclevy/firepwd/refs/heads/master/firepwd.py -o /opt/adscan/tools/firepwd/firepwd.py; \
338+
adscan-curl -fsSL https://raw.githubusercontent.com/lclevy/firepwd/refs/heads/master/requirements.txt -o /opt/adscan/tools/firepwd/requirements.txt; \
305339
python3 -m venv /opt/adscan/tool_venvs/firepwd/venv; \
306340
/opt/adscan/tool_venvs/firepwd/venv/bin/python -m pip install --no-cache-dir -U pip; \
307341
/opt/adscan/tool_venvs/firepwd/venv/bin/python -m pip install --no-cache-dir -r /opt/adscan/tools/firepwd/requirements.txt; \
@@ -312,19 +346,19 @@ RUN set -eux; \
312346
/opt/adscan/tool_venvs/LSA-Reaper/venv/bin/python -m pip install --no-cache-dir -r /opt/adscan/tools/LSA-Reaper/requirements.txt impacket; \
313347
\
314348
mkdir -p /opt/adscan/tools/PKINITtools; \
315-
curl -fsSL https://raw.githubusercontent.com/dirkjanm/PKINITtools/refs/heads/master/gettgtpkinit.py -o /opt/adscan/tools/PKINITtools/gettgtpkinit.py; \
316-
curl -fsSL https://raw.githubusercontent.com/dirkjanm/PKINITtools/refs/heads/master/getnthash.py -o /opt/adscan/tools/PKINITtools/getnthash.py; \
317-
curl -fsSL https://raw.githubusercontent.com/dirkjanm/PKINITtools/refs/heads/master/requirements.txt -o /opt/adscan/tools/PKINITtools/requirements.txt; \
349+
adscan-curl -fsSL https://raw.githubusercontent.com/dirkjanm/PKINITtools/refs/heads/master/gettgtpkinit.py -o /opt/adscan/tools/PKINITtools/gettgtpkinit.py; \
350+
adscan-curl -fsSL https://raw.githubusercontent.com/dirkjanm/PKINITtools/refs/heads/master/getnthash.py -o /opt/adscan/tools/PKINITtools/getnthash.py; \
351+
adscan-curl -fsSL https://raw.githubusercontent.com/dirkjanm/PKINITtools/refs/heads/master/requirements.txt -o /opt/adscan/tools/PKINITtools/requirements.txt; \
318352
python3 -m venv /opt/adscan/tool_venvs/PKINITtools/venv; \
319353
/opt/adscan/tool_venvs/PKINITtools/venv/bin/python -m pip install --no-cache-dir -U pip; \
320354
/opt/adscan/tool_venvs/PKINITtools/venv/bin/python -m pip install --no-cache-dir -r /opt/adscan/tools/PKINITtools/requirements.txt; \
321355
\
322356
mkdir -p /opt/adscan/tools/kerbrute; \
323-
curl -fsSL https://github.com/ropnop/kerbrute/releases/download/v1.0.3/kerbrute_linux_amd64 -o /opt/adscan/tools/kerbrute/kerbrute; \
357+
adscan-curl -fsSL https://github.com/ropnop/kerbrute/releases/download/v1.0.3/kerbrute_linux_amd64 -o /opt/adscan/tools/kerbrute/kerbrute; \
324358
chmod +x /opt/adscan/tools/kerbrute/kerbrute; \
325359
\
326360
mkdir -p /opt/adscan/tools/ligolo-ng/proxy/linux-amd64; \
327-
curl -fsSL \
361+
adscan-curl -fsSL \
328362
"https://github.com/nicocha30/ligolo-ng/releases/download/v${LIGOLO_NG_VERSION}/ligolo-ng_proxy_${LIGOLO_NG_VERSION}_linux_amd64.tar.gz" \
329363
-o /tmp/ligolo_proxy.tar.gz; \
330364
tar -xzf /tmp/ligolo_proxy.tar.gz -C /opt/adscan/tools/ligolo-ng/proxy/linux-amd64 proxy; \
@@ -334,7 +368,7 @@ RUN set -eux; \
334368
rm -f /tmp/ligolo_proxy.tar.gz; \
335369
\
336370
mkdir -p /opt/adscan/tools/ligolo-ng/agent/windows-amd64; \
337-
curl -fsSL \
371+
adscan-curl -fsSL \
338372
"https://github.com/nicocha30/ligolo-ng/releases/download/v${LIGOLO_NG_VERSION}/ligolo-ng_agent_${LIGOLO_NG_VERSION}_windows_amd64.zip" \
339373
-o /tmp/ligolo_agent_windows_amd64.zip; \
340374
unzip -q /tmp/ligolo_agent_windows_amd64.zip agent.exe -d /opt/adscan/tools/ligolo-ng/agent/windows-amd64; \
@@ -447,20 +481,20 @@ RUN set -eux; \
447481
/opt/adscan/tools/windows-tools/runascs; \
448482
\
449483
# mimikatz – credential extraction (official gentilkiwi release ZIP)
450-
curl -fsSL \
484+
adscan-curl -fsSL \
451485
"https://github.com/gentilkiwi/mimikatz/releases/download/${MIMIKATZ_VERSION}/mimikatz_trunk.zip" \
452486
-o /tmp/mimikatz.zip; \
453487
unzip -p /tmp/mimikatz.zip x64/mimikatz.exe \
454488
> /opt/adscan/tools/windows-tools/mimikatz/mimikatz.exe; \
455489
rm /tmp/mimikatz.zip; \
456490
\
457491
# Rubeus – Kerberos attacks (Ghostpack compiled binaries mirror)
458-
curl -fsSL \
492+
adscan-curl -fsSL \
459493
"https://github.com/r3motecontrol/Ghostpack-CompiledBinaries/raw/master/Rubeus.exe" \
460494
-o /opt/adscan/tools/windows-tools/rubeus/Rubeus.exe; \
461495
\
462496
# Certify – ADCS exploitation (Ghostpack compiled binaries mirror)
463-
curl -fsSL \
497+
adscan-curl -fsSL \
464498
"https://github.com/r3motecontrol/Ghostpack-CompiledBinaries/raw/master/Certify.exe" \
465499
-o /opt/adscan/tools/windows-tools/certify/Certify.exe; \
466500
\
@@ -486,14 +520,14 @@ RUN set -eux; \
486520
rm -rf /tmp/Whisker; \
487521
\
488522
# Seatbelt – host security enumeration (Ghostpack compiled binaries mirror)
489-
curl -fsSL \
523+
adscan-curl -fsSL \
490524
"https://github.com/r3motecontrol/Ghostpack-CompiledBinaries/raw/master/Seatbelt.exe" \
491525
-o /opt/adscan/tools/windows-tools/seatbelt/Seatbelt.exe; \
492526
\
493527
# SharpHound – BloodHound collection from inside the target.
494528
# Keep this aligned with the managed BloodHound CE version. For BH CE v8.7.0,
495529
# upstream pins SHARPHOUND_VERSION=v2.10.0 in their Dockerfiles.
496-
curl -fsSL \
530+
adscan-curl -fsSL \
497531
"https://github.com/SpecterOps/SharpHound/releases/download/${SHARPHOUND_VERSION}/SharpHound_${SHARPHOUND_VERSION}_windows_x86.zip" \
498532
-o /tmp/sharphound.zip; \
499533
unzip -p /tmp/sharphound.zip SharpHound.exe \
@@ -504,12 +538,12 @@ RUN set -eux; \
504538
# The historical GitHub release URL now returns 404 and the source tree
505539
# requires a larger Mono/xbuild compatibility patch set than we want inside
506540
# the runtime image, so use the maintained OffSec knowledge-base binary.
507-
curl -fsSL "${KRBRELAYUP_URL}" \
541+
adscan-curl -fsSL "${KRBRELAYUP_URL}" \
508542
-o /opt/adscan/tools/windows-tools/krbrelayup/KrbRelayUp.exe; \
509543
\
510544
# RunasCs – run as different user (official GitHub release ZIP)
511545
# Also symlinked to the legacy path so runascs_manager.py finds it.
512-
curl -fsSL \
546+
adscan-curl -fsSL \
513547
"https://github.com/antonioCoco/RunasCs/releases/download/v${RUNASCS_VERSION}/RunasCs.zip" \
514548
-o /tmp/runascs.zip; \
515549
unzip -p /tmp/runascs.zip RunasCs.exe \
@@ -524,19 +558,29 @@ RUN set -eux; \
524558

525559
# Wordlists
526560
RUN set -eux; \
561+
download_wordlist() { \
562+
local url="$1"; \
563+
local dest="$2"; \
564+
if curl -fsSL "$url" -o "$dest"; then \
565+
return 0; \
566+
fi; \
567+
case "$url" in \
568+
https://weakpass.com/*) \
569+
echo "warning: TLS verification failed for $url; retrying with insecure fallback (-k)" >&2; \
570+
curl -kfsSL "$url" -o "$dest"; \
571+
;; \
572+
*) \
573+
return 1; \
574+
;; \
575+
esac; \
576+
}; \
527577
mkdir -p /opt/adscan/wordlists; \
528-
curl -fsSL https://github.com/brannondorsey/naive-hashcat/releases/download/data/rockyou.txt -o /opt/adscan/wordlists/rockyou.txt; \
529-
curl -fsSL https://gist.github.com/The-Viper-One/a1ee60d8b3607807cc387d794e809f0b/raw/b7d83af6a8bbb43013e04f78328687d19d0cf9a7/kerberoast_pws.xz -o /opt/adscan/wordlists/kerberoast_pws.xz; \
578+
download_wordlist https://github.com/brannondorsey/naive-hashcat/releases/download/data/rockyou.txt /opt/adscan/wordlists/rockyou.txt; \
579+
download_wordlist https://gist.github.com/The-Viper-One/a1ee60d8b3607807cc387d794e809f0b/raw/b7d83af6a8bbb43013e04f78328687d19d0cf9a7/kerberoast_pws.xz /opt/adscan/wordlists/kerberoast_pws.xz; \
530580
xz -d -c /opt/adscan/wordlists/kerberoast_pws.xz > /opt/adscan/wordlists/kerberoast_pws; \
531-
curl -fsSL https://weakpass.com/download/2073/hashmob.net_2025.medium.found.7z -o /opt/adscan/wordlists/hashmob.net_2025.medium.found.7z; \
532-
7z x -y -o/opt/adscan/wordlists /opt/adscan/wordlists/hashmob.net_2025.medium.found.7z; \
533-
curl -fsSL https://weakpass.com/download/1938/kaonashi14M.txt.7z -o /opt/adscan/wordlists/kaonashi14M.txt.7z; \
534-
7z x -y -o/opt/adscan/wordlists /opt/adscan/wordlists/kaonashi14M.txt.7z; \
535581
mkdir -p /usr/share/wordlists; \
536582
git clone --depth 1 https://github.com/insidetrust/statistically-likely-usernames.git /usr/share/wordlists/statistically-likely-usernames; \
537583
rm -f /opt/adscan/wordlists/kerberoast_pws.xz; \
538-
rm -f /opt/adscan/wordlists/hashmob.net_2025.medium.found.7z; \
539-
rm -f /opt/adscan/wordlists/kaonashi14M.txt.7z; \
540584
chmod -R 0777 /opt/adscan/wordlists /usr/share/wordlists/statistically-likely-usernames
541585

542586
COPY adscan_internal/assets/wordlists/kerberos-format-inference.txt /opt/adscan/wordlists/kerberos-format-inference.txt
@@ -558,8 +602,23 @@ RUN chmod +x /usr/local/bin/adscan-entrypoint
558602
###############################################################################
559603
FROM runtime-common AS runtime-pro
560604

605+
ARG ADSCAN_RUNTIME_VERSION=""
606+
607+
ENV ADSCAN_RUNTIME_LICENSE_MODE=PRO \
608+
ADSCAN_RUNTIME_VERSION=${ADSCAN_RUNTIME_VERSION}
609+
610+
# Partner tag baked at build time — identifies which partner this image was built for.
611+
# Passed via: docker build --build-arg ADSCAN_PARTNER_TAG=glenn-mssp-beta1
612+
# Empty in untagged builds (dev/CI). Used by telemetry for partner-level filtering.
613+
ARG ADSCAN_PARTNER_TAG=""
614+
ENV ADSCAN_PARTNER_TAG=${ADSCAN_PARTNER_TAG}
615+
561616
COPY dist/adscan /usr/local/bin/adscan
562-
RUN chmod +x /usr/local/bin/adscan
617+
RUN set -eux; \
618+
chmod +x /usr/local/bin/adscan; \
619+
if [[ -n "${ADSCAN_RUNTIME_VERSION}" ]]; then \
620+
printf '%s\n' "${ADSCAN_RUNTIME_VERSION}" > /opt/adscan/version; \
621+
fi
563622

564623
ENTRYPOINT ["/usr/local/bin/adscan-entrypoint"]
565624

@@ -568,6 +627,11 @@ ENTRYPOINT ["/usr/local/bin/adscan-entrypoint"]
568627
###############################################################################
569628
FROM runtime-common AS runtime-lite
570629

630+
ARG ADSCAN_RUNTIME_VERSION=""
631+
632+
ENV ADSCAN_RUNTIME_LICENSE_MODE=LITE \
633+
ADSCAN_RUNTIME_VERSION=${ADSCAN_RUNTIME_VERSION}
634+
571635
# Runtime Python dependencies for source-mode ADscan CLI.
572636
RUN set -eux; \
573637
python3 -m venv /opt/adscan/venv; \
@@ -609,6 +673,7 @@ RUN set -eux; \
609673
textual==0.80.1 \
610674
"redis>=5.0.0,<5.3.0" \
611675
weasyprint>=60.0 \
676+
playwright==1.57.0 \
612677
jinja2>=3.0; \
613678
runtime_python="$(readlink -f /opt/adscan/venv/bin/python)"; \
614679
setcap cap_net_bind_service+ep "${runtime_python}"
@@ -640,4 +705,9 @@ RUN printf '%s\n' \
640705
> /usr/local/bin/adscan \
641706
&& chmod +x /usr/local/bin/adscan
642707

708+
RUN set -eux; \
709+
if [[ -n "${ADSCAN_RUNTIME_VERSION}" ]]; then \
710+
printf '%s\n' "${ADSCAN_RUNTIME_VERSION}" > /opt/adscan/version; \
711+
fi
712+
643713
ENTRYPOINT ["/usr/local/bin/adscan-entrypoint"]

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
# ADscan - Active Directory Pentesting CLI
66

7-
[![Version](https://img.shields.io/badge/version-7.2.0--lite-blue.svg)](https://github.com/ADscanPro/adscan/releases)
7+
[![Version](https://img.shields.io/badge/version-8.0.0--lite-blue.svg)](https://github.com/ADscanPro/adscan/releases)
88
[![downloads](https://static.pepy.tech/badge/adscan)](https://pepy.tech/projects/adscan)
99
[![License: BSL 1.1](https://img.shields.io/badge/license-BSL%201.1-blue.svg)](https://github.com/ADscanPro/adscan/blob/main/LICENSE)
1010
[![Platform](https://img.shields.io/badge/platform-Linux-lightgrey.svg)](https://github.com/ADscanPro/adscan)

0 commit comments

Comments
 (0)