Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
cwe_checker
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
fact-depend
cwe_checker
Commits
41b84a41
Commit
41b84a41
authored
Feb 22, 2019
by
Enkelmann
Committed by
Thomas Barabosch
Feb 22, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cwe476 (#11)
* improved CWE476-check with dataflow analysis
parent
44cb572a
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
182 additions
and
152 deletions
+182
-152
CHANGES.md
CHANGES.md
+7
-6
cwe_190.ml
src/checkers/cwe_190.ml
+2
-2
cwe_190.mli
src/checkers/cwe_190.mli
+2
-2
cwe_215.ml
src/checkers/cwe_215.ml
+8
-9
cwe_215.mli
src/checkers/cwe_215.mli
+3
-3
cwe_243.ml
src/checkers/cwe_243.ml
+6
-7
cwe_243.mli
src/checkers/cwe_243.mli
+2
-2
cwe_248.ml
src/checkers/cwe_248.ml
+1
-1
cwe_248.mli
src/checkers/cwe_248.mli
+1
-1
cwe_332.ml
src/checkers/cwe_332.ml
+3
-4
cwe_332.mli
src/checkers/cwe_332.mli
+2
-2
cwe_367.ml
src/checkers/cwe_367.ml
+3
-3
cwe_367.mli
src/checkers/cwe_367.mli
+2
-2
cwe_426.ml
src/checkers/cwe_426.ml
+2
-2
cwe_426.mli
src/checkers/cwe_426.mli
+5
-5
cwe_457.ml
src/checkers/cwe_457.ml
+3
-3
cwe_457.mli
src/checkers/cwe_457.mli
+1
-1
cwe_467.ml
src/checkers/cwe_467.ml
+5
-5
cwe_467.mli
src/checkers/cwe_467.mli
+2
-2
cwe_476.ml
src/checkers/cwe_476.ml
+0
-0
cwe_476.mli
src/checkers/cwe_476.mli
+18
-5
cwe_676.ml
src/checkers/cwe_676.ml
+1
-2
cwe_676.mli
src/checkers/cwe_676.mli
+1
-1
cwe_782.ml
src/checkers/cwe_782.ml
+2
-2
cwe_782.mli
src/checkers/cwe_782.mli
+1
-1
config.json
src/config.json
+4
-0
cwe_checker.ml
src/cwe_checker.ml
+30
-26
json_utils.ml
src/utils/json_utils.ml
+7
-0
json_utils.mli
src/utils/json_utils.mli
+1
-0
cwe_476.c
test/artificial_samples/cwe_476.c
+5
-4
makefile
test/artificial_samples/makefile
+52
-49
No files found.
CHANGES.md
View file @
41b84a41
0.2-dev (2019-XX-XX)
=====
-
Refactoring: Unification of cwe_checker function interface
-
Refactoring: Created utils module for JSON functionality
-
Added check for CWE 248: Uncaught Exception (PR #5)
-
Added automated test suite (run with make test) (PR #7)
-
Improved cross compiling for acceptance test cases by using dockcross (PR #8)
-
Added BAP recipe for standard cwe_checker run (PR #9)
-
Refactoring: Unification of cwe_checker function interface
-
Refactoring: Created utils module for JSON functionality
-
Added check for CWE 248: Uncaught Exception (PR #5)
-
Added automated test suite (run with make test) (PR #7)
-
Improved cross compiling for acceptance test cases by using dockcross (PR #8)
-
Added BAP recipe for standard cwe_checker run (PR #9)
-
Improved check for CWE-476 (NULL Pointer Dereference) using data flow analysis (PR #11)
0.
1 (2018-10-08)
=====
...
...
src/checkers/cwe_190.ml
View file @
41b84a41
...
...
@@ -27,10 +27,10 @@ let check_multiplication_before_symbol proj prog sub blk jmp tid_map symbols =
(
Address_translation
.
translate_tid_to_assembler_address_string
(
Term
.
tid
blk
)
tid_map
)
(
Symbol_utils
.
get_symbol_name_from_jmp
jmp
symbols
))
let
check_cwe
prog
proj
tid_map
symbol_names
=
let
check_cwe
prog
proj
tid_map
symbol_names
_
=
match
symbol_names
with
|
hd
::
[]
->
let
symbols
=
Symbol_utils
.
build_symbols
hd
prog
in
let
symbols
=
Symbol_utils
.
build_symbols
hd
prog
in
let
calls
=
call_finder
#
run
prog
[]
in
let
relevant_calls
=
filter_calls_to_symbols
calls
symbols
in
check_calls
relevant_calls
prog
proj
tid_map
symbols
check_multiplication_before_symbol
...
...
src/checkers/cwe_190.mli
View file @
41b84a41
...
...
@@ -3,6 +3,6 @@ CWE-190 (Integer Overflow or Wraparound)
https://cwe.mitre.org/data/definitions/190.html
*)
val
name
:
string
val
version
:
string
val
version
:
string
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
unit
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
string
list
->
unit
src/checkers/cwe_215.ml
View file @
41b84a41
...
...
@@ -3,17 +3,17 @@ open Bap.Std
open
Unix
(* TODO: IVG via gitter:
I see, so you need the CU information, and yes BAP doesn't provide this.
The right way to do this thing (a little bit complicated, but it
I see, so you need the CU information, and yes BAP doesn't provide this.
The right way to do this thing (a little bit complicated, but it
will preserve the abstractions), would be the following:
- Define the abstract interface for the CU providers (you can use Source module
or just define it manually with the interface you like)
- Write plugins that will provide implementations
(i.e., using readelf, objdump, IDA, LLVM, or whatever). The implementation shall
- Write plugins that will provide implementations
(i.e., using readelf, objdump, IDA, LLVM, or whatever). The implementation shall
subscribe to Project.Info.file information stream and generate CU information every time a new file is open.
Of course, for the prototype your approach will work,
Of course, for the prototype your approach will work,
but in general case it is better to use the approach described above. *)
let
name
=
"CWE215"
...
...
@@ -29,8 +29,8 @@ let read_lines in_chan =
In_channel
.
close
in_chan
;
List
.
rev
!
lines
(* TODO: check if program contains strings like "DEBUG"*)
let
check_cwe
_
project
_
_
=
(* TODO: check if program contains strings like "DEBUG"*)
let
check_cwe
_
project
_
_
_
=
match
Project
.
get
project
filename
with
|
Some
fname
->
begin
let
cmd
=
Format
.
sprintf
"readelf --debug-dump=decodedline %s | grep CU"
fname
in
...
...
@@ -38,8 +38,7 @@ let check_cwe _ project _ _ =
let
in_chan
=
Unix
.
open_process_in
cmd
in
read_lines
in_chan
|>
List
.
iter
~
f
:
(
fun
l
->
Log_utils
.
warn
"[%s] {%s} (Information Exposure Through Debug Information) %s"
name
version
l
)
with
Unix
.
Unix_error
(
e
,
fm
,
argm
)
->
Unix
.
Unix_error
(
e
,
fm
,
argm
)
->
Log_utils
.
error
"[%s] {%s} %s %s %s"
name
version
(
Unix
.
error_message
e
)
fm
argm
end
|
_
->
failwith
"[CWE215] symbol_names not as expected"
src/checkers/cwe_215.mli
View file @
41b84a41
(** This module checks if a binary contains sensitive debugging information that could be leveraged to
(** This module checks if a binary contains sensitive debugging information that could be leveraged to
get a better understanding of it in less time. This is basically CWE-215 (https://cwe.mitre.org/data/definitions/215.html *)
val
name
:
string
val
version
:
string
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
unit
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
string
list
->
unit
src/checkers/cwe_243.ml
View file @
41b84a41
open
Core_kernel
.
Std
open
Bap
.
Std
open
Symbol_utils
open
Symbol_utils
include
Self
()
...
...
@@ -30,10 +30,10 @@ let get_call_dests_of_sub sub =
end
|
_
->
[]
let
rec
check
dests
symbols
=
let
rec
check
dests
symbols
=
match
dests
with
|
[]
->
(
List
.
length
symbols
)
=
0
|
hd
::
tl
->
|
hd
::
tl
->
begin
match
symbols
with
|
[]
->
true
...
...
@@ -45,7 +45,7 @@ let rec check dests symbols =
end
let
check_route
sub
symbols
=
let
call_dests
=
get_call_dests_of_sub
sub
in
let
call_dests
=
get_call_dests_of_sub
sub
in
let
res
=
check
call_dests
symbols
in
if
res
then
res
else
res
...
...
@@ -62,7 +62,7 @@ let check_path prog tid_map sub path =
else
false
(** Checks a subfunction for CWE-243. Only functions that actually call "chroot" are considered.
(** Checks a subfunction for CWE-243. Only functions that actually call "chroot" are considered.
It checks each of the configured VALID pathes found in config.json, e.g.
"chroot_pathes": [["chroot", "chdir"], ["chdir", "chroot", "setresuid"], ["chdir", "chroot", "seteuid"],
["chdir", "chroot", "setreuid"], ["chdir", "chroot", "setuid"]].
...
...
@@ -81,10 +81,9 @@ let check_subfunction prog tid_map sub pathes =
(
Term
.
name
sub
)
end
let
check_cwe
prog
proj
tid_map
pathes
=
let
check_cwe
prog
proj
tid_map
pathes
_
=
let
chroot_symbol
=
find_symbol
prog
"chroot"
in
match
chroot_symbol
with
|
Some
_
->
Seq
.
iter
(
Term
.
enum
sub_t
prog
)
~
f
:
(
fun
sub
->
check_subfunction
prog
tid_map
sub
pathes
)
|
_
->
()
src/checkers/cwe_243.mli
View file @
41b84a41
(** This module implements a check for CWE-243 (Creation of chroot Jail Without Changing Working Directory).
According to http://www.unixwiz.net/techtips/chroot-practices.html, there are several ways to achieve the
According to http://www.unixwiz.net/techtips/chroot-practices.html, there are several ways to achieve the
safe creation of a chroot jail, e.g. chdir -> chroot -> setuid. They are configurable in config.json.
See https://cwe.mitre.org/data/definitions/243.html for detailed description. *)
val
name
:
string
val
version
:
string
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
unit
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
string
list
->
unit
src/checkers/cwe_248.ml
View file @
41b84a41
...
...
@@ -59,7 +59,7 @@ let rec find_uncaught_exceptions subfunction already_checked_functions program ~
(* Search for uncatched exceptions for each entry point into the binary.
TODO: Exceptions, that are catched when starting from one entry point, but not from another, are masked this
way. We should check whether this produces a lot of false negatives. *)
let
check_cwe
program
project
tid_map
symbol_pairs
=
let
check_cwe
program
project
tid_map
symbol_pairs
_
=
let
entry_points
=
Symbol_utils
.
get_program_entry_points
program
in
let
_
=
Seq
.
fold
entry_points
~
init
:
[]
~
f
:
(
fun
already_checked_functions
sub
->
find_uncaught_exceptions
~
tid_map
:
tid_map
sub
already_checked_functions
program
)
in
()
src/checkers/cwe_248.mli
View file @
41b84a41
...
...
@@ -8,4 +8,4 @@ can actually catch the thrown exceptions, thus we generate some false negatives.
val
name
:
string
val
version
:
string
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
unit
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
string
list
->
unit
src/checkers/cwe_332.ml
View file @
41b84a41
open
Bap
.
Std
open
Core_kernel
.
Std
open
Graph_utils
open
Graph_utils
open
Symbol_utils
let
name
=
"CWE332"
let
version
=
"0.1"
let
version
=
"0.1"
let
check_cwe
program
proj
tid_map
symbol_pairs
=
let
check_cwe
program
proj
tid_map
symbol_pairs
_
=
match
Option
.
both
(
find_symbol
program
"srand"
)
(
find_symbol
program
"rand"
)
with
|
None
->
begin
match
(
find_symbol
program
"rand"
)
with
...
...
@@ -15,4 +15,3 @@ let check_cwe program proj tid_map symbol_pairs =
|
Some
_
->
Log_utils
.
warn
"[%s] {%s} (Insufficient Entropy in PRNG) program uses rand without calling srand before"
name
version
end
|
Some
(
srand_tid
,
rand_tid
)
->
()
src/checkers/cwe_332.mli
View file @
41b84a41
(** This module implements a check for CWE332 (Insufficient Entropy in PRNG).
This can happen, for instance, if the PRNG is not seeded. A classical example
would be calling rand without srand. This could lead to predictable random
numbers and could, for example, weaken crypto functionality.
numbers and could, for example, weaken crypto functionality.
See https://cwe.mitre.org/data/definitions/332.html for detailed description. *)
val
name
:
string
val
version
:
string
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
'
a
->
'
b
->
string
list
list
->
unit
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
'
a
->
'
b
->
string
list
list
->
'
c
->
unit
src/checkers/cwe_367.ml
View file @
41b84a41
...
...
@@ -18,14 +18,14 @@ let get_calls_to_symbol symbol_name callsites program =
let
get_blk_tid_of_tid
sub
tid
=
let
blk
=
Seq
.
find
(
Term
.
enum
blk_t
sub
)
~
f
:
(
fun
b
->
fun
b
->
match
Term
.
last
jmp_t
b
with
|
Some
last_term
->
tid
=
(
Term
.
tid
last_term
)
|
None
->
false
)
in
match
blk
with
|
Some
b
->
Term
.
tid
b
|
_
->
assert
(
false
)
let
is_reachable
sub
source
sink
=
let
cfg
=
Sub
.
to_graph
sub
in
let
source_tid
=
Term
.
tid
source
in
...
...
@@ -57,6 +57,6 @@ let handle_sub sub program tid_map symbols source sink =
else
()
let
check_cwe
program
proj
tid_map
symbol_pairs
=
let
check_cwe
program
proj
tid_map
symbol_pairs
_
=
let
symbols
=
Symbol_utils
.
build_symbols
[
"access"
;
"open"
;]
in
Seq
.
iter
(
Term
.
enum
sub_t
program
)
~
f
:
(
fun
s
->
handle_sub
s
program
tid_map
symbols
"access"
"open"
)
src/checkers/cwe_367.mli
View file @
41b84a41
...
...
@@ -3,6 +3,6 @@ CWE-367 (Time-of-check Time-of-use (TOCTOU) Race Condition)
https://en.wikipedia.org/wiki/Time_of_check_to_time_of_use
*)
val
name
:
string
val
version
:
string
val
version
:
string
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
unit
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
string
list
->
unit
src/checkers/cwe_426.ml
View file @
41b84a41
...
...
@@ -20,8 +20,8 @@ let handle_sub sub program tid_map symbols =
()
end
else
()
let
check_cwe
program
proj
tid_map
symbols
=
let
check_cwe
program
proj
tid_map
symbols
_
=
match
symbols
with
|
hd
::
[]
->
Seq
.
iter
(
Term
.
enum
sub_t
program
)
~
f
:
(
fun
s
->
handle_sub
s
program
tid_map
hd
)
...
...
src/checkers/cwe_426.mli
View file @
41b84a41
(** This module checks for CWE-426 (Untrusted Search Path) (https://cwe.mitre.org/data/definitions/426.html). Basically, the program searches
for critical resources on an untrusted search path that can be adjusted by an adversary. For example, see Nebula Level 1
(https://exploit-exercises.com/nebula/level01/).
(https://exploit-exercises.com/nebula/level01/).
According to "man system" the following problems can arise:
"Do not use system() from a program with set-user-ID or set-group-ID privileges, because strange values for some environment variables might
be used to subvert system integrity. Use the exec(3) family of functions instead, but not execlp(3) or execvp(3). system() will not, in
fact, work properly from programs with set-user-ID or set-group-ID privileges on systems on which /bin/sh is bash version 2, since bash 2
"Do not use system() from a program with set-user-ID or set-group-ID privileges, because strange values for some environment variables might
be used to subvert system integrity. Use the exec(3) family of functions instead, but not execlp(3) or execvp(3). system() will not, in
fact, work properly from programs with set-user-ID or set-group-ID privileges on systems on which /bin/sh is bash version 2, since bash 2
drops privileges on startup. (Debian uses a modified bash which does not do this when invoked as sh.)"
*)
val
name
:
string
val
version
:
string
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
unit
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
string
list
->
unit
src/checkers/cwe_457.ml
View file @
41b84a41
...
...
@@ -38,7 +38,7 @@ let get_min_fp_offset arch =
match
arch
with
|
`x86
|
`x86_64
->
0x10000
|
_
->
0x0
(*FIXME: this is architecture dependent and ugly*)
let
get_fp_of_arch
arch
=
match
arch
with
...
...
@@ -91,6 +91,6 @@ let check_subfunction prog proj tid_map sub =
end
)
end
end
)
let
check_cwe
prog
proj
tid_map
symbol_names
=
let
check_cwe
prog
proj
tid_map
symbol_names
_
=
Seq
.
iter
(
Term
.
enum
sub_t
prog
)
~
f
:
(
fun
sub
->
check_subfunction
prog
proj
tid_map
sub
)
src/checkers/cwe_457.mli
View file @
41b84a41
...
...
@@ -4,4 +4,4 @@ See https://cwe.mitre.org/data/definitions/457.html for detailed description. *)
val
name
:
string
val
version
:
string
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
unit
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
string
list
->
unit
src/checkers/cwe_467.ml
View file @
41b84a41
open
Core_kernel
.
Std
open
Bap
.
Std
open
Symbol_utils
open
Symbol_utils
let
name
=
"CWE467"
let
version
=
"0.1"
let
get_pointer_size
arch
=
Size
.
in_bytes
@@
Arch
.
addr_size
arch
Size
.
in_bytes
@@
Arch
.
addr_size
arch
let
check_input_is_pointer_size
proj
prog
sub
blk
jmp
tid_map
symbols
=
Seq
.
iter
(
Term
.
enum
def_t
blk
)
~
f
:
(
fun
d
->
match
Exp
.
eval
@@
Def
.
rhs
d
with
...
...
@@ -23,11 +23,11 @@ let check_input_is_pointer_size proj prog sub blk jmp tid_map symbols =
end
|
_
->
()
)
let
check_cwe
prog
proj
tid_map
symbol_names
=
let
check_cwe
prog
proj
tid_map
symbol_names
_
=
match
symbol_names
with
|
hd
::
[]
->
let
symbols
=
Symbol_utils
.
build_symbols
hd
prog
in
let
symbols
=
Symbol_utils
.
build_symbols
hd
prog
in
let
calls
=
call_finder
#
run
prog
[]
in
let
relevant_calls
=
filter_calls_to_symbols
calls
symbols
in
check_calls
relevant_calls
prog
proj
tid_map
symbols
check_input_is_pointer_size
...
...
src/checkers/cwe_467.mli
View file @
41b84a41
...
...
@@ -2,11 +2,11 @@
In a nutshell, it before a function call to symbols like malloc and memmove, which
take a size parameter and a pointer to data as input, if not accidentally the size
of the pointer instead of the data is passed. This can have severe consequences.
The check is quite basic: it checks if before the call an immediate value that
The check is quite basic: it checks if before the call an immediate value that
equals the size of a pointer (e.g. 4 bytes on x86) is referenced (e.g. pushed
onto the stack).The symbols are configurable in config.json.
See https://cwe.mitre.org/data/definitions/467.html for detailed description. *)
val
name
:
string
val
version
:
string
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
unit
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
string
list
->
unit
src/checkers/cwe_476.ml
View file @
41b84a41
This diff is collapsed.
Click to expand it.
src/checkers/cwe_476.mli
View file @
41b84a41
(** This module implements a check for CWE-476 (NULL Pointer Dereference).
It checks if the result of a function that may return a NULL value is checked immediately
for NULL. The symbols are configurable in config.json.
See https://cwe.mitre.org/data/definitions/476.html for detailed description. *)
val
name
:
string
It checks if the result of a function that may return a NULL value is checked
for NULL before any memory gets accessed using the return values. The symbols
are configurable in config.json. See https://cwe.mitre.org/data/definitions/476.html
for detailed description.
Parameters:
- strict_call_policy={true, false}: Determines behaviour on call and return instructions.
If false, we assume that the callee, resp. the caller on a return instruction,
checks all unchecked values still contained in the registers. If true, every
unchecked value on a call or return instruction gets reported.
- max_steps=<num>: Max number of steps for the dataflow fixpoint algorithm.
Notes: The check relies on Bap-generated stubs to identify return registers of the
checked functions. Therefore it only works for functions for which Bap generates
these stubs. *)
val
name
:
string
val
version
:
string
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
unit
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
string
list
->
unit
src/checkers/cwe_676.ml
View file @
41b84a41
...
...
@@ -35,7 +35,7 @@ let resolve_symbols prog symbols =
Seq
.
filter
~
f
:
(
fun
s
->
List
.
exists
~
f
:
(
fun
x
->
x
=
Sub
.
name
s
)
symbols
)
let
check_cwe
prog
proj
tid_map
symbol_names
=
let
check_cwe
prog
proj
tid_map
symbol_names
_
=
match
symbol_names
with
|
hd
::
[]
->
let
subfunctions
=
Term
.
enum
sub_t
prog
in
...
...
@@ -43,4 +43,3 @@ let check_cwe prog proj tid_map symbol_names =
get_calls_to_symbols
cg
subfunctions
(
resolve_symbols
prog
hd
)
|>
print_calls
~
tid_map
:
tid_map
|
_
->
failwith
"[CWE676] symbol_names not as expected"
src/checkers/cwe_676.mli
View file @
41b84a41
...
...
@@ -5,4 +5,4 @@ See https://cwe.mitre.org/data/definitions/676.html for detailed description. *)
val
name
:
string
val
version
:
string
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
unit
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
string
list
->
unit
src/checkers/cwe_782.ml
View file @
41b84a41
...
...
@@ -14,6 +14,6 @@ let handle_sub sub program tid_map symbols =
(
Address_translation
.
translate_tid_to_assembler_address_string
(
Term
.
tid
sub
)
tid_map
)
else
()
let
check_cwe
program
proj
tid_map
symbols
=
let
check_cwe
program
proj
tid_map
symbols
_
=
Seq
.
iter
(
Term
.
enum
sub_t
program
)
~
f
:
(
fun
s
->
handle_sub
s
program
tid_map
symbols
)
src/checkers/cwe_782.mli
View file @
41b84a41
...
...
@@ -4,4 +4,4 @@ https://cwe.mitre.org/data/definitions/782.html *)
val
name
:
string
val
version
:
string
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
unit
val
check_cwe
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
string
list
->
unit
src/config.json
View file @
41b84a41
...
...
@@ -95,6 +95,10 @@
"CWE476"
:
{
"_comment"
:
"any function that possibly returns a NULL value."
,
"_comment1"
:
"included functions of the following libs: stdlib.h, locale.h, stdio.h, cstring.h, wchar.h"
,
"parameters"
:
[
"strict_call_policy=true"
,
"max_steps=100"
],
"symbols"
:
[
"malloc"
,
"calloc"
,
...
...
src/cwe_checker.ml
View file @
41b84a41
...
...
@@ -7,50 +7,54 @@ open Yojson.Basic.Util
include
Self
()
type
cwe_module
=
{
cwe_func
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
unit
;
cwe_func
:
Bap
.
Std
.
program
Bap
.
Std
.
term
->
Bap
.
Std
.
project
->
Bap
.
Std
.
word
Bap
.
Std
.
Tid
.
Map
.
t
->
string
list
list
->
string
list
->
unit
;
name
:
string
;
version
:
string
;
requires_pairs
:
bool
;
has_parameters
:
bool
;
}
let
known_modules
=
[{
cwe_func
=
Cwe_190
.
check_cwe
;
name
=
Cwe_190
.
name
;
version
=
Cwe_190
.
version
;
requires_pairs
=
false
};
{
cwe_func
=
Cwe_215
.
check_cwe
;
name
=
Cwe_215
.
name
;
version
=
Cwe_215
.
version
;
requires_pairs
=
false
};
{
cwe_func
=
Cwe_243
.
check_cwe
;
name
=
Cwe_243
.
name
;
version
=
Cwe_243
.
version
;
requires_pairs
=
true
};
{
cwe_func
=
Cwe_248
.
check_cwe
;
name
=
Cwe_248
.
name
;
version
=
Cwe_248
.
version
;
requires_pairs
=
false
};
{
cwe_func
=
Cwe_332
.
check_cwe
;
name
=
Cwe_332
.
name
;
version
=
Cwe_332
.
version
;
requires_pairs
=
true
};
{
cwe_func
=
Cwe_367
.
check_cwe
;
name
=
Cwe_367
.
name
;
version
=
Cwe_367
.
version
;
requires_pairs
=
true
};
{
cwe_func
=
Cwe_426
.
check_cwe
;
name
=
Cwe_426
.
name
;
version
=
Cwe_426
.
version
;
requires_pairs
=
false
};
{
cwe_func
=
Cwe_457
.
check_cwe
;
name
=
Cwe_457
.
name
;
version
=
Cwe_457
.
version
;
requires_pairs
=
false
};
{
cwe_func
=
Cwe_467
.
check_cwe
;
name
=
Cwe_467
.
name
;
version
=
Cwe_467
.
version
;
requires_pairs
=
false
};
{
cwe_func
=
Cwe_476
.
check_cwe
;
name
=
Cwe_476
.
name
;
version
=
Cwe_476
.
version
;
requires_pairs
=
false
};
{
cwe_func
=
Cwe_676
.
check_cwe
;
name
=
Cwe_676
.
name
;
version
=
Cwe_676
.
version
;
requires_pairs
=
false
};
{
cwe_func
=
Cwe_782
.
check_cwe
;
name
=
Cwe_782
.
name
;
version
=
Cwe_782
.
version
;
requires_pairs
=
false
}]
let
known_modules
=
[{
cwe_func
=
Cwe_190
.
check_cwe
;
name
=
Cwe_190
.
name
;
version
=
Cwe_190
.
version
;
requires_pairs
=
false
;
has_parameters
=
false
};
{
cwe_func
=
Cwe_215
.
check_cwe
;
name
=
Cwe_215
.
name
;
version
=
Cwe_215
.
version
;
requires_pairs
=
false
;
has_parameters
=
false
};
{
cwe_func
=
Cwe_243
.
check_cwe
;
name
=
Cwe_243
.
name
;
version
=
Cwe_243
.
version
;
requires_pairs
=
true
;
has_parameters
=
false
};
{
cwe_func
=
Cwe_248
.
check_cwe
;
name
=
Cwe_248
.
name
;
version
=
Cwe_248
.
version
;
requires_pairs
=
false
;
has_parameters
=
false
};
{
cwe_func
=
Cwe_332
.
check_cwe
;
name
=
Cwe_332
.
name
;
version
=
Cwe_332
.
version
;
requires_pairs
=
true
;
has_parameters
=
false
};
{
cwe_func
=
Cwe_367
.
check_cwe
;
name
=
Cwe_367
.
name
;
version
=
Cwe_367
.
version
;
requires_pairs
=
true
;
has_parameters
=
false
};
{
cwe_func
=
Cwe_426
.
check_cwe
;
name
=
Cwe_426
.
name
;
version
=
Cwe_426
.
version
;
requires_pairs
=
false
;
has_parameters
=
false
};
{
cwe_func
=
Cwe_457
.
check_cwe
;
name
=
Cwe_457
.
name
;
version
=
Cwe_457
.
version
;
requires_pairs
=
false
;
has_parameters
=
false
};
{
cwe_func
=
Cwe_467
.
check_cwe
;
name
=
Cwe_467
.
name
;
version
=
Cwe_467
.
version
;
requires_pairs
=
false
;
has_parameters
=
false
};
{
cwe_func
=
Cwe_476
.
check_cwe
;
name
=
Cwe_476
.
name
;
version
=
Cwe_476
.
version
;
requires_pairs
=
false
;
has_parameters
=
true
};
{
cwe_func
=
Cwe_676
.
check_cwe
;
name
=
Cwe_676
.
name
;
version
=
Cwe_676
.
version
;
requires_pairs
=
false
;
has_parameters
=
false
};
{
cwe_func
=
Cwe_782
.
check_cwe
;
name
=
Cwe_782
.
name
;
version
=
Cwe_782
.
version
;
requires_pairs
=
false
;
has_parameters
=
false
}]
let
build_version_sexp
()
=
let
build_version_sexp
()
=
List
.
map
known_modules
~
f
:
(
fun
cwe
->
Format
.
sprintf
"(
\"
%s
\"
\"
%s
\"
)"
cwe
.
name
cwe
.
version
)
|>
String
.
concat
~
sep
:
" "
let
print_module_versions
()
=
Log_utils
.
info
"[cwe_checker] module_versions: (%s)"
(
build_version_sexp
()
)
let
execute_cwe_module
cwe
json
program
project
tid_address_map
=
let
parameters
=
match
cwe
.
has_parameters
with
|
false
->
[]
|
true
->
Json_utils
.
get_parameter_list_from_json
json
cwe
.
name
in
if
cwe
.
requires_pairs
=
true
then
begin
let
symbol_pairs
=
Json_utils
.
get_symbol_lists_from_json
json
cwe
.
name
in
cwe
.
cwe_func
program
project
tid_address_map
symbol_pairs
let
symbol_pairs
=
Json_utils
.
get_symbol_lists_from_json
json
cwe
.
name
in
cwe
.
cwe_func
program
project
tid_address_map
symbol_pairs
parameters
end
else
begin
let
symbols
=
Json_utils
.
get_symbols_from_json
json
cwe
.
name
in
cwe
.
cwe_func
program
project
tid_address_map
[
symbols
]
let
symbols
=
Json_utils
.
get_symbols_from_json
json
cwe
.
name
in
cwe
.
cwe_func
program
project
tid_address_map
[
symbols
]
parameters
end
let
partial_run
project
config
modules
=
let
program
=
Project
.
program
project
in
let
program
=
Project
.
program
project
in
let
tid_address_map
=
Address_translation
.
generate_tid_map
program
in
let
json
=
Yojson
.
Basic
.
from_file
config
in
let
json
=
Yojson
.
Basic
.
from_file
config
in
Log_utils
.
info
"[cwe_checker] Just running the following analyses: %s."
modules
;
List
.
iter
(
String
.
split
modules
~
on
:
'
,
'
)
~
f
:
(
fun
cwe
->
try
begin
...
...
@@ -59,15 +63,15 @@ let partial_run project config modules =
execute_cwe_module
cwe_mod
json
program
project
tid_address_map
end
with
Not_found
->
failwith
"[CWE_CHECKER] Unknown CWE module"
)
let
full_run
project
config
=
let
full_run
project
config
=
let
program
=
Project
.
program
project
in
let
tid_address_map
=
Address_translation
.
generate_tid_map
program
in
let
json
=
Yojson
.
Basic
.
from_file
config
in
let
json
=
Yojson
.
Basic
.
from_file
config
in
begin
List
.
iter
known_modules
~
f
:
(
fun
cwe
->
execute_cwe_module
cwe
json
program
project
tid_address_map
)
end
let
main
config
module_versions
partial_update
project
=
Log_utils
.
set_log_level
Log_utils
.
DEBUG
;
Log_utils
.
set_output
stdout
;
...
...
@@ -89,7 +93,7 @@ let main config module_versions partial_update project =
partial_run
project
config
partial_update
end
end
module
Cmdline
=
struct
open
Config
let
config
=
param
string
"config"
~
doc
:
"Path to configuration file."
...
...
src/utils/json_utils.ml
View file @
41b84a41
...
...
@@ -23,3 +23,10 @@ let get_symbol_lists_from_json json cwe =
|>
filter_member
"pairs"
|>
flatten
|>
List
.
map
~
f
:
(
fun
l
->
List
.
map
(
to_list
l
)
~
f
:
to_string
)
let
get_parameter_list_from_json
json
cwe
=
[
json
]
|>
filter_member
cwe
|>
filter_member
"parameters"
|>
flatten
|>
List
.
map
~
f
:
to_string
src/utils/json_utils.mli
View file @
41b84a41
...
...
@@ -2,3 +2,4 @@
val
get_symbol_lists_from_json
:
Yojson
.
Basic
.
json
->
string
->
string
list
list
val
get_symbols_from_json
:
Yojson
.
Basic
.
json
->
string
->
string
list
val
get_parameter_list_from_json
:
Yojson
.
Basic
.
json
->
string
->
string
list
test/artificial_samples/cwe_476.c
View file @
41b84a41
#include <stdlib.h>
void
func1
(){
void
*
data
=
malloc
(
20
);
void
*
data
=
malloc
(
20
000
);
if
(
data
==
NULL
){
exit
(
42
);
}
...
...
@@ -9,13 +9,14 @@ void func1(){
}
void
func2
(){
void
*
data
=
malloc
(
20
);
int
*
data
=
malloc
(
200000
);
printf
(
"%i"
,
data
[
0
]);
free
(
data
);
}
}
void
main
()
{
func1
();
func2
();
}
test/artificial_samples/makefile
View file @
41b84a41
...
...
@@ -10,114 +10,117 @@ CPP_ARM=arm-linux-gnueabi-g++-5
CPP_MIPS
=
mips-linux-gnu-g++-5
CPP_PPC
=
powerpc-linux-gnu-g++-5
CFLAGS_X64
=
-O0
-g
-fno-stack-protector
-std
=
c11
CFLAGS_X86
=
-O0
-g
-m32
-fno-stack-protector
-std
=
c11
CFLAGS_ARM
=
-O0
-g
-fno-stack-protector
-std
=
c11
CFLAGS_MIPS
=
-O0
-g
-fno-stack-protector
-std
=
c11
CFLAGS_PPC
=
-O0
-g
-fno-stack-protector
-std
=
c11
CPPFLAGS_X64
=
-O0
-g
-fno-stack-protector
CPPFLAGS_X86
=
-O0
-g
-m32
-fno-stack-protector
CPPFLAGS_ARM
=
-O0
-g
-fno-stack-protector
CPPFLAGS_MIPS
=
-O0
-g
-fno-stack-protector
CPPFLAGS_PPC
=
-O0
-g
-fno-stack-protector
CFLAGS_X64
=
-g
-fno-stack-protector
-std
=
c11
CFLAGS_X86
=
-g
-m32
-fno-stack-protector
-std
=
c11
CFLAGS_ARM
=
-g
-fno-stack-protector
-std
=
c11
CFLAGS_MIPS
=
-g
-fno-stack-protector
-std
=
c11
CFLAGS_PPC
=
-g
-fno-stack-protector
-std
=
c11
CPPFLAGS_X64
=
-g
-fno-stack-protector
CPPFLAGS_X86
=
-g
-m32
-fno-stack-protector
CPPFLAGS_ARM
=
-g
-fno-stack-protector
CPPFLAGS_MIPS
=
-g
-fno-stack-protector
CPPFLAGS_PPC
=
-g
-fno-stack-protector
OPTIMIZE
=
-O3
NO_OPTIMIZE
=
-O0
define
compile_x64
@echo "Compiling x64 target
:
" $(1)
$(CC_x64)
$(CFLAGS_X64)
-o
build/
$
(
1
)
_x64.out
$
(
1
)
.c
execstack
-s
build/
$
(
1
)
_x64.out
$(CC_x64)
$(CFLAGS_X64)
$
(
2
)
-o
build/
$
(
1
)
_x64.out
$
(
1
)
.c
execstack
-s
build/
$
(
1
)
_x64.out
endef
define
compile_x64_cpp
@echo "Compiling x64 target
:
" $(1)
$(CPP_x64)
$(CPPFLAGS_X64)
-o
build/
$
(
1
)
_x64.out
$
(
1
)
.cpp
$(CPP_x64)
$(CPPFLAGS_X64)
$
(
2
)
-o
build/
$
(
1
)
_x64.out
$
(
1
)
.cpp
execstack
-s
build/
$
(
1
)
_x64.out
endef
define
compile_x86
@echo "Compiling x86 target
:
" $(1)
$(CC_X86)
$(CFLAGS_X86)
-o
build/
$
(
1
)
_x86.out
$
(
1
)
.c
$(CC_X86)
$(CFLAGS_X86)
$
(
2
)
-o
build/
$
(
1
)
_x86.out
$
(
1
)
.c
execstack
-s
build/
$
(
1
)
_x86.out
endef
define
compile_x86_cpp
@echo "Compiling x86 target
:
" $(1)
$(CPP_X86)
$(CPPFLAGS_X86)
-o
build/
$
(
1
)
_x86.out
$
(
1
)
.cpp
$(CPP_X86)
$(CPPFLAGS_X86)
$
(
2
)
-o
build/
$
(
1
)
_x86.out
$
(
1
)
.cpp
execstack
-s
build/
$
(
1
)
_x86.out
endef
define
compile_mips
@echo "Compiling mips target
:
" $(1)
$(CC_MIPS)
$(CFLAGS_MIPS)
-o
build/
$
(
1
)
_mips.out
$
(
1
)
.c
$(CC_MIPS)
$(CFLAGS_MIPS)
$
(
2
)
-o
build/
$
(
1
)
_mips.out
$
(
1
)
.c
execstack
-s
build/
$
(
1
)
_mips.out
endef
define
compile_mips_cpp
@echo "Compiling mips target
:
" $(1)
$(CPP_MIPS)
$(CPPFLAGS_MIPS)
-o
build/
$
(
1
)
_mips.out
$
(
1
)
.cpp
$(CPP_MIPS)
$(CPPFLAGS_MIPS)
$
(
2
)
-o
build/
$
(
1
)
_mips.out
$
(
1
)
.cpp
execstack
-s
build/
$
(
1
)
_mips.out
endef
define
compile_arm
@echo "Compiling arm target
:
" $(1)
$(CC_ARM)
$(CFLAGS_ARM)
-o
build/
$
(
1
)
_arm.out
$
(
1
)
.c
$(CC_ARM)
$(CFLAGS_ARM)
$
(
2
)
-o
build/
$
(
1
)
_arm.out
$
(
1
)
.c
execstack
-s
build/
$
(
1
)
_arm.out
endef
define
compile_arm_cpp
@echo "Compiling arm target
:
" $(1)
$(CPP_ARM)
$(CPPFLAGS_ARM)
-o
build/
$
(
1
)
_arm.out
$
(
1
)
.cpp
$(CPP_ARM)
$(CPPFLAGS_ARM)
$
(
2
)
-o
build/
$
(
1
)
_arm.out
$
(
1
)
.cpp
execstack
-s
build/
$
(
1
)
_arm.out
endef
define
compile_ppc
@echo "Compiling ppc target
:
" $(1)
$(CC_PPC)
$(CFLAGS_PPC)
-o
build/
$
(
1
)
_ppc.out
$
(
1
)
.c
$(CC_PPC)
$(CFLAGS_PPC)
$
(
2
)
-o
build/
$
(
1
)
_ppc.out
$
(
1
)
.c
execstack
-s
build/
$
(
1
)
_ppc.out
endef
define
compile_ppc_cpp
@echo "Compiling ppc target
:
" $(1)
$(CPP_PPC)
$(CPPFLAGS_PPC)
-o
build/
$
(
1
)
_ppc.out
$
(
1
)
.cpp
$(CPP_PPC)
$(CPPFLAGS_PPC)
$
(
2
)
-o
build/
$
(
1
)
_ppc.out
$
(
1
)
.cpp
execstack
-s
build/
$
(
1
)
_ppc.out
endef
define
compile_all
$(shell
mkdir
-p
"build"
)
$(call
compile_x64,$(1))
$(call
compile_x86,$(1))
$(call
compile_arm,$(1))
$(call
compile_mips,$(1))
$(call
compile_ppc,$(1))
$(call
compile_x64,$(1)
,$(2)
)
$(call
compile_x86,$(1)
,$(2)
)
$(call
compile_arm,$(1)
,$(2)
)
$(call
compile_mips,$(1)
,$(2)
)
$(call
compile_ppc,$(1)
,$(2)
)
endef
define
compile_all_cpp
$(shell
mkdir
-p
"build"
)
$(call
compile_x64_cpp,$(1))
$(call
compile_x86_cpp,$(1))
$(call
compile_arm_cpp,$(1))
$(call
compile_mips_cpp,$(1))
$(call
compile_ppc_cpp,$(1))
$(call
compile_x64_cpp,$(1)
,$(2)
)
$(call
compile_x86_cpp,$(1)
,$(2)
)
$(call
compile_arm_cpp,$(1)
,$(2)
)
$(call
compile_mips_cpp,$(1)
,$(2)
)
$(call
compile_ppc_cpp,$(1)
,$(2)
)
endef
all
:
$
(
call compile_all,c_constructs
)
$
(
call compile_all,cwe_190
)
$
(
call compile_all,cwe_243
)
$
(
call compile_all,cwe_243_clean
)
$
(
call compile_all_cpp,cwe_248
)
$
(
call compile_all,cwe_332
)
$
(
call compile_all,cwe_367
)
$
(
call compile_all,cwe_415
)
$
(
call compile_all,cwe_426
)
$
(
call compile_all,cwe_457
)
$
(
call compile_all,cwe_467
)
$
(
call compile_all,cwe_476
)
$
(
call compile_all,cwe_478
)
$
(
call compile_all,cwe_676
)
$
(
call compile_x64,cwe_782
)
$
(
call compile_all,arrays
)
$
(
call compile_all,memory_access
)
$
(
call compile_all,c_constructs
,
$(NO_OPTIMIZE)
)
$
(
call compile_all,cwe_190
,
$(NO_OPTIMIZE)
)
$
(
call compile_all,cwe_243
,
$(NO_OPTIMIZE)
)
$
(
call compile_all,cwe_243_clean
,
$(NO_OPTIMIZE)
)
$
(
call compile_all_cpp,cwe_248
,
$(NO_OPTIMIZE)
)
$
(
call compile_all,cwe_332
,
$(NO_OPTIMIZE)
)
$
(
call compile_all,cwe_367
,
$(NO_OPTIMIZE)
)
$
(
call compile_all,cwe_415
,
$(NO_OPTIMIZE)
)
$
(
call compile_all,cwe_426
,
$(NO_OPTIMIZE)
)
$
(
call compile_all,cwe_457
,
$(NO_OPTIMIZE)
)
$
(
call compile_all,cwe_467
,
$(NO_OPTIMIZE)
)
$
(
call compile_all,cwe_476
,
$(OPTIMIZE)
)
$
(
call compile_all,cwe_478
,
$(NO_OPTIMIZE)
)
$
(
call compile_all,cwe_676
,
$(NO_OPTIMIZE)
)
$
(
call compile_x64,cwe_782
,
$(NO_OPTIMIZE)
)
$
(
call compile_all,arrays
,
$(NO_OPTIMIZE)
)
$
(
call compile_all,memory_access
,
$(NO_OPTIMIZE)
)
clean
:
rm
-rf
build
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment