Cross-Build Injection attacks are a completely new class of attacks that take place at build time. In this presentation (which was presented at JavaOne 2012) I show what the problem is and what can be done about. As always, security doesn't come for free: you'll have to work to get it right!
(unfortunately, some graphics got mangled by the SlideShare conversion. Sorry!)
Report
Share
Report
Share
1 of 38
More Related Content
Cross-Build Injection attacks: how safe is your Java build?
2. About
Coding at
( )
Writing Blog @
branchandbound.net
Speaking
3. Trust
‘Reflections on Trusting Trust’
Ken Thompson, 1984
UNIX co-creator
4. Trust
‘Reflections on Trusting Trust’
Moral:
You can't trust code
that you did not
totally create yourself
Ken Thompson, 1984
UNIX co-creator
5. Trust
‘Reflections on Trusting Trust’
phpMyAdmin backdoor
... SourceForge became aware of a
corrupted copy of phpMyAdmin being
Moral: served from the ‘cdnetworks-kr-1′ mirror
in Korea.
You can't trust code
that you did not
totally create yourself
6. Trust
‘Reflections on Trusting Trust’
That was 30 years ago...
With the C compiler...
How is this relevant?
Demo / javac
7. Trust
‘Reflections on Trusting Trust’
That was 30 years ago... Could be any build system
with a central repository though!
With the C compiler...
How is this relevant?
Demo / javac
8. Maven Central
Internet
Maven
Central
- Dependencies
- Plugins
Local
Maven
uses
Maven Local
javac
Repo maven-compiler-plugin
9. Maven Central
400k components Maven
Central
7.5 billion req/year
60k organisations using Maven Central
In short: a prime target
* source: Sonatype
10. Cross Build Injection
Internet
Maven
Central
Internet
MITM
Local
Maven
Maven Local
Repo
11. Cross Build Injection
Internet Internet Internet
Maven Maven Hacker
Central Central Central
Internet Internet
Local DNS
MITM
Poisoning
Local Local
Maven Maven
Maven Local Maven Local
Repo Repo
12. Cross Build Injection
Compromised Maven Central
Internet
Maven
Central
Local
Maven
Maven Local
Repo
13. Cross Build Injection
Compromised Maven Central
Internet
Maven
Central
Different attack vectors,
one result: compromised
binaries through
Cross-Build Injection
Local
Maven
Maven Local
Repo
14. Countermeasures
https
Maven Central http-only
https for Sonatype customers
‘alternative’: https://oss.sonatype.org/
15. Countermeasures
https
Maven Central http-only
https for Sonatype customers
‘alternative’: https://oss.sonatype.org/
16. Countermeasures
‘Cutting all ties’
Internet
Maven
Central
Internal Maven repo
Local
Repository can be disconnected
Manager
Maven
Shortens XBI attack
window
Maven Local
Repo
Manual verification?
17. Countermeasures
Checksums
Maven
Maven
Central
.jar .pom
.jar.sha1 .pom.sha1
.jar.md5 .pom.md5
Checksums only detect transport issues
Automatic check, but no failure error!
Use: <checksumPolicy>fail</checksumPolicy>
Note: MD5 is broken anyway...
18. Countermeasures
Checksums
Maven
Maven
Central
.jar .pom
.jar.sha1 .pom.sha1
.jar.md5 .pom.md5
Downloading:
<snipped>/ws/spring-‐ws/1.5.8/spring-‐ws-‐1.5.8.pom
Checksums only detect transport issues
427b
downloaded
(spring-‐ws-‐1.5.8.pom)
[WARNING]
***
CHECKSUM
FAILED
-‐
Checksum
failed
on
download:
local
=
'14d6901e3f251f5d312b9be726c75a
Automatic check, but no failure error!
68f78045ac';
remote
=
'659bbed2c2dae12e9dbb65f8cad8fce1a1ea0845'
-‐
RETRYING
Downloading:
<snipped>/ws/spring-‐ws/1.5.8/spring-‐ws-‐1.5.8.pom
427b
downloaded
(spring-‐ws-‐1.5.8.pom)
Use: <checksumPolicy>fail</checksumPolicy>
[WARNING]
***
CHECKSUM
FAILED
-‐
Checksum
failed
on
download:
local
=
'14d6901e3f251f5d312b9be726c75a
68f78045ac';
remote
=
'659bbed2c2dae12e9dbb65f8cad8fce1a1ea0845'
-‐
IGNORING
Note: MD5 is broken anyway...
Ignorance is not bliss... Failure is an option!
19. Countermeasures
Signed artifacts
Pretty Good Privacy
OpenPGP standard
Encrypt or sign
Popularized by email signing
Asymmetric pub/private keypair
GnuPG (GPG): free implementation
20. Countermeasures
Signed artifacts
Maven
Maven
Central
.jar .pom
.jar.asc .pom.asc
(mandatory past 3 years)
21. Countermeasures
Signed artifacts
Maven
Maven
Central
.jar .pom
.jar.asc .pom.asc
(mandatory past 3 years)
.asc +
Library PGP Key
Developer Server
22. Manual verification
Getting the signature
$
wget
http://repo1.maven.org/maven2/org/sonatype/plexus/plexus-‐cipher/1.7/
plexus-‐cipher-‐1.7.jar.asc
$
cat
plexus-‐cipher-‐1.7.jar.asc
-‐-‐-‐-‐-‐BEGIN
PGP
SIGNATURE-‐-‐-‐-‐-‐
Version:
GnuPG
v1.4.10
(GNU/Linux)
iEYEABECAAYFAk4vAikACgkQA3TPLo3Rvf05hgCffG9+M1bAefuM5Kmu6IASNlPX
zhYAnAvI4VNXSFXH4nz6z/uXaWz9kpXz
=i6KI
-‐-‐-‐-‐-‐END
PGP
SIGNATURE-‐-‐-‐-‐-‐
$
gpg
-‐-‐verify
plexus-‐cipher-‐1.7.jar.asc
~/repo/.../plexus-‐chipher-‐1.7.jar
gpg:
Signature
made
Tue
Jul
26
20:06:33
2011
CEST
using
DSA
key
ID
8DD1BDFD
gpg:
Can't
check
signature:
public
key
not
found
23. Manual verification
Getting the signature
$
wget
http://repo1.maven.org/maven2/org/sonatype/plexus/plexus-‐cipher/1.7/
plexus-‐cipher-‐1.7.jar.asc
$
cat
plexus-‐cipher-‐1.7.jar.asc
-‐-‐-‐-‐-‐BEGIN
PGP
SIGNATURE-‐-‐-‐-‐-‐
Version:
GnuPG
v1.4.10
(GNU/Linux)
iEYEABECAAYFAk4vAikACgkQA3TPLo3Rvf05hgCffG9+M1bAefuM5Kmu6IASNlPX
zhYAnAvI4VNXSFXH4nz6z/uXaWz9kpXz
=i6KI
-‐-‐-‐-‐-‐END
PGP
SIGNATURE-‐-‐-‐-‐-‐
$
gpg
-‐-‐verify
plexus-‐cipher-‐1.7.jar.asc
~/repo/.../plexus-‐chipher-‐1.7.jar
gpg:
Signature
made
Tue
Jul
26
20:06:33
2011
CEST
using
DSA
key
ID
8DD1BDFD
gpg:
Can't
check
signature:
public
key
not
found
24. Manual verification
Getting the key
$
gpg
-‐-‐verify
plexus-‐cipher-‐1.7.jar.asc
~/repo/.../plexus-‐cipher-‐1.7.jar
gpg:
Signature
made
Tue
Jul
26
20:06:33
2011
CEST
using
DSA
key
ID
8DD1BDFD
gpg:
Can't
check
signature:
public
key
not
found
$
gpg
-‐-‐keyserver
pgp.mit.edu
-‐-‐recv-‐key
8DD1BDFD
gpg:
requesting
key
8DD1BDFD
from
hkp
server
pgp.mit.edu
gpg:
key
8DD1BDFD:
public
key
"Sonatype,
Inc.
(Sonatype
release
key)
<dev@sonatype.com>"
imported
gpg:
no
ultimately
trusted
keys
found
gpg:
Total
number
processed:
1
gpg:
imported:
1
$
gpg
-‐-‐verify
plexus-‐cipher-‐1.7.jar.asc
~/repo/.../plexus-‐chipher-‐1.7.jar
gpg:
Signature
made
Tue
Jul
26
20:06:33
2011
CEST
using
DSA
key
ID
8DD1BDFD
gpg:
Good
signature
from
"Sonatype,
Inc.
(Sonatype
release
key)
<dev@sonatype.com>"
gpg:
WARNING:
This
key
is
not
certified
with
a
trusted
signature!
gpg:
There
is
no
indication
that
the
signature
belongs
to
the
owner.
Primary
key
fingerprint:
2BCB
DD0F
23EA
1CAF
CC11
D486
0374
CF2E
8DD1
BDFD
25. Manual verification
Getting the key
$
gpg
-‐-‐verify
plexus-‐cipher-‐1.7.jar.asc
~/repo/.../plexus-‐cipher-‐1.7.jar
gpg:
Signature
made
Tue
Jul
26
20:06:33
2011
CEST
using
DSA
key
ID
8DD1BDFD
gpg:
Can't
check
signature:
public
key
not
found
$
gpg
-‐-‐keyserver
pgp.mit.edu
-‐-‐recv-‐key
8DD1BDFD
gpg:
requesting
key
8DD1BDFD
from
hkp
server
pgp.mit.edu
gpg:
key
8DD1BDFD:
public
key
"Sonatype,
Inc.
(Sonatype
release
key)
<dev@sonatype.com>"
imported
gpg:
no
ultimately
trusted
keys
found
gpg:
Total
number
processed:
1
gpg:
imported:
1
$
gpg
-‐-‐verify
plexus-‐cipher-‐1.7.jar.asc
~/repo/.../plexus-‐chipher-‐1.7.jar
gpg:
Signature
made
Tue
Jul
26
20:06:33
2011
CEST
using
DSA
key
ID
8DD1BDFD
gpg:
Good
signature
from
"Sonatype,
Inc.
(Sonatype
release
key)
<dev@sonatype.com>"
gpg:
WARNING:
This
key
is
not
certified
with
a
trusted
signature!
gpg:
There
is
no
indication
that
the
signature
belongs
to
the
owner.
Primary
key
fingerprint:
2BCB
DD0F
23EA
1CAF
CC11
D486
0374
CF2E
8DD1
BDFD
26. Manual verification
Getting the key
$
gpg
-‐-‐verify
plexus-‐cipher-‐1.7.jar.asc
~/repo/.../plexus-‐cipher-‐1.7.jar
gpg:
Signature
made
Tue
Jul
26
20:06:33
2011
CEST
using
DSA
key
ID
8DD1BDFD
gpg:
Can't
check
signature:
public
key
not
found
$
gpg
-‐-‐keyserver
pgp.mit.edu
-‐-‐recv-‐key
8DD1BDFD
gpg:
requesting
key
8DD1BDFD
from
hkp
server
pgp.mit.edu
gpg:
key
8DD1BDFD:
public
key
"Sonatype,
Inc.
(Sonatype
release
key)
<dev@sonatype.com>"
imported
gpg:
no
ultimately
trusted
keys
found
gpg:
Total
number
processed:
1
gpg:
imported:
1
$
gpg
-‐-‐verify
plexus-‐cipher-‐1.7.jar.asc
~/repo/.../plexus-‐chipher-‐1.7.jar
gpg:
Signature
made
Tue
Jul
26
20:06:33
2011
CEST
using
DSA
key
ID
8DD1BDFD
gpg:
Good
signature
from
"Sonatype,
Inc.
(Sonatype
release
key)
<dev@sonatype.com>"
gpg:
WARNING:
This
key
is
not
certified
with
a
trusted
signature!
gpg:
There
is
no
indication
that
the
signature
belongs
to
the
owner.
Primary
key
fingerprint:
2BCB
DD0F
23EA
1CAF
CC11
D486
0374
CF2E
8DD1
BDFD
27. Pretty Good Privacy
Web of Trust
Sonatype Sonatype
Release key Release key
Brian F. Brian F.
John C. Other
John C. people
in web
of trust
Damian B. Damian B.
28. Pretty Good Privacy
Web of Trust
Sonatype Sonatype
Release key Release key
ru st
n &t
ig
o r t, s Sander M.
Imp
Brian F. Brian F.
John C. Other
John C. people
in web
of trust
Damian B. Damian B.
Things I&#x2019;d like to show:\n1) unknown dangers in software builds\n2) what you can do to improve build security\nThis talk is not about security flaws in libraries (CSRF or SQL injection etc), but rather deliberate injection of harmful code during the build process\n
\n
Tell the story about the self-modifying C-compiler. Compile perfectly legal code, and get trojan horses in your output... Even CPU microcode could be rigged! \n
OpenSSH: OpenBSD&#x2019;s port tool downloaded, compiled and installed tainted OpenSSH source code. Allowed hacker to connect with priviliges of installer\nSendmail: buildsystem was compromised, and trojan horse shipped with Sendmail distribution\n
Demo consists of compiling and running a plain Java class with Maven, with surprising results. The &#x2018;attack&#x2019; is performed by introducing a malicious version of the maven-compiler-plugin.\n\nWe use Maven here, but the problems apply to any build tool that fetches dependencies from the internet.\n
We warn our parents not to download and run arbitrary binaries. Yet we do this very thing ourselves everytime we run a build.\n\nExplain what just happened. Cross-build injection is about attackers targeting your build to introduce malicious code (remote code execution attack: game over).\nThe Maven install is uncompromised, as is the javac. The problem is introduced by a malicious version of maven-compiler-plugin. So how can this end up in your build?\nSo how could this malicious version of the maven-compiler-plugin end up in our local repository?\n
Free service for community, first by Jason van Zyl, now Sonatype\n
Possible attack vectors because of http. Maven Central not https accessible (only for Sonatype customers)\nAnother, more extreme possibility: Maven Central itself compromised.\n
Term Crossbuild injection/XBI coined by Fortify in a whitepaper in 2007. Sounds like XSS/SQL injection.\nAnother, more extreme possibility: Maven Central itself compromised.\n
Term Crossbuild injection/XBI coined by Fortify in a whitepaper in 2007. Sounds like XSS/SQL injection.\nAnother, more extreme possibility: Maven Central itself compromised.\n
Using https prevents aforementioned attacks, but does nothing to ensure authenticity of dependency downloads per se. If Maven Central were somehow compromised, you wouldn&#x2019;t know.\n\nThe alternative is not really an alternative: smaller selection of artifacts, and cannot withstand the load of Maven Central.\n\nOf course, you can also object how safe is https (Diginotar, Comodo). Security is always a continuum! (though this is pushing it...)\n
Most extreme case: shun automatic dependency management all together (not practical). Alternative: introduce local repo-manager. Either disconnected and managed by hand (again not practical, and how good is the vetting process?) or directly proxying other public repos.\n\nStill, same attack vectors apply, only attack surface decreased by downloading once into local managed repo once.\n
MD5/SHA-1 offers no authenticity check, only integrity. But since checksums are served from same http-repo as the binary, both can be replaced/faked. MD5/SHA-1 can be easily recalculated on malicious jars.\nStill, there&#x2019;s no good reason to ignore checksum failures!\n
PGP has many uses, here we focus on creating signatures for artifacts. Private key of author is used to create signature. End-user can obtain corresponding public key to verify authenticity and integrity of artifact. Problems: where to get the key, and can you trust the key/signer?\n
Before library is synced to central, signature must be present and key distributed to Mit keyserver. Pom must be signed as well, it is equally important (otherwise adding transitive deps/repos would go undetected)\nSigning ensures both integrity (like checksums) and authenticity.\nMultiple keys because Maven Central filled by different contributors. Other systems like Windows/Apple update have it comparatively easy: they can use a single key because they control the client and all binaries that are pushed!\n
\n
PGP keys need to be in the keyring for succesful signature verification. Here example of manual key retrieval.\nNotice the warning though: even if the signature is valid, is it made by the person we think??\n
PGP keys need to be in the keyring for succesful signature verification. Here example of manual key retrieval.\nNotice the warning though: even if the signature is valid, is it made by the person we think??\n
PGP keys need to be in the keyring for succesful signature verification. Here example of manual key retrieval.\nNotice the warning though: even if the signature is valid, is it made by the person we think??\n
PGP keys need to be in the keyring for succesful signature verification. Here example of manual key retrieval.\nNotice the warning though: even if the signature is valid, is it made by the person we think??\n
So we have a way of obtaining the key, but how do we know that the key belongs to the stated identity? Hard problem, solved by PGP with the Web of Trust. You assign trust to a key based on &#x2018;out-of-band&#x2019; communication (fingerprints can be used for this). Not practical, so there is a notion of transitive trust. Public keys can be signed by different people. If you already trust a person who has signed the key you&#x2019;re interested, you automatically trust this other key. \n\n-> contrast with Certificate Authorities for SSL certificates: centralized vs. distributed trust.\n
-> Key signing party at Sonatype booth, get your web of trust started!\n\n
Here, I have a trusted key from a Sonatype developer in my keyring. Then, I instruct PGP to automatically retrieve the necessary key from the keyserver to verify the .asc signature. Since I have the trusted developer in my keyring (who signed the Sonatype release key), the Sonatype release key is transitively trusted. Hence, the signature is deemed good.\n
By now, you&#x2019;re probably thinking to yourself: too much effort! Can&#x2019;t this be automated? Unfortunately not using Maven itself.\nNexus Pro can download & check PGP checks automatically, and ban dependencies which have no PGP-sig or where check fails. Still, which keys do you trust automatically?! \n
Preventing XBI is one thing, but says nothing about the ultimate security of libs.\n\nThese measures are never enough by themselves, nor scalable, but offer another layer of defense to the systems security.\n
We&#x2019;ve seen some technical approaches to authenticity/integrity, but the solutions can&#x2019;t only be technical. Just because you didn&#x2019;t write the code doesn&#x2019;t mean you&#x2019;re not ultimately responsible! Be aware of what is happening with your code and what you&#x2019;re putting into your applications.\n
\n
Small recap: all repository based tools have to face this problem. Solution is part technical, part process. There is a serious awareness issue!\n\nSecurity is not binary: secure/unsecure. Nothing is 100% secure, but the default used in many organizations is definitely insecure as shown in this talk. Applying PGP signing/verification is not a panacea. It has associated costs, but also increases security and safety of software development. There are countless high-profile, high-value builds that are potentially vulnerable.\n\nAgain, everything discussed applies not just to Maven: Perl CPAN, .Net NuGet, Ruby Gems all have the same underlying dangers. &#x2018;Software is eating the world&#x2019;, and it&#x2019;s our duty to ensure it is as secure as possible.\n