mirror of
https://github.com/elicpeter/nyx.git
synced 2026-07-03 20:41:00 +02:00
refactor(dynamic): standardize shell commands across fixtures, add __NYX_SINK_HIT__ markers, improve PHP support
This commit is contained in:
parent
ca075a7141
commit
fe09986a25
32 changed files with 707 additions and 71 deletions
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
void UserService_run(const char *input, size_t len) {
|
||||
(void)len;
|
||||
/* Uses execve via fork; the shell never sees `input`. */
|
||||
/* Uses execve via fork; the shell never sees or echoes `input`. */
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
char *argv[] = { (char*)"/bin/echo", (char*)(input ? input : ""), NULL };
|
||||
execv("/bin/echo", argv);
|
||||
char *argv[] = { (char*)"/usr/bin/true", (char*)(input ? input : ""), NULL };
|
||||
execv("/usr/bin/true", argv);
|
||||
_exit(127);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
void UserService_run(const char *input, size_t len) {
|
||||
(void)len;
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "echo %s", input ? input : "");
|
||||
snprintf(buf, sizeof(buf), "true %s", input ? input : "");
|
||||
/* SINK: tainted input → system(3) */
|
||||
system(buf);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ public:
|
|||
void run(const std::string& input) {
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
const char* argv[] = { "/bin/echo", input.c_str(), nullptr };
|
||||
execv("/bin/echo", const_cast<char* const*>(argv));
|
||||
const char* argv[] = { "/usr/bin/true", input.c_str(), nullptr };
|
||||
execv("/usr/bin/true", const_cast<char* const*>(argv));
|
||||
_exit(127);
|
||||
}
|
||||
int status = 0;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ class UserService {
|
|||
public:
|
||||
UserService() = default;
|
||||
void run(const std::string& input) {
|
||||
std::string cmd = std::string("echo ") + input;
|
||||
std::string cmd = std::string("true ") + input;
|
||||
// SINK: tainted input → system(3)
|
||||
std::system(cmd.c_str());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ import "os/exec"
|
|||
type UserService struct{}
|
||||
|
||||
func (UserService) Run(input string) string {
|
||||
out, _ := exec.Command("/bin/echo", input).Output()
|
||||
out, _ := exec.Command("true", input).Output()
|
||||
return string(out)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@ type UserService struct{}
|
|||
|
||||
func (UserService) Run(input string) string {
|
||||
// SINK: tainted input → shell -c
|
||||
out, _ := exec.Command("sh", "-c", "echo "+input).Output()
|
||||
out, _ := exec.Command("sh", "-c", "true "+input).Output()
|
||||
return string(out)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,16 @@
|
|||
// Phase 19 (Track M.1) — class-method benign control for Java.
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
//
|
||||
// The payload is passed as an argv element to true(1), so no shell parses or
|
||||
// echoes marker bytes.
|
||||
public class Benign {
|
||||
public static class UserRepository {
|
||||
public UserRepository() {}
|
||||
|
||||
public void findByName(String name) throws SQLException {
|
||||
Connection c = DriverManager.getConnection("jdbc:sqlite::memory:");
|
||||
PreparedStatement ps = c.prepareStatement("SELECT id FROM users WHERE name = ?");
|
||||
ps.setString(1, name);
|
||||
ps.execute();
|
||||
ps.close();
|
||||
c.close();
|
||||
public void findByName(String name) throws Exception {
|
||||
Process p = new ProcessBuilder("/usr/bin/true", name)
|
||||
.redirectErrorStream(true)
|
||||
.start();
|
||||
p.waitFor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,22 @@
|
|||
// Phase 19 (Track M.1) — class-method vuln fixture for Java.
|
||||
//
|
||||
// UserRepository.findByName concatenates user input into a JDBC SQL
|
||||
// statement. Default constructor exists so the harness can build the
|
||||
// receiver without stubbing dependencies.
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.Statement;
|
||||
import java.sql.SQLException;
|
||||
// UserRepository.findByName concatenates user input into a shell command.
|
||||
// The nested class has a default constructor so the ClassMethod harness can
|
||||
// build the receiver reflectively.
|
||||
import java.io.InputStream;
|
||||
|
||||
public class Vuln {
|
||||
public static class UserRepository {
|
||||
public UserRepository() {}
|
||||
|
||||
public void findByName(String name) throws SQLException {
|
||||
Connection c = DriverManager.getConnection("jdbc:sqlite::memory:");
|
||||
Statement s = c.createStatement();
|
||||
// SINK: tainted concat into SQL
|
||||
String sql = "SELECT id FROM users WHERE name = '" + name + "'";
|
||||
s.execute(sql);
|
||||
s.close();
|
||||
c.close();
|
||||
public void findByName(String name) throws Exception {
|
||||
Process p = new ProcessBuilder("sh", "-c", "true " + name)
|
||||
.redirectErrorStream(true)
|
||||
.start();
|
||||
try (InputStream in = p.getInputStream()) {
|
||||
in.transferTo(System.out);
|
||||
}
|
||||
p.waitFor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
// Phase 19 (Track M.1) — class-method benign control for JavaScript.
|
||||
//
|
||||
// UserService.run routes the input through execFileSync with argv form so
|
||||
// the shell never interprets the string.
|
||||
// the shell never interprets the string or echoes marker bytes.
|
||||
'use strict';
|
||||
const { execFileSync } = require('child_process');
|
||||
|
||||
class UserService {
|
||||
constructor() {}
|
||||
run(input) {
|
||||
return execFileSync('/bin/echo', [input]).toString();
|
||||
return execFileSync('true', [input]).toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class UserService {
|
|||
constructor() {}
|
||||
run(input) {
|
||||
// SINK: untrusted input → shell
|
||||
return execSync('echo ' + input).toString();
|
||||
return execSync('true ' + input).toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@ class UserService {
|
|||
public function __construct() {}
|
||||
|
||||
public function run($input) {
|
||||
return shell_exec('echo ' . escapeshellarg($input));
|
||||
return shell_exec('true ' . escapeshellarg($input));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@ class UserService {
|
|||
|
||||
public function run($input) {
|
||||
// SINK: tainted input → shell.
|
||||
return shell_exec('echo ' . $input);
|
||||
return shell_exec('true ' . $input);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ class UserService
|
|||
end
|
||||
|
||||
def run(input)
|
||||
`echo #{Shellwords.escape(input)}`
|
||||
`true #{Shellwords.escape(input)}`
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@ class UserService
|
|||
|
||||
def run(input)
|
||||
# SINK: tainted input → shell
|
||||
`echo #{input}`
|
||||
`true #{input}`
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ pub struct UserService;
|
|||
|
||||
impl UserService {
|
||||
pub fn run(&self, input: &str) -> String {
|
||||
let out = std::process::Command::new("/bin/echo")
|
||||
let out = std::process::Command::new("true")
|
||||
.arg(input)
|
||||
.output()
|
||||
.expect("exec");
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ pub struct UserService;
|
|||
impl UserService {
|
||||
pub fn run(&self, input: &str) -> String {
|
||||
// SINK: tainted input → shell -c
|
||||
let cmd = format!("echo {}", input);
|
||||
let cmd = format!("true {}", input);
|
||||
let out = std::process::Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(&cmd)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
// Phase 19 (Track M.1) — class-method benign control for TypeScript.
|
||||
import { execFileSync } from 'child_process';
|
||||
'use strict';
|
||||
const { execFileSync } = require('child_process');
|
||||
|
||||
export class UserService {
|
||||
class UserService {
|
||||
constructor() {}
|
||||
run(input: string): string {
|
||||
return execFileSync('/bin/echo', [input]).toString();
|
||||
run(input) {
|
||||
return execFileSync('true', [input]).toString();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { UserService };
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
// Phase 19 (Track M.1) — class-method vuln fixture for TypeScript.
|
||||
//
|
||||
// UserService.run forwards user input directly to a shell. Default ctor.
|
||||
import { execSync } from 'child_process';
|
||||
// UserService.run forwards user input directly to a shell. The source
|
||||
// stays CommonJS-compatible because the harness stages TS fixtures as
|
||||
// entry.js for stock Node.
|
||||
'use strict';
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
export class UserService {
|
||||
class UserService {
|
||||
constructor() {}
|
||||
run(input: string): string {
|
||||
run(input) {
|
||||
// SINK: untrusted input flows into the shell
|
||||
return execSync('echo ' + input).toString();
|
||||
return execSync('true ' + input).toString();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { UserService };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue