Socat address parser read over end of string when there was unbalanced quoting

This commit is contained in:
Gerhard Rieger 2020-10-13 19:25:21 +02:00
parent 8e6b341f59
commit b62ff0c005
4 changed files with 43 additions and 1 deletions

View file

@ -7,6 +7,11 @@ Security:
Thanks to Lê Hiếu Bùi for reporting this issue and sending an Thanks to Lê Hiếu Bùi for reporting this issue and sending an
example exploit. example exploit.
Corrections:
Socats address parser read over end of string when there were unbalanced
quotes
Test: UNBALANCED_QUOTE
Testing: Testing:
test.sh now produces a list of tests that could not be performed for test.sh now produces a list of tests that could not be performed for
any reason. This helps to analyse these cases. any reason. This helps to analyse these cases.

View file

@ -159,6 +159,7 @@ static int _nestlex(const char **addr,
if (result == 0 && dropquotes) { if (result == 0 && dropquotes) {
/* we strip the trailing quote */ /* we strip the trailing quote */
if (!in[0] || strncmp(in, *quotx, strlen(*quotx))) return 1;
in += strlen(*quotx); in += strlen(*quotx);
} else if (result < 0) { } else if (result < 0) {
*addr = in; *token = out; return result; *addr = in; *token = out; return result;

31
test.sh
View file

@ -13510,6 +13510,37 @@ PORT=$((PORT+1))
N=$((N+1)) N=$((N+1))
# Test if unbalanced quoting in Socat addresses is detected
NAME=UNBALANCED_QUOTE
case "$TESTS" in
*%$N%*|*%functions%*|*%bugs%*|*%$NAME%*)
TEST="$NAME: Test fix of unbalanced quoting"
# Invoke Socat with an address containing unbalanced quoting. If Socat prints
# a "syntax error" message, the test succeeds
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"
CMD0="$TRACE $SOCAT $opts -u FILE:$td/ab\"cd FILE:/dev/null"
printf "test $F_n $TEST... " $N
$CMD0 >/dev/null 2>"${te}0"
if grep -q "syntax error" "${te}0"; 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
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

View file

@ -367,6 +367,8 @@ xiofile_t *xioopen(const char *addr, /* address specification */
return NULL; return NULL;
} }
Debug1("xioopen(\"%s\")", addr);
if ((xfd = xioparse_dual(&addr)) == NULL) { if ((xfd = xioparse_dual(&addr)) == NULL) {
return NULL; return NULL;
} }
@ -384,6 +386,8 @@ xiofile_t *xioopen(const char *addr, /* address specification */
return xfd; return xfd;
} }
/* parse an address string that might contain !!
return NULL on error */
static xiofile_t *xioparse_dual(const char **addr) { static xiofile_t *xioparse_dual(const char **addr) {
xiofile_t *xfd; xiofile_t *xfd;
xiosingle_t *sfd1; xiosingle_t *sfd1;
@ -445,6 +449,7 @@ static int xioopen_dual(xiofile_t *xfd, int xioflags) {
static xiosingle_t *xioparse_single(const char **addr) { static xiosingle_t *xioparse_single(const char **addr) {
const char *addr0 = *addr; /* save for error messages */
xiofile_t *xfd; xiofile_t *xfd;
xiosingle_t *sfd; xiosingle_t *sfd;
struct addrname *ae; struct addrname *ae;
@ -540,7 +545,7 @@ static xiosingle_t *xioparse_single(const char **addr) {
len = sizeof(token); tokp = token; len = sizeof(token); tokp = token;
if (nestlex(addr, &tokp, &len, ends, hquotes, squotes, nests, if (nestlex(addr, &tokp, &len, ends, hquotes, squotes, nests,
true, true, false) != 0) { true, true, false) != 0) {
Error2("syntax error in address \"%s%s\"", token, *addr); Error1("syntax error in address \"%s\"", addr0);
} }
*tokp = '\0'; *tokp = '\0';
if ((sfd->argv[sfd->argc++] = strdup(token)) == NULL) { if ((sfd->argv[sfd->argc++] = strdup(token)) == NULL) {