Needing a victim for an OT related talk, I decided to hit eBay and quickly found a cheap offer for a few Hirschmann industrial router/firewall/VPN node “EAGLE One”. For about 25Euro each, they were perfectly in budget and although it was the old and seemingly EOL version, I ordered two and had a look.

A Short Disclaimer

  • Yes, it seems the device belonged to Daimler.
  • No it’s not about shaming Daimler in any way. Shit happens no matter how good your processes are!
  • Just take the post as a little bit of technical fun and a hard warning on how important safe disposal processes are!
  • There are a few vulns, on Hirschmann’s side!

The Device

In the version I received, the router is equipped with two Ethernet ports (one for the internal network, one for the uplink), an RJ-11 socket for a serial console and a USB A port. It also has a few status LEDs and a clamp header for the redundant power supply.


Side 1 Side 2

As you can see, the device had been dealt with by NETWAYS, which is German company offering various IT Services. The device names “WOEGWUUTUW021-10-8-247-142” and “WOEGWRFNBN021-K22z-178-73” are printed on the device.

I named the devices h1 and h2, just to keep them apart in my documentation.

Initial Setup, public side, h1

I set up a simple Linux VM, inserted a USB-NIC, connected the external port of the router and powered it up.

Initial Connect

  • Static IP:
  • LLDP: System Name = WOEGWUUTUW021-10-8-247-142 Hirschmann EAGLE Security Device - SW: SDV-05.3.00
  • Looking for (ARP)

Host IP Set to

  • VRRP
  • At some point looking for (ARP)

Host IP Set to

  • Syslog to

Initial Setup, public side, h2

Initial Connect

  • Static IP:
  • LLDP: System Name = WOEGWRFNBN021-K22z-178-73 System Description = Hirschmann EAGLE Security Device - SW: SDV-05.3.00
  • Looking for

Host IP Set to

  • NTP to
  • Looking for (ARP)
  • Looking for (ARP)

NTP under made available

  • SNMP to
  • SNMP to
  • Syslog to

Syslog under made available

  • Delivers logs


  • Closed 139, 3389, 5900, 9300
    • Match alerts in firewall Syslog

First Insights

A quick Whois lookup for results in

inetnum: -
netname:        DAIMLER-NET1
org:            ORG-DA474-RIPE
descr:          Daimler AG
country:        DE
admin-c:        BS4256-RIPE
tech-c:         BS4256-RIPE
status:         LEGACY
mnt-by:         DAIMLER-MNT
created:        1970-01-01T00:00:00Z
last-modified:  2015-05-05T01:43:34Z
source:         RIPE


% Information related to ''

descr:          DAIMLER-NET1
origin:         AS31399
mnt-by:         DAIMLER-MNT
created:        2006-03-14T10:05:37Z
last-modified:  2009-03-03T20:11:42Z
source:         RIPE

So the device seems to have been in use in a Daimler environment. Following this, the naming schema “WOE” could be an indicator for their plant in Wörth. This is actually confirmed by the firewall config on the device, which includes the entry fwL3TplIdName = "IP-Segmente_Woerth".

I ran most of the IP addresses I found through Shodan and didn’t find a single open Port.

Serial Access

As initially said, the Eagle One has a six-pin RJ-11 header for serial access. As I didn’t have a matching cable, I used an old Cisco cable and crimping tools to create an adapter.

Serial Cable

The connection parameters are 9600 baud, 8N1, flow control off

< Eagle  (Boot) Release: 04.3.00 Build: 2008-09-17 17:34 HW: 1.02 >

Press <1> to enter System Monitor 1 ...
 1 0Loading operating system ...
Inflating operating system ...
Starting operating system ...

2013-01-01 00:00:15  NOTICE #02070001 (Redundancy, tVRRP): Redundancy state changed to 'Backup','Host check running' on VRIDs 1 and 141

< EAGLE  (OS)   Release: SDV-05.3.00 Build: 2013-11-05 12:32 HW: 1.02 >

         Copyright (c) 2007-2012 Hirschmann Automation and Control GmbH

                             All rights reserved

                           EAGLE Release SDV-05.3.00

                         (Build date 2013-11-05 12:32)

                       System Name:  WOEGWUUTUW021-10-8-247-142
                       Netw. Mode :  router
                       Base-MAC   :  00:80:63:5E:E4:4C
                       System Time:  TUE JAN 01 01:00:11 2013


The default credentials from the manual (admin:private and user:public) did not work. Probably because, the router starts sends RADIUS requests, when I try to login. ;-)

Boot Console

The serial interface also offers us access to a boot console.

   System Monitor 1

   Selected OS: SDV-05.3.00-FINAL (2013-11-05 12:32)

   1  Select Boot Operating System
   2  Update Operating System
   3  Start Selected Operating System
   4  End (reset and reboot)
   5  Erase main configuration file
   6  Show Bootcode information



Although a radius server is quickly setup with FreeRadius, authentication isn’t quite as trivial, as the Radius packets are encrypted and authenticated.

Radius Request

So even though, we can just acknowledge all login attempts, we can’t send a valid response.

Physical Access

The way things are with me, I usually prefer to try physical access vectors before playing with the IP interfaces.

So, removing the front sticker and a few screws….

The two Ethernet modules can be removed, to make space for the other configuration options, we can see on Belden’s website.

After removing the modules, we find a few different chips


And also three 10 Pin headers, where I had hoped to find some JTAG. With a bit of measuring I created the following tables

Header 1

Chip Func     Func Chip
  VCC 1 (square) 2 P53, IO Altera
    3 4 P22, TMS Altera
BCMA P64, JTAG_EN 5 6    
BCMA P33, TDO 7 8 GND  
    9 10 P54, IO Altera

Header 2

Chip Func     Func Chip
  GND 1 (square) 2 GND  
    3 4    
  3v3 5 6 5v  
Altera P68, IO 7 8 P70, IO Altera
  GND 9 10 GND  

Header 3

Chip Func     Func Chip
Altera P15, IO 1 (square) 2 GND  
Altera P62, IO 3 4 VCC  
    5 6    
Altera P28, IO 7 8    
    9 10 GND  

My first approach was to connect my Saleae Logic Analyzer and power cycle the device a few times, hoping to see another hidden serial console. But sadly no. I then connect a JTAGulator and let it do its magic, sadly also no results.

As the device’s memory was in BGA, I decided to pause working on the hardware and looking at my other options.

The Internal Interface

The internal interface on both routes presented DHCP and gave me IP addresses, with the Eagle One as router. The router itself can be “accessed” via port 443. Needing Java 6.x I unpacked an XP VM, which worked just as badly as my current Linux. Luckily, the page’s source code shows the link to the jar file, which can be Downloaded and executed with `java -jar’


<BODY topmargin="0" leftmargin="0" marginwidth="0" marginheight="0">
<APPLET ARCHIVE="STARTeagle05300_00.jar" CODEBASE="/java/base"
CODE="com.hirschmann.deviceMgmt.quickstart.Start.class" WIDTH="100%" HEIGHT="100%"
ALT="The Web-based interface uses the Java(TM) Runtime Environment Version 6.x Plugin from">
<PARAM NAME = "launchClass" VALUE="com.hirschmann.deviceMgmt.products.eagle.Main">
<PARAM NAME = "productName" VALUE="EagleSDV">
<PARAM NAME = "productVersion" VALUE="05.3.00">
<PARAM NAME = "PortNo" VALUE="161">
<PARAM NAME = "Retries" VALUE="3">
<PARAM NAME = "Timeout" VALUE="20">
<PARAM NAME = "snmpV3Enabled" VALUE="true">
<PARAM NAME = "java_arguments" VALUE="-Xmx128m">
<PARAM NAME = "separate_jvm" VALUE="true">
<PARAM NAME = "codebase" VALUE="/java/base">
<PARAM NAME = "main_archive" VALUE="eagle05300_00.jar.pack.gz">
<PARAM NAME = "userfirewallEnabled" VALUE="true">
<PARAM NAME = "https_port" VALUE="-1">
The Web-based interface uses the Java(TM) Runtime Environment<br> Version6.x Plugin from <a href=""></a>.

The application initially establishes a connection to the router via SNMP and then switches over to using SSL on port 443/TCP, so probably HTTPs. The login fails, yet again, due to lack of credentials.

Usually, I would have used burp for a MiTM setup, but had various issues with the initial connection SMTP and then “upgrading” the connection to SSL via port 443/TCP. It will be possible, but I didn’t have the time to fully implement a solution.

Buying Two More Devices & Reset

Not having any direct access options, I decided to reset a device, to be able to analyze the configuration interface and shell for potential issues, that I might use to gain access to configured devices. Being interested in the secrets on the devices and already having taken one to pieces for soldering on it, I wanted to ensure that I had backup device just in case.


The device I started working on was WOEGW03C_Labor2-WW1-163-22, Public IP After verifying in Wireshark, that it behaved just as my previous ones, I entered the boot console, used 5 Erase main configuration file and deleted the config. A few seconds later I was able to login using the default credentials (admin:private) and started exploring.

I quickly reached the show config profiles nv command and was very surprised to find two named config files on the device.


Config File

The full config file can be found at the end of this page. Here are a few interesting excerpts.

User Config

      userConfigEntry = {
          userName = "V3-Managereagle"
          userPassword = ":v1:b45ec94ae96dfdecf8f255d2ba6029978d7b550f400feff4c05f565e3d8ef706:"
          userAccessMode = "2"
          userSnmpAuthenticationType = "1"
          userSnmpEncryptionType = "1"
          userAuthenticationList = "Radius"
          userStatus = "1"
          userName = "admin"
          userPassword = ":v1:b44e9f5bff59cca9f17110d3cb2a68ecd24f792c28b0e10497e45ee96ef209e3:"
          userAccessMode = "2"
          userSnmpAuthenticationType = "1"
          userSnmpEncryptionType = "1"
          userAuthenticationList = "systemLoginDefaultList"
          userStatus = "2"
          userName = "user"
          userPassword = ":v1:83539d5aff4fcc2f4f0bc91ac3ef59ddce2b437fd3d29514b848b0b9309f6b4d:"
          userAccessMode = "1"
          userSnmpAuthenticationType = "1"
          userSnmpEncryptionType = "0"
          userAuthenticationList = "systemLoginDefaultList"
          userStatus = "1"

Radius Config

      RadiusAuthServerEntry = {
          INDEX = 1
          radiusAuthServerAddress = ""
          radiusAuthServerPort = "1812"
          radiusAuthServerSecret = ":v1:b45ec94ae96dfdecf8f255d2ba6029978d7b550f400feff4c05f565e3d8ef706:"
          radiusAuthServerStatus = "1"
          INDEX = 2
          radiusAuthServerAddress = ""
          radiusAuthServerPort = "1812"
          radiusAuthServerSecret = ":v1:b45ec94ae96dfdecf8f255d2ba6029978d7b550f400feff4c05f565e3d8ef706:"
          radiusAuthServerStatus = "1"
          INDEX = 3
          radiusAuthServerAddress = ""
          radiusAuthServerPort = "1812"
          radiusAuthServerSecret = ":v1:f1d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e85d18:"
          radiusAuthServerStatus = "2"

Breaking The Code

Be aware of a not properly separated Hex and ASCII char mix!

Being able to change the password, I decided to follow through with some known plaintext and compare it with the output.

Question 1: Is there a pattern between input and output?

a 61 90 36d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e85d
b 62 93 36d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e85d
c 63 92 36d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e85d
d 64 95 36d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e85d
e 65 94 36d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e85d

Answer 1: Oh yes! One character, one Byte difference!

There also is a very obvious and familiar pattern in between the Bytes: +3, -1, +3, +1

As further confirmation: capital letters

A b0 36d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e85d
B b3 36d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e85d
C b2 36d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e85d
D b5 36d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e85d
E b4 36d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e85d

Same pattern :)

Question 2: Does the first character influence the second character?

aa 90 57 fc d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e8
ab 90 54 fc d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e8
ba 93 57 fc d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e8
bb 93 54 fc d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e8

Answer 2: No, but the same character in second position is encoded differently!

Question 3: What’s +3, -2, +3, -1?

When I saw the alternating distance between the chars, it somehow tasted like the use of XOR, which I wanted to verify:

61 XOR 90 f1
62 XOR 93 f1
63 XOR 92 f1
64 XOR 95 f1
65 XOR 94 f1

Answer 3: It is XOR

Using some longer strings we get

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 90579d5ffb5cadfaaef54485dbdd7d0e3d7162896787b60932cef25029f84b1d
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 93549e5cf85faef9adf64786d8de7e0d3e72618a6484b50a31cdf1532afb481e

Applying XOR again, we get f136fc3e9a3dcc9bcf9425e4babc1c6f5c1003e806e6d76853af933148992a7c Which ought to be our master secret! :)

So, let’s test it:

Parameter Plain User
hdr_configSecret = “:v1:b44e9f5bff59cca9f17110d3cb2a68ecd24f792c28b0e10497e45ee96ef209e3:” Exceed  
netPPPoEPassword = “:v1:9858885be853a9efcf9c18e7d63de87bef6abfe1c22b4e37fec0ee656f7080c2:” internet netPPPoEUsername = “”
netPPPPassword = “:v1:81449548fb49a99b1de6f913cca6889993b69fdb17e9cd2631782fc78f696a5a:” private netPPPUsername = “admin”
netDynDNSPassword = “:v1:f1d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e85d18:” empty netDynDNSLogin = “”
userPassword = “:v1:b45ec94ae96dfdecf8f255d2ba6029978d7b550f400feff4c05f565e3d8ef706:” Eh5tsP1w7fp6 userName = “V3-Managereagle”
userPassword = “:v1:b44e9f5bff59cca9f17110d3cb2a68ecd24f792c28b0e10497e45ee96ef209e3:” Exceed userName = “admin”
userPassword = “:v1:83539d5aff4fcc2f4f0bc91ac3ef59ddce2b437fd3d29514b848b0b9309f6b4d:” reader userName = “user”
vpnRemoteCtlPwd = “:v1:f1d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e85d18:” empty  
radiusAuthServerSecret = “:v1:b45ec94ae96dfdecf8f255d2ba6029978d7b550f400feff4c05f565e3d8ef706:” Eh5tsP1w7fp6 radiusAuthServerAddress = “”
radiusAuthServerSecret = “:v1:b45ec94ae96dfdecf8f255d2ba6029978d7b550f400feff4c05f565e3d8ef706:” Eh5tsP1w7fp6 radiusAuthServerAddress = “”
radiusAuthServerSecret = “:v1:f1d5efe514e1c1e519815f6c053fb411488573af88d79e0307d2d40ad4e85d18:” empty radiusAuthServerAddress = “”

Seems valid and I guess we now have Daimler’s radius secret.

Radius Test

We first add the client to /etc/freeradius/3.0/clients.conf by appending

client hm3 {
    ipaddr =
    secret = Eh5tsP1w7fp6
    require_message_authenticator = no

and then a user to /etc/freeradius/3.0/users

bob     Cleartext-Password := "hello"
        Service-Type = Administrative-User

I had initially omitted the Service-Type, but the Hirschman documentation states, that it’s mandatory to allow login.

Radius Accept

When adding the radius secret to Wireshark, it will show us the data in plaintext.

Back to h1

As a test, I reconnected h1 and was able to successfully log in. While doing so I also extracted it’s config and tested the extracted XOR key from h3 and it also worked perfectly, extracting the same set of secrets, from the same crypt-texts.

Serial Console

Command Set


NOTE: Enter '?' for Command Help.  Command help displays all options
      that are valid for the particular mode.
      For the syntax of a particular command form, please
      consult the documentation.

!(Hirschmann Eagle) >enable

!(Hirschmann Eagle) #
  clear                Clear several items.
  configure            Enter into global config mode.
  copy                 Copy different kinds of items.
  debug                Service functions to find configuration errors.
  exit                 Exit from current mode.
  help                 Display help for various special keys.
  history              Show a list of previously run commands.
  login                Set login parameters.
  logout               Exit this session.
  network              Modify network parameters.
  ping                 Send ICMP echo packets to a specified IP address.
  profile              Activate or delete configuration profiles.
  reboot               Reset the device (cold start).
  save                 Save configuration.
  set                  Set device parameters.
  show                 Display device options and settings.
  traceroute           Trace route to a specified host.

!(Hirschmann Eagle) #

The first look at the firmware update, showed that the router ran a VxWorks, so I had a look around and found sweet little hidden command bobshell

!(Hirschmann Eagle) #bobshell

-> ?
C interp: syntax error.
-> help

help                           Print this list
dbgHelp                        Print debugger help info
edrHelp                        Print ED&R help info
ioHelp                         Print I/O utilities help info
nfsHelp                        Print nfs help info
netHelp                        Print network help info
rtpHelp                        Print process help info
spyHelp                        Print task histogrammer help info
timexHelp                      Print execution timer help info
h         [n]                  Print (or set) shell history
i         [task]               Summary of tasks' TCBs
ti        task                 Complete info on TCB for task
sp        adr,args...          Spawn a task, pri=100, opt=0x19, stk=20000
taskSpawn name,pri,opt,stk,adr,args... Spawn a task
td        task                 Delete a task
ts        task                 Suspend a task
tr        task                 Resume a task
tw        task                 Print pending task detailed info
w         [task]               Print pending task info

Type <CR> to continue, Q<CR> to stop: 

d         [adr[,nunits[,width]]] Display memory
m         adr[,width]          Modify memory
mRegs     [reg[,task]]         Modify a task's registers interactively
pc        [task]               Return task's program counter
iam       "user"[,"passwd"]    Set user name and passwd
whoami                         Print user name
devs                           List devices
ld        [syms[,noAbort][,"name"]] Load stdin, or file, into memory
                               (syms = add symbols to table:
                               -1 = none, 0 = globals, 1 = all)
lkup      ["substr"]           List symbols in system symbol table
lkAddr    address              List symbol table entries near address
checkStack  [task]             List task stack sizes and usage
printErrno  value              Print the name of a status value
period    secs,adr,args...     Spawn task to call function periodically
repeat    n,adr,args...        Spawn task to call function n times (0=forever)
version                        Print VxWorks version info, and boot line
shConfig  ["config"]           Display or set shell configuration variables
strFree   [address]            Free strings allocated within the shell (-1=all)

Type <CR> to continue, Q<CR> to stop: 

NOTE:  Arguments specifying 'task' can be either task ID or name.

value = 1 = 0x1

Which gives us direct access to the VxWorks C Shell and in return we can use cmd to get a bash like shell

-> cmd
[vxWorks]# ls
[vxWorks]# help

List of the registered topics:
VM                  List of the shell commands related to virual memory.
basic               List of basic shell commands.
breakpoint          List of the shell commands related to breakpoints.
filesystem          List of the shell commands related to file system.
interpreter         Interpreter shell commands.
memory              List of the shell commands related to memory.
modules             List of the shell commands related to kernel modules.
network             Network commands
object              List of the shell commands related to objects.
symbols             List of the shell commands related to symbols.
tasks               List of the shell commands related to tasks.

List of the registered commands:
C                   Switch to C interpreter
alias               Add an alias or display alias
arp                 IPNET arp control
bp                  Display, set or unset a breakpoint
cd                  Change current directory.
demangle            Display demangled string
echo                Display a line of text
exit                Exit the shell session.
expr                Evaluate expressions
file ...
getenv              Get an environment variable
help                Display the list of the shell commands
hwcrypto_ixp425     Test IXP425 hardware crypto
ifconfig            IPNET interface configuration
ike                 IPIKE daemon control
ipf                 Firewall
ipnet_ctrl          IPNET runtime debugger util
ipsecctrl           config ipsec
ipssh_list          List connected ssh clients
ipssh_stop          Stop SSH spawns
keyadm              admin IPsec keys
keyfp               Generate key finger print
logout              Logout the shell session.
lookup              Lookup a symbol
mem ...
module ...
more                Browse and page through a text file.
nat                 NAT control
netstat             IPNET socket and route stats
nslookup            Query Internet name servers interactively
object ...
pcap                Packet capture utility
ping                IPNET ping utility
pppconfig           ppp config
print ...
printf              Write formatted output
pwd                 Display current working directory.
radiusc             Radius client
reboot              Reboot the system
repeat              Repeat a command
route               IPNET route table control
set ...
setenv              Set an environment variable
sftp                sftp file transfer
show ...
sleep               Suspend execution for an interval.
string ...
sysvar              System variable tool
task ...
traceroute          Trace route command for IPv4
unalias             Remove an alias
unset ...
version             Display VxWorks version information.
vm ...

From here we have full access to the router including debugging functionality and direct access to the device’s storage and RAM.

Btw, we’re running

VxWorks (for IXP425 - Eagle BE (debug:no, board:0xdd)) version 6.5.
Kernel: WIND version 2.10.
Made on Nov  5 2013, 13:33:02.
Boot line:
tffs(0,0)host:/tffs0/os.bin h= e= u=user pw=pass tn=eagle f=0x08 o=ixe

Something to have a closer look at on a rainy day :)

Firmware Image

It took me quite a long time to actually download the firmware image, due to plain blindness and stupidity!

In addition to running into quite a few of these

Belden Site Error

I hadn’t realized that the configurator wasn’t only for the quote function, but also to provide the correct firmware for the selected hardware configuration….

Belden Site Error

Java Application

As mentioned before, there is a Java application that can be used to manage the device.

Java Application

As noted before it starts of talking SNMP


The used here, is the password used for authentication, which we can enter in Wireshark to view it in plaintext


The then following SSL channel via port 443/TCP can be disabled on the device, to make access to the communication possible. I initially played with this a little, as I had hoped the application would be “encrypting” the password when changing it, but it’s only encrypted on the device.

Next Steps

This is all for the first “quick” look at the devices. By now I’ve got four Hirschmann mGuard TX/TX and two Hirschmann Eagle 20 TX/TX on my desk, all of them being devices from Daimler. I also found two nice Hirschman RSR20 industrial/rail ethernet switches, which I’ll be having a closer look at.

For the Daimler part, I’m currently looking into some passive network recon based on the included firewall configurations and will give an insight in a few days. For the Hirschmann part I’m putting together a few tools for testing the exposed interfaces and will share results as they come together.

Full Config File

Complete config file WWOEGW03C_Labor2-WW1-163-22.cfg as extracted from h3.