mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
version 2.0.0-b5 - fixed READLINE buffer overflow
This commit is contained in:
parent
e3788fa8de
commit
2d24bc3157
4 changed files with 71 additions and 16 deletions
13
CHANGES
13
CHANGES
|
@ -1,4 +1,17 @@
|
|||
|
||||
####################### V 2.0.0-b5:
|
||||
|
||||
security:
|
||||
fixed a possible heap buffer overflow in the readline address. This bug
|
||||
could be exploited when all of the following conditions were met:
|
||||
1) one of the addresses is READLINE without the noprompt and without the
|
||||
prompt options.
|
||||
2) the other (almost arbitrary address) reads malicious data (which is
|
||||
then transferred by socat to READLINE).
|
||||
Workaround: when using the READLINE address apply option prompt or
|
||||
noprompt.
|
||||
Full credits to Johan Thillemann for finding and reporting this issue.
|
||||
|
||||
####################### V 2.0.0-b4:
|
||||
|
||||
security:
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
"2.0.0-b4"
|
||||
"2.0.0-b5"
|
||||
|
|
46
test.sh
46
test.sh
|
@ -1,6 +1,6 @@
|
|||
#! /bin/bash
|
||||
# source: test.sh
|
||||
# Copyright Gerhard Rieger 2001-2009
|
||||
# Copyright Gerhard Rieger 2001-2012
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# perform lots of tests on socat
|
||||
|
@ -10528,7 +10528,7 @@ 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"
|
||||
rm -f "$td/test$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
|
||||
|
@ -10584,6 +10584,48 @@ PORT=$((PORT+1))
|
|||
N=$((N+1))
|
||||
|
||||
|
||||
# socat up to 1.7.2.0 and 2.0.0-b4 had a bug in xioscan_readline() that could
|
||||
# be exploited
|
||||
# to overflow a heap based buffer (socat security advisory 3)
|
||||
# problem reported by Johan Thillemann
|
||||
NAME=READLINE_OVFL
|
||||
case "$TESTS" in
|
||||
*%functions%*|*%bugs%*|*%security%*|*%$NAME%*)
|
||||
TEST="$NAME: test for buffer overflow in readline prompt handling"
|
||||
# address 1 is the readline where write data was handled erroneous
|
||||
# address 2 provides data to trigger the buffer overflow
|
||||
# when no SIGSEGV or so occurs the test succeeded (bug fixed)
|
||||
if ! eval $NUMCOND; then :; else
|
||||
tf="$td/test$N.stdout"
|
||||
te="$td/test$N.stderr"
|
||||
ti="$td/test$N.data"
|
||||
CMD0="$SOCAT $opts READLINE $ti"
|
||||
printf "test $F_n $TEST... " $N
|
||||
# prepare long data - perl might not be installed
|
||||
#perl -e 'print "\r","Z"x513' >"$ti"
|
||||
echo $E -n "\rA" >"$ti"
|
||||
i=0; while [ $i -lt 32 ]; do echo -n "AAAAAAAAAAAAAAAA" >>"$ti"; let i=i+1; done
|
||||
$SOCAT - system:"$CMD0; echo rc=\$? >&2",pty >/dev/null 2>"${te}0"
|
||||
rc=$?
|
||||
rc0="$(grep ^rc= "${te}0" |sed 's/.*=//')"
|
||||
if [ $rc -ne 0 ]; then
|
||||
$PRINTF "${YELLOW}framework failed${NORMAL}\n"
|
||||
elif [ $rc0 -eq 0 ]; then
|
||||
$PRINTF "$OK\n"
|
||||
numOK=$((numOK+1))
|
||||
else
|
||||
$PRINTF "$FAILED\n"
|
||||
echo "$CMD0"
|
||||
grep -v ^rc= "${te}0"
|
||||
numFAIL=$((numFAIL+1))
|
||||
fi
|
||||
fi # NUMCOND
|
||||
;;
|
||||
esac
|
||||
PORT=$((PORT+1))
|
||||
N=$((N+1))
|
||||
|
||||
|
||||
|
||||
echo "summary: $((N-1)) tests; $numOK ok, $numFAIL failed, $numCANT could not be performed"
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* source: xio-readline.c */
|
||||
/* Copyright Gerhard Rieger 2002-2009 */
|
||||
/* Copyright Gerhard Rieger 2002-2012 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for opening the readline address */
|
||||
|
@ -224,25 +224,26 @@ void xioscan_readline(struct single *pipe, const void *buff, size_t bytes) {
|
|||
if (pipe->dtype == XIODATA_READLINE && pipe->para.readline.dynprompt) {
|
||||
/* we save the last part of the output as possible prompt */
|
||||
const void *ptr = buff;
|
||||
const void *pcr = memrchr(buff, '\r', bytes);
|
||||
const void *plf = memrchr(buff, '\n', bytes);
|
||||
const void *pcr;
|
||||
const void *plf;
|
||||
size_t len;
|
||||
|
||||
if (bytes > pipe->para.readline.dynbytes) {
|
||||
ptr = (const char *)buff + bytes - pipe->para.readline.dynbytes;
|
||||
len = pipe->para.readline.dynbytes;
|
||||
} else {
|
||||
len = bytes;
|
||||
}
|
||||
if (pcr) {
|
||||
pcr = memrchr(ptr, '\r', len);
|
||||
plf = memrchr(ptr, '\n', len);
|
||||
if (pcr != NULL || plf != NULL) {
|
||||
const void *peol = Max(pcr, plf);
|
||||
/* forget old prompt */
|
||||
pipe->para.readline.dynend = pipe->para.readline.dynprompt;
|
||||
len -= (peol+1 - ptr);
|
||||
/* new prompt starts here */
|
||||
ptr = (const char *)pcr+1;
|
||||
ptr = (const char *)peol+1;
|
||||
}
|
||||
if (plf && plf >= ptr) {
|
||||
/* forget old prompt */
|
||||
pipe->para.readline.dynend = pipe->para.readline.dynprompt;
|
||||
/* new prompt starts here */
|
||||
ptr = (const char *)plf+1;
|
||||
}
|
||||
len = (const char *)buff-(const char *)ptr+bytes;
|
||||
if (pipe->para.readline.dynend - pipe->para.readline.dynprompt + len >
|
||||
pipe->para.readline.dynbytes) {
|
||||
memmove(pipe->para.readline.dynprompt,
|
||||
|
@ -253,7 +254,6 @@ void xioscan_readline(struct single *pipe, const void *buff, size_t bytes) {
|
|||
pipe->para.readline.dynprompt + pipe->para.readline.dynbytes - len;
|
||||
}
|
||||
memcpy(pipe->para.readline.dynend, ptr, len);
|
||||
/*pipe->para.readline.dynend = pipe->para.readline.dynprompt + len;*/
|
||||
pipe->para.readline.dynend = pipe->para.readline.dynend + len;
|
||||
}
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue