Fossil SCM
Improvements to fossil_assert_safe_command_string(), especially for windows.
Commit
ce16c59499bf9ac722ef55c9b6d2d1aa6ee7a0fa7cd8bb86ec1f4ceb831ba362
Parent
4a8ca98f2a67888…
1 file changed
+20
-7
+20
-7
| --- src/util.c | ||
| +++ src/util.c | ||
| @@ -178,13 +178,14 @@ | ||
| 178 | 178 | ** This routine is intended as a second line of defense against attack. |
| 179 | 179 | ** It should never fail. Dangerous shell strings should be detected and |
| 180 | 180 | ** fixed before calling fossil_system(). This routine serves only as a |
| 181 | 181 | ** safety net in case of bugs elsewhere in the system. |
| 182 | 182 | ** |
| 183 | -** If an unsafe string is seen, either abort or return false. | |
| 183 | +** If an unsafe string is seen, either abort (default) or print | |
| 184 | +** a warning message (if safeCmdStrTest is true). | |
| 184 | 185 | */ |
| 185 | -static int fossil_assert_safe_command_string(const char *z){ | |
| 186 | +static void fossil_assert_safe_command_string(const char *z){ | |
| 186 | 187 | int unsafe = 0; |
| 187 | 188 | #ifndef _WIN32 |
| 188 | 189 | /* Unix */ |
| 189 | 190 | int inQuote = 0; |
| 190 | 191 | int i, c; |
| @@ -226,21 +227,35 @@ | ||
| 226 | 227 | /* Windows */ |
| 227 | 228 | int i, c; |
| 228 | 229 | int inQuote = 0; |
| 229 | 230 | for(i=0; !unsafe && (c = z[i])!=0; i++){ |
| 230 | 231 | switch( c ){ |
| 232 | + case '>': | |
| 233 | + case '<': | |
| 231 | 234 | case '|': |
| 232 | 235 | case '&': |
| 233 | 236 | case '\n': { |
| 234 | 237 | if( inQuote==0 && z[i+1]!=0 ) unsafe = i+1; |
| 235 | 238 | break; |
| 239 | + } | |
| 240 | + case '\\': { | |
| 241 | + if( z[i+1]=='"' ){ i++; } | |
| 242 | + break; | |
| 236 | 243 | } |
| 237 | 244 | case '"': { |
| 238 | 245 | if( inQuote==c ){ |
| 239 | 246 | inQuote = 0; |
| 240 | 247 | }else{ |
| 241 | 248 | inQuote = c; |
| 249 | + } | |
| 250 | + break; | |
| 251 | + } | |
| 252 | + case '^': { | |
| 253 | + if( z[i+1]=='"' ){ | |
| 254 | + unsafe = i+2; | |
| 255 | + }else if( z[i+1]!=0 ){ | |
| 256 | + i++; | |
| 242 | 257 | } |
| 243 | 258 | break; |
| 244 | 259 | } |
| 245 | 260 | } |
| 246 | 261 | } |
| @@ -253,11 +268,10 @@ | ||
| 253 | 268 | fossil_print("%z\n", zMsg); |
| 254 | 269 | }else{ |
| 255 | 270 | fossil_panic("%s", zMsg); |
| 256 | 271 | } |
| 257 | 272 | } |
| 258 | - return !unsafe; | |
| 259 | 273 | } |
| 260 | 274 | |
| 261 | 275 | /* |
| 262 | 276 | ** This function implements a cross-platform "system()" interface. |
| 263 | 277 | */ |
| @@ -270,20 +284,19 @@ | ||
| 270 | 284 | char *zNewCmd = mprintf("\"%s\"", zOrigCmd); |
| 271 | 285 | wchar_t *zUnicode = fossil_utf8_to_unicode(zNewCmd); |
| 272 | 286 | if( g.fSystemTrace ) { |
| 273 | 287 | fossil_trace("SYSTEM: %s\n", zNewCmd); |
| 274 | 288 | } |
| 275 | - if( fossil_assert_safe_command_string(zOrigCmd) ){ | |
| 276 | - rc = _wsystem(zUnicode); | |
| 277 | - } | |
| 289 | + fossil_assert_safe_command_string(zOrigCmd); | |
| 290 | + rc = _wsystem(zUnicode); | |
| 278 | 291 | fossil_unicode_free(zUnicode); |
| 279 | 292 | free(zNewCmd); |
| 280 | 293 | #else |
| 281 | 294 | /* On unix, evaluate the command directly. |
| 282 | 295 | */ |
| 283 | 296 | if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zOrigCmd); |
| 284 | - if( !fossil_assert_safe_command_string(zOrigCmd) ) return 1; | |
| 297 | + fossil_assert_safe_command_string(zOrigCmd); | |
| 285 | 298 | |
| 286 | 299 | /* Unix systems should never shell-out while processing an HTTP request, |
| 287 | 300 | ** either via CGI, SCGI, or direct HTTP. The following assert verifies |
| 288 | 301 | ** this. And the following assert proves that Fossil is not vulnerable |
| 289 | 302 | ** to the ShellShock or BashDoor bug. |
| 290 | 303 |
| --- src/util.c | |
| +++ src/util.c | |
| @@ -178,13 +178,14 @@ | |
| 178 | ** This routine is intended as a second line of defense against attack. |
| 179 | ** It should never fail. Dangerous shell strings should be detected and |
| 180 | ** fixed before calling fossil_system(). This routine serves only as a |
| 181 | ** safety net in case of bugs elsewhere in the system. |
| 182 | ** |
| 183 | ** If an unsafe string is seen, either abort or return false. |
| 184 | */ |
| 185 | static int fossil_assert_safe_command_string(const char *z){ |
| 186 | int unsafe = 0; |
| 187 | #ifndef _WIN32 |
| 188 | /* Unix */ |
| 189 | int inQuote = 0; |
| 190 | int i, c; |
| @@ -226,21 +227,35 @@ | |
| 226 | /* Windows */ |
| 227 | int i, c; |
| 228 | int inQuote = 0; |
| 229 | for(i=0; !unsafe && (c = z[i])!=0; i++){ |
| 230 | switch( c ){ |
| 231 | case '|': |
| 232 | case '&': |
| 233 | case '\n': { |
| 234 | if( inQuote==0 && z[i+1]!=0 ) unsafe = i+1; |
| 235 | break; |
| 236 | } |
| 237 | case '"': { |
| 238 | if( inQuote==c ){ |
| 239 | inQuote = 0; |
| 240 | }else{ |
| 241 | inQuote = c; |
| 242 | } |
| 243 | break; |
| 244 | } |
| 245 | } |
| 246 | } |
| @@ -253,11 +268,10 @@ | |
| 253 | fossil_print("%z\n", zMsg); |
| 254 | }else{ |
| 255 | fossil_panic("%s", zMsg); |
| 256 | } |
| 257 | } |
| 258 | return !unsafe; |
| 259 | } |
| 260 | |
| 261 | /* |
| 262 | ** This function implements a cross-platform "system()" interface. |
| 263 | */ |
| @@ -270,20 +284,19 @@ | |
| 270 | char *zNewCmd = mprintf("\"%s\"", zOrigCmd); |
| 271 | wchar_t *zUnicode = fossil_utf8_to_unicode(zNewCmd); |
| 272 | if( g.fSystemTrace ) { |
| 273 | fossil_trace("SYSTEM: %s\n", zNewCmd); |
| 274 | } |
| 275 | if( fossil_assert_safe_command_string(zOrigCmd) ){ |
| 276 | rc = _wsystem(zUnicode); |
| 277 | } |
| 278 | fossil_unicode_free(zUnicode); |
| 279 | free(zNewCmd); |
| 280 | #else |
| 281 | /* On unix, evaluate the command directly. |
| 282 | */ |
| 283 | if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zOrigCmd); |
| 284 | if( !fossil_assert_safe_command_string(zOrigCmd) ) return 1; |
| 285 | |
| 286 | /* Unix systems should never shell-out while processing an HTTP request, |
| 287 | ** either via CGI, SCGI, or direct HTTP. The following assert verifies |
| 288 | ** this. And the following assert proves that Fossil is not vulnerable |
| 289 | ** to the ShellShock or BashDoor bug. |
| 290 |
| --- src/util.c | |
| +++ src/util.c | |
| @@ -178,13 +178,14 @@ | |
| 178 | ** This routine is intended as a second line of defense against attack. |
| 179 | ** It should never fail. Dangerous shell strings should be detected and |
| 180 | ** fixed before calling fossil_system(). This routine serves only as a |
| 181 | ** safety net in case of bugs elsewhere in the system. |
| 182 | ** |
| 183 | ** If an unsafe string is seen, either abort (default) or print |
| 184 | ** a warning message (if safeCmdStrTest is true). |
| 185 | */ |
| 186 | static void fossil_assert_safe_command_string(const char *z){ |
| 187 | int unsafe = 0; |
| 188 | #ifndef _WIN32 |
| 189 | /* Unix */ |
| 190 | int inQuote = 0; |
| 191 | int i, c; |
| @@ -226,21 +227,35 @@ | |
| 227 | /* Windows */ |
| 228 | int i, c; |
| 229 | int inQuote = 0; |
| 230 | for(i=0; !unsafe && (c = z[i])!=0; i++){ |
| 231 | switch( c ){ |
| 232 | case '>': |
| 233 | case '<': |
| 234 | case '|': |
| 235 | case '&': |
| 236 | case '\n': { |
| 237 | if( inQuote==0 && z[i+1]!=0 ) unsafe = i+1; |
| 238 | break; |
| 239 | } |
| 240 | case '\\': { |
| 241 | if( z[i+1]=='"' ){ i++; } |
| 242 | break; |
| 243 | } |
| 244 | case '"': { |
| 245 | if( inQuote==c ){ |
| 246 | inQuote = 0; |
| 247 | }else{ |
| 248 | inQuote = c; |
| 249 | } |
| 250 | break; |
| 251 | } |
| 252 | case '^': { |
| 253 | if( z[i+1]=='"' ){ |
| 254 | unsafe = i+2; |
| 255 | }else if( z[i+1]!=0 ){ |
| 256 | i++; |
| 257 | } |
| 258 | break; |
| 259 | } |
| 260 | } |
| 261 | } |
| @@ -253,11 +268,10 @@ | |
| 268 | fossil_print("%z\n", zMsg); |
| 269 | }else{ |
| 270 | fossil_panic("%s", zMsg); |
| 271 | } |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | /* |
| 276 | ** This function implements a cross-platform "system()" interface. |
| 277 | */ |
| @@ -270,20 +284,19 @@ | |
| 284 | char *zNewCmd = mprintf("\"%s\"", zOrigCmd); |
| 285 | wchar_t *zUnicode = fossil_utf8_to_unicode(zNewCmd); |
| 286 | if( g.fSystemTrace ) { |
| 287 | fossil_trace("SYSTEM: %s\n", zNewCmd); |
| 288 | } |
| 289 | fossil_assert_safe_command_string(zOrigCmd); |
| 290 | rc = _wsystem(zUnicode); |
| 291 | fossil_unicode_free(zUnicode); |
| 292 | free(zNewCmd); |
| 293 | #else |
| 294 | /* On unix, evaluate the command directly. |
| 295 | */ |
| 296 | if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zOrigCmd); |
| 297 | fossil_assert_safe_command_string(zOrigCmd); |
| 298 | |
| 299 | /* Unix systems should never shell-out while processing an HTTP request, |
| 300 | ** either via CGI, SCGI, or direct HTTP. The following assert verifies |
| 301 | ** this. And the following assert proves that Fossil is not vulnerable |
| 302 | ** to the ShellShock or BashDoor bug. |
| 303 |