mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
socat security advisory 8: stack overflow in nestlex()
This commit is contained in:
parent
eab3c89f2d
commit
226c555edb
4 changed files with 92 additions and 10 deletions
15
CHANGES
15
CHANGES
|
@ -1,5 +1,18 @@
|
||||||
|
|
||||||
security:
|
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
|
Socat security advisory 7
|
||||||
MSVR-1499
|
MSVR-1499
|
||||||
In the OpenSSL address implementation the hard coded 1024 bit DH p
|
In the OpenSSL address implementation the hard coded 1024 bit DH p
|
||||||
|
@ -18,7 +31,7 @@ security:
|
||||||
|
|
||||||
security:
|
security:
|
||||||
Socat security advisory 6
|
Socat security advisory 6
|
||||||
CVE-2015-1379
|
CVE-2015-1379: Possible DoS with fork
|
||||||
Fixed problems with signal handling caused by use of not async signal
|
Fixed problems with signal handling caused by use of not async signal
|
||||||
safe functions in signal handlers that could freeze socat, allowing
|
safe functions in signal handlers that could freeze socat, allowing
|
||||||
denial of service attacks.
|
denial of service attacks.
|
||||||
|
|
49
nestlex.c
49
nestlex.c
|
@ -1,5 +1,5 @@
|
||||||
/* source: nestlex.c */
|
/* source: nestlex.c */
|
||||||
/* Copyright Gerhard Rieger 2006-2010 */
|
/* Copyright Gerhard Rieger */
|
||||||
/* 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 */
|
||||||
|
@ -9,6 +9,17 @@
|
||||||
|
|
||||||
#include "sysincludes.h"
|
#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 dropquotes,
|
||||||
|
bool c_esc,
|
||||||
|
bool html_esc
|
||||||
|
);
|
||||||
|
|
||||||
/* sub: scan a string and copy its value to output string
|
/* sub: scan a string and copy its value to output string
|
||||||
end scanning when an unescaped, unnested string from ends array is found
|
end scanning when an unescaped, unnested string from ends array is found
|
||||||
|
@ -33,6 +44,22 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
bool c_esc, /* solve C char escapes: \n \t \0 etc */
|
bool c_esc, /* solve C char escapes: \n \t \0 etc */
|
||||||
bool html_esc /* solve HTML char escapes: %0d %08 etc */
|
bool html_esc /* solve HTML char escapes: %0d %08 etc */
|
||||||
) {
|
) {
|
||||||
|
return
|
||||||
|
_nestlex(addr, token, (ptrdiff_t *)len, ends, hquotes, squotes, nests,
|
||||||
|
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 dropquotes,
|
||||||
|
bool c_esc,
|
||||||
|
bool html_esc
|
||||||
|
) {
|
||||||
const char *in = *addr; /* pointer into input string */
|
const char *in = *addr; /* pointer into input string */
|
||||||
const char **endx; /* loops over end patterns */
|
const char **endx; /* loops over end patterns */
|
||||||
const char **quotx; /* loops over quote patterns */
|
const char **quotx; /* loops over quote patterns */
|
||||||
|
@ -77,16 +104,18 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
if (--*len <= 0) { *addr = in; *token = out; return -1; }
|
if (--*len <= 0) { *addr = in; *token = out; return -1; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* we call nestlex recursively */
|
/* we call _nestlex recursively */
|
||||||
endnest[0] = *quotx;
|
endnest[0] = *quotx;
|
||||||
endnest[1] = NULL;
|
endnest[1] = NULL;
|
||||||
result =
|
result =
|
||||||
nestlex(&in, &out, len, endnest, NULL/*hquotes*/,
|
_nestlex(&in, &out, len, endnest, NULL/*hquotes*/,
|
||||||
NULL/*squotes*/, NULL/*nests*/,
|
NULL/*squotes*/, NULL/*nests*/,
|
||||||
false, c_esc, html_esc);
|
false, c_esc, html_esc);
|
||||||
if (result == 0 && dropquotes) {
|
if (result == 0 && dropquotes) {
|
||||||
/* we strip this quote */
|
/* we strip this quote */
|
||||||
in += strlen(*quotx);
|
in += strlen(*quotx);
|
||||||
|
} else if (result < 0) {
|
||||||
|
*addr = in; *token = out; return result;
|
||||||
} else {
|
} else {
|
||||||
/* we copy the trailing quote */
|
/* we copy the trailing quote */
|
||||||
for (i = strlen(*quotx); i > 0; --i) {
|
for (i = strlen(*quotx); i > 0; --i) {
|
||||||
|
@ -110,7 +139,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
if (!strncmp(in, *quotx, strlen(*quotx))) {
|
if (!strncmp(in, *quotx, strlen(*quotx))) {
|
||||||
/* this quote pattern matches */
|
/* this quote pattern matches */
|
||||||
/* we strip this quote */
|
/* we strip this quote */
|
||||||
/* we call nestlex recursively */
|
/* we call _nestlex recursively */
|
||||||
const char *endnest[2];
|
const char *endnest[2];
|
||||||
if (dropquotes) {
|
if (dropquotes) {
|
||||||
/* we strip this quote */
|
/* we strip this quote */
|
||||||
|
@ -124,13 +153,15 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
endnest[0] = *quotx;
|
endnest[0] = *quotx;
|
||||||
endnest[1] = NULL;
|
endnest[1] = NULL;
|
||||||
result =
|
result =
|
||||||
nestlex(&in, &out, len, endnest, hquotes,
|
_nestlex(&in, &out, len, endnest, hquotes,
|
||||||
squotes, nests,
|
squotes, nests,
|
||||||
false, c_esc, html_esc);
|
false, c_esc, html_esc);
|
||||||
|
|
||||||
if (result == 0 && dropquotes) {
|
if (result == 0 && dropquotes) {
|
||||||
/* we strip the trailing quote */
|
/* we strip the trailing quote */
|
||||||
in += strlen(*quotx);
|
in += strlen(*quotx);
|
||||||
|
} else if (result < 0) {
|
||||||
|
*addr = in; *token = out; return result;
|
||||||
} else {
|
} else {
|
||||||
/* we copy the trailing quote */
|
/* we copy the trailing quote */
|
||||||
for (i = strlen(*quotx); i > 0; --i) {
|
for (i = strlen(*quotx); i > 0; --i) {
|
||||||
|
@ -162,7 +193,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
}
|
}
|
||||||
|
|
||||||
result =
|
result =
|
||||||
nestlex(&in, &out, len, endnest, hquotes, squotes, nests,
|
_nestlex(&in, &out, len, endnest, hquotes, squotes, nests,
|
||||||
false, c_esc, html_esc);
|
false, c_esc, html_esc);
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
/* copy endnest */
|
/* copy endnest */
|
||||||
|
@ -175,6 +206,8 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
}
|
}
|
||||||
--i;
|
--i;
|
||||||
}
|
}
|
||||||
|
} else if (result < 0) {
|
||||||
|
*addr = in; *token = out; return result;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -211,7 +244,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 +255,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 */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* source: nestlex.h */
|
/* source: nestlex.h */
|
||||||
/* Copyright Gerhard Rieger 2006 */
|
/* Copyright Gerhard Rieger */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __nestlex_h_included
|
#ifndef __nestlex_h_included
|
||||||
|
|
36
test.sh
36
test.sh
|
@ -10989,6 +10989,42 @@ esac
|
||||||
PORT=$((PORT+1))
|
PORT=$((PORT+1))
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
# socat up to 1.7.3.0 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
|
# test for a bug in gopen that lead to crash or warning when opening a unix
|
||||||
# domain socket with GOPEN
|
# domain socket with GOPEN
|
||||||
|
|
Loading…
Reference in a new issue