区块链中,智能合约的安全检测和验证具有十分重要的意义。通过历史的合约漏洞导致的多个区块链庞大的损失就能看出其重要性。目前区块链平台众多如ETH、EOS、ONT、TRON、FISCO-BCOS、Fabric,但是从智能合约的角度来看,对于目前安全漏洞及功能逻辑缺陷的检测主要包括以下几个方面。(初步入门,个人总结,仅供参考)
代码规范问题
代码规范问题产生的问题,通常是由于代码不规范,比如多余的代码、多余的参数变量等,为了合约的规范,也是推荐做代码的审查的。这里基本都是静态审查问题。
编程语言漏洞
由于一些编程语言其自身在做编译的过程中产生的一些漏洞,如整型溢出、整数截断、等,以及高级点的GO的CVE-2018-6574漏洞、。
业务逻辑漏洞
业务逻辑漏洞主要是交易顺序、业务流程等,这个更多的是需要通过人工审计、合约模板生成来严格规定其业务逻辑。
区块链特性漏洞
比如基于合约的重入漏洞、伪随机数漏洞、块参数依赖漏洞、时间依赖漏洞。多数是区块链本身的漏洞,但是比如时间依赖这一种也是完全可以在合约中进行避免的。
本文针对Fabric,对GO的链码审计进行目前常见的开源工具介绍,仅仅涉及到代码规范问题和编程语言漏洞两个方面。后期随着对审计的深入了解将再进一步探讨。
目前,找到的审查工具比较靠谱的有三个GoReporter、GoMetaLinter、golangci-lint。
(以下信息针对lint的英文描述不翻译,避免因人而异的理解偏差。)
GoReporter
GoReporter是国内的,挂gitee上,地址:https://gitee.com/wgliang/goreporter#http://wgliang.github.io/pages/goreporter-report.html 项目下面有个演示地址,可以进去后看到,其大概样子如下:
主要支持的检测有:
• gofmt - Checks if the code is properly formatted and could not be further simplified.
• govet - Reports variables that may have been unintentionally shadowed.
• golint - Golint is a linter for Go source code.
• unittest - Golang unit test status.
• deadcode - Finds unused code.
• gocyclo - Computes the cyclomatic complexity of functions.
• varcheck - Find unused global variables and constants.
• structcheck - Find unused struct fields.
• aligncheck - Warn about un-optimally aligned structures.
• errcheck - Check that error return values are used.
• copycode(dupl) - Reports potentially duplicated code.
• gosimple - Report simplifications in code.
• staticcheck - Statically detect bugs, both obvious and subtle ones.
• godepgraph - Godepgraph is a program for generating a dependency graph of Go packages.
• misspell - Correct commonly misspelled English words... quickly.
• countcode - Count lines and files of project.
• interfacer - Suggest narrower interfaces that can be used.
• depth - Count the maxdepth of go functions.
• flen - Flen provides stats on functions/methods lengths in a Golang package.
GoMetaLinter
GoMetaLinter是SonarQube中支持的审查工具,地址在https://github.com/alecthomas/gometalinter。
默认支持的审查主要有
• go vet - Reports potential errors that otherwise compile.
• go tool vet --shadow - Reports variables that may have been unintentionally shadowed.
• gotype - Syntactic and semantic analysis similar to the Go compiler.
• gotype -x - Syntactic and semantic analysis in external test packages (similar to the Go compiler).
• deadcode - Finds unused code.
• gocyclo - Computes the cyclomatic complexity of functions.
• golint - Google's (mostly stylistic) linter.
• varcheck - Find unused global variables and constants.
• structcheck - Find unused struct fields.
• maligned - Detect structs that would take less memory if their fields were sorted.
• errcheck - Check that error return values are used.
• staticcheck - Statically detect bugs, both obvious and subtle ones.
• dupl - Reports potentially duplicated code.
• ineffassign - Detect when assignments to existing variables are not used.
• interfacer - Suggest narrower interfaces that can be used.
• unconvert - Detect redundant type conversions.
• goconst - Finds repeated strings that could be replaced by a constant.
• gosec - Inspects source code for security problems by scanning the Go AST.
默认不开启的,可是使用--enable=
• testify - Show location of failed testify assertions.
• test - Show location of test failures from the stdlib testing module.
• gofmt -s - Checks if the code is properly formatted and could not be further simplified.
• goimports - Checks missing or unreferenced package imports.
• gochecknoinits - Report init functions, to reduce side effects in code.
• gochecknoglobals - Report global vars, to reduce side effects in code.
• lll - Report long lines (see --line-length=N).
• misspell - Finds commonly misspelled English words.
• nakedret - Finds naked returns.
• unparam - Find unused function parameters.
• safesql - Finds potential SQL injection vulnerabilities.
golangci-lint
默认开启的linters:
deadcode: Finds unused code [fast: false, auto-fix: false]
errcheck: Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases [fast: false, auto-fix: false]
gosimple (megacheck): Linter for Go source code that specializes in simplifying a code [fast: false, auto-fix: false]
govet (vet, vetshadow): Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string [fast: false, auto-fix: false]
ineffassign: Detects when assignments to existing variables are not used [fast: true, auto-fix: false]
staticcheck (megacheck): Staticcheck is a go vet on steroids, applying a ton of static analysis checks [fast: false, auto-fix: false]
structcheck: Finds unused struct fields [fast: false, auto-fix: false]
typecheck: Like the front-end of a Go compiler, parses and type-checks Go code [fast: false, auto-fix: false]
unused (megacheck): Checks Go code for unused constants, variables, functions and types [fast: false, auto-fix: false]
varcheck: Finds unused global variables and constants [fast: false, auto-fix: false]
默认不支持的linters,可以通过 -E/--enable 来开启支持:
asciicheck: Simple linter to check that your code does not contain non-ASCII identifiers [fast: true, auto-fix: false]
bidichk: Checks for dangerous unicode character sequences [fast: true, auto-fix: false]
bodyclose: checks whether HTTP response body is closed successfully [fast: false, auto-fix: false]
contextcheck: check the function whether use a non-inherited context [fast: false, auto-fix: false]
cyclop: checks function and package cyclomatic complexity [fast: false, auto-fix: false]
depguard: Go linter that checks if package imports are in a list of acceptable packages [fast: false, auto-fix: false]
dogsled: Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false]
dupl: Tool for code clone detection [fast: true, auto-fix: false]
durationcheck: check for two durations multiplied together [fast: false, auto-fix: false]
errname: Checks that sentinel errors are prefixed with the Err
and error types are suffixed with the Error
. [fast: false, auto-fix: false]
errorlint: errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. [fast: false, auto-fix: false]
exhaustive: check exhaustiveness of enum switch statements [fast: false, auto-fix: false]
exhaustivestruct: Checks if all struct's fields are initialized [fast: false, auto-fix: false]
exportloopref: checks for pointers to enclosing loop variables [fast: false, auto-fix: false]
forbidigo: Forbids identifiers [fast: true, auto-fix: false]
forcetypeassert: finds forced type assertions [fast: true, auto-fix: false]
funlen: Tool for detection of long functions [fast: true, auto-fix: false]
gci: Gci control golang package import order and make it always deterministic. [fast: true, auto-fix: true]
gochecknoglobals: check that no global variables exist [fast: true, auto-fix: false]
gochecknoinits: Checks that no init functions are present in Go code [fast: true, auto-fix: false]
gocognit: Computes and checks the cognitive complexity of functions [fast: true, auto-fix: false]
goconst: Finds repeated strings that could be replaced by a constant [fast: true, auto-fix: false]
gocritic: Provides diagnostics that check for bugs, performance and style issues. [fast: false, auto-fix: false]
gocyclo: Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false]
godot: Check if comments end in a period [fast: true, auto-fix: true]
godox: Tool for detection of FIXME, TODO and other comment keywords [fast: true, auto-fix: false]
goerr113: Golang linter to check the errors handling expressions [fast: false, auto-fix: false]
gofmt: Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification [fast: true, auto-fix: true]
gofumpt: Gofumpt checks whether code was gofumpt-ed. [fast: true, auto-fix: true]
goheader: Checks is file header matches to pattern [fast: true, auto-fix: false]
goimports: In addition to fixing imports, goimports also formats your code in the same style as gofmt. [fast: true, auto-fix: true]
golint: Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes [fast: false, auto-fix: false]
gomnd: An analyzer to detect magic numbers. [fast: true, auto-fix: false]
gomoddirectives: Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. [fast: true, auto-fix: false]
gomodguard: Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. [fast: true, auto-fix: false]
goprintffuncname: Checks that printf-like functions are named with f
at the end [fast: true, auto-fix: false]
gosec (gas): Inspects source code for security problems [fast: false, auto-fix: false]
ifshort: Checks that your code uses short syntax for if-statements whenever possible [fast: true, auto-fix: false]
importas: Enforces consistent import aliases [fast: false, auto-fix: false]
interfacer: Linter that suggests narrower interface types [fast: false, auto-fix: false]
ireturn: Accept Interfaces, Return Concrete Types [fast: false, auto-fix: false]
lll: Reports long lines [fast: true, auto-fix: false]
makezero: Finds slice declarations with non-zero initial length [fast: false, auto-fix: false]
maligned: Tool to detect Go structs that would take less memory if their fields were sorted [fast: false, auto-fix: false]
misspell: Finds commonly misspelled English words in comments [fast: true, auto-fix: true]
nakedret: Finds naked returns in functions greater than a specified function length [fast: true, auto-fix: false]
nestif: Reports deeply nested if statements [fast: true, auto-fix: false]
nilerr: Finds the code that returns nil even if it checks that the error is not nil. [fast: false, auto-fix: false]
nilnil: Checks that there is no simultaneous return of nil
error and an invalid value. [fast: false, auto-fix: false]
nlreturn: nlreturn checks for a new line before return and branch statements to increase code clarity [fast: true, auto-fix: false]
noctx: noctx finds sending http request without context.Context [fast: false, auto-fix: false]
nolintlint: Reports ill-formed or insufficient nolint directives [fast: true, auto-fix: false]
paralleltest: paralleltest detects missing usage of t.Parallel() method in your Go test [fast: true, auto-fix: false]
prealloc: Finds slice declarations that could potentially be preallocated [fast: true, auto-fix: false]
predeclared: find code that shadows one of Go's predeclared identifiers [fast: true, auto-fix: false]
promlinter: Check Prometheus metrics naming via promlint [fast: true, auto-fix: false]
revive: Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint. [fast: false, auto-fix: false]
rowserrcheck: checks whether Err of rows is checked successfully [fast: false, auto-fix: false]
scopelint: Scopelint checks for unpinned variables in go programs [fast: true, auto-fix: false]
sqlclosecheck: Checks that sql.Rows and sql.Stmt are closed. [fast: false, auto-fix: false]
stylecheck: Stylecheck is a replacement for golint [fast: false, auto-fix: false]
tagliatelle: Checks the struct tags. [fast: true, auto-fix: false]
tenv: tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 [fast: false, auto-fix: false]
testpackage: linter that makes you use a separate _test package [fast: true, auto-fix: false]
thelper: thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers [fast: false, auto-fix: false]
tparallel: tparallel detects inappropriate usage of t.Parallel() method in your Go test codes [fast: false, auto-fix: false]
unconvert: Remove unnecessary type conversions [fast: false, auto-fix: false]
unparam: Reports unused function parameters [fast: false, auto-fix: false]
varnamelen: checks that the length of a variable's name matches its scope [fast: false, auto-fix: false]
wastedassign: wastedassign finds wasted assignment statements. [fast: false, auto-fix: false]
whitespace: Tool for detection of leading and trailing whitespace [fast: true, auto-fix: true]
wrapcheck: Checks that errors returned from external packages are wrapped [fast: false, auto-fix: false]
wsl: Whitespace Linter - Forces you to use empty lines! [fast: true, auto-fix: false]