// HackTricks · Network Services

1723 - Pentesting PPTP

1723 - Pentesting PPTP

Basic Information

Point-to-Point Tunneling Protocol (PPTP) is an old VPN tunneling protocol used for remote access. It uses TCP port 1723 for the control channel and IP protocol 47 (GRE) to carry the PPP payload. The traffic inside the tunnel is commonly protected with MPPE, while authentication is frequently based on MS-CHAPv2.

From an offensive perspective, the interesting part is usually not the control connection itself but the fact that capturing a PPTP/MS-CHAPv2 handshake can enable offline password or NT-hash recovery. Also remember that a host can answer on TCP/1723 while the tunnel still fails because GRE (protocol 47) is filtered.

From an assessment perspective, exposed PPTP in 2026 is usually a legacy signal. Modern Microsoft guidance has started pushing it out of default deployments: new RRAS setups on Windows Server 2025 don’t accept PPTP by default, and MSCHAPv2-based WiFi/VPN connections are explicitly called out as being subject to NTLMv1-like attacks. If you still find PPTP enabled externally, it often means an old compatibility path was kept alive on purpose.[5][6]

Default Port:1723

Enumeration

nmap -Pn -sSV -p1723 <IP>
nmap -Pn -sV --script pptp-version -p1723 <IP>
nmap -Pn -sO --protocol 47 <IP>

nmap’s pptp-version NSE script can sometimes extract hostname, vendor, or firmware details from the PPTP control channel, which is useful for quickly spotting legacy routers/VPN concentrators.

If you only confirm tcp/1723 and miss GRE, you can easily get a false sense that the VPN is reachable. During troubleshooting or sniffing, capture both the control and encapsulated traffic:

sudo tcpdump -ni <iface> 'tcp port 1723 or gre' -w pptp-handshake.pcap
tshark -r pptp-handshake.pcap -Y 'pptp || gre || ppp || chap'

If you are capturing on the VPN endpoint itself instead of from a SPAN/mirror port or another on-path vantage point, keep in mind that local PPP capture can be incomplete. On Linux in particular, normal libpcap capture on the PPP interface may miss PPP control traffic; for local troubleshooting you may need to capture the GRE packets on the physical interface or use pppd record style logging to preserve the control exchange.

If you can influence the pppd invocation on a Linux client/server, the built-in recorder is often more reliable than sniffing pppX:

# Add to the pppd options / peer file
record /tmp/pptp.record

# Decode the recorded PPP conversation later
pppdump -p /tmp/pptp.record

Brute Force

Attack Notes

MS-CHAPv2 handshake capture

For PPTP, the relevant material is the PPP authentication exchange transported inside GRE. In MS-CHAPv2 the response depends on:

  • The server AuthenticatorChallenge
  • The client Peer-Challenge
  • The username
  • The NT-Response

That means a packet capture is often enough to move the attack offline. If you can sniff the initial connection, request the user to reconnect, or position yourself on-path, capture the handshake and extract the challenge/response data.

Useful quick filters:

tshark -r pptp-handshake.pcap -Y 'chap'
tshark -r pptp-handshake.pcap -Y 'ppp and chap'

Extract the exact MS-CHAPv2 fields with tshark

Wireshark’s CHAP dissector exposes enough data to script the extraction without relying only on chapcrack:

tshark -r pptp-handshake.pcap -Y 'chap.code == 1 || chap.code == 2' \
  -T fields -e frame.number -e chap.code -e chap.identifier -e chap.value -e chap.name
  • chap.code == 1 is the server Challenge packet; chap.value is the 16-byte AuthenticatorChallenge.
  • chap.code == 2 is the client Response packet; chap.value is laid out as PeerChallenge[16] | Reserved[8] | NT-Response[24] | Flags[1].
  • chap.identifier helps you match the correct Challenge and Response if the capture contains retries or multiple negotiations.
  • chap.name usually contains the username used in the exchange.

Example split of a response chap.value:

python3 - <<'PY'
resp = bytes.fromhex('<chap.value from CHAP Response>')
print('PeerChallenge =', resp[:16].hex())
print('Reserved      =', resp[16:24].hex())
print('NT-Response   =', resp[24:48].hex())
print('Flags         =', f'{resp[48]:02x}')
PY

This is handy when you want to mass-process PCAPs, validate what chapcrack extracted, or feed the values into a custom hashcat/asleap conversion script.

Convert the handshake into a hashcat workload

For PPTP/MS-CHAPv2, the 24-byte NT-Response alone is not the full story. Per RFC 2759, the effective 8-byte challenge is derived from:[3]

  • The server AuthenticatorChallenge
  • The client Peer-Challenge
  • The UserName

In practice, this means you need to preserve those fields during extraction if you want to move from a packet capture into a modern GPU workflow. A useful pattern is:

  1. Parse the capture with chapcrack or tshark
  2. Extract the username, peer-challenge, authenticator challenge, and NT-Response
  3. Convert the result into a hashcat-compatible NetNTLMv1/ESS style line

Do not throw away the rest of the response blob too early: in the CHAP Response Value, the Peer-Challenge, reserved bytes, NT-Response, and flags all sit next to each other, and parsing mistakes there are a common reason for uncrackable conversions.

The exact hashcat representation commonly used for MS-CHAPv2 is:[4]

<user>::<domain_or_blank>:<peer_challenge>:<nt_response>:<authenticator_challenge>

Example attack:

hashcat -m 5500 -a 0 mschapv2.hashes /usr/share/wordlists/rockyou.txt

This is operationally useful when you want to keep everything local instead of sending a token to an external cracking service, or when you already have a tuned hashcat rules/masks workflow.

Parse and decrypt with chapcrack

chapcrack is still one of the cleanest ways to process a PPTP capture:[1]

chapcrack.py parse -i pptp-handshake.pcap

If you recover the underlying secret material, you can decrypt the PPTP packet capture:

chapcrack.py decrypt -i pptp-handshake.pcap -o pptp-decrypted.pcap -n <recovered_nt_hash_or_token>

This is especially useful when the goal is not only credential recovery but also session decryption and post-auth traffic analysis.

Crack challenge/response material

If you already extracted the challenge/response pair, asleap can still be used directly against PPTP/MS-CHAPv2 material:

asleap -C 58:16:d5:ac:4b:dc:e4:0f -R 50:ae:a3:0a:10:9e:28:f9:33:1b:44:b1:3d:9e:20:91:85:e8:2e:c3:c5:4c:00:23 -W /usr/share/wordlists/rockyou.txt

asleap also supports working from packet captures or precomputed lookup tables, but for PPTP assessments the most common workflow is:

  1. Capture the PPTP handshake
  2. Extract the challenge/response
  3. Run offline cracking with asleap, chapcrack, or a custom workflow

Recent tradecraft also includes NT-hash-first workflows such as assless-chaps, which recover the NT hash from MS-CHAPv2/NTLMv1 challenge-response material using a prepared hash database. This can be faster than conventional password cracking if you maintain a good NT-hash corpus:[2]

./assless-chaps <challenge> <response> <hashes.db>

This matters because for PPTP the recovered NT hash is operationally valuable by itself: once obtained, it can be used to validate the crack, decrypt captures, and pivot into Windows-oriented reuse checks.

If you plan to use this at scale during assessments, the practical bottleneck is usually not the cracking step but maintaining a good NT-hash database. assless-chaps becomes especially useful when you can prebuild SQLite databases from breached NTLM corpora, HIBP-derived NT hashes, or aggressive in-house rule expansions generated with hashcat.[2]

Protocol weakness summary

  • PPTP depends on a separate GRE data channel, so firewalls often expose tcp/1723 while silently breaking the tunnel.
  • MS-CHAPv2 security effectively collapses to recovering DES-derived material / NT-hash-equivalent secrets, making passive capture much more dangerous than with modern VPNs.
  • Even if the password is not immediately recovered, the handshake can usually be stored and attacked offline later.
  • In current enterprise environments, a reachable PPTP listener often indicates a deliberately preserved legacy path, not a default deployment, which makes it especially interesting for password-reuse and lateral-movement testing.

References