Skip to content
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

Feat: add golang checksec intial commit #249

Merged
merged 1 commit into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
project_name: checksec

builds:
- id: linux
binary: checksec
main: ./main.go
env:
- CGO_ENABLED=0
goos:
- linux
goarch:
#- amd64
- arm64

- id: darwin
binary: checksec
main: ./main.go
env:
- CGO_ENABLED=0
goos:
- darwin
goarch:
#- amd64
- arm64

# - id: windows
# binary: checksec
# main: ./main.go
# goos:
# - windows
# goarch:
# - amd64
# - arm64
# ldflags:
# - -buildmode=exe
9 changes: 7 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,14 @@ repos:
hooks:
- id: forbid-crlf
- id: remove-crlf
- id: remove-tabs
- id: forbid-tabs
- repo: https://github.com/sirosen/fix-smartquotes
rev: 0.2.0
hooks:
- id: fix-smartquotes
- repo: https://github.com/dnephin/pre-commit-golang
rev: v0.5.1
hooks:
- id: go-fmt
- id: go-vet
# - id: go-lint
- id: go-mod-tidy
22 changes: 18 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
FROM photon:3.0
FROM ubuntu:22.04

COPY checksec /bin/
RUN tdnf clean all && tdnf remove -y toybox && tdnf upgrade -y && \
tdnf install -y coreutils util-linux sed tar texinfo procps-ng grep findutils gzip file which awk binutils && \
chmod +x /bin/checksec

RUN apt-get update && apt-get -y -q upgrade && DEBIAN_FRONTEND=noninteractive apt-get -y -q install \
bc bison flex build-essential ccache git file \
libncurses-dev libssl-dev u-boot-tools wget \
xz-utils vim xfce4 libxml2-utils python3 python3-pip jq \
gcc clang && apt-get clean \
pip3 install --upgrade pip && pip3 install setuptools && \
pip3 install demjson3 && mkdir -p /zig && \
wget https://ziglang.org/builds/zig-linux-$(uname -m)-0.12.0-dev.3667+77abd3a96.tar.xz && \
tar xf zig-linux-$(uname -m)-0.12.0-dev.3667+77abd3a96.tar.xz -C /zig --strip-components=1 && \
rm -rf zig-linux-$(uname -m)-0.12.0-dev.3667+77abd3a96.tar.xz && \
chmod +x /bin/checksec

COPY . /root
WORKDIR /root

COPY dist/linux_linux_arm64/checksec /bin/checksec-go
File renamed without changes.
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ test:
./tests/test-checksec.sh

.PHONY: compose-test
compose-test:
compose-test: go
docker-compose build
docker-compose run

.PHONY: go
go:
goreleaser build --snapshot --clean
29 changes: 23 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
checksec
========

**Bash version entering feature freeze**

Checksec is a bash script to check the properties of executables (like PIE, RELRO, Canaries, ASLR, Fortify Source).
It has been originally written by Tobias Klein and the original source is available here: http://www.trapkit.de/tools/checksec.html


Updates
-------
** MAJOR UPDATES ** 2.1.0
- Changed structure to be more modular and switched to getopts so options can be in any order. e.g. format=json can be at the end now, however.
- All options now require `--$option=$value` instead of `--$option $value`
- --extended option now includes clang CFI and safe stack checks

Last Update: 2024-06-08
** Version 2.7.x should be the last version of checksec in bash
Version 3.x will be released as a golang static binary
Checksec was originally released with 1.0 in early 2009 and has been used for validating binary checks of Linux systems for over a decade. Over time as more checks were supported and Linux distributions have changed, this has brought more dependencies into checksec. Adding more and more dependenies to be able to check the security flags of files, it not an ideal solution for systems with minor dependencies including embedded systems, distroless containers, and cross platform checks.
- Feature partial between the bash version and the golang version will be mostly supported.
- Adding support for yaml output
- Removing support for CSV
- JSON and XML will still both be supported
- Much faster results. When checking 694 files in a directory
- bash: real 0m10.348s
- golang: real 0m0.691s
- Adds recursive directory support
TODO:
[] Fix Partial RELRO
[] Add fortify file function results
[] Add fortifyPorc
[] Add ProcLibs
[] Add selinux checks
[] Add additional kernel flag checks
[] Update and Validate all current tests
[] Enable golint validation

For OSX
-------
Expand Down
33 changes: 33 additions & 0 deletions cmd/dir.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package cmd

import (
"checksec/pkg/utils"

"github.com/spf13/cobra"
)

// dirCmd represents the dir command
var dirCmd = &cobra.Command{
Use: "dir",
Short: "check all files in a directory",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
dir := args[0]
recursive, _ := cmd.Flags().GetBool("recursive")
utils.CheckDirExists(dir)
var Elements []interface{}
var ElementColors []interface{}
for _, file := range utils.GetAllFilesFromDir(dir, recursive) {
data, color := utils.RunFileChecks(file)
Elements = append(Elements, data...)
ElementColors = append(ElementColors, color...)
}
utils.FilePrinter(outputFormat, Elements, ElementColors)

},
}

func init() {
rootCmd.AddCommand(dirCmd)
dirCmd.Flags().BoolP("recursive", "r", false, "Enable recursive through the directories")
}
25 changes: 25 additions & 0 deletions cmd/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cmd

import (
"checksec/pkg/utils"

"github.com/spf13/cobra"
)

// fileCmd represents the file command
var fileCmd = &cobra.Command{
Use: "file",
Short: "Check a single binary file",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
file := args[0]

utils.CheckElfExists(file)
data, color := utils.RunFileChecks(file)
utils.FilePrinter(outputFormat, data, color)
},
}

func init() {
rootCmd.AddCommand(fileCmd)
}
58 changes: 58 additions & 0 deletions cmd/fortifyFile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package cmd

import (
"checksec/pkg/checksec"
"checksec/pkg/utils"

"github.com/spf13/cobra"
)

// fortifyFileCmd represents the fortifyFile command
var fortifyFileCmd = &cobra.Command{
Use: "fortifyFile",
Short: "Check Fortify for binary file",
Run: func(cmd *cobra.Command, args []string) {
file := args[0]

utils.CheckElfExists(file)
binary := utils.GetBinary(file)
fortify := checksec.Fortify(file, binary)
output := []interface{}{
map[string]interface{}{
"name": file,
"checks": map[string]interface{}{
"fortify_source": fortify.Output,
"fortified": fortify.Fortified,
"fortifyable": fortify.Fortifiable,
"noFortify": fortify.NoFortify,
"libcSupport": fortify.LibcSupport,
"numLibcFunc": fortify.NumLibcFunc,
"numFileFunc": fortify.NumFileFunc,
},
},
}
color := []interface{}{
map[string]interface{}{
"name": file,
"checks": map[string]interface{}{
"fortified": fortify.Fortified,
"fortifiedColor": "unset",
"noFortify": fortify.NoFortify,
"fortifyable": fortify.Fortifiable,
"fortifyableColor": "unset",
"fortify_source": fortify.Output,
"fortify_sourceColor": fortify.Color,
"libcSupport": fortify.LibcSupport,
"libcSupportColor": fortify.LibcSupportColor,
"numLibcFunc": fortify.NumLibcFunc,
"numFileFunc": fortify.NumFileFunc,
},
},
}
utils.FortifyPrinter(outputFormat, output, color)
},
}

func init() {
rootCmd.AddCommand(fortifyFileCmd)
}
30 changes: 30 additions & 0 deletions cmd/fortifyProc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package cmd

import (
"fmt"

"github.com/spf13/cobra"
)

// fortifyProcCmd represents the fortifyProc command
var fortifyProcCmd = &cobra.Command{
Use: "fortifyProc",
Short: "Check Fortify for running process",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("fortifyProc called")
},
}

func init() {
rootCmd.AddCommand(fortifyProcCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// fortifyProcCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// fortifyProcCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
40 changes: 40 additions & 0 deletions cmd/kernel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package cmd

import (
"checksec/pkg/utils"

"github.com/spf13/cobra"
)

// kernelCmd represents the kernel command
var kernelCmd = &cobra.Command{
Use: "kernel",
Short: "Check kernel security flags",
Run: func(cmd *cobra.Command, args []string) {
var configFile string
if len(args) > 0 {
configFile = args[0]
} else {
configFile = "/proc/config.gz"
}

utils.CheckFileExists(configFile)

kernel, kernelColors := utils.ParseKernel(configFile)
utils.KernelPrinter(outputFormat, kernel, kernelColors)
},
}

func init() {
rootCmd.AddCommand(kernelCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// kernelCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// kernelCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
35 changes: 35 additions & 0 deletions cmd/proc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package cmd

import (
"checksec/pkg/utils"
"fmt"
"os"

"path/filepath"

"github.com/spf13/cobra"
)

// procCmd represents the proc command
var procCmd = &cobra.Command{
Use: "proc",
Short: "Check a file of a running process",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
proc := args[0]

file, err := os.Readlink(filepath.Join("/proc", proc, "exe"))
if err != nil {
fmt.Printf("Error: Pid %s not found", proc)
os.Exit(1)
}

utils.CheckElfExists(file)
data, color := utils.RunFileChecks(file)
utils.FilePrinter(outputFormat, data, color)
},
}

func init() {
rootCmd.AddCommand(procCmd)
}
40 changes: 40 additions & 0 deletions cmd/procAll.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package cmd

import (
"checksec/pkg/utils"
"fmt"
"os"
"path/filepath"

"github.com/shirou/gopsutil/v3/process"
"github.com/spf13/cobra"
)

// procAllCmd represents the procAll command
var procAllCmd = &cobra.Command{
Use: "procAll",
Short: "Check all running processes",
Run: func(cmd *cobra.Command, args []string) {

var Elements []interface{}
var ElementColors []interface{}
processes, _ := process.Processes()
for _, process := range processes {
proc := process.Pid
filePath := filepath.Join("/proc", fmt.Sprint(proc), "exe")
file, err := os.Readlink(filePath)
if err != nil {
fmt.Printf("Error: Pid %d not found", proc)
os.Exit(1)
}
data, color := utils.RunFileChecks(file)
Elements = append(Elements, data...)
ElementColors = append(ElementColors, color...)
}
utils.FilePrinter(outputFormat, Elements, ElementColors)
},
}

func init() {
rootCmd.AddCommand(procAllCmd)
}
Loading
Loading