iopshell: A shell-like application for communicating with IOPSYS devices

You might’ve noticed I’ve been using a custom application for demonstrating vulnerabilities I’ve discovered on IOPSYS (Inteno) devices for the last few posts. This application is iopshell, which aims to provide an easy way of communicating with the backend of these devices.

I wrote this application for a couple of reasons:

  • Ease of access

Previously, it was a bit of a pain to do any sort of communication with IOPSYS. The connection works over a custom WebSockets protocol, which means it’s quite hard to talk to these devices. After picking IOPSYS as my attack target, I soon realised I’d be spending most of my time crafting JSON payloads to send to the device which is just cumbersome. iopshell provides a couple of features to remedy this: payloads no longer have to be fully JSON-encoded (but they still can be!) and use a custom syntax instead, which will be interpreted by the shell and transformed into proper JSON automagically. This means that instead of writing {"id":2,"jsonrpc":"2.0","method":"call","params":["9fe82306dae3c5d3c5d36d9ace11d300","file","stat",{"path":"/etc/passwd"}]} just to read a file, I can simply authenticate once and do call file stat path:/etc/passwd, which is a lot more sane and readable. Furthermore, after calling list, the shell populates its autocompletion feature, so I don’t have to compare against a JSON list just to see whether I can call a function or not, or what parameters it expects - I can just press tab!

  • Scripting

If you’ve seen any of my previous exploits, you’ll know they’re all written in Python. Roughly half of the exploits’ code is there just to establish a connection to the device, authenticate, be able to call functions, etc. By abstracting these common requirements to a shell-like application which accepts scripts as input, I can write exploits very fast, as I no longer have to worry whether I have established a connection, authenticated correctly, and so on. Unfortunately so far, I’ve not yet extended the scripting capabilities of iopshell, so the scripts work on quite a basic, “interpret everything line-by-line” basis. More commonly than not, this is good enough.

  • Learn how IOPSYS internals work

While IOPSYS is based on OpenWRT/LEDE and shares much of its internals, Inteno has changed certain aspects of the backend. Namely, while OpenWRT uses ubus to get the front-end admin panel to communicate with the backend, this is usually done through simple HTTP POST requests to an API endpoint, usually located at /ubus. Inteno has scrapped this system - instead, they use their own custom owsd webserver, which communicates asynchronously with ubus via a WebSockets connection. Besides the obvious speed advantages, it also enables the existence of sleek JavaScript-powered front-end admin panels such as JUCI. Writing iopshell has granted me insight into how exactly this design works as a coherent system.

  • Learn Go

I’ll be honest - the code is a mess. I used iopshell as my introduction into the Go language, writing it as my first project. While I have enjoyed writing Go, looking over the code now makes me slightly cringe and would cause frustration or perhaps even slight rage to any seasoned Go developer. While I consider the thing to be usable, I’m still planning on going over the codebase and refactoring most of what I can sometime soon. Of course, if you want to help, contributions are very welcome.

Feel free to check out and grab the project from its GitHub page. The readme has instructions on setting it up, details on different commands and even how to write your own commands. Unfortunately, the Go toolchain is currently needed to compile the project, but I’m planning on distributing precompiled binaries soon after I’ve ironed out some more bugs.

Author | nns

Ethical Hacking and Cybersecurity professional with a special interest for hardware hacking, IoT and Linux/GNU.