Professional Documents
Culture Documents
Lets Bughunt in Routeros Nova SD 2020
Lets Bughunt in Routeros Nova SD 2020
Lets Bughunt in Routeros Nova SD 2020
Jacob Baines
March 8, 2020
Slides and Code
https://github.com/tenable/routeros
2
Purpose & Assumptions
3
Talk Overview
4
albinolobster@ubuntu:~$ whoami
Jacob Baines
Principal Research Engineer @ Tenable
@Junior_Baines
jacob-baines
6
Introduction
Who is this guy?
Introduction
What’s RouterOS?
● Headquartered in Latvia.
● Produces networking devices and software.
● Sold worldwide.
● Active user base:
■ https://mum.mikrotik.com/
■ https://forum.mikrotik.com
■ https://www.reddit.com/r/mikrotik
8
Introduction
What’s RouterOS?
9
Introduction
Why Should I Care?
10
Introduction
Why Should I Care?
11
Introduction
Why Should I Care?
12
Introduction
Why Should I Care?
13
Acquiring RouterOS
Just Download It
● NPK Format
■ MIPSBE, SMIPS, MMIPS, TILE, PPC, x86, and ARM.
■ All the same code. Just different architectures.
● x86 has some extra cloud goodness.
■ Main package is a fat NPK containing the base
features.
■ Extra package is a zip with many NPK.
15
Acquiring RouterOS
But Which One?!
● Not pictured:
■ Legacy: the last 5.x release.
16
Acquiring RouterOS
History is cool!
17
Acquiring RouterOS
What’s this NPK?
18
Acquiring RouterOS
What’s in the ISO?
19
Getting Root
...But Why?
21
Getting Root
Acquiring Hardware
https://www.amazon.com/Mikrotik-RB951UI-2ND-RouterBoard-RB951Ui-2nD-hAP
22 /dp/B0144ESOSM/
Getting Root
Getting Hardware… With a USB Port
Rooting RouterOS with a USB Drive Owning the Network with BadUSB
23
Getting Root
Where’s My Root Shell?
24
Getting Root
Before 6.43.15 (Long-term) and 6.44 (Stable)
25
Getting Root
Before 6.45.8 (Long-term) and 6.46.1 (Stable)
27
Getting Root
Install VirtualBox
https://www.virtualbox.org/
28
Getting Root
Grab an x86 ISO
29
Getting Root
Create a 32-bit “Other Linux” VM
30
Getting Root
Start Up Downloaded ISO
31
Getting Root
Install All The Things!
32
Getting Root
Installed All The Things!
33
Getting Root
Successful Installation
34
Getting Root
Get an IP Address
35
Getting Root
Reminder
36
Getting Root
Meet Milo
https://github.com/tenable/routeros/tree/master/poc/execute_milo
37
Getting Root
A Wild Binary Appears
38
Getting Root
Executing Milo
39
Getting Root
Replacing Milo
40
Getting Root
FTP VM Bins to Router
41
Getting Root
Reboot into a LiveCD
42
Getting Root
Try Ubuntu
43
Getting Root
Mount RouterOS System Directory
44
Getting Root
Setting Executable Bits and Moving Milo
45
Getting Root
Triggering Milo
46
Filesystem Layout
Most Everything is Mounted SquashFS
48
Filesystem Layout
MikroTik Binaries and Libraries
● Libraries in /lib/.
■ Some open source: uClibc
■ Some MikroTik developed: libumsg
50
Filesystem Layout
User Filespace
54
Attack Surface
Web Interface
● M2 Messages?
■ Custom binary protocol. Discuss more later.
■ Encrypted after authentication.
● With examples:
■ CVE-2018-14847
■ CVE-2019-3943
Attack Surface
Web Interface
57
Attack Surface
Winbox
● Port 8291
■ /nova/bin/mproxy
■ Handles input from Winbox Client
58
Attack Surface
Winbox
59
Attack Surface
VPNs
● Supports PPTP
■ ppp.npk
■ License refers to very old implementation.
● Supports IPSec
■ security.npk
60
Attack Surface
Service Manager Ports
● /nova/bin/sermgr
● Forks to some listening services:
■ FTP: /nova/bin/ftpd
■ Telnet: /nova/bin/telnet
■ SSH: /ram/pckg/security/nova/bin/ssh
■ API: /nova/bin/console (?)
61
Attack Surface
Others!
● SMB: /nova/bin/smb
● SNMP: /nova/bin/snmp
● DNS Server: /nova/bin/resolver
● DHCP Server: /ram/pckg/dhcp/nova/bin/dhcp
● HTTP Proxy: /nova/bin/wproxy
● SOCKS Proxy: /nova/bin/socks
● Cloud: /nova/bin/cloud
62
Examine a Bug
Why Examine Published Vulnerabilities?
64
Examine a Bug
CVE-2018-14847
https://nvd.nist.gov/vuln/detail/CVE-2018-14847
65
Examine a Bug
Origins of CVE-2018-14847
66 https://forum.mikrotik.com/viewtopic.php?f=2&t=133438
Examine a Bug
Early Proof of Concept
67
https://github.com/BasuCert/WinboxPoC/blob/master/WinboxExploit.py
Examine a Bug
Exploit Payload Translated to M2
{ bff0005:1,
uff0006:5,
uff0007:7,
s1: '/////./..//////./..//////./../flash/rw/store/user.dat',
Uff0002:[0,8],
Uff0001:[2,2]}
68
Examine a Bug
Exploit Payload Translated to M2
{ bff0005:1,
uff0006:5,
uff0007:7,
s1: '/////./..//////./..//////./../flash/rw/store/user.dat',
Uff0002:[0,8],
Uff0001:[2,2]}
69
Examine a Bug
Payload M2 Type Explained
Type ID Value
70
Examine a Bug
M2 Payload Fields Meaning
string 1 […]/user.dat
71
Examine a Bug
M2 Payload Destination
[2,2]
/nova/etc/system.x3
72
Examine a Bug
M2 Payload Destination
[2,2] https://github.com/tenable/routeros/tree/master/msg_re/parse_x3
/nova/bin/mproxy
73
Examine a Bug
CVE-2018-14847 Analysis
https://ghidra-sre.org/
74
Examine a Bug
Load mproxy into Ghidra
75
Examine a Bug
Open mproxy for Analysis
76
Examine a Bug
Ghidra CodeBrowser
77
Examine a Bug
M2 Payload Destination
[2,2]
78
Examine a Bug
M2 Payload Destination
[2,2]
79
Examine a Bug
M2 Payload Destination
[2,2]
80
Examine a Bug
M2 Payload Destination
[2,2]
81
Examine a Bug
M2 Payload Destination
[2,2]
82
Examine a Bug
M2 Payload Destination
[2,2]
83
Examine a Bug
M2 Payload Command
0xfe0001 cmdGetPolicies
0xfe000e cmdSet
0xfe0015 cmdGetCount
84
Examine a Bug
M2 Payload Command
0xfe0001 cmdGetPolicies
0xfe000e cmdSet
0xfe0015 cmdGetCount
85
Examine a Bug
M2 Payload Command… Unknown?
86
Examine a Bug
M2 Payload Destination
{ bff0005:1,
uff0006:5,
uff0007:7,
s1: '...',
Uff0002:[0,8],
Uff0001:[2,2]}
87
Examine a Bug
M2 Payload Command
0xfe0001 cmdGetPolicies
0xfe000e cmdSet
0xfe0015 cmdGetCount
88
Examine a Bug
Looks Reasonable?
89
Examine a Bug
Switching Payloads
https://github.com/tenable/routeros/tree/master/poc/cve_2018_14847
90
Examine a Bug
Where to Set a Breakpoint?
91
Examine a Bug
Attaching GDB to mproxy
92
Examine a Bug
Set the Breakpoint
93
Examine a Bug
Stacktrace
94
Examine a Bug
M2 Command to Switch Statement
{ bff0005:1,
uff0006:5,
uff0007:7,
s1: './.././.././../etc/passwd',
Uff0002:[0,8],
Uff0001:[2,2]}
95
Examine a Bug
M2 Command Switch Statement
{ bff0005:1,
uff0006:5,
uff0007:7,
s1: './.././.././../etc/passwd',
Uff0002:[0,8],
Uff0001:[2,2]}
96
Examine a Bug
M2 Get String 1
{ bff0005:1,
uff0006:5,
uff0007:7,
s1: './.././.././../etc/passwd',
Uff0002:[0,8],
Uff0001:[2,2]}
97
Examine a Bug
User Input to open()
98
Examine a Bug
M2 Payload Passed to open()
{ bff0005:1,
uff0006:5,
uff0007:7,
s1: './.././.././../etc/passwd',
Uff0002:[0,8],
Uff0001:[2,2]}
99
Examine a Bug
Why Does Normal Traversal Fail?
100
Examine a Bug
Failure Case
102
Examine a Bug
Results at the Breakpoint
103
Examine a Bug
Something is Happening
104
Examine a Bug
Path Traversal Algorithm
std::vector<std::string>::iter token_iter = token_vector.begin();
while (true) {
if (token_iter == token_vector.end()) {
// no invalid path traversal!
return 1;
}
if (*token_iter == NULL) {
// erase empty strings
token_iter = erase(token_iter);
} else {
if (*token_iter == "..") {
if (token_iter == token_vector.begin()) {
// path traversal at start of path. Invalid!
return 0;
}
// erase current token *and* the previous token
token_iter = erase(token_iter);
token_iter = erase(token_iter - 1);
continue;
}
token_iter++;
}
}
Examine a Bug
Test Cases
std::vector<std::string>::iter token_iter = token_vector.begin();
while (true) {
if (token_iter == token_vector.end()) { ● Allows ‘..’ as long as it’s balanced with the
// no invalid path traversal!
return 1; same number of directories.
}
if (*token_iter == NULL) {
● Erroneously treats ‘.’ as a normal directory.
// erase empty strings
token_iter = erase(token_iter);
● Valid Strings
} else { ■ passwd
if (*token_iter == "..") {
if (token_iter == token_vector.begin()) { ■ etc/passwd
// path traversal at start of path. Invalid! ■ etc/../passwd
return 0;
} ■ ./etc/passwd
// erase current token *and* the previous token ■ ./../etc/passwd
token_iter = erase(token_iter);
token_iter = erase(token_iter - 1); ● Invalid Strings
continue;
} ■ ../etc
token_iter++; ■ etc/../../passwd
}
}
Examine a Bug
Patch in RouterOS 6.42.1
Examine a Bug
What Did We Learn?
108
Future Work
● initrd rootkit
● NPK setup analysis
● cloud analysis
● pptp analysis
● More client analysis
■ CVE-2020-5720
110
Slides and Code
https://github.com/tenable/routeros
@Junior_Baines
jacob-baines
112