Hacker Newsnew | past | comments | ask | show | jobs | submit | TiddoLangerak's commentslogin

Fwiw, in plain git, there's 2 dates associated with commits. The author date tells when the content was authored, and doesn't change with rebase. Only the commit date changes. So the correct metadata is already there, and even more precise. It can tell you both when it was authored, and when it's history was last changed.


The author date was when it was introduced to Parliament, the commit date is the date of Royal Assent. Ditto with the date a referendum was called versus when its results were certified, etc.


This is only true if your latency distribution is fully random, which is rarely the case. More often than not, it's the same small group of users hitting most of the p99 because their accounts are simply more resource intensive.


Depending on how the system distributes work such users can interfere with random with requests from other users through shared resources, so to that cohort these will look like a random latency distribution.


You're missing the biggest root cause though, and that significantly hinders how well this translates between languages: the Java community has settled on fewer but large monolithic dependencies, whereas the JavaScript community has settled on many but small composable dependencies (for good historical reasons, but that's a topic in and off itself).

This directly influences how well e.g. version pinning works. In the Java world, package versions are _relatively_ independent from eachother and have few transitive dependencies, and as such version conflicts are relatively rare. This means you can get away with full pinning of all dependencies, with the occasional manual override of a conflicting transitive dependency.

This doesn't work in JavaScript. The dependency ecosystem is massively intertwined, if every library would specify exact versions you'd end up with literally hundreds of conflicts to resolve. That's not feasible. As a result, they've chosen the middle ground of using lock files in addition to version ranges.

This also hurts the effectiveness of verified namespaces: when packages come from hundreds of different sources, you're not going to notice 1 or 2 sketchy ones in there.

Other consequences of the big monolithic packages in Java are that updates tend to be less frequent, and more often from large reputable venders. Both of these help to reduce the problem too.

While the JavaScript toolchain can definitely learn a lot from the Java toolchains, the problems it needs to solve are not the same, and thus solutions don't translate 1-1.

At least I hope that they'll get rid of install scripts, that's such a low hanging fruit that really should've be done a decade ago.


> At least I hope that they'll get rid of install scripts, that's such a low hanging fruit that really should've be done a decade ago.

How will that help? It's just going to break things that legitimately require them.

Instead of being infected upon running "npm install", you'll just get infected upon running "npm run" instead. The former is slightly more reliable but fixing that is just kicking the can down the road. Maybe we'll have a few days before the payloads get rewritten.


I have a different pubkey per device. I store all the pubkeys in the pass repo, and have a shell script to re-encrypt everything with those keys. So when I add a new device, I just need to add its pubkey, and then re-encrypt on an existing device.


The beauty of pass is that there's a distinction between giving access to the encrypted vault vs giving access to decryption, and you can leverage this.

How I've been doing this is that I have 2 (sets of) backup people. The first set has access to the repo, but can't decrypt. The second set can decrypt (i.e. I have their pubkeys imported), but don't have access to the repo. I've chosen the people such that it's unlikely they collude against me, but in case something happens it's likely they'll be able to get in touch with each other.

There's also other possible approaches: e.g. instead of building a dead man's switch based on the encryption, you can build a dead man's switch based on the data. I.e. you'll use their pubkeys for encryption, but the repo itself is behind a dead man's switch.


Thanks, I totally forgot about both sides; I only looked on the side of the key.


Am I missing something, or does the step in

> Pushing Malicious Changes to the Pipeline

mean that they already have full access to the repository in the first place? Normally I wouldn't expect an attacker to be able to push to master (or any branch for that matter). Without that, the exploit won't work. And with that access, there's so many other exploits one can do that it's really no longer about ci/cd vulns.


From TFA:

> A surprising number of websites still expose their .git directories to the public. When scanning for such exposures on a target, I noticed that the .git folder was publicly accessible.

[...]

> With access to .git/config, I found credentials, which opened the door to further exploitation. I could just clone the entire repository using the URL found inside the config file.

The URL with credentials was found in the `.git/config` file, defined in the [remote "origin"] section. This is the way they won full access to the repo.


I don't see how this is specific to "exploiting CI / CD Pipelines" when he's really just exploiting someone encoding their github username AND password credentials (unorthodox af) into the url for remote.


Yes, that first part was not. But the article continues like this:

- they use that credentials to make a commit adding malicious code to the CI pipeline

- The rouge pipeline job adds their public SSH key to the `.allowed_keys` file in the production server

As the pipeline is run automatically on push, they get ssh access to the remote server.

That is the "CI / CD Pipelines" bit. That being said, it's a bit underwhelming, because given the title I though they were going to exploit a bug in the CI/CD software itself. I don't know if I'd call that "exploiting" CI/CD software.


Because 1) the .git directory was deployed with the app code (the exploit vector), and 2) the deployment pipeline automatically integrated and pushed the attacker’s commit to a production system (completing the exploit), I’d say that claim is accurate. These are both defects in the thing the attacker claims to have exploited.

It sure wasn’t a good decision to use git-config to store creds for CI though! I wonder if OP found a developer’s old cached creds in the history that weren’t used anymore but happened to still be valid?


You're right, there are other avenues of exploitation. This particular approach was interesting to me because it is easily automatable (scour the internet for exposed credentials, clone the repo and detect if Pipelines are being used, profit).

Other exploits might need more targeted steps to achieve. For example, embedding a malware into the source code might require language / framework fingerprinting.


I am not sure, but it sounds like the pipeline runs for any pushed branch/PR, and it runs the pipeline configuration of that branch (so you can run a pipeline configuration without having to merge to master).

I'm not saying that this is fine, just that access to master is probably protected, but it's still vulnerable.


edit: Credentials for modifying the piepline were found in the .git/config file


With Bitbucket, as well as Gitlab and likely others that I haven't used, the CI pipelines are stored as a plaintext configuration in the repo itself. So, repo commit access automatically gives you the ability to modify the pipeline.


This is why things like codeowners files are so important


It's right at the start of the post - the git remote including credentials was exposed via the .git directory


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: