Skip to content

Commit 14cae20

Browse files
committed
Implement tests added in a3fe95
1 parent 634598f commit 14cae20

1 file changed

Lines changed: 48 additions & 0 deletions

File tree

tests/client/client-test.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,54 @@ def test_s_client_x509(self):
6060
self.assertIn("-----BEGIN CERTIFICATE-----", result.stdout,
6161
"Expected x509 PEM output not found")
6262

63+
class ShellInjectionTest(unittest.TestCase):
64+
"""Regression tests for shell command injection via hostname.
65+
66+
Applies to the WOLFSSL_USE_POPEN_HOST path where peer is concatenated
67+
into a popen() shell command. On other builds, getaddrinfo /
68+
gethostbyname reject these hostnames before any shell is involved,
69+
so the tests pass either way -- the injected command must never run.
70+
"""
71+
72+
INJECTION_PROBE = "clu_injection_probe.txt"
73+
74+
def setUp(self):
75+
if os.path.exists(self.INJECTION_PROBE):
76+
os.remove(self.INJECTION_PROBE)
77+
self.addCleanup(lambda: os.remove(self.INJECTION_PROBE)
78+
if os.path.exists(self.INJECTION_PROBE) else None)
79+
80+
def _assert_no_injection(self, peer, description):
81+
"""Run s_client with the given -connect peer and verify that the
82+
injected `touch` command did not execute."""
83+
subprocess.run(
84+
[WOLFSSL_BIN, "s_client", "-connect", peer],
85+
capture_output=True,
86+
stdin=subprocess.DEVNULL,
87+
timeout=30,
88+
)
89+
self.assertFalse(
90+
os.path.exists(self.INJECTION_PROBE),
91+
f"SECURITY FAILURE: command injection via hostname "
92+
f"({description})")
93+
94+
def test_semicolon_injection(self):
95+
"""evil.com;touch probe:443 must not execute the touch command."""
96+
self._assert_no_injection(
97+
f"evil.com;touch {self.INJECTION_PROBE}:443",
98+
"semicolon")
99+
100+
def test_command_substitution_injection(self):
101+
"""evil$(touch probe).com:443 must not execute the touch command."""
102+
self._assert_no_injection(
103+
f"evil$(touch {self.INJECTION_PROBE}).com:443",
104+
"command substitution")
105+
106+
def test_pipe_injection(self):
107+
"""evil.com|touch probe:443 must not execute the touch command."""
108+
self._assert_no_injection(
109+
f"evil.com|touch {self.INJECTION_PROBE}:443",
110+
"pipe")
63111

64112
if __name__ == "__main__":
65113
test_main()

0 commit comments

Comments
 (0)