Skip to content

Commit d187c70

Browse files
committed
fix shell command injection
1 parent 9bdc4ae commit d187c70

2 files changed

Lines changed: 45 additions & 0 deletions

File tree

src/client/client.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,17 @@ static WC_INLINE void clu_build_addr(SOCKADDR_IN4_T* addr, SOCKADDR_IN6_T* ipv6,
147147
FILE* fp;
148148
char host_out[100];
149149
char cmd[100];
150+
const char* cp;
151+
152+
/* Validate hostname: only allow characters valid in DNS names
153+
* (RFC 1123) to prevent shell injection via popen(). */
154+
for (cp = peer; *cp != '\0'; cp++) {
155+
if (!isalnum((unsigned char)*cp) &&
156+
*cp != '.' && *cp != '-') {
157+
err_sys("invalid character in hostname");
158+
return;
159+
}
160+
}
150161

151162
XSTRNCPY(cmd, "host ", 6);
152163
XSTRNCAT(cmd, peer, 99 - XSTRLEN(cmd));

tests/client/client-test.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,39 @@ fi
2525

2626
rm tmp.crt
2727

28+
# Regression tests: shell injection via hostname must not execute injected command.
29+
# Applies to the WOLFSSL_USE_POPEN_HOST path where peer is concatenated into a
30+
# popen() shell command. On other builds, getaddrinfo/gethostbyname reject
31+
# these hostnames before any shell is involved, so the tests pass either way.
32+
INJFILE="clu_injection_probe.txt"
33+
rm -f "$INJFILE"
34+
35+
# Semicolon: "evil.com;touch clu_injection_probe.txt" passed as peer
36+
./wolfssl s_client -connect 'evil.com;touch clu_injection_probe.txt:443' \
37+
2>/dev/null
38+
if [ -f "$INJFILE" ]; then
39+
echo "SECURITY FAILURE: command injection via hostname (semicolon)"
40+
rm -f "$INJFILE"
41+
exit 99
42+
fi
43+
44+
# Command substitution: "$(touch clu_injection_probe.txt)" passed as peer
45+
./wolfssl s_client -connect '$(touch clu_injection_probe.txt):443' \
46+
2>/dev/null
47+
if [ -f "$INJFILE" ]; then
48+
echo "SECURITY FAILURE: command injection via hostname (command substitution)"
49+
rm -f "$INJFILE"
50+
exit 99
51+
fi
52+
53+
# Pipe: "evil.com|touch clu_injection_probe.txt" passed as peer
54+
./wolfssl s_client -connect 'evil.com|touch clu_injection_probe.txt:443' \
55+
2>/dev/null
56+
if [ -f "$INJFILE" ]; then
57+
echo "SECURITY FAILURE: command injection via hostname (pipe)"
58+
rm -f "$INJFILE"
59+
exit 99
60+
fi
61+
2862
echo "Done"
2963
exit 0

0 commit comments

Comments
 (0)