Skip to content

Commit

Permalink
NVSHAS-8842 Fixed an issue with amazon cve parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Acmarr committed Apr 1, 2024
1 parent ee23045 commit 0e96be5
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 30 deletions.
73 changes: 43 additions & 30 deletions updater/fetchers/amazon/amazon.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ var (
ovals []ovalInfo = []ovalInfo{
ovalInfo{"amazon/alas.rss.gz", "Amazon Linux", 1},
ovalInfo{"amazon/alas2.rss.gz", "Amazon Linux 2", 2},
// ovalInfo{"amazon/alas2022.rss.gz", "Amazon Linux 2022"},
ovalInfo{"amazon/alas2023.rss.gz", "Amazon Linux 2023", 2023},
}
)

Expand Down Expand Up @@ -141,7 +141,7 @@ func (u *AmazonFetcher) fetchOvalFeed(o *ovalInfo, net updater.NetInterface) ([]
Link: item.Link,
}

switch tokens[1] {
switch strings.ToLower(tokens[1]) {
case "(critical):":
vuln.FeedRating = "Critical"
vuln.Severity = common.Critical
Expand All @@ -157,9 +157,15 @@ func (u *AmazonFetcher) fetchOvalFeed(o *ovalInfo, net updater.NetInterface) ([]

cves := strings.Split(item.CVEs, " ")
vuln.CVEs = make([]common.CVE, len(cves))
for i, cve := range cves {
vuln.CVEs[i].Name = strings.TrimRight(cve, ",")
count := 0
for _, cve := range cves {
name := strings.TrimRight(cve, ",\n ")
if name != "" {
vuln.CVEs[count].Name = name
count++
}
}
vuln.CVEs = vuln.CVEs[:count]

vuln.IssuedDate, _ = time.Parse(time.RFC1123, item.Issued)
vuln.LastModDate, _ = time.Parse(time.RFC1123, item.LastMod)
Expand All @@ -170,15 +176,10 @@ func (u *AmazonFetcher) fetchOvalFeed(o *ovalInfo, net updater.NetInterface) ([]
vuln.LastModDate = vuln.IssuedDate
}

pkgs := make([]string, len(tokens)-2)
for i, token := range tokens[2:] {
pkgs[i] = strings.TrimRight(token, ",")
}

if desc, vers, err := getAlas(vuln.Name, vuln.Link, pkgs, net); err != nil {
if desc, vers, err := getAlas(vuln.Name, vuln.Link, net); err != nil {
log.WithFields(log.Fields{"cve": vuln.Name, "error": err}).Warn("Failed to parse amazon CVE page")
} else if len(vers) == 0 {
log.WithFields(log.Fields{"cve": vuln.Name, "pkgs": pkgs}).Warn("Failed to parse amazon CVE page, no package version")
log.WithFields(log.Fields{"cve": vuln.Name}).Warn("Failed to parse amazon CVE page, no package versions")
} else {
vuln.Description = strings.TrimSpace(desc)

Expand Down Expand Up @@ -211,7 +212,7 @@ func (u *AmazonFetcher) fetchOvalFeed(o *ovalInfo, net updater.NetInterface) ([]
func (u *AmazonFetcher) Clean() {
}

func parseAlasPage(name, body, plain string, pkgs []string, net updater.NetInterface) (string, map[string]string, error) {
func parseAlasPage(name, body, plain string) (string, map[string]string, error) {
var description string
if a := strings.Index(plain, "Issue Overview:"); a > 0 {
if b := strings.Index(plain, "Affected Packages:"); b > 0 {
Expand All @@ -229,39 +230,51 @@ func parseAlasPage(name, body, plain string, pkgs []string, net updater.NetInter
}
plain = strings.ReplaceAll(plain, "<br />", " ")
plain = strings.ReplaceAll(plain, "&nbsp;", " ")

strs := strings.Split(plain, " ")
var arch string

for _, str := range strs {
str = strings.TrimSpace(str)
if strings.HasSuffix(str, ":") {
arch = fmt.Sprintf(".%s", str[:len(str)-1])
} else if arch != "" {
if s := strings.Index(str, arch); s > 0 {
for _, pkg := range pkgs {
if strings.HasPrefix(str, pkg) {
version := str[len(pkg)+1 : s]
if verRegexp.MatchString(version) {
pkgVers[pkg] = version
}
}
}
if len(pkgVers) == len(pkgs) {
return description, pkgVers, nil
pkgName := ""
if strings.HasSuffix(str, ":") || str == "" {
//arch = fmt.Sprintf(".%s", str[:len(str)-1])
//skip arch line
continue
} else {
//Find name by locating beginning of version
versionStart := regexp.MustCompile(`[a-z+]-[0-9]`)
alternateVersionStart := regexp.MustCompile(`[0-9]-[0-9]`)
lastDotIndex := strings.LastIndex(str, ".")
versionStartIndex := versionStart.FindAllStringIndex(str, -1)
if versionStartIndex == nil {
versionStartIndex = alternateVersionStart.FindAllStringIndex(str, -1)
if versionStartIndex == nil {
log.WithFields(log.Fields{"name": name, "str": str}).Warning("Failed to find version start index for ALAS page")
continue
}
//use first match rather than last for this case
pkgName = str[:versionStartIndex[0][0]+1]
version := str[versionStartIndex[0][0]+2 : lastDotIndex]
pkgVers[pkgName] = version
continue
}
pkgName = str[:versionStartIndex[len(versionStartIndex)-1][0]+1]
//Find version by taking characters between start of version and last "."
version := str[versionStartIndex[len(versionStartIndex)-1][0]+2 : lastDotIndex]
//arch := str[lastDotIndex:]

pkgVers[pkgName] = version
}
}
}

return description, pkgVers, nil
}

func getAlas(name, link string, pkgs []string, net updater.NetInterface) (string, map[string]string, error) {
func getAlas(name, link string, net updater.NetInterface) (string, map[string]string, error) {
body, plain, err := net.DownloadHTMLPage(link)
if err != nil {
return "", nil, err
}

return parseAlasPage(name, body, plain, pkgs, net)
return parseAlasPage(name, body, plain)
}
114 changes: 114 additions & 0 deletions updater/fetchers/amazon/amazon_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package amazon

import (
"testing"

"github.com/k3a/html2text"
)

var htmlBody = `
<!doctype html>
<html>
<body class="Site">
<main class="Site-content">
<div class="container">
<nav class="navbar navbar-fixed-top navbar-inverse" style="background-color: #000000" id="bs-navbar">
<a style="font-size: 20px; color: #FF9900" class="navbar-brand" href="/"><b>Amazon Linux Security Center</b></a>
<ul class="nav navbar-nav navbar-right" style="color: #ff9900">
<li style="background-color: #333333;"> <a style="color: #FFFFFF" href="/index.html">Amazon Linux 1</a> </li><li style="background-color: #333333;"> <a style="color: #FFFFFF" href="/alas2.html">Amazon Linux 2</a> </li><li style="background-color: #FF9900;"> <a style="color: #000000" href="/alas2023.html">Amazon Linux 2023</a> </li><li style="background-color: #333333;"> <a style="color: #FFFFFF" href="/announcements.html">Announcements</a> </li><li style="background-color: #333333;"> <a style="color: #FFFFFF" href="/faqs.html">FAQs</a> </li>
</ul>
</nav>
</div>
<div style='min-height: 523px; margin-top:80px;' class='nine columns content-with-nav' role='main'>
<section>
<div class='title'>
<h1 id='ALAS2023-2023-368'>ALAS2023-2023-368</h1>
</div>
<div class='text'>
<hr class='mid-pad'>
<span class='alas-info'>
<b>Amazon Linux 2023 Security Advisory:</b> ALAS-2023-368
</span><br />
<span class='alas-info'><b>Advisory Release Date:</b> 2023-09-27 21:06 Pacific</span><br />
<span class='alas-info'><b>Advisory Updated Date:</b> 2023-10-03 20:50 Pacific</span><br />
<div id='severity' class='alas-info'>
<b>Severity:</b>
<span class='date'>
<span class='bulletin-type'>
<i class='fas fa-exclamation-triangle'></i>
</span>
</span>
Important<br />
</div>
<div id='references'>
<b>References:</b>
<a href='/cve/html/CVE-2023-38039.html' target='_blank' rel='noopener noreferrer'>CVE-2023-38039&nbsp;</a>
<br />
<a href="../../faqs.html">FAQs regarding Amazon Linux ALAS/CVE Severity</a>
</div>
<hr class='mid-pad'>
<div id='issue_overview'>
<b>Issue Overview:</b>
<p>HTTP headers eat all memory</p><p>NOTE: https://www.openwall.com/lists/oss-security/2023/09/13/1<br />NOTE: https://curl.se/docs/CVE-2023-38039.html<br />NOTE: Introduced by: https://github.com/curl/curl/commit/7c8c723682d524ac9580b9ca3b71419163cb5660 (curl-7_83_0)<br />NOTE: Experimental tag removed in: https://github.com/curl/curl/commit/4d94fac9f0d1dd02b8308291e4c47651142dc28b (curl-7_84_0)<br />NOTE: Fixed by: https://github.com/curl/curl/commit/3ee79c1674fd6f99e8efca52cd7510e08b766770 (curl-8_3_0) (CVE-2023-38039)</p>
</div>
<div id='affected_packages' class='alas-info'>
<br />
<b>Affected Packages:</b>
<br />
<p>curl</p>
</div>
<div id='issue_correction'>
<br />
<b>Issue Correction:</b>
<br />Run <i>dnf update curl --releasever 2023.2.20231002</i> to update your system.<br /></div>
<br />
<div id='new_packages'>
<b>New Packages:</b><pre>aarch64:<br />&nbsp;&nbsp;&nbsp; libcurl-debuginfo-8.3.0-1.amzn2023.0.1.aarch64<br />&nbsp;&nbsp;&nbsp; java-1.8.0-amazon-corretto-1.8.0_402.b08-1.amzn2023.aarch64<br />&nbsp;&nbsp;&nbsp; libcurl-minimal-debuginfo-8.3.0-1.amzn2023.0.1.aarch64<br />&nbsp;&nbsp;&nbsp; curl-8.3.0-1.amzn2023.0.1.aarch64<br />&nbsp;&nbsp;&nbsp; curl-minimal-8.3.0-1.amzn2023.0.1.aarch64<br />&nbsp;&nbsp;&nbsp; curl-debuginfo-8.3.0-1.amzn2023.0.1.aarch64<br />&nbsp;&nbsp;&nbsp; curl-minimal-debuginfo-8.3.0-1.amzn2023.0.1.aarch64<br />&nbsp;&nbsp;&nbsp; curl-debugsource-8.3.0-1.amzn2023.0.1.aarch64<br />&nbsp;&nbsp;&nbsp; libcurl-minimal-8.3.0-1.amzn2023.0.1.aarch64<br />&nbsp;&nbsp;&nbsp; libcurl-8.3.0-1.amzn2023.0.1.aarch64<br />&nbsp;&nbsp;&nbsp; libcurl-devel-8.3.0-1.amzn2023.0.1.aarch64<br /><br />src:<br />&nbsp;&nbsp;&nbsp; curl-8.3.0-1.amzn2023.0.1.src<br /><br />x86_64:<br />&nbsp;&nbsp;&nbsp; curl-minimal-debuginfo-8.3.0-1.amzn2023.0.1.x86_64<br />&nbsp;&nbsp;&nbsp; curl-debuginfo-8.3.0-1.amzn2023.0.1.x86_64<br />&nbsp;&nbsp;&nbsp; libcurl-minimal-8.3.0-1.amzn2023.0.1.x86_64<br />&nbsp;&nbsp;&nbsp; curl-minimal-8.3.0-1.amzn2023.0.1.x86_64<br />&nbsp;&nbsp;&nbsp; curl-debugsource-8.3.0-1.amzn2023.0.1.x86_64<br />&nbsp;&nbsp;&nbsp; libcurl-debuginfo-8.3.0-1.amzn2023.0.1.x86_64<br />&nbsp;&nbsp;&nbsp; curl-8.3.0-1.amzn2023.0.1.x86_64<br />&nbsp;&nbsp;&nbsp; libcurl-minimal-debuginfo-8.3.0-1.amzn2023.0.1.x86_64<br />&nbsp;&nbsp;&nbsp; libcurl-8.3.0-1.amzn2023.0.1.x86_64<br />&nbsp;&nbsp;&nbsp; libcurl-devel-8.3.0-1.amzn2023.0.1.x86_64<br />&nbsp;&nbsp;&nbsp; kernel-debuginfo-common-i686-4.14.336-180.562.amzn1.i686<br /></pre></div>
</div>
</html>`

func TestParseAlasPage(t *testing.T) {
expectedLen := 12
expectedVersions := map[string]string{
"libcurl-debuginfo": "8.3.0-1.amzn2023.0.1",
"java-1.8.0-amazon-corretto": "1.8.0_402.b08-1.amzn2023",
"libcurl-minimal-debuginfo": "8.3.0-1.amzn2023.0.1",
"curl": "8.3.0-1.amzn2023.0.1",
"curl-minimal": "8.3.0-1.amzn2023.0.1",
"curl-debuginfo": "8.3.0-1.amzn2023.0.1",
"curl-minimal-debuginfo": "8.3.0-1.amzn2023.0.1",
"curl-debugsource": "8.3.0-1.amzn2023.0.1",
"libcurl-minimal": "8.3.0-1.amzn2023.0.1",
"libcurl": "8.3.0-1.amzn2023.0.1",
"libcurl-devel": "8.3.0-1.amzn2023.0.1",
"kernel-debuginfo-common-i686": "4.14.336-180.562.amzn1",
}
plain := html2text.HTML2Text(string(htmlBody))
_, vers, err := parseAlasPage("ALAS-2023-368", htmlBody, plain)
if err != nil {
t.Errorf("Error during parseAlasPage:%v\n", err)
}

//check length of version map
if len(vers) != expectedLen {
t.Errorf("Expected length of parseAlasPage:%v , returned length:%v\n", expectedLen, len(vers))
}
//Check contents of version map
for key, value := range expectedVersions {
val, ok := vers[key]
if ok {
if val != value {
t.Errorf("parseAlasPage vers key:%s, value:%s, does not match expected value:%s,\n", key, val, value)
}
} else {
t.Errorf("Missing key in vers from parseAlasPage:%s\n", key)
}
}
}

0 comments on commit 0e96be5

Please sign in to comment.