1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

http uri arguments process in fragments

This makes the URI argument processing split each parameter into
a "fragment".  Processing header content as fragments already exists
in lws, because it's legal to deliver header content by repeating
the header.

Now there's an api to access individual fragments, also add the
code to the test server to print each URI argument separately.

Adapt attack.sh to parse the fragments.

Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
Andy Green 2015-12-15 22:57:19 +08:00
parent f35801b19d
commit 4eb36373d7
4 changed files with 75 additions and 19 deletions

View file

@ -24,9 +24,6 @@
const unsigned char *lws_token_to_string(enum lws_token_indexes token)
{
if (token == WSI_TOKEN_HTTP_URI_ARGS)
return (unsigned char *)"Uri-Args:";
if ((unsigned int)token >= ARRAY_SIZE(set))
return NULL;

View file

@ -323,8 +323,24 @@ int lws_parse(struct lws *wsi, unsigned char c)
switch (wsi->u.hdr.ups) {
case URIPS_IDLE:
/* genuine delimiter */
if (c == '&' && !enc) {
issue_char(wsi, c);
/* swallow the terminator */
ah->frags[ah->nfrag].len--;
/* link to next fragment */
ah->frags[ah->nfrag].nfrag = ah->nfrag + 1;
ah->nfrag++;
if (ah->nfrag >= ARRAY_SIZE(ah->frags))
goto excessive;
/* start next fragment after the & */
ah->frags[ah->nfrag].offset = ah->pos;
ah->frags[ah->nfrag].len = 0;
ah->frags[ah->nfrag].nfrag = 0;
goto swallow;
}
/* issue the first / always */
if (c == '/')
if (c == '/' && !ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS])
wsi->u.hdr.ups = URIPS_SEEN_SLASH;
break;
case URIPS_SEEN_SLASH:
@ -365,7 +381,8 @@ int lws_parse(struct lws *wsi, unsigned char c)
}
/* it was like /.dir ... regurgitate the . */
wsi->u.hdr.ups = URIPS_IDLE;
issue_char(wsi, '.');
if (issue_char(wsi, '.') < 0)
return -1;
break;
case URIPS_SEEN_SLASH_DOT_DOT:
@ -380,19 +397,20 @@ int lws_parse(struct lws *wsi, unsigned char c)
break;
}
if (c == '?' && !enc) { /* start of URI arguments */
if (c == '?' && !enc &&
!ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS]) { /* start of URI arguments */
/* seal off uri header */
ah->data[ah->pos++] = '\0';
/* move to using WSI_TOKEN_HTTP_URI_ARGS */
ah->nfrag++;
if (ah->nfrag >= ARRAY_SIZE(ah->frags))
goto excessive;
ah->frags[ah->nfrag].offset = ah->pos;
ah->frags[ah->nfrag].len = 0;
ah->frags[ah->nfrag].nfrag = 0;
ah->frag_index[WSI_TOKEN_HTTP_URI_ARGS] = ah->nfrag;
/* defeat normal uri path processing */
wsi->u.hdr.ups = URIPS_IDLE;
goto swallow;
}
@ -501,6 +519,7 @@ swallow:
start_fragment:
ah->nfrag++;
excessive:
if (ah->nfrag == ARRAY_SIZE(ah->frags)) {
lwsl_warn("More hdr frags than we can deal with\n");
return -1;

View file

@ -35,14 +35,32 @@ function check {
fi
fi
if [ "$1" == "args" ] ; then
a="`dd if=$LOG bs=1 skip=$LEN 2>/dev/null |grep Uri.Args\: | tr -s ' ' | cut -d' ' -f4-`"
if [ "$1" == "1" ] ; then
a="`dd if=$LOG bs=1 skip=$LEN 2>/dev/null |grep URI\ Arg\ 1\: | tr -s ' ' | cut -d' ' -f5-`"
if [ "$a" != "$2" ] ; then
echo "Args '$a' not $2"
echo "Arg 1 '$a' not $2"
exit 1
fi
fi
LEN=`stat $LOG -c %s`
if [ "$1" == "2" ] ; then
a="`dd if=$LOG bs=1 skip=$LEN 2>/dev/null |grep URI\ Arg\ 2\: | tr -s ' ' | cut -d' ' -f5-`"
if [ "$a" != "$2" ] ; then
echo "Arg 2 '$a' not $2"
exit 1
fi
fi
if [ "$1" == "3" ] ; then
a="`dd if=$LOG bs=1 skip=$LEN 2>/dev/null |grep URI\ Arg\ 3\: | tr -s ' ' | cut -d' ' -f5-`"
if [ "$a" != "$2" ] ; then
echo "Arg 3 '$a' not $2"
exit 1
fi
fi
if [ -z "$1" ] ; then
LEN=`stat $LOG -c %s`
fi
}
@ -60,22 +78,24 @@ echo
echo "---- /cgi-bin/settingsjs?UPDATE_SETTINGS=1&Root_Channels_1_Channel_name_http_post=%3F&Root_Channels_1_Channel_location_http_post=%3F"
rm -f /tmp/lwscap
echo -e "GET /cgi-bin/settingsjs?UPDATE_SETTINGS=1&Root_Channels_1_Channel_name_http_post=%3F&Root_Channels_1_Channel_location_http_post=%3F HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
check args "UPDATE_SETTINGS=1&Root_Channels_1_Channel_name_http_post=?&Root_Channels_1_Channel_location_http_post=?"
check 1 "UPDATE_SETTINGS=1"
check 2 "Root_Channels_1_Channel_name_http_post=?"
check 3 "Root_Channels_1_Channel_location_http_post=?"
check
echo
echo "---- ? processing (%2f%2e%2e%2f%2e./test.html?arg=1)"
rm -f /tmp/lwscap
echo -e "GET %2f%2e%2e%2f%2e./test.html?arg=1 HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
check args "arg=1"
check 1 "arg=1"
check
echo
echo "---- ? processing (%2f%2e%2e%2f%2e./test.html?arg=/../.)"
rm -f /tmp/lwscap
echo -e "GET %2f%2e%2e%2f%2e./test.html?arg=/../. HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
check args "arg=/../."
check 1 "arg=/../."
check
echo
echo "---- spam enough crap to not be GET"
@ -172,55 +192,63 @@ echo -e "GET /test.html HTTP/1.1\x0d\x0a\x0d\x0aILLEGAL-PAYLOAD.................
"......................................................................................................................." \
| nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
check default
check
echo
echo "---- directory attack 1 (/../../../../etc/passwd should be /etc/passswd)"
rm -f /tmp/lwscap
echo -e "GET /../../../../etc/passwd HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
check forbidden
check
echo
echo "---- directory attack 2 (/../ should be /)"
rm -f /tmp/lwscap
echo -e "GET /../ HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
check default
check
echo
echo "---- directory attack 3 (/./ should be /)"
rm -f /tmp/lwscap
echo -e "GET /./ HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
check default
check
echo
echo "---- directory attack 4 (/blah/.. should be /)"
rm -f /tmp/lwscap
echo -e "GET /blah/.. HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
check default
check
echo
echo "---- directory attack 5 (/blah/../ should be /)"
rm -f /tmp/lwscap
echo -e "GET /blah/../ HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
check default
check
echo
echo "---- directory attack 6 (/blah/../. should be /)"
rm -f /tmp/lwscap
echo -e "GET /blah/../. HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
check default
check
echo
echo "---- directory attack 7 (/%2e%2e%2f../../../etc/passwd should be /etc/passswd)"
rm -f /tmp/lwscap
echo -e "GET /%2e%2e%2f../../../etc/passwd HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
check forbidden
check
echo
echo "---- directory attack 7 (%2f%2e%2e%2f%2e./.%2e/.%2e%2fetc/passwd should be /etc/passswd)"
rm -f /tmp/lwscap
echo -e "GET %2f%2e%2e%2f%2e./.%2e/.%2e%2fetc/passwd HTTP/1.1\x0d\x0a\x0d\x0a" | nc $SERVER $PORT | sed '1,/^\r$/d'> /tmp/lwscap
check forbidden
check
echo
echo "--- survived OK ---"

View file

@ -137,6 +137,18 @@ int callback_http(struct lws_context *context, struct lws *wsi,
dump_handshake_info(wsi);
/* dump the individual URI Arg parameters */
m = 1;
n = 0;
while (m > 0) {
m = lws_hdr_copy_fragment(wsi, buf, sizeof(buf),
WSI_TOKEN_HTTP_URI_ARGS, n);
if (m < 0)
continue;
n++;
lwsl_info("URI Arg %d: %s\n", n, buf);
}
if (len < 1) {
lws_return_http_status(context, wsi,
HTTP_STATUS_BAD_REQUEST, NULL);