socat security advisory 8: stack overflow in nestlex()

This commit is contained in:
Gerhard Rieger 2016-01-26 19:06:55 +01:00
parent 20f5963f13
commit fe2313f50f
4 changed files with 93 additions and 9 deletions

13
CHANGES
View file

@ -1,5 +1,18 @@
security:
Socat security advisory 8
A stack overflow in vulnerability was found that can be triggered when
command line arguments (complete address specifications, host names,
file names) are longer than 512 bytes.
Successful exploitation might allow an attacker to execute arbitrary
code with the privileges of the socat process.
This vulnerability can only be exploited when an attacker is able to
inject data into socat's command line.
A vulnerable scenario would be a CGI script that reads data from clients
and uses (parts of) this data as hostname for a Socat invocation.
Test: NESTEDOVFL
Credits to Takumi Akiyama for finding and reporting this issue.
Socat security advisory 7
MSVR-1499
In the OpenSSL address implementation the hard coded 1024 bit DH p

View file

@ -1,5 +1,5 @@
/* source: nestlex.c */
/* Copyright Gerhard Rieger 2006-2010 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
/* a function for lexical scanning of nested character patterns */
@ -9,6 +9,18 @@
#include "sysincludes.h"
static int _nestlex(const char **addr,
char **token,
ptrdiff_t *len,
const char *ends[],
const char *hquotes[],
const char *squotes[],
const char *nests[],
bool dropspace,
bool dropquotes,
bool c_esc,
bool html_esc
);
/* sub: scan a string and copy its value to output string
end scanning when an unescaped, unnested string from ends array is found
@ -34,6 +46,23 @@ int nestlex(const char **addr, /* input string; aft points to end token */
bool c_esc, /* solve C char escapes: \n \t \0 etc */
bool html_esc /* solve HTML char escapes: %0d %08 etc */
) {
return
_nestlex(addr, token, (ptrdiff_t *)len, ends, hquotes, squotes, nests,
dropspace, dropquotes, c_esc, html_esc);
}
static int _nestlex(const char **addr,
char **token,
ptrdiff_t *len,
const char *ends[],
const char *hquotes[],
const char *squotes[],
const char *nests[],
bool dropspace,
bool dropquotes,
bool c_esc,
bool html_esc
) {
const char *in = *addr; /* pointer into input string */
const char **endx; /* loops over end patterns */
const char **quotx; /* loops over quote patterns */
@ -84,16 +113,18 @@ int nestlex(const char **addr, /* input string; aft points to end token */
if (--*len <= 0) { *addr = in; *token = out; return -1; }
}
}
/* we call nestlex recursively */
/* we call _nestlex recursively */
endnest[0] = *quotx;
endnest[1] = NULL;
result =
nestlex(&in, &out, len, endnest, NULL/*hquotes*/,
_nestlex(&in, &out, len, endnest, NULL/*hquotes*/,
NULL/*squotes*/, NULL/*nests*/,
false, false, c_esc, html_esc);
if (result == 0 && dropquotes) {
/* we strip this quote */
in += strlen(*quotx);
} else if (result < 0) {
*addr = in; *token = out; return result;
} else {
/* we copy the trailing quote */
for (i = strlen(*quotx); i > 0; --i) {
@ -118,7 +149,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */
if (!strncmp(in, *quotx, strlen(*quotx))) {
/* this quote pattern matches */
/* we strip this quote */
/* we call nestlex recursively */
/* we call _nestlex recursively */
const char *endnest[2];
if (dropquotes) {
/* we strip this quote */
@ -132,13 +163,15 @@ int nestlex(const char **addr, /* input string; aft points to end token */
endnest[0] = *quotx;
endnest[1] = NULL;
result =
nestlex(&in, &out, len, endnest, hquotes,
_nestlex(&in, &out, len, endnest, hquotes,
squotes, nests,
false, false, c_esc, html_esc);
if (result == 0 && dropquotes) {
/* we strip the trailing quote */
in += strlen(*quotx);
} else if (result < 0) {
*addr = in; *token = out; return result;
} else {
/* we copy the trailing quote */
for (i = strlen(*quotx); i > 0; --i) {
@ -171,7 +204,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */
}
result =
nestlex(&in, &out, len, endnest, hquotes, squotes, nests,
_nestlex(&in, &out, len, endnest, hquotes, squotes, nests,
false, false, c_esc, html_esc);
if (result == 0) {
/* copy endnest */
@ -184,6 +217,8 @@ int nestlex(const char **addr, /* input string; aft points to end token */
}
--i;
}
} else if (result < 0) {
*addr = in; *token = out; return result;
}
break;
}
@ -221,7 +256,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 */
@ -233,7 +268,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 */

View file

@ -1,5 +1,5 @@
/* source: nestlex.h */
/* Copyright Gerhard Rieger 2006-2007 */
/* Copyright Gerhard Rieger */
/* Published under the GNU General Public License V.2, see file COPYING */
#ifndef __nestlex_h_included

36
test.sh
View file

@ -11403,6 +11403,42 @@ esac
PORT=$((PORT+1))
N=$((N+1))
# socat up to 1.7.3.0 and to 2.0.0-b8 had a stack overflow vulnerability that occurred when
# command line arguments (whole addresses, host names, file names) were longer
# than 512 bytes and specially crafted.
NAME=NESTEDOVFL
case "$TESTS" in
*%$N%*|*%functions%*|*%bugs%*|*%security%*|*%exec%*|*%$NAME%*)
TEST="$NAME: stack overflow on overly long nested arg"
# 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/test$N.dat"
i=0; while [ $i -lt 64 ]; do echo -n "AAAAAAAAAAAAAAAA" >>"$td/test$N.dat"; i=$((i+1)); done
CMD0="$TRACE $SOCAT $opts EXEC:[$(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))
listFAIL="$listFAIL $N"
fi
fi # NUMCOND
;;
esac
PORT=$((PORT+1))
N=$((N+1))
# test for a bug in gopen that lead to crash or warning when opening a unix
# domain socket with GOPEN