feat: init nightly vuls for blackhat
This commit is contained in:
71
pkg/scan/ospkg/apk/apk.go
Normal file
71
pkg/scan/ospkg/apk/apk.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package apk
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
scanTypes "github.com/future-architect/vuls/pkg/scan/types"
|
||||
"github.com/future-architect/vuls/pkg/types"
|
||||
)
|
||||
|
||||
type Analyzer struct {
|
||||
}
|
||||
|
||||
func (a Analyzer) Name() string {
|
||||
return "apk analyzer"
|
||||
}
|
||||
|
||||
func (a Analyzer) Analyze(ctx context.Context, ah *scanTypes.AnalyzerHost) error {
|
||||
status, stdout, stderr, err := ah.Host.Exec(ctx, "apk info -v", false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, `exec "apk info -v"`)
|
||||
}
|
||||
if stderr != "" {
|
||||
return errors.New(stderr)
|
||||
}
|
||||
if status != 0 {
|
||||
return errors.Errorf("exit status is %d", status)
|
||||
}
|
||||
|
||||
ah.Host.Packages.OSPkg, err = ParseInstalledPackage(stdout)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parse installed package")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ParseInstalledPackage(stdout string) (map[string]types.Package, error) {
|
||||
pkgs := map[string]types.Package{}
|
||||
|
||||
scanner := bufio.NewScanner(strings.NewReader(stdout))
|
||||
for scanner.Scan() {
|
||||
name, version, err := parseApkInfo(scanner.Text())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "parse apk info line")
|
||||
}
|
||||
if name == "" || version == "" {
|
||||
continue
|
||||
}
|
||||
pkgs[name] = types.Package{
|
||||
Name: name,
|
||||
Version: version,
|
||||
}
|
||||
}
|
||||
|
||||
return pkgs, nil
|
||||
}
|
||||
|
||||
func parseApkInfo(line string) (string, string, error) {
|
||||
ss := strings.Split(line, "-")
|
||||
if len(ss) < 3 {
|
||||
if strings.Contains(ss[0], "WARNING") {
|
||||
return "", "", nil
|
||||
}
|
||||
return "", "", errors.Errorf(`unexpected package line format. accepts: "<package name>-<version>-<release>", received: "%s"`, line)
|
||||
}
|
||||
return strings.Join(ss[:len(ss)-2], "-"), strings.Join(ss[len(ss)-2:], "-"), nil
|
||||
}
|
||||
95
pkg/scan/ospkg/dpkg/dpkg.go
Normal file
95
pkg/scan/ospkg/dpkg/dpkg.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package dpkg
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
scanTypes "github.com/future-architect/vuls/pkg/scan/types"
|
||||
"github.com/future-architect/vuls/pkg/types"
|
||||
)
|
||||
|
||||
type Analyzer struct {
|
||||
}
|
||||
|
||||
func (a Analyzer) Name() string {
|
||||
return "dpkg analyzer"
|
||||
}
|
||||
|
||||
func (a Analyzer) Analyze(ctx context.Context, ah *scanTypes.AnalyzerHost) error {
|
||||
status, stdout, stderr, err := ah.Host.Exec(ctx, `dpkg-query -W -f="\${binary:Package},\${db:Status-Abbrev},\${Version},\${Architecture},\${source:Package},\${source:Version}\n"`, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, `exec "dpkg-query -W -f="\${binary:Package},\${db:Status-Abbrev},\${Version},\${Architecture},\${source:Package},\${source:Version}\n"`)
|
||||
}
|
||||
if stderr != "" {
|
||||
return errors.New(stderr)
|
||||
}
|
||||
if status != 0 {
|
||||
return errors.Errorf("exit status is %d", status)
|
||||
}
|
||||
|
||||
ah.Host.Packages.OSPkg, err = ParseInstalledPackage(stdout)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parse installed package")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ParseInstalledPackage(stdout string) (map[string]types.Package, error) {
|
||||
pkgs := map[string]types.Package{}
|
||||
|
||||
scanner := bufio.NewScanner(strings.NewReader(stdout))
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if trimmed := strings.TrimSpace(line); len(trimmed) != 0 {
|
||||
name, status, version, arch, srcName, srcVersion, err := parseDPKGQueryLine(trimmed)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "parse dpkq query line")
|
||||
}
|
||||
|
||||
packageStatus := status[1]
|
||||
// Package status:
|
||||
// n = Not-installed
|
||||
// c = Config-files
|
||||
// H = Half-installed
|
||||
// U = Unpacked
|
||||
// F = Half-configured
|
||||
// W = Triggers-awaiting
|
||||
// t = Triggers-pending
|
||||
// i = Installed
|
||||
if packageStatus != 'i' {
|
||||
continue
|
||||
}
|
||||
pkgs[name] = types.Package{
|
||||
Name: name,
|
||||
Version: version,
|
||||
Arch: arch,
|
||||
SrcName: srcName,
|
||||
SrcVersion: srcVersion,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pkgs, nil
|
||||
}
|
||||
|
||||
func parseDPKGQueryLine(line string) (string, string, string, string, string, string, error) {
|
||||
ss := strings.Split(line, ",")
|
||||
if len(ss) == 6 {
|
||||
// remove :amd64, i386...
|
||||
name, _, _ := strings.Cut(ss[0], ":")
|
||||
status := strings.TrimSpace(ss[1])
|
||||
if len(status) < 2 {
|
||||
return "", "", "", "", "", "", errors.Errorf(`unexpected db:Status-Abbrev format. accepts: "ii", received: "%s"`, status)
|
||||
}
|
||||
version := ss[2]
|
||||
arch := ss[3]
|
||||
srcName, _, _ := strings.Cut(ss[4], " ")
|
||||
srcVersion := ss[5]
|
||||
return name, status, version, arch, srcName, srcVersion, nil
|
||||
}
|
||||
return "", "", "", "", "", "", errors.Errorf(`unexpected package line format. accepts: "<bin name>,<status>,<bin version>,<arch>,<src name>,<src version>", received: "%s"`, line)
|
||||
}
|
||||
114
pkg/scan/ospkg/rpm/rpm.go
Normal file
114
pkg/scan/ospkg/rpm/rpm.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package rpm
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-version"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
scanTypes "github.com/future-architect/vuls/pkg/scan/types"
|
||||
"github.com/future-architect/vuls/pkg/types"
|
||||
)
|
||||
|
||||
type Analyzer struct {
|
||||
}
|
||||
|
||||
func (a Analyzer) Name() string {
|
||||
return "rpm analyzer"
|
||||
}
|
||||
|
||||
func (a Analyzer) Analyze(ctx context.Context, ah *scanTypes.AnalyzerHost) error {
|
||||
status, stdout, stderr, err := ah.Host.Exec(ctx, `rpm --version`, false)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, `exec "rpm --version"`)
|
||||
}
|
||||
if stderr != "" {
|
||||
return errors.New(stderr)
|
||||
}
|
||||
if status != 0 {
|
||||
return errors.Errorf("exit status is %d", status)
|
||||
}
|
||||
|
||||
cmd := `rpm -qa --queryformat "%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{ARCH} %{VENDOR}\n"`
|
||||
rpmver, err := version.NewVersion(strings.TrimPrefix(strings.TrimSpace(stdout), "RPM version "))
|
||||
rpmModukaritylabel, err := version.NewVersion("4.15.0")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parse rpm version for modularitylabel")
|
||||
}
|
||||
rpmEpochNum, err := version.NewVersion("4.8.0")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parse rpm version for epochnum")
|
||||
}
|
||||
if rpmver.GreaterThanOrEqual(rpmModukaritylabel) {
|
||||
cmd = `rpm -qa --queryformat "%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH} %{VENDOR} %{MODULARITYLABEL}\n"`
|
||||
} else if rpmver.GreaterThanOrEqual(rpmEpochNum) {
|
||||
cmd = `rpm -qa --queryformat "%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH} %{VENDOR}\n"`
|
||||
}
|
||||
|
||||
status, stdout, stderr, err = ah.Host.Exec(ctx, cmd, false)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, `exec "%s"`, cmd)
|
||||
}
|
||||
if stderr != "" {
|
||||
return errors.New(stderr)
|
||||
}
|
||||
if status != 0 {
|
||||
return errors.Errorf("exit status is %d", status)
|
||||
}
|
||||
|
||||
ah.Host.Packages.OSPkg, err = ParseInstalledPackage(stdout)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "parse installed package")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ParseInstalledPackage(stdout string) (map[string]types.Package, error) {
|
||||
pkgs := map[string]types.Package{}
|
||||
|
||||
scanner := bufio.NewScanner(strings.NewReader(stdout))
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if trimmed := strings.TrimSpace(line); len(trimmed) != 0 {
|
||||
name, version, release, arch, vendor, modularitylabel, err := parseRpmQaLine(trimmed)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "parse rpm -qa line")
|
||||
}
|
||||
|
||||
pkgs[name] = types.Package{
|
||||
Name: name,
|
||||
Version: version,
|
||||
Release: release,
|
||||
Arch: arch,
|
||||
Vendor: vendor,
|
||||
ModularityLabel: modularitylabel,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pkgs, nil
|
||||
}
|
||||
|
||||
func parseRpmQaLine(line string) (string, string, string, string, string, string, error) {
|
||||
ss := strings.Fields(line)
|
||||
if len(ss) < 6 {
|
||||
return "", "", "", "", "", "", errors.Errorf(`unexpected rpm -qa line format. accepts: "<name> <epoch> <version> <release> <arch> <vendor>( <modularitylabel>)", received: "%s"`, line)
|
||||
}
|
||||
|
||||
ver := ss[2]
|
||||
epoch := ss[1]
|
||||
if epoch != "0" && epoch != "(none)" {
|
||||
ver = fmt.Sprintf("%s:%s", epoch, ss[2])
|
||||
}
|
||||
|
||||
var modularitylabel string
|
||||
if len(ss) == 7 {
|
||||
modularitylabel = ss[5]
|
||||
}
|
||||
|
||||
return ss[0], ver, ss[3], ss[4], ss[5], modularitylabel, nil
|
||||
}
|
||||
Reference in New Issue
Block a user