mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
version 1.7.2.1 - fixed READLINE buffer overflow
This commit is contained in:
parent
42ef3f4645
commit
464d23a34f
4 changed files with 70 additions and 16 deletions
13
CHANGES
13
CHANGES
|
@ -1,4 +1,17 @@
|
||||||
|
|
||||||
|
####################### V 1.7.2.1:
|
||||||
|
|
||||||
|
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 1.7.2.0:
|
####################### V 1.7.2.0:
|
||||||
|
|
||||||
corrections:
|
corrections:
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
"1.7.2.0"
|
"1.7.2.1"
|
||||||
|
|
45
test.sh
45
test.sh
|
@ -1,6 +1,6 @@
|
||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
# source: test.sh
|
# source: test.sh
|
||||||
# Copyright Gerhard Rieger 2001-2011
|
# Copyright Gerhard Rieger 2001-2012
|
||||||
# Published under the GNU General Public License V.2, see file COPYING
|
# Published under the GNU General Public License V.2, see file COPYING
|
||||||
|
|
||||||
# perform lots of tests on socat
|
# perform lots of tests on socat
|
||||||
|
@ -10465,7 +10465,7 @@ te="$td/test$N.stderr"
|
||||||
tdiff="$td/test$N.diff"
|
tdiff="$td/test$N.diff"
|
||||||
da="test$N $(date) $RANDOM"
|
da="test$N $(date) $RANDOM"
|
||||||
# prepare long data - perl might not be installed
|
# 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
|
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"
|
CMD0="$SOCAT $opts TCP-CONNECT:$(cat "$td/test$N.dat"):$PORT STDIO"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
|
@ -10776,6 +10776,47 @@ esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
# socat up to 1.7.2.0 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))
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# here come tests that might affect your systems integrity. Put normal tests
|
# here come tests that might affect your systems integrity. Put normal tests
|
||||||
# before this paragraph.
|
# before this paragraph.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* source: xio-readline.c */
|
/* source: xio-readline.c */
|
||||||
/* Copyright Gerhard Rieger 2002-2011 */
|
/* Copyright Gerhard Rieger 2002-2012 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for opening the readline address */
|
/* this file contains the source for opening the readline address */
|
||||||
|
@ -214,25 +214,26 @@ void xioscan_readline(struct single *pipe, const void *buff, size_t bytes) {
|
||||||
if (pipe->dtype == XIODATA_READLINE && pipe->para.readline.dynprompt) {
|
if (pipe->dtype == XIODATA_READLINE && pipe->para.readline.dynprompt) {
|
||||||
/* we save the last part of the output as possible prompt */
|
/* we save the last part of the output as possible prompt */
|
||||||
const void *ptr = buff;
|
const void *ptr = buff;
|
||||||
const void *pcr = memrchr(buff, '\r', bytes);
|
const void *pcr;
|
||||||
const void *plf = memrchr(buff, '\n', bytes);
|
const void *plf;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
if (bytes > pipe->para.readline.dynbytes) {
|
if (bytes > pipe->para.readline.dynbytes) {
|
||||||
ptr = (const char *)buff + 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 */
|
/* forget old prompt */
|
||||||
pipe->para.readline.dynend = pipe->para.readline.dynprompt;
|
pipe->para.readline.dynend = pipe->para.readline.dynprompt;
|
||||||
|
len -= (peol+1 - ptr);
|
||||||
/* new prompt starts here */
|
/* 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 >
|
if (pipe->para.readline.dynend - pipe->para.readline.dynprompt + len >
|
||||||
pipe->para.readline.dynbytes) {
|
pipe->para.readline.dynbytes) {
|
||||||
memmove(pipe->para.readline.dynprompt,
|
memmove(pipe->para.readline.dynprompt,
|
||||||
|
@ -243,7 +244,6 @@ void xioscan_readline(struct single *pipe, const void *buff, size_t bytes) {
|
||||||
pipe->para.readline.dynprompt + pipe->para.readline.dynbytes - len;
|
pipe->para.readline.dynprompt + pipe->para.readline.dynbytes - len;
|
||||||
}
|
}
|
||||||
memcpy(pipe->para.readline.dynend, ptr, 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;
|
pipe->para.readline.dynend = pipe->para.readline.dynend + len;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in a new issue