From 6340d5d2c81e55e61522c4b40a6cdd5c39738cc6 Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Sun, 3 Oct 2010 11:36:50 +0200 Subject: [PATCH] fixed a stack overflow vulnerability with long command line args --- CHANGES | 9 +++++++ nestlex.c | 6 ++--- test.sh | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 85 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 39cd3ee..96717ba 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,13 @@ +security: + fixed a stack overflow vulnerability that occurred when command + line arguments (whole addresses, host names, file names) were longer + than 512 bytes. + Note that this could only be exploited when an attacker was able to + inject data into socat's command line. + Full credits to Felix Gröbert, Google Security Team, for finding and + reporting this issue + ####################### V 1.7.1.2: corrections: diff --git a/nestlex.c b/nestlex.c index 0f0b7c8..97778bc 100644 --- a/nestlex.c +++ b/nestlex.c @@ -1,5 +1,5 @@ /* source: nestlex.c */ -/* Copyright Gerhard Rieger 2006 */ +/* Copyright Gerhard Rieger 2006-2010 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* a function for lexical scanning of nested character patterns */ @@ -211,7 +211,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */ } *out++ = c; --*len; - if (len == 0) { + if (*len == 0) { *addr = in; *token = out; return -1; /* output overflow */ @@ -222,7 +222,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */ /* just a simple char */ *out++ = c; --*len; - if (len == 0) { + if (*len == 0) { *addr = in; *token = out; return -1; /* output overflow */ diff --git a/test.sh b/test.sh index d15d504..230d021 100755 --- a/test.sh +++ b/test.sh @@ -10115,6 +10115,7 @@ fi fi # NUMCOND ;; esac +PORT=$((PORT+1)) N=$((N+1)) @@ -10167,6 +10168,76 @@ fi fi # NUMCOND ;; esac +PORT=$((PORT+1)) +N=$((N+1)) + + +# socat up to 1.7.1.2 had a stack overflow vulnerability that occurred when +# command line arguments (whole addresses, host names, file names) were longer +# than 512 bytes. +NAME=HOSTNAMEOVFL +case "$TESTS" in +*%functions%*|*%bugs%*|*%security%*|*%socket%*|*%$NAME%*) +TEST="$NAME: stack overflow on overly long host name" +# provide a long host name to TCP-CONNECT and check socats exit code +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +da="test$N $(date) $RANDOM" +# prepare long data - perl might not be installed +rm -f "$td/terst$N.dat" +i=0; while [ $i -lt 64 ]; do echo -n "AAAAAAAAAAAAAAAA" >>"$td/test$N.dat"; i=$((i+1)); done +CMD0="$SOCAT $opts TCP-CONNECT:$(cat "$td/test$N.dat"):$PORT STDIO" +printf "test $F_n $TEST... " $N +$CMD0 &0 2>"${te}0" +rc0=$? +if [ $rc0 -lt 128 ] || [ $rc0 -eq 255 ]; then + $PRINTF "$OK\n" + numOK=$((numOK+1)) +else + $PRINTF "$FAILED\n" + echo "$CMD0" + cat "${te}0" + numFAIL=$((numFAIL+1)) +fi +fi # NUMCOND + ;; +esac +PORT=$((PORT+1)) +N=$((N+1)) + +# socat up to 1.7.1.2 had a stack overflow vulnerability that occurred when +# command line arguments (whole addresses, host names, file names) were longer +# than 512 bytes. +NAME=FILENAMEOVFL +case "$TESTS" in +*%functions%*|*%bugs%*|*%security%*|*%openssl%*|*%$NAME%*) +TEST="$NAME: stack overflow on overly long file name" +# provide a 600 bytes long key file option to SSL-CONNECT and check socats exit code +if ! eval $NUMCOND; then :; else +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +da="test$N $(date) $RANDOM" +i=0; while [ $i -lt 64 ]; do echo -n "AAAAAAAAAAAAAAAA" >>"$td/test$N.dat"; i=$((i+1)); done +CMD0="$SOCAT $opts OPENSSL:localhost:$PORT,key=$(cat "$td/test$N.dat") STDIO" +printf "test $F_n $TEST... " $N +$CMD0 &0 2>"${te}0" +rc0=$? +if [ $rc0 -lt 128 ] || [ $rc0 -eq 255 ]; then + $PRINTF "$OK\n" + numOK=$((numOK+1)) +else + $PRINTF "$FAILED\n" + echo "$CMD0" + cat "${te}0" + numFAIL=$((numFAIL+1)) +fi +fi # NUMCOND + ;; +esac +PORT=$((PORT+1)) N=$((N+1)) @@ -10276,7 +10347,7 @@ CMD1="$SOCAT $opts - client-address" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! -waitport $xy 1 +waitport $PORT 1 echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? kill $pid0 2>/dev/null; wait @@ -10294,4 +10365,5 @@ fi fi # NUMCOND ;; esac +PORT=$((PORT+1)) N=$((N+1))