Fossil SCM

Improvements to fossil_assert_safe_command_string(), especially for windows.

drh 2020-06-09 23:32 trunk
Commit ce16c59499bf9ac722ef55c9b6d2d1aa6ee7a0fa7cd8bb86ec1f4ceb831ba362
1 file changed +20 -7
+20 -7
--- src/util.c
+++ src/util.c
@@ -178,13 +178,14 @@
178178
** This routine is intended as a second line of defense against attack.
179179
** It should never fail. Dangerous shell strings should be detected and
180180
** fixed before calling fossil_system(). This routine serves only as a
181181
** safety net in case of bugs elsewhere in the system.
182182
**
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).
184185
*/
185
-static int fossil_assert_safe_command_string(const char *z){
186
+static void fossil_assert_safe_command_string(const char *z){
186187
int unsafe = 0;
187188
#ifndef _WIN32
188189
/* Unix */
189190
int inQuote = 0;
190191
int i, c;
@@ -226,21 +227,35 @@
226227
/* Windows */
227228
int i, c;
228229
int inQuote = 0;
229230
for(i=0; !unsafe && (c = z[i])!=0; i++){
230231
switch( c ){
232
+ case '>':
233
+ case '<':
231234
case '|':
232235
case '&':
233236
case '\n': {
234237
if( inQuote==0 && z[i+1]!=0 ) unsafe = i+1;
235238
break;
239
+ }
240
+ case '\\': {
241
+ if( z[i+1]=='"' ){ i++; }
242
+ break;
236243
}
237244
case '"': {
238245
if( inQuote==c ){
239246
inQuote = 0;
240247
}else{
241248
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++;
242257
}
243258
break;
244259
}
245260
}
246261
}
@@ -253,11 +268,10 @@
253268
fossil_print("%z\n", zMsg);
254269
}else{
255270
fossil_panic("%s", zMsg);
256271
}
257272
}
258
- return !unsafe;
259273
}
260274
261275
/*
262276
** This function implements a cross-platform "system()" interface.
263277
*/
@@ -270,20 +284,19 @@
270284
char *zNewCmd = mprintf("\"%s\"", zOrigCmd);
271285
wchar_t *zUnicode = fossil_utf8_to_unicode(zNewCmd);
272286
if( g.fSystemTrace ) {
273287
fossil_trace("SYSTEM: %s\n", zNewCmd);
274288
}
275
- if( fossil_assert_safe_command_string(zOrigCmd) ){
276
- rc = _wsystem(zUnicode);
277
- }
289
+ fossil_assert_safe_command_string(zOrigCmd);
290
+ rc = _wsystem(zUnicode);
278291
fossil_unicode_free(zUnicode);
279292
free(zNewCmd);
280293
#else
281294
/* On unix, evaluate the command directly.
282295
*/
283296
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);
285298
286299
/* Unix systems should never shell-out while processing an HTTP request,
287300
** either via CGI, SCGI, or direct HTTP. The following assert verifies
288301
** this. And the following assert proves that Fossil is not vulnerable
289302
** to the ShellShock or BashDoor bug.
290303
--- 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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button