CuddleFish malware infecting Small Home Home Office routers

Image Courtesy of JordyMeow published April 16, 2015 can be found here

Just looking for the Yara rules? They can be found here or on the github

Overview

This malware will infect routers and firewalls that have internet facing management interfaces (exposed web admin interface or ssh port) to install tools that will intercept, re-route, and hijack DNS requests from devices connected to the local network. The adversary will infect the infrastructure using vulnerable services or exposed management interfaces, to deploy CuddleFish and then redirect or deny services to the victim. In the past similar attacks have targeted the FortiOS to attack the Netherlands Ministry of Defence [Tennable] and CISA issued a Cybersecurity Advisory that stated "Volt Typhoon typically gains initial access to the IT network by exploiting known or zero-day vulnerabilities in public-facing network appliances (e.g., routers, virtual private networks [VPNs], and firewalls) and then connects to the victim’s network via VPN for follow-on activities."[CISA 1]. Note that Volt Typhoon is the Microsoft nomenclature for Chinese based state hackers.

Detection/Inspection

Detection can range from difficult to trivial depending on the historical network information you have logged and how it is being logged, on the router or on a remote logging server. By inspecting routes to make sure the IP addresses along the path to well known hosts are not resolving to hosts that are not expected and if possible inspecting the operating system at a base level to determine if compromise has occurred. If you have an advanced SOC that makes it easy to implement yara rules then see the very very bottom of this article for my Yara rules based off of the IOC's provided by Black Lotus Labs: https://github.com/blacklotuslabs/IOCs/blob/main/Cuttlefish_IOCs.txt.

If you have an off the shelf basic home router that does not provide very many options for operating system inspection or logging go ahead and skip over this next paragraph and follow the recommendations found in the next shorter paragraph. If you have the capabilities then inspecting your router at the console level could be a good exercise, even if you are not compromised it is a great way to become familiar with your router. I know I got a few kicks from poking around on my routers CLI after not finding any CuttleFish infections. SOHO and Enterprise network equipment manufactured by Cisco, MikroTik, PfSense, Fortiguard, and other network vendors usually include a console cable and a command line interface that does not rely on the network based management ports. This is the prefered method to preform inspection of the operating system for two reasons; one you do not expose your routers direct command line interface to the network and two because you may be working on compromised hardware that may or may not give you accurate results when looking at data over the network. This is especially true because this malware affects routes and network data making threat hunting less accurate. If all you have is the network based management then it is still worth looking at because the attacker may not have deployed that capability and as a general rule assume compromise but do not give up use what you have to do what you can but if there is a better way then do that.

Reboot your router, patch your router with the most recent security updates, Don't expose management interfaces to the public internet, implement a regular powercycle of these network devices if possible, and replace devices that are no longer supported by the manufacturer [Lumen]. I would like to add in going ahead and restoring to factory default and restoring from a known good configuration would be ideal but sometimes not feasible, once again depending on your capabilities and preparation for an incident. If indicators of compromise are found such as unexpected account logins or domains not matching up to sites or dropping off then its best to just replace the router or firewall sometimes this cannot be done but there has to be a very very solid reason for not replacing. Kind of like not replacing a flat tire before driving 90 miles spewing sparks and rubber along the innerstate eventually you'll end up smashing into someone or something and getting pulled over or pulled out of the wreckage by an EMT or a cop but they didnt show up because your buddy ratted you out for not replacing the bald tires on your truck.

Conclusion

It is scary and I understand that, it does no good to ignore problems but it can be just as bad and sometimes worse to exaggerate things and make them larger than they are or fret over things that you alone are not able to change. As Frank Herbert wrote "I must not fear. Fear is the mind-killer. Fear is the little-death that brings total obliteration. I will face my fear apply patches and reboot my fucking router." okay maybe not that last bit. If you let yourself live in fear it ends up governing your life and you end up not being the one living. On another side of the dark spectrum it can be equally infuriating knowing that a client will not take your advice or upgrade something that needs to be upgraded because you know that criminal organizations, who's purpose is not just making money but facilitating child sexual abuse material, drug trafficing, human trafficang and other unspeakables, use what you cannot fix against the people you work with and work for.

Personal Notes

I have written about some malware targeting honeypots searching for already exposed management interfaces on MikroTik Routers but today I wanted to focus on the CuttleFish malware that is targeting SOHO (Small Office Home Office) routers and network devices. I found this malware particularly interesting because it is following a trend seen with compromising small and medium business network equipment to create proxy networks in order to launch attacks with almost perfect anonymity allowing attackers to use these overlooked devices to facilitate hostile nation state activities [CISA 2], [Reuters], [Department of Justice], and [Tenable]. This goes into a deeper problem with unpatched vulnerable systems; they may not be targeting you but instead using you as a vehicle to facilitate other activities completely unrelated to you as a person. This means its not something you necessarily see or notice but it ends up touching your life.

The thing about the saying "Its just information and its not that big of a deal" just does not fly with me. It is information that is used to make decsions and information that is used to build friendships or ruin lives it is information that we make the decision to eat out or stay in or that EMT's use to decide the best route to the person having a heart attack. It is not just information it is part of how our world functions and like it or not its based on flawed technology that can be exploited.

Cybersecurity is not just patching and messing around with NMAP and wireshark its about taking the bigger picture into account. It is not just getting a job or getting turned down for a job because some recruiter didnt see your resume because you didnt have the word lacross in your bio, its about doing what you can for who you can to make a difference where you can. Remembering its not the clients job to understand what you are talking about its their job to do whatever they are doing in society you are just facliltating their IT needs. Acknowledging and taking inventory of the things that have changed for the better can be helpful to keep the darkness at bay or reasses if you are working for the right people and not only is it better for your headspace but it ends up helping you give your client context to understand what you are doing for them.

A note on sources

Black Lotus Labs did a fantastic article and if you are interested in the technical details about the attack then I would go there for all the deets, the advisories from CISA go into greater detail on activities and some IOCs, Tenable is the developer of Nessus a professional tool for vulnerability scanning and management, and Reuters is a decent news organization that puts out short blips about current events not always cybersecurity related. Why the .gov links? I pay taxes and they publish research just like all the other capable industry professionals they just have a bigger river to source from.

[Lumen] - Eight Arms To Hold You The CuttleFish Malware - Black Lotus Labs - https://blog.lumen.com/eight-arms-to-hold-you-the-cuttlefish-malware/

[Lumen IOC] - https://github.com/blacklotuslabs/IOCs/blob/main/Cuttlefish_IOCs.txt

[CISA 1] - https://www.cisa.gov/news-events/cybersecurity-advisories/aa24-038a

[CISA 2] - https://www.cisa.gov/news-events/cybersecurity-advisories/aa21-200b

[Reuters] Reuters - By Christopher Bing and Karen Freifeld - https://www.reuters.com/world/us/us-disabled-chinese-hacking-network-targeting-critical-infrastructure-sources-2024-01-29/

[Department of Justice] - https://www.justice.gov/opa/pr/us-government-disrupts-botnet-peoples-republic-china-used-conceal-hacking-critical

[Tenable] -Tenable Blog - by Satnam Narang - https://www.tenable.com/blog/cve-2024-21762-critical-fortinet-fortios-out-of-bound-write-ssl-vpn-vulnerability

YARA rules based on the Black Lotus Labs IOC's

This is broken up into several sections because I have a funny feeling that the last rule CuttleFish_UniqueStrings will get a lot of false positives

Direct Link: here

rule CuttleFish_URL {
    strings:
        $url1 = "209.141.49.178"
        $url2 = "205.185.122.121"
        $url3 = "198.98.56.93"
        $url4 = "107.189.28.251"
        $url5 = "kkthreas.com"
        $url6 = "pp.kkthreas.com"

    condition:
        any of ($url*)
}

rule CuttleFish_FileNames {

        $file_path1 = "/tmp/.timezone"
        $file_path2 = "/tmp/config js"
        $file_path3 = "/tmp/log.txt"
        $file_path4 = "/tmp/n2nconfigjs"
        $file_path5 = "/tmp/thconfigjs"
        $file_path6 = "/tmp/.Pg88s51gQG4tFyImFsT9qy6ZM5TeTF8.so"
        $file_path7 = "/tmp/.putin"
    condition:
        any of ($file_path*)
}
rule CuttleFish_FileHashes {
        $file_hash = "6722aeed5f5d8297de4eb2cba1c5abb900afe4a4cd64b10e2835463087936666"
        $file_hash1 = "10a4edbbb852a1b01fc6fbf0aa1407bc8589432bddb2001ae62702f18d919e89"
        $file_hash2 = "94812d391160e4fce821701b944cfd8f5fd9454b3cbb8e8974d1dc259310e500"
        $file_hash3 = "4aa23fbdc27d317c6e54481b6d884b962adf6e691a4731c859ddaf9af09822c6"
        $file_hash4 = "1168e97ccf61600536e93e9c371ee7671bae4198d4bf566550328b241ec52e89"
        $file_hash5 = "70693211cd0b14a7463b39b2fa801ce1fdefc85c7f3e003772d1b4deeb78efde"
        $file_hash6 = "2f0911fb892d448910c36a37c9fbdec8c73ccfecc274854b1fa053fb1cc2369b"
        $file_hash7 = "07df37d8168e911b189bbe0912b4842fa1fe48d5264e99738ad3247f9c818478"
        $file_hash8 = "44b769be0c2a807082a9bfd2f33fdc744552c5c7ca88a812ef4bd0393a50f132"
        $file_hash9 = "6295d5cb21c441066d2da81a76440bcac9bd5a7830fc9faea9668bd0b2015046"
        $file_hash10 = "eb7a7ab952080f66c82fe8350da131ce0d7766f203bd4d97b0798b4f59283a27"
        $file_hash11 = "99d5cf32f8198e99c530be4f5e05487e280bacdb8ef26aaf38dc20e301aad75f"
        $file_hash12 = "3d9ee05c0841ad65547c0cc8516d092cff48dad5e7bbf97c99ddd44ee94a24bc"
        $file_hash13 = "2ed174523bd80a93b7d09940d375f9c0d71e1ce8ecffb2320e02a78f4b601408"
        $file_hash14 = "23c2e7ff2602e5f76b3f2c354761ef39966facb3b12ed05551816f482d4d5608"
        $file_hash15 = "E48c250c47dd071dcee984a8e9f27b170004ff81c3f0da6a50364fdecf800fd3"
    condition:
        any of ($file_hash*)
}        

 rule CuttleFish_UniqueStrings {
        $keyword1 = "username="
        $keyword2 = "user_name="
        $keyword3 = "account="
        $keyword4 = "passwd"
        $keyword5 = "password"
        $keyword6 = "<passwd>"
        $keyword7 = "<pass_word>"
        $keyword8 = "<userName>"
        $keyword9 = "<password>"
        $keyword10 = "passwd="
        $keyword11 = "password="
        $keyword12 = "pass_word="
        $keyword13 = "Authorization:"
        $keyword14 = "access_key="
        $keyword15 = "access_token="
        $keyword16 = "admin_pass="
        $keyword17 = "admin_user="
        $keyword18 = "algolia_admin_key="
        $keyword19 = "algolia_api_key="
        $keyword20 = "alias_pass="
        $keyword21 = "alicloud_access_key="
        $keyword22 = "amazon_secret_access_key="
        $keyword23 = "amazonaws="
        $keyword24 = "ansible_vault_password="
        $keyword25 = "aos_key="
        $keyword26 = "api_key="
        $keyword27 = "api_key_secret="
        $keyword28 = "api_key_sid="
        $keyword29 = "api_secret="
        $keyword30 = "api.googlemaps AIza="
        $keyword31 = "apidocs="
        $keyword32 = "apikey="
        $keyword33 = "apiSecret="
        $keyword34 = "app_debug="
        $keyword35 = "app_id="
        $keyword36 = "app_key="
        $keyword37 = "app_log_level="
        $keyword38 = "app_secret="
        $keyword39 = "appkey="
        $keyword40 = "appkeysecret="
        $keyword41 = "application_key="
        $keyword42 = "appsecret="
        $keyword43 = "appspot="
        $keyword44 = "auth_token="
        $keyword45 = "authorizationToken="
        $keyword46 = "authsecret="
        $keyword47 = "aws_access="
        $keyword48 = "aws_access_key_id="
        $keyword49 = "aws_bucket="
        $keyword50 = "aws_key="
        $keyword51 = "aws_secret="
        $keyword52 = "aws_secret_key="
        $keyword53 = "aws_token="
        $keyword54 = "AWSSecretKey="
        $keyword55 = "b2_app_key="
        $keyword56 = "bashrc password="
        $keyword57 = "bintray_apikey="
        $keyword58 = "bintray_gpg_password="
        $keyword59 = "bintray_key="
        $keyword60 = "bintraykey="
        $keyword61 = "bluemix_api_key="
        $keyword62 = "bluemix_pass="
        $keyword63 = "browserstack_access_key="
        $keyword64 = "bucket_password="
        $keyword65 = "bucketeer_aws_access_key_id="
        $keyword66 = "bucketeer_aws_secret_access_key="
        $keyword67 = "built_branch_deploy_key="
        $keyword68 = "bx_password="
        $keyword69 = "cache_driver="
        $keyword70 = "cache_s3_secret_key="
        $keyword71 = "cattle_access_key="
        $keyword72 = "cattle_secret_key="
        $keyword73 = "certificate_password="
        $keyword74 = "ci_deploy_password="
        $keyword75 = "client_secret="
        $keyword76 = "client_zpk_secret_key="
        $keyword77 = "clojars_password="
        $keyword78 = "cloud_api_key="
        $keyword79 = "cloud_watch_aws_access_key="
        $keyword80 = "cloudant_password="
        $keyword81 = "cloudflare_api_key="
        $keyword82 = "cloudflare_auth_key="
        $keyword83 = "cloudinary_api_secret="
        $keyword84 = "cloudinary_name="
        $keyword85 = "codecov_token="
        $keyword86 = "config="
        $keyword87 = "conn.login="
        $keyword88 = "connectionstring="
        $keyword89 = "consumer_key="
        $keyword90 = "consumer_secret="
        $keyword91 = "credentials="
        $keyword92 = "cypress_record_key="
        $keyword93 = "database_password="
        $keyword94 = "database_schema_test="
        $keyword95 = "datadog_api_key="
        $keyword96 = "datadog_app_key="
        $keyword97 = "db_password="
        $keyword98 = "db_server="
        $keyword99 = "db_username="
        $keyword100 = "dbpasswd="
        $keyword101 = "dbpassword="
        $keyword102 = "dbuser="
        $keyword103 = "deploy_password="
        $keyword104 = "digitalocean_ssh_key_body="
        $keyword105 = "digitalocean_ssh_key_ids="
        $keyword106 = "docker_hub_password="
        $keyword107 = "docker_key="
        $keyword108 = "docker_pass="
        $keyword109 = "docker_passwd="
        $keyword110 = "docker_password="
        $keyword111 = "dockerhub_password="
        $keyword112 = "dockerhubpassword="
        $keyword113 = "dot-files="
        $keyword114 = "dotfiles="
        $keyword115 = "droplet_travis_password="
        $keyword116 = "dynamoaccesskeyid="
        $keyword117 = "dynamosecretaccesskey="
        $keyword118 = "elastica_host="
        $keyword119 = "elastica_port="
        $keyword120 = "elasticsearch_password="
        $keyword121 = "encryption_key="
        $keyword122 = "encryption_password="
        $keyword123 = "env.heroku_api_key="
        $keyword124 = "env.sonatype_password="
        $keyword125 = "eureka.awssecretkey="

    condition:
        any of ($keyword*)
}

disclaimer: The ideas and statements made in this article are the sole views of Exylum Technical.