Home » Did I just get hacked?

Did I just get hacked?



there is one good reason why this post is attracting so much attention: you managed to record the whole, live session of an intruder on your PC. This is very different from our everyday experience, where we deal with the discovery of the consequences of his actions and try to redress them. Here we see him at work, see him having some problems with establishing the backdoor, retrace his steps, work feverishly (perhaps because he was sitting at your desk, as suggested above, or perhaps, and in my opinion more likely, because he was unable to make his malware run on the system, read below), and try to deploy fully self-contained instruments of control.
This is what security researchers witness daily with their honey traps. For me, this is a very rare chance, and the source of some amusement.

You have definitely been hacked. The evidence for this does not come from the snippet of the auth.log file you displayed, because this reports an unsuccessful login attempt, occurring over a short time span (two secs). You will notice that the second line states Failed password, while the third one reports a pre-auth disconnect: the guy tried and failed.

The evidence comes instead from the content of the two files and which the attacker downloaded onto your system.

The site is currently open to anyone to download them, which I did. I first ran file on them, which showed:

$ file y*
yjz:      ELF 32-bit LSB  executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.2.5, not stripped
yjz1:     ELF 32-bit LSB  executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.9, not stripped

Then I brought them onto a 64-bit Debian VM I have; an examination of their content thru the strings command revealed much that was suspicious (reference to various well-known attacks, to commands to be substituted for, a script that was clearly used to set up a new service, and so on).

I then produced the MD5-hashes of both files, and fed them to Cymru’s hash database to see whether they are known agents of malware. While yjz is not, yjz1 is, and Cymru reports a probability of detection by anti-virus software of 58%. It also states that this file was last seen some three days ago, so it is reasonably recent.

Running clamscan (part of the clamav package) on the two files I obtained:

$ clamscan y*
yjz: Linux.Backdoor.Gates FOUND
yjz1: Linux.Trojan.Xorddos FOUND

so we are now certain that standard Linux software can identify it.

What should you do?

Though rather new, neither system is very new, see this Jan. 2015 article on XorDdos, for instance. So most free packages should be able to remove it. You should try: clamav, rkhunter, chkrootkit. I have Googled around, and seen that they claim to be able to spot it. Use them to check on the predecessor’s work, but after running these three programs you should be ready to go.

As for the larger question, what should you do to prevent future infections, Journeyman’s answer is a good first step. Just keep in mind that it is an ongoing struggle, one that all of us (including me!) may very well have lost without even knowing it.


At Viktor Toth’s (indirect) prompt, I would like to add a few comments. It is certainly true that the intruder encountered some difficulties: he downloads two distinct hacking tools, changes their permissions several times, restarts them several times, and tries many times to disable the firewall. It is easy to guess what is happening: he expects his hacking tools to open a communication channel toward one of his infected pcs (see later), and, when he does not see this new channel spring up on his control GUI, fears his hacking tool is being blocked by the firewall, so he repeats the installation procedure. I agree with Viktor Toth that this particular stage of his operation does not seem to bring the expected fruits, but I would like to encourage you very strongly not to underestimate the extent of the damage inflicted on your pc.

I provide here a partial output of strings yjz1:

# chkconfig: 12345 90 90
# description: %s
# Provides:             %s
# Required-Start:
# Required-Stop:
# Default-Start:        1 2 3 4 5
# Default-Stop:
# Short-Description:    %s
case $1 in
sed -i '//etc/cron.hourly/gcc4.sh/d' /etc/crontab && echo '*/3 * * * * root /etc/cron.hourly/gcc4.sh' >> /etc/crontab
GET %s HTTP/1.1
%sHost: %s
POST %s HTTP/1.1
%sHost: %s
Content-Type: application/x-www-form-urlencoded
Content-Length: %d
Accept: */*
Accept-Language: zh-cn
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1;      TencentTraveler ; .NET CLR 1.1.4322)
Connection: Keep-Alive

This provides evidence of tampering with the services (in /etc/init.d and in /etc/rc.d), with crontab, with the history file of mysql, and a couple of files in proc which are links to bash (which suggests a custom-made fraudulent version of your shell has been planted). Then the program generates an HTTP request (to a Chinese-speaking site,

 Accept-Language: zh-cn

which gives substance to David Schwartz’s comment above), which may create even more havoc. In the request, binaries (Content-Type: application/x-www-form-urlencoded) are to be downloaded to the attacked pc (GET) and uploaded to the controlling machine (POST). I could not establish what would be downloaded to the attacked pc, but, given the small size of both yjz and yjz1 (1.1MB and 600kB, repectively), I can venture to surmise that most of the files needed to cloak the rootkit, i.e. the altered versions of ls, netstat, ps, ifconfig,…, would be downloaded this way. And this would explain the attacker’s feverish attempts to get this download going.

There is no certainty that the above exhausts all possibilities: we certainly lack part of the transcript (between lines 457 and 481) and we do not see a logout; furthermore, especially worrisome are lines 495-497,

cd /tmp;  ./yd_cd/make

which refer to a file we did not see downloaded, and which might be a compilation: if so, it means the attacker has (finally?) understood what the problem with his executables was, and is trying to fix it, in which case the attacked pc has gone for good. [In fact, the two versions of the malware which the attacker downloaded onto the hacked machine (and I onto my 64bit Debian VM) are for an unsuitable architecture, x86, while the name alone of the hacked-into pc gives away the fact that he was dealing with an arm architecture].

The reason why I wrote this edit is to urge you as strongly as possible either to comb your system with a professional instrument, or to re-install from scratch.

And, by the way, should this prove useful to anyone, this is the list of of the 331 IP addresses to which yjz tries to connect. This list is so large (and probably destined to become larger still) that I believe this is the reason for tampering with mysql. The list provided by the other backdoor is identical, which, I presume, is the reason for leaving such an important piece of information out in the open (I think the attacker did not wish to make the effort to store them in kernel format, so he put the whole list in a clear-text file, which is probably read-in by all of his backdoors, for whichever OS):

The following code

 echo 0 > out
 while read i; do
       whois $i | grep -m 1 -i country >> out
 done < filename
 cat out | grep -i cn | wc -l

on the above list shows that 302 out of a total 331 addresses are in mainland China, the remaining ones are in Hong Kong, Mongolia, Taiwan. This adds further support to David Schwartz’s contention that this is mostly a Chinese bot ring.


At @vaid’s request (the author of the OP, read his comment below), I will add a comment about how to strengthen security of a basic Linux system (for a system providing many services, this is a far more complex topic). vaid states he did the following:

  1. Reinstall the system

  2. changed root password to a 16 character long password with mixed lower- and uppercase letters and characters and digits.

  3. Changed the username to a 6 mixed character long username and applied the same password as used for root

  4. changed SSH port to something above 5000

  5. turned off SSH root login.

This is fine (except I use a port above 10,000 since many useful programs use the ports below 10,000). But I cannot emphasize enough the need to use cryptographic keys for ssh login, instead of passwords. I will give you a personal example. On one of my VPSes, I was uncertain whether to change the ssh port; I left it at 22, but used crypto keys for authentication. I had hundreds of break-in attempts per day, none succeeded. When, tired to check daily that no one had succeeded, I eventually switched the port to something above 10,000, break-in attempts went to zero. Mind you, it is not that hackers are stupid (they are not!), they just hunt down easier prey.

It is easy to activate a crypto key with RSA as a signature algorithm, see comment below by Jan Hudec (thanks!):

 cd; mkdir .ssh; chmod 700 .ssh; cd .ssh; ssh-keygen -t rsa (then hit <kbd>ENTER>/kbd> three times); cat id_rsa.pub >> authorized_keys; chmod 600 *

Now all you have to do is to copy the file id_rsa to the machine from which you want to connect (in a directory .ssh, also chmod‘ed to 700), then issue the command

ssh -p YourChosenNonStandardPort -i ~/.ssh/id_rsa me@RemoteMachine

When you are sure that this works, edit on the server (=the machine you want to connect to) the file /etc/ssh/sshd_config, and change the line

#PasswordAuthentication yes


PasswordAuthentication no

and restart the ssh service (service ssh restart or systemctl restart ssh, or something like this, depending on distro).

This will withstand a lot. In fact, there are currently no known exploits against the current versions of openssh v2, and of RSA as employed by openssh v2.

Lastly, in order to really bolt down your machine, you will need to configure the firewall (netfilter/iptables) as follows:

 iptables -A INPUT -p tcp --dport YourChosenNonStandardPort -j ACCEPT
 iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
 iptables -P INPUT DROP
 iptables -P OUTPUT ACCEPT
 iptables -A INPUT -i lo -j ACCEPT
 iptables -A OUTPUT -o lo -j ACCEPT

This, 1) allows ssh connections from both LAN and WAN, 2) allows all input which was originated by your requests (for instance, when you load a Web page), 3) drops everything else on the input, 4) allows everything on the output, and 5-6) allows everything on the loopback interface.

As your needs grow, and more ports need to be opened, you may do so by adding, at the top of the list, rules like:

 iptables -A INPUT -p tcp --dport 80 -j ACCEPT

to allow for instance people to access your Web browser.

Welcome to the Internet – where any open SSH server is likely going to get probed, brute-forced, and have various indignities inflicted upon it.

To start, you need to completely wipe the storage on the product. Image it if you want to pass it on for forensics, but the Linux install on it is now suspect.

Bit of guesswork but

  1. You got brute-forced or use a common password. It’s security by obscurity but you don’t want a dictionary password or to use a root account open to SSH. Disable root SSH access if it’s an option or at least change the name so they need to guess both. SSHing as root is terrible security practice anyhow. If you must use root, log in as another user and use su or sudo to switch.

  2. Depending on the product, you might want to lock down SSH access in some way. A total lock-down sounds like a good idea, and allows users to open it up as needed. Depending on what resources you can spare, consider only allowing IP addresses in your own subnet, or some kind of login throttling system. If you don’t need it on the final product make sure it’s turned off.

  3. Use a non standard port. Security by obscurity again, but it means an attacker needs to target your port.

  4. Do not ever use a default password. The best approach I’ve seen is to randomly generate a password for a specific device and ship it with your product. Best practice is key based authentication, but I’ve no idea how you’d approach that on a mass market product.

Oh, you have been definitely hacked. Someone appears to have been able to gain root credentials and attempted to download a Trojan to your system. MariusMatutiae provided an analysis of the payload.

Two questions arise: a) Was the attacker successful? And b) what can you do about it?

The answer to the first question may be a no. Notice how the attacker repeatedly tries to download and run the payload, apparently without success. I suspect that something (SELinux, perchance?) stood in his way.

HOWEVER: The attacker also altered your /etc/rc.d/rc.local file, in the hope that when you restart your system, the payload will be activated. If you have not yet restarted the system, don’t restart until you have removed these alterations from /etc/rc.d/rc.local. If you have already restarted it… well, tough luck.

As to what you can do about it: The safest thing to do is to wipe the system and reinstall from scratch. But this may not always be an option. A significantly less safe thing to do is to analyze exactly what happened and wipe every trace of it, if you can. Again, if you have not yet restarted the system, perhaps all it takes is clean /etc/rc.d/rc.local, remove anything downloaded by the attacker, and last but not least, change the darn password!

However, if the attacker was already able to run the payload, there may be other modifications to your system that may be difficult to detect. Which is why a complete wipe is really the only safe (and recommended) option. As you indicated, the equipment in question may be a test/development target so perhaps wiping it is not as painful as it may be in other cases.

Update: Notwithstanding what I wrote about a possible recovery, I wish to echo MariusMatutiae’s very strong recommendation not to underestimate the potential damage caused by this payload and the extent to which it may have compromised the target system.

Related Solutions

Extract file from docker image?

You can extract files from an image with the following commands: docker create $image # returns container ID docker cp $container_id:$source_path $destination_path docker rm $container_id According to the docker create documentation, this doesn't run the...

Transfer files using scp: permission denied

Your commands are trying to put the new Document to the root (/) of your machine. What you want to do is to transfer them to your home directory (since you have no permissions to write to /). If path to your home is something like /home/erez try the following:...

What’s the purpose of DH Parameters?

What exactly is the purpose of these DH Parameters? These parameters define how OpenSSL performs the Diffie-Hellman (DH) key-exchange. As you stated correctly they include a field prime p and a generator g. The purpose of the availability to customize these...

How to rsync multiple source folders

You can pass multiple source arguments. rsync -a /etc/fstab /home/user/download bkp This creates bkp/fstab and bkp/download, like the separate commands you gave. It may be desirable to preserve the source structure instead. To do this, use / as the source and...

Benefits of Structured Logging vs basic logging

There are two fundamental advances with the structured approach that can't be emulated using text logs without (sometimes extreme levels of) additional effort. Event Types When you write two events with log4net like: log.Debug("Disk quota {0} exceeded by user...

Interfaces vs Types in TypeScript

2019 Update The current answers and the official documentation are outdated. And for those new to TypeScript, the terminology used isn't clear without examples. Below is a list of up-to-date differences. 1. Objects / Functions Both can be used to describe the...

Get total as you type with added column (append) using jQuery

One issue if that the newly-added column id's are missing the id number. If you look at the id, it only shows "price-", when it should probably be "price-2-1", since the original ones are "price-1", and the original ones should probably be something like...

Determining if a file is a hard link or symbolic link?

Jim's answer explains how to test for a symlink: by using test's -L test. But testing for a "hard link" is, well, strictly speaking not what you want. Hard links work because of how Unix handles files: each file is represented by a single inode. Then a single...

How to restrict a Google search to results of a specific language?

You can do that using the advanced search options: http://www.googleguide.com/sharpening_queries.html I also found this, which might work for you: http://www.searchenginejournal.com/how-to-see-google-search-results-for-other-locations/25203/ Just wanted to add...

Random map generation

Among the many other related questions on the site, there's an often linked article for map generation: Polygonal Map Generation for Games you can glean some good strategies from that article, but it can't really be used as is. While not a tutorial, there's an...

How to prettyprint a JSON file?

The json module already implements some basic pretty printing in the dump and dumps functions, with the indent parameter that specifies how many spaces to indent by: >>> import json >>> >>> your_json = '["foo", {"bar":["baz", null,...

How can I avoid the battery charging when connected via USB?

I have an Android 4.0.3 phone without root access so can't test any of this but let me point you to /sys/class/power_supply/battery/ which gives some info/control over charging issues. In particular there is charging_enabled which gives the current state (0 not...

How to transform given dataset in python? [closed]

From your expected result, it appears that each "group" is based on contiguous id values. For this, you can use the compare-cumsum-groupby pattern, and then use agg to get the min and max values. # Sample data. df = pd.DataFrame( {'id': [1, 2, 2, 2, 2, 2, 1, 1,...

Output of the following C++ Program [closed]

It works exactly like this non-recursive translation: int func_0() { return 2; } int func_1() { return 3; } int func_2() { return func_1() + func_0(); } // Returns 3 + 2 = 5 int func_3() { return func_2() + func_1(); } // Returns 5 + 3 = 8 int func_4() { return...

Making a circle out of . (periods) [closed]

Here's the maths and even an example program in C: http://pixwiki.bafsoft.com/mags/5/articles/circle/sincos.htm (link no longer exists). And position: absolute, left and top will let you draw: http://www.w3.org/TR/CSS2/visuren.html#choose-position Any further...

Should I use a code converter (Python to C++)?

Generally it's an awful way to write code, and does not guarantee that it will be any faster. Things which are simple and fast in one language can be complex and slow in another. You're better off either learning how to write fast Python code or learning C++...

tkinter: cannot concatenate ‘str’ and ‘float’ objects

This one line is more than enough to cause the problem: text="რეგულარი >> "+2.23+ 'GEL' 2.23 is a floating-point value; 'GEL' is a string. What does it mean to add an arithmetic value and a string of letters? If you want the string label 'რეგულარი...