Photo by American Public Power Association on Unsplash

How photovoltaic system data ends up online

Another IoT Story

FHantke
InfoSec Write-ups
Published in
6 min readFeb 15, 2020

--

My parents bought a photovoltaic system developed to produce and use their own energy. Of course, as with every IoT-device nowadays, one may use an App to monitor the produced data. However, when I was home for Christmas my parents told me monitoring with an App is stupid and they want to store and view the data on their personal computer. After some research I found no PC interface available for the system and decided to dig deeper into it.

Reversing

To begin my research, I looked up the IP address of the system and scanned for open ports with nmap. This is generally a good first step when analyzing systems as it helps to find hidden services. Nmap found that port 23 (telnet), 80 (HTTP), and 8899 (lite-ospf) were open.

I connected to port 23 via netcat and was asked to enter the credentials. The standard credentials my parents used to set the system up worked just fine. On the terminal I was able to modify configurations and see status, such as bootcfg, ifconfig and more. Yet, I did not find a database or even a hint of the data I was looking for.

Next, I tested port 80 and again, credentials were needed. With the same credentials as before, I entered the page and once more, I was able to configure settings. Browsing through the pages, I found no relevant data for me and gave up on this path shortly after.

A screenshot from configuration webpage.

Finally, I checked ospf-lite, which is an advanced version of OSPF, a network routing protocol. We don’t need to go into more details on this as we only need to know, ospf-lite simply routes the network traffic — another protocol can lay on top. Knowing this, I tried to connect with netcat again. Although the connection stayed open and I could send data, no answer came back. In the hope that the App would give me a hint, I opened it — and boom! — I received data on the open netcat connection. However, when I closed the App the data stream stopped; when I opened it again the stream continued.

Now the fun begins and it’s time for some bits and bytes. I recorded more data of various events in the App and tried to detect a pattern in the data. After a while, I recognized that the sequence 0x2b05 appeared regularly. That is often followed by 0x05 or 0x08 and continued by one of a number of keywords, for instance 0xb55ba2ce.

2b05081ac87aa043cf855b0f0a2b0104db2d2d69ae000000009c362b050891617c5843cfb00411873e0508db11855b000000044b8e2b05080cb5d21b0000000417072b05055f33284e06490b2b0505dc6679580368172b0508b55ba2ce4082c5ec20302b0508a7fa5c5d435e2b0104bd2b0508bd55905f440104b1ef67ce63ec10970e9d4737c7e4787a2b0508c0cc81b6498a52c197622b0508b1ef67ce498a52c1cfbb2b0508959930b42b0104701a0482796f8b9ff0083f7851ec2ce02b0505701a048201abb52b0505fed51bd2000bc12b050599ee89cb008a8c2b050837f9d5ca0000

After I reached the point when just staring at the bytes did not lead to any solution, I decided it was time to reverse the APK. I simply used an online decompiler which actually showed quite a good result. While I was going through the code, I found the classes ClientThread and HEXParser that show how to send_read, send_write, calc_crc and how to parse the data. Furthermore, I discovered protocol keywords which are used to request specific information. For instance, 0xb55ba2ce, I mentioned earlier, stands for the voltage of solar panel A. I found this out about this as in the decompiled code I noticed the negative number -1252285746 which is just the same as the two’s complement interpretation of 0xb55ba2ce.

To understand the process of reverse engineering, the code below is an adequate example.

Decompiled code from class ClientThread

The name of the function details that it could be used to request/read data. We see that, if some protocol is 1, the app would send 43, which equals 0x2b — a byte we’ve seen a number of times before. In the next line, the crc for these messages is initialised. In line 6 and 7 bytes 0x0104 are sent and after the if statement a four byte long key word is sent. Looking into send byte we would see that a new crc is calculated with each call. Finally, in line 15 the crc
calculation is finished and the crc is sent. Consequently, the result is 0x2b0104 + key word +crc.

Before reimplementing a function, I always try to verify my intuition first by finding proof in the dynamic analysis. In the previously recorded data we can see 0x2b0104db2d2d69ae, which I tested to resend. A moment later, I received an answer and hold evidence for my static analysis. This means we only need to reimplement this function plus the crc calculation and then we can request any data we want.

To wrap things up, I found all the relevant information I needed to send requests and receive the data. However, I did not interpret all keywords but only the few I was interested in.

The Protocol

The protocol, as far as I reversed it, is quite simple. Nevertheless, there are more functions I did not look into more deeply.

First the client sends 0x2b0104 + key word + crc to request data. As a result, it receives 0x2b05 + length + key word + data + crc. Data is hex encoded and can be integers, floats, strings or booleans.

The Internet

While reading the manual of the photovoltaic system, I was surprised to find a section on “Internet based remote access to the inverter”. In this section the company offers a step-by-step instruction how to forward port 8899 on the router with the purpose that the user can use the App from everywhere outside his local network. The only warning I could find is “Remote Access to devices connected to a home network using an internet connection always poses a potential security risk’’.

The problem with this is that it is only port forwarding without further security. This means that there is no encryption. What isn’t a big problem in the local network can be a problem in the wild internet, because everyone who knows the protocol can easily access the data. This includes energy consumption, solar panel production and more.

To prove this claim ,I first followed the step-by-step instruction for my own router. Afterwards, I extracted my own data using an external server outside of my local network. As expected, it worked without any problems. Secondly, I was interested if anyone made use of this named feature. Therefore, I scanned the IP ranges of german providers with zmap, since I know the company is german and searched for an open port 8899. Subsequently, I sent the key word for requesting the battery status. From all public IP addresses with an open port 8899 I received 14 positive answers. This means, anyone could read arbitrary data from their system without any notice. I did not request any data further, as I only wanted to prove my statement.

Response

I contacted the photovoltaic provider on 2020-01-04 through their service mail and explained to them what I had found. On the next day they responded, where they told me that they take this issue seriously and work on a cloud solution via TLS which is planned for summer 2020. Furthermore, they assured me that they make every customer aware of the risks associated with port forwarding. They answered some further questions I had and were always nice and friendly. On their request I removed the companies name from the article.

Conclusion

Generally speaking, even if a device was mainly developed for local network usage, as I believe this system was, it is important to use encryption. It was possible to find private photovoltaic data online without a lot of of effort. People who develop any protocol nowadays should always consider and implement encryption. They should not develop new encryption methods but rely on existing standards, proven industry standards.

I believe I have given an interesting insight into reversing everyday devices and hopefully encourage people to question their own devices.

--

--