comparison src/http/ngx_http_parse.c @ 8530:b4073527be81

Disabled control characters in URIs. Control characters (0x00-0x1f, 0x7f) were never allowed in URIs, and must be percent-encoded by clients. Further, these are not believed to appear in practice. On the other hand, passing such characters might make various attacks possible or easier, despite the fact that currently allowed control characters are not significant for HTTP request parsing.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 28 Jun 2021 18:01:15 +0300
parents 52338ddf9e2f
children 41f4bd4c51f1
comparison
equal deleted inserted replaced
8529:52338ddf9e2f 8530:b4073527be81
9 #include <ngx_core.h> 9 #include <ngx_core.h>
10 #include <ngx_http.h> 10 #include <ngx_http.h>
11 11
12 12
13 static uint32_t usual[] = { 13 static uint32_t usual[] = {
14 0xffffdbfe, /* 1111 1111 1111 1111 1101 1011 1111 1110 */ 14 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */
15 15
16 /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ 16 /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
17 0x7fff37d6, /* 0111 1111 1111 1111 0011 0111 1101 0110 */ 17 0x7fff37d6, /* 0111 1111 1111 1111 0011 0111 1101 0110 */
18 18
19 /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ 19 /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
22 #else 22 #else
23 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 23 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
24 #endif 24 #endif
25 25
26 /* ~}| {zyx wvut srqp onml kjih gfed cba` */ 26 /* ~}| {zyx wvut srqp onml kjih gfed cba` */
27 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 27 0x7fffffff, /* 0111 1111 1111 1111 1111 1111 1111 1111 */
28 28
29 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 29 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
30 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 30 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
31 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 31 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
32 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ 32 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */
526 state = sw_uri; 526 state = sw_uri;
527 break; 527 break;
528 case '+': 528 case '+':
529 r->plus_in_uri = 1; 529 r->plus_in_uri = 1;
530 break; 530 break;
531 case '\0': 531 default:
532 return NGX_HTTP_PARSE_INVALID_REQUEST; 532 if (ch < 0x20 || ch == 0x7f) {
533 default: 533 return NGX_HTTP_PARSE_INVALID_REQUEST;
534 }
534 state = sw_check_uri; 535 state = sw_check_uri;
535 break; 536 break;
536 } 537 }
537 break; 538 break;
538 539
590 state = sw_uri; 591 state = sw_uri;
591 break; 592 break;
592 case '+': 593 case '+':
593 r->plus_in_uri = 1; 594 r->plus_in_uri = 1;
594 break; 595 break;
595 case '\0': 596 default:
596 return NGX_HTTP_PARSE_INVALID_REQUEST; 597 if (ch < 0x20 || ch == 0x7f) {
598 return NGX_HTTP_PARSE_INVALID_REQUEST;
599 }
600 break;
597 } 601 }
598 break; 602 break;
599 603
600 /* URI */ 604 /* URI */
601 case sw_uri: 605 case sw_uri:
619 r->http_minor = 9; 623 r->http_minor = 9;
620 goto done; 624 goto done;
621 case '#': 625 case '#':
622 r->complex_uri = 1; 626 r->complex_uri = 1;
623 break; 627 break;
624 case '\0': 628 default:
625 return NGX_HTTP_PARSE_INVALID_REQUEST; 629 if (ch < 0x20 || ch == 0x7f) {
630 return NGX_HTTP_PARSE_INVALID_REQUEST;
631 }
632 break;
626 } 633 }
627 break; 634 break;
628 635
629 /* space+ after URI */ 636 /* space+ after URI */
630 case sw_http_09: 637 case sw_http_09:
1116 state = sw_check_uri; 1123 state = sw_check_uri;
1117 break; 1124 break;
1118 } 1125 }
1119 1126
1120 switch (ch) { 1127 switch (ch) {
1121 case ' ':
1122 return NGX_ERROR;
1123 case '.': 1128 case '.':
1124 r->complex_uri = 1; 1129 r->complex_uri = 1;
1125 state = sw_uri; 1130 state = sw_uri;
1126 break; 1131 break;
1127 case '%': 1132 case '%':
1148 break; 1153 break;
1149 case '+': 1154 case '+':
1150 r->plus_in_uri = 1; 1155 r->plus_in_uri = 1;
1151 break; 1156 break;
1152 default: 1157 default:
1158 if (ch <= 0x20 || ch == 0x7f) {
1159 return NGX_ERROR;
1160 }
1153 state = sw_check_uri; 1161 state = sw_check_uri;
1154 break; 1162 break;
1155 } 1163 }
1156 break; 1164 break;
1157 1165
1175 state = sw_after_slash_in_uri; 1183 state = sw_after_slash_in_uri;
1176 break; 1184 break;
1177 case '.': 1185 case '.':
1178 r->uri_ext = p + 1; 1186 r->uri_ext = p + 1;
1179 break; 1187 break;
1180 case ' ':
1181 return NGX_ERROR;
1182 #if (NGX_WIN32) 1188 #if (NGX_WIN32)
1183 case '\\': 1189 case '\\':
1184 r->complex_uri = 1; 1190 r->complex_uri = 1;
1185 state = sw_after_slash_in_uri; 1191 state = sw_after_slash_in_uri;
1186 break; 1192 break;
1198 state = sw_uri; 1204 state = sw_uri;
1199 break; 1205 break;
1200 case '+': 1206 case '+':
1201 r->plus_in_uri = 1; 1207 r->plus_in_uri = 1;
1202 break; 1208 break;
1209 default:
1210 if (ch <= 0x20 || ch == 0x7f) {
1211 return NGX_ERROR;
1212 }
1213 break;
1203 } 1214 }
1204 break; 1215 break;
1205 1216
1206 /* URI */ 1217 /* URI */
1207 case sw_uri: 1218 case sw_uri:
1209 if (usual[ch >> 5] & (1U << (ch & 0x1f))) { 1220 if (usual[ch >> 5] & (1U << (ch & 0x1f))) {
1210 break; 1221 break;
1211 } 1222 }
1212 1223
1213 switch (ch) { 1224 switch (ch) {
1214 case ' ':
1215 return NGX_ERROR;
1216 case '#': 1225 case '#':
1217 r->complex_uri = 1; 1226 r->complex_uri = 1;
1227 break;
1228 default:
1229 if (ch <= 0x20 || ch == 0x7f) {
1230 return NGX_ERROR;
1231 }
1218 break; 1232 break;
1219 } 1233 }
1220 break; 1234 break;
1221 } 1235 }
1222 } 1236 }