diff --git a/lib/parsers.c b/lib/parsers.c index bfda32d0..c5142519 100644 --- a/lib/parsers.c +++ b/lib/parsers.c @@ -297,6 +297,20 @@ int libwebsocket_parse(struct libwebsocket *wsi, unsigned char c) case URIPS_SEEN_SLASH_DOT: /* swallow second . */ if (c == '.') { + /* + * back up one dir level if possible + * safe against header fragmentation because + * the method URI can only be in 1 fragment + */ + if (wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len > 2) { + wsi->u.hdr.ah->pos--; + wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len--; + do { + wsi->u.hdr.ah->pos--; + wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len--; + } while (wsi->u.hdr.ah->frags[wsi->u.hdr.ah->next_frag_index].len > 1 && + wsi->u.hdr.ah->data[wsi->u.hdr.ah->pos] != '/'); + } wsi->u.hdr.ups = URIPS_SEEN_SLASH_DOT_DOT; goto swallow; } diff --git a/test-server/attack.sh b/test-server/attack.sh index c1279077..e6f10be1 100755 --- a/test-server/attack.sh +++ b/test-server/attack.sh @@ -164,32 +164,35 @@ if [ $? -ne 0 ] ; then fi echo -echo "---- directory attack 4 (/blah/.. should be /blah/)" +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 -if [ -z "`grep '

403 Forbidden

' /tmp/lwscap`" ] ; then - echo "FAIL: should have told forbidden (test server has no dirs)" +diff /tmp/lwscap /usr/share/libwebsockets-test-server/test.html > /dev/null +if [ $? -ne 0 ] ; then + echo "FAIL: got something other than test.html back" exit 1 fi echo -echo "---- directory attack 5 (/blah/../ should be /blah/)" +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 -if [ -z "`grep '

403 Forbidden

' /tmp/lwscap`" ] ; then - echo "FAIL: should have told forbidden (test server has no dirs)" +diff /tmp/lwscap /usr/share/libwebsockets-test-server/test.html > /dev/null +if [ $? -ne 0 ] ; then + echo "FAIL: got something other than test.html back" exit 1 fi echo -echo "---- directory attack 6 (/blah/../. should be /blah/)" +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 -if [ -z "`grep '

403 Forbidden

' /tmp/lwscap`" ] ; then - echo "FAIL: should have told forbidden (test server has no dirs)" +diff /tmp/lwscap /usr/share/libwebsockets-test-server/test.html > /dev/null +if [ $? -ne 0 ] ; then + echo "FAIL: got something other than test.html back" exit 1 fi