Fossil

Check-in [2269ac697f]
Login

Check-in [2269ac697f]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Write failed attempts to POST from a different origin into the error log. Add a new category to the error log filter for such messages.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 2269ac697f5b06117c94de896f0b6adf852485fd463af7e08c37ec3fd6751319
User & Date: drh 2025-03-17 13:16:58.912
Context
2025-03-17
13:25
Fix the "All Messages" link on the summary table for the /errorlog page. ... (check-in: 8025b52a90 user: drh tags: trunk)
13:16
Write failed attempts to POST from a different origin into the error log. Add a new category to the error log filter for such messages. ... (check-in: 2269ac697f user: drh tags: trunk)
12:46
Fix the cgi_same_origin() routine so that it is able to deal with HTTP-encoded REFERER strings in the request header. Probable fix for the problem reported at [forum:/forumpost/dc5baee6085eb590|forum post dc5baee6085]. ... (check-in: 3046c5e960 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/cgi.c.
686
687
688
689
690
691
692




693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714



715
716
717
718
719
720
721
  }
  return zRef;
}


/*
** Return true if the current request is coming from the same origin.




*/
int cgi_same_origin(void){
  const char *zRef;
  char *zToFree = 0;
  int nBase;
  int rc;
  if( g.zBaseURL==0 ) return 0;
  zRef = P("HTTP_REFERER");
  if( zRef==0 ) return 0;
  if( strchr(zRef,'%')!=0 ){
    zToFree = strdup(zRef);
    dehttpize(zToFree);
    zRef = zToFree;
  }
  nBase = (int)strlen(g.zBaseURL);
  if( fossil_strncmp(g.zBaseURL,zRef,nBase)!=0 ){
    rc = 0;
  }else if( zRef[nBase]!=0 && zRef[nBase]!='/' ){
    rc = 0;
  }else{
    rc = 1;
  }



  fossil_free(zToFree);
  return rc;
}

/*
** Return true if the current CGI request is a POST request
*/







>
>
>
>

|




















>
>
>







686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
  }
  return zRef;
}


/*
** Return true if the current request is coming from the same origin.
**
** If the request comes from a different origin and bErrorLog is true, then
** put a warning message on the error log as this was a possible hack
** attempt.
*/
int cgi_same_origin(int bErrorLog){
  const char *zRef;
  char *zToFree = 0;
  int nBase;
  int rc;
  if( g.zBaseURL==0 ) return 0;
  zRef = P("HTTP_REFERER");
  if( zRef==0 ) return 0;
  if( strchr(zRef,'%')!=0 ){
    zToFree = strdup(zRef);
    dehttpize(zToFree);
    zRef = zToFree;
  }
  nBase = (int)strlen(g.zBaseURL);
  if( fossil_strncmp(g.zBaseURL,zRef,nBase)!=0 ){
    rc = 0;
  }else if( zRef[nBase]!=0 && zRef[nBase]!='/' ){
    rc = 0;
  }else{
    rc = 1;
  }
  if( rc==0 && bErrorLog ){
    fossil_errorlog("warning: POST from different origin");
  }
  fossil_free(zToFree);
  return rc;
}

/*
** Return true if the current CGI request is a POST request
*/
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
**     1:   Request comes from the same origin
**     2:   (1) plus it is a POST request
**     3:   (2) plus there is a valid "csrf" token in the request
*/
int cgi_csrf_safe(int securityLevel){
  if( g.okCsrf<0 ) return 0;
  if( g.okCsrf==0 ){
    if( !cgi_same_origin() ){
      g.okCsrf = -1;
    }else{
      g.okCsrf = 1;
      if( cgi_is_post_request() ){
        g.okCsrf = 2;
        if( fossil_strcmp(P("csrf"), g.zCsrfToken)==0 ){
          g.okCsrf = 3;







|







751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
**     1:   Request comes from the same origin
**     2:   (1) plus it is a POST request
**     3:   (2) plus there is a valid "csrf" token in the request
*/
int cgi_csrf_safe(int securityLevel){
  if( g.okCsrf<0 ) return 0;
  if( g.okCsrf==0 ){
    if( !cgi_same_origin(1) ){
      g.okCsrf = -1;
    }else{
      g.okCsrf = 1;
      if( cgi_is_post_request() ){
        g.okCsrf = 2;
        if( fossil_strcmp(P("csrf"), g.zCsrfToken)==0 ){
          g.okCsrf = 3;
Changes to src/main.c.
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
        json_bootstrap_late();
        jsonOnce = 1;
      }
    }
#endif
    if( (pCmd->eCmdFlags & CMDFLAG_RAWCONTENT)==0 ){
      cgi_decode_post_parameters();
      if( !cgi_same_origin() ){
        isReadonly = 1;
        db_protect(PROTECT_READONLY);
      }
    }
    if( g.fCgiTrace ){
      fossil_trace("######## Calling %s #########\n", pCmd->zName);
      cgi_print_all(1, 1, 0);







|







2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
        json_bootstrap_late();
        jsonOnce = 1;
      }
    }
#endif
    if( (pCmd->eCmdFlags & CMDFLAG_RAWCONTENT)==0 ){
      cgi_decode_post_parameters();
      if( !cgi_same_origin(0) ){
        isReadonly = 1;
        db_protect(PROTECT_READONLY);
      }
    }
    if( g.fCgiTrace ){
      fossil_trace("######## Calling %s #########\n", pCmd->zName);
      cgi_print_all(1, 1, 0);
Changes to src/security_audit.c.
811
812
813
814
815
816
817

818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835

836
837
838
839
840
841
842
**
** Show the content of the error log.  Only the administrator can view
** this page.
**
**    y=0x01          Show only hack attempts
**    y=0x02          Show only panics and assertion faults
**    y=0x04          Show hung backoffice processes

**    y=0x40          Show other uncategorized messages
**
** If y is omitted or is zero, a count of the various message types is
** shown.
*/
void errorlog_page(void){
  i64 szFile;
  FILE *in;
  char *zLog;
  const char *zType = P("y");
  static const int eAllTypes = 0x47;
  long eType = 0;
  int bOutput = 0;
  int prevWasTime = 0;
  int nHack = 0;
  int nPanic = 0;
  int nOther = 0;
  int nHang = 0;

  char z[10000];
  char zTime[10000];

  login_check_credentials();
  if( !g.perm.Admin ){
    login_needed(0);
    return;







>










|







>







811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
**
** Show the content of the error log.  Only the administrator can view
** this page.
**
**    y=0x01          Show only hack attempts
**    y=0x02          Show only panics and assertion faults
**    y=0x04          Show hung backoffice processes
**    y=0x08          Show POST requests from a different origin
**    y=0x40          Show other uncategorized messages
**
** If y is omitted or is zero, a count of the various message types is
** shown.
*/
void errorlog_page(void){
  i64 szFile;
  FILE *in;
  char *zLog;
  const char *zType = P("y");
  static const int eAllTypes = 0x4f;
  long eType = 0;
  int bOutput = 0;
  int prevWasTime = 0;
  int nHack = 0;
  int nPanic = 0;
  int nOther = 0;
  int nHang = 0;
  int nXPost = 0;
  char z[10000];
  char zTime[10000];

  login_check_credentials();
  if( !g.perm.Admin ){
    login_needed(0);
    return;
899
900
901
902
903
904
905



906
907
908
909
910
911
912
    }
    if( eType & 0x02 ){
      @ <li>Panics and assertion faults
    }
    if( eType & 0x04 ){
      @ <li>Hung backoffice processes
    }



    if( eType & 0x40 ){
      @ <li>Other uncategorized messages
    }
    @ </ul>
  }
  @ <hr>
  if( eType ){







>
>
>







901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
    }
    if( eType & 0x02 ){
      @ <li>Panics and assertion faults
    }
    if( eType & 0x04 ){
      @ <li>Hung backoffice processes
    }
    if( eType & 0x08 ){
      @ <li>POST requests from different origin
    }
    if( eType & 0x40 ){
      @ <li>Other uncategorized messages
    }
    @ </ul>
  }
  @ <hr>
  if( eType ){
921
922
923
924
925
926
927
928





929
930
931
932
933
934
935
      if( (strncmp(z,"panic: ", 7)==0 || strstr(z," assertion fault ")!=0) ){
        bOutput = (eType & 0x02)!=0;
        nPanic++;
      }else
      if( sqlite3_strglob("warning: backoffice process * still *",z)==0 ){
        bOutput = (eType & 0x04)!=0;
        nHang++;
      }else{





        bOutput = (eType & 0x40)!=0;
        nOther++;
      }
      if( bOutput ){
        @ %h(zTime)\
      }
    }







|
>
>
>
>
>







926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
      if( (strncmp(z,"panic: ", 7)==0 || strstr(z," assertion fault ")!=0) ){
        bOutput = (eType & 0x02)!=0;
        nPanic++;
      }else
      if( sqlite3_strglob("warning: backoffice process * still *",z)==0 ){
        bOutput = (eType & 0x04)!=0;
        nHang++;
      }else
      if( sqlite3_strglob("warning: POST from different origin*",z)==0 ){
        bOutput = (eType & 0x08)!=0;
        nXPost++;
      }else
      {
        bOutput = (eType & 0x40)!=0;
        nOther++;
      }
      if( bOutput ){
        @ %h(zTime)\
      }
    }
946
947
948
949
950
951
952
953
954
955
956
957

958
959
960
961
962
963

964

965
966
967
968
969

970
971

972
973
974
975
976
977

978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
    }
  }
  fclose(in);
  if( eType ){
    @ </pre>
  }
  if( eType==0 ){
    int nNonHack = nPanic+nHang+nOther;
    int nTotal = nNonHack + nHack;
    @ <p><table border="a" cellspacing="0" cellpadding="5">
    @ <tr><td align="right">%d(nPanic)</td>
    if( nPanic>0 ){

      @     <td><a href="./errorlog?y=2">Panics</a></td>
    } else {
      @     <td>Panics</td>
    }
    @ <tr><td align="right">%d(nHack)</td>
    if( nHack>0 ){

      @     <td><a href="./errorlog?y=1">Hack Attempts</a></td>

      if( nNonHack ){
        @ <tr><td align="right">%d(nNonHack)</td>
        @ <td><a href="%R/errorlog?y=70">Other than hack attempts</a></td>
      }
    }else{

      @     <td>Hack Attempts</td>
    }

    @ <tr><td align="right">%d(nHang)</td>
    if( nHang>0 ){
      @     <td><a href="./errorlog?y=4/">Hung Backoffice</a></td>
    }else{
      @     <td>Hung Backoffice</td>
    }

    @ <tr><td align="right">%d(nHang)</td>
    if( nOther>0 ){
      @     <td><a href="./errorlog?y=64/">Other</a></td>
    }else{
      @     <td>Other</td>
    }
    @ <tr><td align="right">%d(nTotal)</td>
    if( nTotal>0 ){
      @     <td><a href="./errorlog">All Messages</a></td>
    }else{
      @     <td>All Messages</td>
    }
    @ </table>
  }
  style_finish_page();
}







|
|

<

>

<
<

<

>

>
|
|
|
|
|
>
|

>
|
<
|
<
<

>
|
<
|
<
<











956
957
958
959
960
961
962
963
964
965

966
967
968


969

970
971
972
973
974
975
976
977
978
979
980
981
982
983

984


985
986
987

988


989
990
991
992
993
994
995
996
997
998
999
    }
  }
  fclose(in);
  if( eType ){
    @ </pre>
  }
  if( eType==0 ){
    int nNonHack = nPanic + nHang + nOther;
    int nTotal = nNonHack + nHack + nXPost;
    @ <p><table border="a" cellspacing="0" cellpadding="5">

    if( nPanic>0 ){
      @ <tr><td align="right">%d(nPanic)</td>
      @     <td><a href="./errorlog?y=2">Panics</a></td>


    }

    if( nHack>0 ){
      @ <tr><td align="right">%d(nHack)</td>
      @     <td><a href="./errorlog?y=1">Hack Attempts</a></td>
    }
    if( nHang>0 ){
      @ <tr><td align="right">%d(nHang)</td>
      @     <td><a href="./errorlog?y=4/">Hung Backoffice</a></td>
    }
    if( nXPost>0 ){
      @ <tr><td align="right">%d(nXPost)</td>
      @     <td><a href="./errorlog?y=8/">POSTs from different origin</a></td>
    }
    if( nOther>0 ){
      @ <tr><td align="right">%d(nOther)</td>

      @     <td><a href="./errorlog?y=64/">Other</a></td>


    }
    if( nHack+nXPost>0 && nNonHack>0 ){
      @ <tr><td align="right">%d(nNonHack)</td>

      @ <td><a href="%R/errorlog?y=70">Other than hack attempts</a></td>


    }
    @ <tr><td align="right">%d(nTotal)</td>
    if( nTotal>0 ){
      @     <td><a href="./errorlog">All Messages</a></td>
    }else{
      @     <td>All Messages</td>
    }
    @ </table>
  }
  style_finish_page();
}