fixed a stack overflow vulnerability with long command line args

This commit is contained in:
Gerhard Rieger 2010-10-03 11:36:50 +02:00
parent 07db31f7ac
commit 6340d5d2c8
3 changed files with 85 additions and 4 deletions

View file

@ -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: ####################### V 1.7.1.2:
corrections: corrections:

View file

@ -1,5 +1,5 @@
/* source: nestlex.c */ /* source: nestlex.c */
/* Copyright Gerhard Rieger 2006 */ /* Copyright Gerhard Rieger 2006-2010 */
/* Published under the GNU General Public License V.2, see file COPYING */ /* Published under the GNU General Public License V.2, see file COPYING */
/* a function for lexical scanning of nested character patterns */ /* 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; *out++ = c;
--*len; --*len;
if (len == 0) { if (*len == 0) {
*addr = in; *addr = in;
*token = out; *token = out;
return -1; /* output overflow */ return -1; /* output overflow */
@ -222,7 +222,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */
/* just a simple char */ /* just a simple char */
*out++ = c; *out++ = c;
--*len; --*len;
if (len == 0) { if (*len == 0) {
*addr = in; *addr = in;
*token = out; *token = out;
return -1; /* output overflow */ return -1; /* output overflow */

74
test.sh
View file

@ -10115,6 +10115,7 @@ fi
fi # NUMCOND fi # NUMCOND
;; ;;
esac esac
PORT=$((PORT+1))
N=$((N+1)) N=$((N+1))
@ -10167,6 +10168,76 @@ fi
fi # NUMCOND fi # NUMCOND
;; ;;
esac 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 </dev/null 1>&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 </dev/null 1>&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)) N=$((N+1))
@ -10276,7 +10347,7 @@ CMD1="$SOCAT $opts - client-address"
printf "test $F_n $TEST... " $N printf "test $F_n $TEST... " $N
$CMD0 >/dev/null 2>"${te}0" & $CMD0 >/dev/null 2>"${te}0" &
pid0=$! pid0=$!
wait<something>port $xy 1 wait<something>port $PORT 1
echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
rc1=$? rc1=$?
kill $pid0 2>/dev/null; wait kill $pid0 2>/dev/null; wait
@ -10294,4 +10365,5 @@ fi
fi # NUMCOND fi # NUMCOND
;; ;;
esac esac
PORT=$((PORT+1))
N=$((N+1)) N=$((N+1))