up
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
id: "c-guarded-system:001"
|
||||
language: c
|
||||
project: guarded-system
|
||||
version: "1.0.0"
|
||||
description: "Command execution guarded by ALLOW_CMD flag (default unreachable)."
|
||||
entrypoints:
|
||||
- "main(argv)"
|
||||
sinks:
|
||||
- id: "GuardedSystem::main"
|
||||
path: "src/main.c::main"
|
||||
kind: "command"
|
||||
location:
|
||||
file: src/main.c
|
||||
line: 26
|
||||
notes: "system() only runs when ALLOW_CMD=1."
|
||||
environment:
|
||||
os_image: "gcc:13-bookworm"
|
||||
runtime:
|
||||
gcc: "13"
|
||||
source_date_epoch: 1730000000
|
||||
build:
|
||||
command: "./build/build.sh"
|
||||
source_date_epoch: 1730000000
|
||||
outputs:
|
||||
artifact_path: outputs/binary.tar.gz
|
||||
coverage_path: outputs/coverage.json
|
||||
traces_path: outputs/traces/traces.json
|
||||
test:
|
||||
command: "./tests/run-tests.sh"
|
||||
expected_coverage:
|
||||
- outputs/coverage.json
|
||||
expected_traces:
|
||||
- outputs/traces/traces.json
|
||||
ground_truth:
|
||||
summary: "Without ALLOW_CMD, the system() sink remains unreachable; with ALLOW_CMD=1, it executes."
|
||||
evidence_files:
|
||||
- "../../../benchmark/truth/c-guarded-system.json"
|
||||
@@ -0,0 +1,36 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static int run_guarded(const char *user_cmd)
|
||||
{
|
||||
const char *allow = getenv("ALLOW_CMD");
|
||||
if (allow == NULL || strcmp(allow, "1") != 0)
|
||||
{
|
||||
puts("command blocked (ALLOW_CMD not set)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char cmd[256];
|
||||
snprintf(cmd, sizeof(cmd), "echo START && %s && echo END", user_cmd);
|
||||
return system(cmd);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "usage: %s <command>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rc = run_guarded(argv[1]);
|
||||
if (rc != 0)
|
||||
{
|
||||
fprintf(stderr, "command failed\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
puts("done");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
OUT="${ROOT}/outputs"
|
||||
APP="${OUT}/app"
|
||||
|
||||
if [[ ! -x "${APP}" ]]; then
|
||||
echo "binary missing; run build first" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tmp="$(mktemp -d)"
|
||||
trap 'rm -rf "${tmp}"' EXIT
|
||||
|
||||
# Run without ALLOW_CMD: should be blocked
|
||||
BLOCK_FILE="${tmp}/blocked.txt"
|
||||
ALLOW_CMD=0 "${APP}" "echo SHOULD_NOT_RUN" > "${BLOCK_FILE}"
|
||||
if grep -q "SHOULD_NOT_RUN" "${BLOCK_FILE}"; then
|
||||
echo "command unexpectedly executed when ALLOW_CMD=0" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Run with ALLOW_CMD set: should execute
|
||||
ALLOW_FILE="${tmp}/allow.txt"
|
||||
ALLOW_CMD=1 "${APP}" "echo ALLOWED" > "${ALLOW_FILE}"
|
||||
if ! grep -q "ALLOWED" "${ALLOW_FILE}"; then
|
||||
echo "command did not execute when ALLOW_CMD=1" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "tests passed"
|
||||
@@ -0,0 +1,37 @@
|
||||
id: "c-memcpy-overflow:001"
|
||||
language: c
|
||||
project: memcpy-overflow
|
||||
version: "1.0.0"
|
||||
description: "Potential overflow: user-controlled length passed to memcpy without bounds."
|
||||
entrypoints:
|
||||
- "process_buffer(len)"
|
||||
sinks:
|
||||
- id: "Overflow::process"
|
||||
path: "src/main.c::process"
|
||||
kind: "memory"
|
||||
location:
|
||||
file: src/main.c
|
||||
line: 23
|
||||
notes: "memcpy uses attacker-controlled length; reachable via process_buffer."
|
||||
environment:
|
||||
os_image: "gcc:13-bookworm"
|
||||
runtime:
|
||||
gcc: "13"
|
||||
source_date_epoch: 1730000000
|
||||
build:
|
||||
command: "./build/build.sh"
|
||||
source_date_epoch: 1730000000
|
||||
outputs:
|
||||
artifact_path: outputs/binary.tar.gz
|
||||
coverage_path: outputs/coverage.json
|
||||
traces_path: outputs/traces/traces.json
|
||||
test:
|
||||
command: "./tests/run-tests.sh"
|
||||
expected_coverage:
|
||||
- outputs/coverage.json
|
||||
expected_traces:
|
||||
- outputs/traces/traces.json
|
||||
ground_truth:
|
||||
summary: "Calling process_buffer with len>256 drives memcpy with attacker length (reachable)."
|
||||
evidence_files:
|
||||
- "../../../benchmark/truth/c-memcpy-overflow.json"
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static int process(size_t len)
|
||||
{
|
||||
char src[512];
|
||||
char dst[128];
|
||||
memset(src, 'A', sizeof(src));
|
||||
memset(dst, 0, sizeof(dst));
|
||||
|
||||
// Attacker-controlled length; no bounds check.
|
||||
memcpy(dst, src, len);
|
||||
|
||||
// Return first byte to keep optimizer from removing the copy.
|
||||
return dst[0];
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "usage: %s <len>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *end = NULL;
|
||||
long len = strtol(argv[1], &end, 10);
|
||||
if (end == argv[1] || len < 0)
|
||||
{
|
||||
fprintf(stderr, "invalid length\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int r = process((size_t)len);
|
||||
printf("result=%d\n", r);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
OUT="${ROOT}/outputs"
|
||||
APP="${OUT}/app"
|
||||
|
||||
if [[ ! -x "${APP}" ]]; then
|
||||
echo "binary missing; run build first" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tmp="$(mktemp -d)"
|
||||
trap 'rm -rf "${tmp}"' EXIT
|
||||
|
||||
# Trigger overflow-prone copy with large length; expect exit code 0
|
||||
RUN_OUT="${tmp}/run.out"
|
||||
"${APP}" "300" > "${RUN_OUT}"
|
||||
|
||||
if ! grep -q "result=" "${RUN_OUT}"; then
|
||||
echo "expected output missing" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "tests passed"
|
||||
37
bench/reachability-benchmark/cases/c/unsafe-system/case.yaml
Normal file
37
bench/reachability-benchmark/cases/c/unsafe-system/case.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
id: "c-unsafe-system:001"
|
||||
language: c
|
||||
project: unsafe-system
|
||||
version: "1.0.0"
|
||||
description: "Command injection sink: user input passed directly to system()."
|
||||
entrypoints:
|
||||
- "main(argv)"
|
||||
sinks:
|
||||
- id: "UnsafeSystem::main"
|
||||
path: "src/main.c::main"
|
||||
kind: "command"
|
||||
location:
|
||||
file: src/main.c
|
||||
line: 21
|
||||
notes: "Untrusted input concatenated into shell command and executed."
|
||||
environment:
|
||||
os_image: "gcc:13-bookworm"
|
||||
runtime:
|
||||
gcc: "13"
|
||||
source_date_epoch: 1730000000
|
||||
build:
|
||||
command: "./build/build.sh"
|
||||
source_date_epoch: 1730000000
|
||||
outputs:
|
||||
artifact_path: outputs/binary.tar.gz
|
||||
coverage_path: outputs/coverage.json
|
||||
traces_path: outputs/traces/traces.json
|
||||
test:
|
||||
command: "./tests/run-tests.sh"
|
||||
expected_coverage:
|
||||
- outputs/coverage.json
|
||||
expected_traces:
|
||||
- outputs/traces/traces.json
|
||||
ground_truth:
|
||||
summary: "Running with argument 'echo OK' executes system() with user-controlled payload."
|
||||
evidence_files:
|
||||
- "../../../benchmark/truth/c-unsafe-system.json"
|
||||
@@ -0,0 +1,30 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static int run_command(const char *user_cmd)
|
||||
{
|
||||
char cmd[256];
|
||||
// Deliberately unsafe: user input embedded directly.
|
||||
snprintf(cmd, sizeof(cmd), "echo START && %s && echo END", user_cmd);
|
||||
return system(cmd);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "usage: %s <command>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rc = run_command(argv[1]);
|
||||
if (rc != 0)
|
||||
{
|
||||
fprintf(stderr, "command failed\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
puts("done");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
OUT="${ROOT}/outputs"
|
||||
APP="${OUT}/app"
|
||||
|
||||
if [[ ! -x "${APP}" ]]; then
|
||||
echo "binary missing; run build first" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tmp="$(mktemp -d)"
|
||||
trap 'rm -rf "${tmp}"' EXIT
|
||||
|
||||
# Run command and capture output deterministically
|
||||
pushd "${tmp}" >/dev/null
|
||||
"${APP}" "echo OK" > "${tmp}/run.out"
|
||||
popd >/dev/null
|
||||
|
||||
if ! grep -q "OK" "${tmp}/run.out"; then
|
||||
echo "expected command output not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "tests passed"
|
||||
Reference in New Issue
Block a user