-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding Vulnerability Scans to Scan #453
base: master
Are you sure you want to change the base?
Changes from 5 commits
2b08bd1
bf34387
d80480c
c751b15
bd29aca
523b8ba
fc9cdff
56ff56b
6dc2e69
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package scan | ||
|
||
import ( | ||
"crypto/rsa" | ||
"crypto/x509" | ||
"errors" | ||
"net/url" | ||
|
||
"github.com/FiloSottile/Heartbleed/heartbleed" | ||
"github.com/cloudflare/cfssl/certinfo" | ||
"github.com/cloudflare/cfssl/helpers" | ||
) | ||
|
||
// Vulnerability contains scanners to detect vulnerabilities such as Heartbleed | ||
var Vulnerability = &Family{ | ||
Description: "Scans a host to detect TLS vulnerabilities.", | ||
Scanners: map[string]*Scanner{ | ||
"Heartbleed": { | ||
"Scan for Heartbleed vulnerability", | ||
heartbleedScan, | ||
}, | ||
"BERserk": { | ||
"Scan for BERserk vulnerability", | ||
BERserkScan, | ||
}, | ||
"LogJam": { | ||
"Scan for LogJam vulnerability", | ||
LogJamScan, | ||
}, | ||
}, | ||
} | ||
|
||
func heartbleedScan(addr, hostname string) (grade Grade, output Output, err error) { | ||
tgt := &heartbleed.Target{ | ||
Service: "https", | ||
HostIp: hostname, | ||
} | ||
|
||
u, err := url.Parse(tgt.HostIp) | ||
if err == nil && u.Host != "" { | ||
tgt.HostIp = u.Host | ||
} | ||
|
||
out, err := heartbleed.Heartbleed(tgt, | ||
[]byte("github.com/FiloSottile/Heartbleed"), true) | ||
if err == heartbleed.Safe { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A switch statement might be a bit more clear here |
||
grade = Good | ||
err = nil | ||
} else if err != nil { | ||
grade = Warning | ||
} else { | ||
grade, output = Bad, out | ||
} | ||
return | ||
} | ||
|
||
func BERserkScan(addr, hostname string) (grade Grade, output Output, err error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. looks like Travis failed here, since this function name's first letter is capitalized, add a comment above it or uncapitalized it. Reference: http://www.goinggo.net/2014/03/exportedunexported-identifiers-in-go.html There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, yes. I'll get to that, thanks. |
||
// Vulnerable if certificate has a 3 as the public exponent | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is not a valid indicator of BERserk vulnerability. BERserk is a client side vuln, and the existence of ANY e=3 trusted roots make ALL websites vulnerable. (Modulo pinning, if you will, but I don't think that's ground for saying that e=3 is a server vulnerability.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, thanks for pointing that out. |
||
// get certificate from host via certinfo | ||
|
||
certData, err := certinfo.ParseCertificateDomain(hostname) | ||
if err != nil { | ||
grade = Bad | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I see. |
||
return | ||
} | ||
|
||
ca, err := helpers.ParseCertificatePEM([]byte(certData.RawPEM)) | ||
if err != nil { | ||
grade = Bad | ||
return | ||
} | ||
|
||
if ca.PublicKeyAlgorithm != x509.RSA { | ||
grade = Good | ||
} | ||
|
||
pub, ok := ca.PublicKey.(*rsa.PublicKey) | ||
if !ok { | ||
grade = Good | ||
} | ||
|
||
if pub.E == 3 { | ||
grade = Bad | ||
err = errors.New("certificate has RSA public exponent 3 and is vulnerable") | ||
} | ||
|
||
if pub.N.BitLen() == 1024 || pub.N.BitLen() == 2048 { | ||
grade = Bad | ||
err = errors.New("certificate has bad public key length") | ||
} | ||
return | ||
} | ||
|
||
func LogJamScan(addr, hostname string) (grade Grade, output Output, err error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see comment above |
||
// do a DHE handshake and look at the public exponent used by the server. | ||
// If it’s 1024 bits, then it’s vulnerable. | ||
|
||
//DHE handshake? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Go's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jacobhaven Hmm, what does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, the Diffie Hellman Parameters are in a separate Server Key Exchange TLS message. You'll need to read and parse that message and detect if |
||
certData, err := certinfo.ParseCertificateDomain(hostname) | ||
if err != nil { | ||
grade = Bad | ||
return | ||
} | ||
|
||
ca, err := helpers.ParseCertificatePEM([]byte(certData.RawPEM)) | ||
if err != nil { | ||
grade = Bad | ||
return | ||
} | ||
|
||
pub, _ := ca.PublicKey.(*rsa.PublicKey) | ||
if pub.N.BitLen() == 1024 { | ||
grade = Bad | ||
err = errors.New("unsupported public key length") | ||
return | ||
} | ||
grade = Good | ||
return | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's assumed that
hostname
will never have a scheme.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, ok. I'll be sure to take that out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need some err handling after this?