Fossil SCM

Rename verify_all_options_cgi() to cgi_check_for_malice(). Add more comments explaining what the function is intended for. Add calls to cgi_check_for_malice() to a few new webpages.

drh 2023-07-16 10:35 verify-options-cgi
Commit 5a8063a8cbe8be922c8c9675b1e322a6f64e622c3cc43474538d55cbd1f58eea
+25 -7
--- src/cgi.c
+++ src/cgi.c
@@ -2709,18 +2709,36 @@
27092709
if( sqlite3_strglob("*iPad*", zAgent)==0 ) return 0;
27102710
return sqlite3_strlike("%mobile%", zAgent, 0)==0;
27112711
}
27122712
27132713
/*
2714
-** If the CGI environment contains any parameters which were not
2715
-** fetched via P(), PD(), or equivalent, its value is passed to
2716
-** cgi_value_spider_check(), fatally failing if the value looks to be
2717
-** malicious. The intent is to block attempts at attacks which post
2718
-** apparent SQL injection attempts using arbitrary query parameter
2719
-** names.
2714
+** Look for query or POST parameters that:
2715
+**
2716
+** (1) Have not been used
2717
+** (2) Appear to be malicious attempts to break into or otherwise
2718
+** harm the system, for example via SQL injection
2719
+**
2720
+** If any such parameters are seen, a 418 ("I'm a teapot") return is
2721
+** generated and processing aborts - this routine does not return.
2722
+**
2723
+** When Fossil is launched via CGI from althttpd, the 418 return signals
2724
+** the webserver to put the requestor IP address into "timeout", blocking
2725
+** subsequent requests for 5 minutes.
2726
+**
2727
+** Fossil is not subject to any SQL injections, as far as anybody knows.
2728
+** This routine is not necessary for the security of the system (though
2729
+** an extra layer of security never hurts). The main purpose here is
2730
+** to shutdown malicious attack spiders and prevent them from burning
2731
+** lots of CPU cycles and bogging down the website. In other words, the
2732
+** objective of this routine is to help prevent denial-of-service.
2733
+**
2734
+** Usage Hint: Put a call to this routine as late in the webpage
2735
+** implementation as possible, ideally just before it begins doing
2736
+** potentially CPU-intensive computations and after all query parameters
2737
+** have been consulted.
27202738
*/
2721
-void verify_all_options_cgi(void){
2739
+void cgi_check_for_malice(void){
27222740
struct QParam * pParam;
27232741
int i;
27242742
for(i = 0; i < nUsedQP; ++i){
27252743
pParam = &aParamQP[i];
27262744
if(0 == pParam->isFetched
27272745
--- src/cgi.c
+++ src/cgi.c
@@ -2709,18 +2709,36 @@
2709 if( sqlite3_strglob("*iPad*", zAgent)==0 ) return 0;
2710 return sqlite3_strlike("%mobile%", zAgent, 0)==0;
2711 }
2712
2713 /*
2714 ** If the CGI environment contains any parameters which were not
2715 ** fetched via P(), PD(), or equivalent, its value is passed to
2716 ** cgi_value_spider_check(), fatally failing if the value looks to be
2717 ** malicious. The intent is to block attempts at attacks which post
2718 ** apparent SQL injection attempts using arbitrary query parameter
2719 ** names.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2720 */
2721 void verify_all_options_cgi(void){
2722 struct QParam * pParam;
2723 int i;
2724 for(i = 0; i < nUsedQP; ++i){
2725 pParam = &aParamQP[i];
2726 if(0 == pParam->isFetched
2727
--- src/cgi.c
+++ src/cgi.c
@@ -2709,18 +2709,36 @@
2709 if( sqlite3_strglob("*iPad*", zAgent)==0 ) return 0;
2710 return sqlite3_strlike("%mobile%", zAgent, 0)==0;
2711 }
2712
2713 /*
2714 ** Look for query or POST parameters that:
2715 **
2716 ** (1) Have not been used
2717 ** (2) Appear to be malicious attempts to break into or otherwise
2718 ** harm the system, for example via SQL injection
2719 **
2720 ** If any such parameters are seen, a 418 ("I'm a teapot") return is
2721 ** generated and processing aborts - this routine does not return.
2722 **
2723 ** When Fossil is launched via CGI from althttpd, the 418 return signals
2724 ** the webserver to put the requestor IP address into "timeout", blocking
2725 ** subsequent requests for 5 minutes.
2726 **
2727 ** Fossil is not subject to any SQL injections, as far as anybody knows.
2728 ** This routine is not necessary for the security of the system (though
2729 ** an extra layer of security never hurts). The main purpose here is
2730 ** to shutdown malicious attack spiders and prevent them from burning
2731 ** lots of CPU cycles and bogging down the website. In other words, the
2732 ** objective of this routine is to help prevent denial-of-service.
2733 **
2734 ** Usage Hint: Put a call to this routine as late in the webpage
2735 ** implementation as possible, ideally just before it begins doing
2736 ** potentially CPU-intensive computations and after all query parameters
2737 ** have been consulted.
2738 */
2739 void cgi_check_for_malice(void){
2740 struct QParam * pParam;
2741 int i;
2742 for(i = 0; i < nUsedQP; ++i){
2743 pParam = &aParamQP[i];
2744 if(0 == pParam->isFetched
2745
+2 -1
--- src/info.c
+++ src/info.c
@@ -641,11 +641,10 @@
641641
@ No such object: %h(zName)
642642
style_finish_page();
643643
return;
644644
}
645645
zRe = P("regex");
646
- verify_all_options_cgi();
647646
if( zRe ) re_compile(&pRe, zRe, 0);
648647
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
649648
zParent = db_text(0,
650649
"SELECT uuid FROM plink, blob"
651650
" WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
@@ -661,10 +660,11 @@
661660
rid, rid
662661
);
663662
zBrName = branch_of_rid(rid);
664663
665664
diffType = preferred_diff_type();
665
+ cgi_check_for_malice();
666666
if( db_step(&q1)==SQLITE_ROW ){
667667
const char *zUuid = db_column_text(&q1, 0);
668668
int nUuid = db_column_bytes(&q1, 0);
669669
char *zEUser, *zEComment;
670670
const char *zUser;
@@ -1247,10 +1247,11 @@
12471247
}
12481248
pCfg = construct_diff_flags(diffType, &DCfg);
12491249
if( DCfg.diffFlags & DIFF_IGNORE_ALLWS ){
12501250
blob_appendf(&qp, "&w");
12511251
}
1252
+ cgi_check_for_malice();
12521253
style_set_current_feature("vdiff");
12531254
if( zBranch==0 ){
12541255
style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
12551256
}
12561257
if( diffType!=0 ){
12571258
--- src/info.c
+++ src/info.c
@@ -641,11 +641,10 @@
641 @ No such object: %h(zName)
642 style_finish_page();
643 return;
644 }
645 zRe = P("regex");
646 verify_all_options_cgi();
647 if( zRe ) re_compile(&pRe, zRe, 0);
648 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
649 zParent = db_text(0,
650 "SELECT uuid FROM plink, blob"
651 " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
@@ -661,10 +660,11 @@
661 rid, rid
662 );
663 zBrName = branch_of_rid(rid);
664
665 diffType = preferred_diff_type();
 
666 if( db_step(&q1)==SQLITE_ROW ){
667 const char *zUuid = db_column_text(&q1, 0);
668 int nUuid = db_column_bytes(&q1, 0);
669 char *zEUser, *zEComment;
670 const char *zUser;
@@ -1247,10 +1247,11 @@
1247 }
1248 pCfg = construct_diff_flags(diffType, &DCfg);
1249 if( DCfg.diffFlags & DIFF_IGNORE_ALLWS ){
1250 blob_appendf(&qp, "&w");
1251 }
 
1252 style_set_current_feature("vdiff");
1253 if( zBranch==0 ){
1254 style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
1255 }
1256 if( diffType!=0 ){
1257
--- src/info.c
+++ src/info.c
@@ -641,11 +641,10 @@
641 @ No such object: %h(zName)
642 style_finish_page();
643 return;
644 }
645 zRe = P("regex");
 
646 if( zRe ) re_compile(&pRe, zRe, 0);
647 zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
648 zParent = db_text(0,
649 "SELECT uuid FROM plink, blob"
650 " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
@@ -661,10 +660,11 @@
660 rid, rid
661 );
662 zBrName = branch_of_rid(rid);
663
664 diffType = preferred_diff_type();
665 cgi_check_for_malice();
666 if( db_step(&q1)==SQLITE_ROW ){
667 const char *zUuid = db_column_text(&q1, 0);
668 int nUuid = db_column_bytes(&q1, 0);
669 char *zEUser, *zEComment;
670 const char *zUser;
@@ -1247,10 +1247,11 @@
1247 }
1248 pCfg = construct_diff_flags(diffType, &DCfg);
1249 if( DCfg.diffFlags & DIFF_IGNORE_ALLWS ){
1250 blob_appendf(&qp, "&w");
1251 }
1252 cgi_check_for_malice();
1253 style_set_current_feature("vdiff");
1254 if( zBranch==0 ){
1255 style_submenu_element("Path", "%R/timeline?me=%T&you=%T", zFrom, zTo);
1256 }
1257 if( diffType!=0 ){
1258
+1
--- src/tar.c
+++ src/tar.c
@@ -831,10 +831,11 @@
831831
@ <input type="submit" value="Download">
832832
@ </form>
833833
style_finish_page();
834834
return;
835835
}
836
+ cgi_check_for_malice();
836837
blob_zero(&tarball);
837838
if( cache_read(&tarball, zKey)==0 ){
838839
tarball_of_checkin(rid, &tarball, zName, pInclude, pExclude, 0);
839840
cache_write(&tarball, zKey);
840841
}
841842
--- src/tar.c
+++ src/tar.c
@@ -831,10 +831,11 @@
831 @ <input type="submit" value="Download">
832 @ </form>
833 style_finish_page();
834 return;
835 }
 
836 blob_zero(&tarball);
837 if( cache_read(&tarball, zKey)==0 ){
838 tarball_of_checkin(rid, &tarball, zName, pInclude, pExclude, 0);
839 cache_write(&tarball, zKey);
840 }
841
--- src/tar.c
+++ src/tar.c
@@ -831,10 +831,11 @@
831 @ <input type="submit" value="Download">
832 @ </form>
833 style_finish_page();
834 return;
835 }
836 cgi_check_for_malice();
837 blob_zero(&tarball);
838 if( cache_read(&tarball, zKey)==0 ){
839 tarball_of_checkin(rid, &tarball, zName, pInclude, pExclude, 0);
840 cache_write(&tarball, zKey);
841 }
842
+1
--- src/zip.c
+++ src/zip.c
@@ -1014,10 +1014,11 @@
10141014
@ <input type="submit" value="Download">
10151015
@ </form>
10161016
style_finish_page();
10171017
return;
10181018
}
1019
+ cgi_check_for_malice();
10191020
blob_zero(&zip);
10201021
if( cache_read(&zip, zKey)==0 ){
10211022
zip_of_checkin(eType, rid, &zip, zName, pInclude, pExclude, 0);
10221023
cache_write(&zip, zKey);
10231024
}
10241025
--- src/zip.c
+++ src/zip.c
@@ -1014,10 +1014,11 @@
1014 @ <input type="submit" value="Download">
1015 @ </form>
1016 style_finish_page();
1017 return;
1018 }
 
1019 blob_zero(&zip);
1020 if( cache_read(&zip, zKey)==0 ){
1021 zip_of_checkin(eType, rid, &zip, zName, pInclude, pExclude, 0);
1022 cache_write(&zip, zKey);
1023 }
1024
--- src/zip.c
+++ src/zip.c
@@ -1014,10 +1014,11 @@
1014 @ <input type="submit" value="Download">
1015 @ </form>
1016 style_finish_page();
1017 return;
1018 }
1019 cgi_check_for_malice();
1020 blob_zero(&zip);
1021 if( cache_read(&zip, zKey)==0 ){
1022 zip_of_checkin(eType, rid, &zip, zName, pInclude, pExclude, 0);
1023 cache_write(&zip, zKey);
1024 }
1025

Keyboard Shortcuts

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