Fossil SCM
Make the repository database read-only if an HTTP request is not from the same origin. This is not required for security. It is just an extra layer of defense.
Commit
7c71f00ac8b239d4ae9cc40a74bdcf43d34c81fe971f44d282a446654140c6c0
Parent
abfec4dd5c62b86…
2 files changed
+17
-7
+3
+17
-7
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -680,31 +680,41 @@ | ||
| 680 | 680 | if( zRef==0 ) zRef = zDefault; |
| 681 | 681 | } |
| 682 | 682 | return zRef; |
| 683 | 683 | } |
| 684 | 684 | |
| 685 | + | |
| 686 | +/* | |
| 687 | +** Return true if the current request is coming from the same origin. | |
| 688 | +*/ | |
| 689 | +int cgi_same_origin(void){ | |
| 690 | + const char *zRef; | |
| 691 | + int nBase; | |
| 692 | + if( g.zBaseURL==0 ) return 0; | |
| 693 | + zRef = P("HTTP_REFERER"); | |
| 694 | + if( zRef==0 ) return 0; | |
| 695 | + nBase = (int)strlen(g.zBaseURL); | |
| 696 | + if( fossil_strncmp(g.zBaseURL,zRef,nBase)!=0 ) return 0; | |
| 697 | + if( zRef[nBase]!=0 && zRef[nBase]!='/' ) return 0; | |
| 698 | + return 1; | |
| 699 | +} | |
| 700 | + | |
| 685 | 701 | /* |
| 686 | 702 | ** Return true if the current request appears to be safe from a |
| 687 | 703 | ** Cross-Site Request Forgery (CSRF) attack. Conditions that must |
| 688 | 704 | ** be met: |
| 689 | 705 | ** |
| 690 | 706 | ** * The HTTP_REFERER must have the same origin |
| 691 | 707 | ** * The REQUEST_METHOD must be POST - or requirePost==0 |
| 692 | 708 | */ |
| 693 | 709 | int cgi_csrf_safe(int requirePost){ |
| 694 | - const char *zRef = P("HTTP_REFERER"); | |
| 695 | - int nBase; | |
| 696 | - if( zRef==0 ) return 0; | |
| 697 | 710 | if( requirePost ){ |
| 698 | 711 | const char *zMethod = P("REQUEST_METHOD"); |
| 699 | 712 | if( zMethod==0 ) return 0; |
| 700 | 713 | if( strcmp(zMethod,"POST")!=0 ) return 0; |
| 701 | 714 | } |
| 702 | - nBase = (int)strlen(g.zBaseURL); | |
| 703 | - if( fossil_strncmp(g.zBaseURL,zRef,nBase)!=0 ) return 0; | |
| 704 | - if( zRef[nBase]!=0 && zRef[nBase]!='/' ) return 0; | |
| 705 | - return 1; | |
| 715 | + return cgi_same_origin(); | |
| 706 | 716 | } |
| 707 | 717 | |
| 708 | 718 | /* |
| 709 | 719 | ** Information about all query parameters, post parameter, cookies and |
| 710 | 720 | ** CGI environment variables are stored in a hash table as follows: |
| 711 | 721 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -680,31 +680,41 @@ | |
| 680 | if( zRef==0 ) zRef = zDefault; |
| 681 | } |
| 682 | return zRef; |
| 683 | } |
| 684 | |
| 685 | /* |
| 686 | ** Return true if the current request appears to be safe from a |
| 687 | ** Cross-Site Request Forgery (CSRF) attack. Conditions that must |
| 688 | ** be met: |
| 689 | ** |
| 690 | ** * The HTTP_REFERER must have the same origin |
| 691 | ** * The REQUEST_METHOD must be POST - or requirePost==0 |
| 692 | */ |
| 693 | int cgi_csrf_safe(int requirePost){ |
| 694 | const char *zRef = P("HTTP_REFERER"); |
| 695 | int nBase; |
| 696 | if( zRef==0 ) return 0; |
| 697 | if( requirePost ){ |
| 698 | const char *zMethod = P("REQUEST_METHOD"); |
| 699 | if( zMethod==0 ) return 0; |
| 700 | if( strcmp(zMethod,"POST")!=0 ) return 0; |
| 701 | } |
| 702 | nBase = (int)strlen(g.zBaseURL); |
| 703 | if( fossil_strncmp(g.zBaseURL,zRef,nBase)!=0 ) return 0; |
| 704 | if( zRef[nBase]!=0 && zRef[nBase]!='/' ) return 0; |
| 705 | return 1; |
| 706 | } |
| 707 | |
| 708 | /* |
| 709 | ** Information about all query parameters, post parameter, cookies and |
| 710 | ** CGI environment variables are stored in a hash table as follows: |
| 711 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -680,31 +680,41 @@ | |
| 680 | if( zRef==0 ) zRef = zDefault; |
| 681 | } |
| 682 | return zRef; |
| 683 | } |
| 684 | |
| 685 | |
| 686 | /* |
| 687 | ** Return true if the current request is coming from the same origin. |
| 688 | */ |
| 689 | int cgi_same_origin(void){ |
| 690 | const char *zRef; |
| 691 | int nBase; |
| 692 | if( g.zBaseURL==0 ) return 0; |
| 693 | zRef = P("HTTP_REFERER"); |
| 694 | if( zRef==0 ) return 0; |
| 695 | nBase = (int)strlen(g.zBaseURL); |
| 696 | if( fossil_strncmp(g.zBaseURL,zRef,nBase)!=0 ) return 0; |
| 697 | if( zRef[nBase]!=0 && zRef[nBase]!='/' ) return 0; |
| 698 | return 1; |
| 699 | } |
| 700 | |
| 701 | /* |
| 702 | ** Return true if the current request appears to be safe from a |
| 703 | ** Cross-Site Request Forgery (CSRF) attack. Conditions that must |
| 704 | ** be met: |
| 705 | ** |
| 706 | ** * The HTTP_REFERER must have the same origin |
| 707 | ** * The REQUEST_METHOD must be POST - or requirePost==0 |
| 708 | */ |
| 709 | int cgi_csrf_safe(int requirePost){ |
| 710 | if( requirePost ){ |
| 711 | const char *zMethod = P("REQUEST_METHOD"); |
| 712 | if( zMethod==0 ) return 0; |
| 713 | if( strcmp(zMethod,"POST")!=0 ) return 0; |
| 714 | } |
| 715 | return cgi_same_origin(); |
| 716 | } |
| 717 | |
| 718 | /* |
| 719 | ** Information about all query parameters, post parameter, cookies and |
| 720 | ** CGI environment variables are stored in a hash table as follows: |
| 721 |
+3
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -2059,10 +2059,13 @@ | ||
| 2059 | 2059 | } |
| 2060 | 2060 | } |
| 2061 | 2061 | #endif |
| 2062 | 2062 | if( (pCmd->eCmdFlags & CMDFLAG_RAWCONTENT)==0 ){ |
| 2063 | 2063 | cgi_decode_post_parameters(); |
| 2064 | + if( !cgi_same_origin() ){ | |
| 2065 | + db_protect(PROTECT_READONLY); | |
| 2066 | + } | |
| 2064 | 2067 | } |
| 2065 | 2068 | if( g.fCgiTrace ){ |
| 2066 | 2069 | fossil_trace("######## Calling %s #########\n", pCmd->zName); |
| 2067 | 2070 | cgi_print_all(1, 1); |
| 2068 | 2071 | } |
| 2069 | 2072 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -2059,10 +2059,13 @@ | |
| 2059 | } |
| 2060 | } |
| 2061 | #endif |
| 2062 | if( (pCmd->eCmdFlags & CMDFLAG_RAWCONTENT)==0 ){ |
| 2063 | cgi_decode_post_parameters(); |
| 2064 | } |
| 2065 | if( g.fCgiTrace ){ |
| 2066 | fossil_trace("######## Calling %s #########\n", pCmd->zName); |
| 2067 | cgi_print_all(1, 1); |
| 2068 | } |
| 2069 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -2059,10 +2059,13 @@ | |
| 2059 | } |
| 2060 | } |
| 2061 | #endif |
| 2062 | if( (pCmd->eCmdFlags & CMDFLAG_RAWCONTENT)==0 ){ |
| 2063 | cgi_decode_post_parameters(); |
| 2064 | if( !cgi_same_origin() ){ |
| 2065 | db_protect(PROTECT_READONLY); |
| 2066 | } |
| 2067 | } |
| 2068 | if( g.fCgiTrace ){ |
| 2069 | fossil_trace("######## Calling %s #########\n", pCmd->zName); |
| 2070 | cgi_print_all(1, 1); |
| 2071 | } |
| 2072 |