Fossil SCM

Add a safety scan of all strings passed into fossil_system(). Fatal error if the input string seems unsafe.

drh 2020-06-08 23:37 trunk
Commit a046f916d3e3be3d5b6b17e851d484a20caebd563f8bed8b3ce5e3b171f95fce
1 file changed +60
+60
--- src/util.c
+++ src/util.c
@@ -155,10 +155,68 @@
155155
zIn++;
156156
}
157157
}
158158
return zStart;
159159
}
160
+
161
+/*
162
+** Check the input string to ensure that it is safe to pass into system().
163
+** A string is unsafe for system() if it contains any of the following:
164
+**
165
+** * Any occurrance of '$' or '`' except after \
166
+** * Any of the following characters, unquoted: ;|& or \n
167
+** * Unbalanced single or double quotes
168
+**
169
+** This routine is intended as a second line of defense against attack.
170
+** It should never fail. Dangerous shell strings should be detected and
171
+** fixed before calling fossil_system(). This routine serves only as a
172
+** safety net in case of bugs elsewhere in the system.
173
+**
174
+** If an unsafe string is seen, the process aborts.
175
+*/
176
+void fossil_assert_safe_command_string(const char *z){
177
+ int inQuote = 0;
178
+ int i, c;
179
+ int unsafe = 0;
180
+ for(i=0; (c = z[i])!=0; i++){
181
+ switch( c ){
182
+ case '$':
183
+ case '`': {
184
+ unsafe = i+1;
185
+ break;
186
+ }
187
+ case ';':
188
+ case '|':
189
+ case '&':
190
+ case '\n': {
191
+ if( inQuote==0 ) unsafe = i+1;
192
+ break;
193
+ }
194
+ case '"':
195
+ case '\'': {
196
+ if( inQuote==0 ){
197
+ inQuote = c;
198
+ }else if( inQuote==c ){
199
+ inQuote = 0;
200
+ }
201
+ break;
202
+ }
203
+ case '\\': {
204
+ if( z[i+1]==0 ){
205
+ unsafe = i+1;
206
+ }else{
207
+ i++;
208
+ }
209
+ break;
210
+ }
211
+ }
212
+ }
213
+ if( unsafe ){
214
+ fossil_fatal("Unsafe command string: %s\n%*shere ----^",
215
+ z, unsafe+13, "");
216
+ }
217
+}
160218
161219
/*
162220
** This function implements a cross-platform "system()" interface.
163221
*/
164222
int fossil_system(const char *zOrigCmd){
@@ -170,17 +228,19 @@
170228
char *zNewCmd = mprintf("\"%s\"", zOrigCmd);
171229
wchar_t *zUnicode = fossil_utf8_to_unicode(zNewCmd);
172230
if( g.fSystemTrace ) {
173231
fossil_trace("SYSTEM: %s\n", zNewCmd);
174232
}
233
+ fossil_assert_safe_command_string(zOrigCmd);
175234
rc = _wsystem(zUnicode);
176235
fossil_unicode_free(zUnicode);
177236
free(zNewCmd);
178237
#else
179238
/* On unix, evaluate the command directly.
180239
*/
181240
if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zOrigCmd);
241
+ fossil_assert_safe_command_string(zOrigCmd);
182242
183243
/* Unix systems should never shell-out while processing an HTTP request,
184244
** either via CGI, SCGI, or direct HTTP. The following assert verifies
185245
** this. And the following assert proves that Fossil is not vulnerable
186246
** to the ShellShock or BashDoor bug.
187247
--- src/util.c
+++ src/util.c
@@ -155,10 +155,68 @@
155 zIn++;
156 }
157 }
158 return zStart;
159 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
161 /*
162 ** This function implements a cross-platform "system()" interface.
163 */
164 int fossil_system(const char *zOrigCmd){
@@ -170,17 +228,19 @@
170 char *zNewCmd = mprintf("\"%s\"", zOrigCmd);
171 wchar_t *zUnicode = fossil_utf8_to_unicode(zNewCmd);
172 if( g.fSystemTrace ) {
173 fossil_trace("SYSTEM: %s\n", zNewCmd);
174 }
 
175 rc = _wsystem(zUnicode);
176 fossil_unicode_free(zUnicode);
177 free(zNewCmd);
178 #else
179 /* On unix, evaluate the command directly.
180 */
181 if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zOrigCmd);
 
182
183 /* Unix systems should never shell-out while processing an HTTP request,
184 ** either via CGI, SCGI, or direct HTTP. The following assert verifies
185 ** this. And the following assert proves that Fossil is not vulnerable
186 ** to the ShellShock or BashDoor bug.
187
--- src/util.c
+++ src/util.c
@@ -155,10 +155,68 @@
155 zIn++;
156 }
157 }
158 return zStart;
159 }
160
161 /*
162 ** Check the input string to ensure that it is safe to pass into system().
163 ** A string is unsafe for system() if it contains any of the following:
164 **
165 ** * Any occurrance of '$' or '`' except after \
166 ** * Any of the following characters, unquoted: ;|& or \n
167 ** * Unbalanced single or double quotes
168 **
169 ** This routine is intended as a second line of defense against attack.
170 ** It should never fail. Dangerous shell strings should be detected and
171 ** fixed before calling fossil_system(). This routine serves only as a
172 ** safety net in case of bugs elsewhere in the system.
173 **
174 ** If an unsafe string is seen, the process aborts.
175 */
176 void fossil_assert_safe_command_string(const char *z){
177 int inQuote = 0;
178 int i, c;
179 int unsafe = 0;
180 for(i=0; (c = z[i])!=0; i++){
181 switch( c ){
182 case '$':
183 case '`': {
184 unsafe = i+1;
185 break;
186 }
187 case ';':
188 case '|':
189 case '&':
190 case '\n': {
191 if( inQuote==0 ) unsafe = i+1;
192 break;
193 }
194 case '"':
195 case '\'': {
196 if( inQuote==0 ){
197 inQuote = c;
198 }else if( inQuote==c ){
199 inQuote = 0;
200 }
201 break;
202 }
203 case '\\': {
204 if( z[i+1]==0 ){
205 unsafe = i+1;
206 }else{
207 i++;
208 }
209 break;
210 }
211 }
212 }
213 if( unsafe ){
214 fossil_fatal("Unsafe command string: %s\n%*shere ----^",
215 z, unsafe+13, "");
216 }
217 }
218
219 /*
220 ** This function implements a cross-platform "system()" interface.
221 */
222 int fossil_system(const char *zOrigCmd){
@@ -170,17 +228,19 @@
228 char *zNewCmd = mprintf("\"%s\"", zOrigCmd);
229 wchar_t *zUnicode = fossil_utf8_to_unicode(zNewCmd);
230 if( g.fSystemTrace ) {
231 fossil_trace("SYSTEM: %s\n", zNewCmd);
232 }
233 fossil_assert_safe_command_string(zOrigCmd);
234 rc = _wsystem(zUnicode);
235 fossil_unicode_free(zUnicode);
236 free(zNewCmd);
237 #else
238 /* On unix, evaluate the command directly.
239 */
240 if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zOrigCmd);
241 fossil_assert_safe_command_string(zOrigCmd);
242
243 /* Unix systems should never shell-out while processing an HTTP request,
244 ** either via CGI, SCGI, or direct HTTP. The following assert verifies
245 ** this. And the following assert proves that Fossil is not vulnerable
246 ** to the ShellShock or BashDoor bug.
247

Keyboard Shortcuts

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