Fossil

Changes On Branch spider-sql-detection
Login

Changes On Branch spider-sql-detection

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

Changes In Branch spider-sql-detection Excluding Merge-Ins

This is equivalent to a diff from 391526232e to 936c122ff9

2023-02-07
16:28
Merge spider-sql-detection branch into trunk, per /chat discussion. ... (check-in: 534c10f6b8 user: stephan tags: trunk)
16:24
Apply the spider SQL check to the diff URL argument of the /vdiff page. Improve some related docs. ... (Closed-Leaf check-in: 936c122ff9 user: stephan tags: spider-sql-detection)
16:18
Inititial draft of an attempt to intercept certain SQL injection attacks recently seen made against fossil repos. Its effect can be seen by visiting: /vdiff?from=trunk&to=trunk&w=drop ... (check-in: 61a608a2df user: stephan tags: spider-sql-detection)
2023-02-06
13:37
Make the --nossl and --nocompress server options available for CGI requests. ... (check-in: 391526232e user: florian tags: trunk)
2023-02-03
15:59
Fix another harmless compiler warning reported by Clang-15. ... (check-in: de184889a7 user: danield tags: trunk)
2019-02-24
16:46
Make the --nossl and --nocompress server options available for CGI requests. ... (Closed-Leaf check-in: a41ef5e6a2 user: florian tags: cgi-server-options)

Changes to src/cgi.c.

92
93
94
95
96
97
98
99
100
101
102
103
104
105


106
107
108
109
110
111
112

#if INTERFACE
/*
** Shortcuts for cgi_parameter.  P("x") returns the value of query parameter
** or cookie "x", or NULL if there is no such parameter or cookie.  PD("x","y")
** does the same except "y" is returned in place of NULL if there is not match.
*/
#define P(x)        cgi_parameter((x),0)
#define PD(x,y)     cgi_parameter((x),(y))
#define PT(x)       cgi_parameter_trimmed((x),0)
#define PDT(x,y)    cgi_parameter_trimmed((x),(y))
#define PB(x)       cgi_parameter_boolean(x)
#define PCK(x)      cgi_parameter_checked(x,1)
#define PIF(x,y)    cgi_parameter_checked(x,y)



/*
** Shortcut for the cgi_printf() routine.  Instead of using the
**
**    @ ...
**
** notation provided by the translate.c utility, you can also







|
|
|
|
|
|
|
>
>







92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

#if INTERFACE
/*
** Shortcuts for cgi_parameter.  P("x") returns the value of query parameter
** or cookie "x", or NULL if there is no such parameter or cookie.  PD("x","y")
** does the same except "y" is returned in place of NULL if there is not match.
*/
#define P(x)          cgi_parameter((x),0)
#define PD(x,y)       cgi_parameter((x),(y))
#define PT(x)         cgi_parameter_trimmed((x),0)
#define PDT(x,y)      cgi_parameter_trimmed((x),(y))
#define PB(x)         cgi_parameter_boolean(x)
#define PCK(x)        cgi_parameter_checked(x,1)
#define PIF(x,y)      cgi_parameter_checked(x,y)
#define P_NoSQL(x)    cgi_parameter_nosql((x),0)
#define PD_NoSQL(x,y) cgi_parameter_nosql((x),(y))

/*
** Shortcut for the cgi_printf() routine.  Instead of using the
**
**    @ ...
**
** notation provided by the translate.c utility, you can also
1502
1503
1504
1505
1506
1507
1508













































1509
1510
1511
1512
1513
1514
1515
      CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue));
      return zValue;
    }
  }
  CGIDEBUG(("no-match [%s]\n", zName));
  return zDefault;
}














































/*
** Return the value of the first defined query parameter or cookie whose
** name appears in the list of arguments.  Or if no parameter is found,
** return NULL.
*/
const char *cgi_coalesce(const char *zName, ...){







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
      CGIDEBUG(("env-match [%s] = [%s]\n", zName, zValue));
      return zValue;
    }
  }
  CGIDEBUG(("no-match [%s]\n", zName));
  return zDefault;
}

/*
** Renders the "begone, spider" page and exists.
*/
static void cgi_begone_spider(void){
  Blob content = empty_blob;

  cgi_set_content(&content);
  style_set_current_feature("test");
  style_header("Spider Detected");
  @ <h2>Begone, Spider!</h2>
  @ <p>This page was generated because Fossil believes it has
  @ detected a spider-based attack. If you believe you are seeing
  @ this in error, please contact us on the forum: https://fossil-scm.org/forum
  style_finish_page();
  cgi_set_status(404,"Spider Detected");
  cgi_reply();
  exit(0);
}

/*
** If might_be_sql() returns true for the given string, calls
** cgi_begin_spider() and does not return, else this function has no
** side effects. The range of checks performed by this function may
** be extended in the future.
*/
void cgi_value_spider_check(const char *zTxt){
  if( might_be_sql(zTxt) ){
    cgi_begone_spider();
  }
}

/*
** A variant of cgi_parameter() with the same semantics except that if
** cgi_parameter(zName,zDefault) returns a value other than zDefault
** then it passes that value to cgi_value_spider_check().
*/
const char *cgi_parameter_nosql(const char *zName, const char *zDefault){
  const char *zTxt = cgi_parameter(zName, zDefault);

  if( zTxt!=zDefault ){
    cgi_value_spider_check(zTxt);
  }
  return zTxt;
}

/*
** Return the value of the first defined query parameter or cookie whose
** name appears in the list of arguments.  Or if no parameter is found,
** return NULL.
*/
const char *cgi_coalesce(const char *zName, ...){

Changes to src/info.c.

451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
** parameters and the to boolean arguments.
*/
DiffConfig *construct_diff_flags(int diffType, DiffConfig *pCfg){
  u64 diffFlags = 0;  /* Zero means do not show any diff */
  if( diffType>0 ){
    int x;
    if( diffType==2 ) diffFlags = DIFF_SIDEBYSIDE;
    if( P("w") )      diffFlags |= DIFF_IGNORE_ALLWS;
    if( PD("noopt",0)!=0 ) diffFlags |= DIFF_NOOPT;
    diffFlags |= DIFF_STRIP_EOLCR;
    diff_config_init(pCfg, diffFlags);

    /* "dc" query parameter determines lines of context */
    x = atoi(PD("dc","7"));
    if( x>0 ) pCfg->nContext = x;








|
|







451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
** parameters and the to boolean arguments.
*/
DiffConfig *construct_diff_flags(int diffType, DiffConfig *pCfg){
  u64 diffFlags = 0;  /* Zero means do not show any diff */
  if( diffType>0 ){
    int x;
    if( diffType==2 ) diffFlags = DIFF_SIDEBYSIDE;
    if( P_NoSQL("w") )  diffFlags |= DIFF_IGNORE_ALLWS;
    if( PD_NoSQL("noopt",0)!=0 ) diffFlags |= DIFF_NOOPT;
    diffFlags |= DIFF_STRIP_EOLCR;
    diff_config_init(pCfg, diffFlags);

    /* "dc" query parameter determines lines of context */
    x = atoi(PD("dc","7"));
    if( x>0 ) pCfg->nContext = x;

646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
     "       datetime(omtime,toLocal()), mtime"
     "  FROM blob, event"
     " WHERE blob.rid=%d"
     "   AND event.objid=%d",
     rid, rid
  );
  zBrName = branch_of_rid(rid);
  
  diffType = preferred_diff_type();
  if( db_step(&q1)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&q1, 0);
    int nUuid = db_column_bytes(&q1, 0);
    char *zEUser, *zEComment;
    const char *zUser;
    const char *zOrigUser;







|







646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
     "       datetime(omtime,toLocal()), mtime"
     "  FROM blob, event"
     " WHERE blob.rid=%d"
     "   AND event.objid=%d",
     rid, rid
  );
  zBrName = branch_of_rid(rid);

  diffType = preferred_diff_type();
  if( db_step(&q1)==SQLITE_ROW ){
    const char *zUuid = db_column_text(&q1, 0);
    int nUuid = db_column_bytes(&q1, 0);
    char *zEUser, *zEComment;
    const char *zUser;
    const char *zOrigUser;
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
    blob_reset(&wiki_add_links);
  }else{
    style_header("Check-in Information");
    login_anonymous_available();
  }
  db_finalize(&q1);
  @ </div>
  builtin_request_js("accordion.js");  
  if( !PB("nowiki") ){
    wiki_render_associated("checkin", zUuid, 0);
  }
  render_backlink_graph(zUuid, 
       "<div class=\"section accordion\">References</div>\n");
  @ <div class="section accordion">Context</div><div class="accordion_panel">
  render_checkin_context(rid, 0, 0, 0);
  @ </div><div class="section accordion">Changes</div>
  @ <div class="accordion_panel">
  @ <div class="sectionmenu">
  pCfg = construct_diff_flags(diffType, &DCfg);







|



|







867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
    blob_reset(&wiki_add_links);
  }else{
    style_header("Check-in Information");
    login_anonymous_available();
  }
  db_finalize(&q1);
  @ </div>
  builtin_request_js("accordion.js");
  if( !PB("nowiki") ){
    wiki_render_associated("checkin", zUuid, 0);
  }
  render_backlink_graph(zUuid,
       "<div class=\"section accordion\">References</div>\n");
  @ <div class="section accordion">Context</div><div class="accordion_panel">
  render_checkin_context(rid, 0, 0, 0);
  @ </div><div class="section accordion">Changes</div>
  @ <div class="accordion_panel">
  @ <div class="sectionmenu">
  pCfg = construct_diff_flags(diffType, &DCfg);
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
    }
  }
  pTo = vdiff_parse_manifest("to", &ridTo);
  if( pTo==0 ) return;
  pFrom = vdiff_parse_manifest("from", &ridFrom);
  if( pFrom==0 ) return;
  zGlob = P("glob");
  zFrom = P("from");
  zTo = P("to");
  if( bInvert ){
    Manifest *pTemp = pTo;
    const char *zTemp = zTo;
    pTo = pFrom;
    pFrom = pTemp;
    zTo = zFrom;
    zFrom = zTemp;







|
|







1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
    }
  }
  pTo = vdiff_parse_manifest("to", &ridTo);
  if( pTo==0 ) return;
  pFrom = vdiff_parse_manifest("from", &ridFrom);
  if( pFrom==0 ) return;
  zGlob = P("glob");
  zFrom = P_NoSQL("from");
  zTo = P_NoSQL("to");
  if( bInvert ){
    Manifest *pTemp = pTo;
    const char *zTemp = zTo;
    pTo = pFrom;
    pFrom = pTemp;
    zTo = zFrom;
    zFrom = zTemp;
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
  static char zDflt[2]
    /*static b/c cookie_link_parameter() does not copy it!*/;
  dflt = db_get_int("preferred-diff-type",-99);
  if( dflt<=0 ) dflt = user_agent_is_likely_mobile() ? 1 : 2;
  zDflt[0] = dflt + '0';
  zDflt[1] = 0;
  cookie_link_parameter("diff","diff", zDflt);
  return atoi(PD("diff",zDflt));
}


/*
** WEBPAGE: fdiff
** URL: fdiff?v1=HASH&v2=HASH
**







|







1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
  static char zDflt[2]
    /*static b/c cookie_link_parameter() does not copy it!*/;
  dflt = db_get_int("preferred-diff-type",-99);
  if( dflt<=0 ) dflt = user_agent_is_likely_mobile() ? 1 : 2;
  zDflt[0] = dflt + '0';
  zDflt[1] = 0;
  cookie_link_parameter("diff","diff", zDflt);
  return atoi(PD_NoSQL("diff",zDflt));
}


/*
** WEBPAGE: fdiff
** URL: fdiff?v1=HASH&v2=HASH
**
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
      if( db_step(&q)==SQLITE_ROW ){
        rid = db_column_int(&q, 0);
        zCI = fossil_strdup(db_column_text(&q, 1));
        zCIUuid = fossil_strdup(zCI);
        url_add_parameter(&url, "ci", zCI);
      }
      db_finalize(&q);
      if( rid==0 ){     
        style_header("No such file");
        @ File '%h(zName)' does not exist in this repository.
      }
    }else{
      style_header("No such artifact");
      @ Artifact '%h(zName)' does not exist in this repository.
    }







|







2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
      if( db_step(&q)==SQLITE_ROW ){
        rid = db_column_int(&q, 0);
        zCI = fossil_strdup(db_column_text(&q, 1));
        zCIUuid = fossil_strdup(zCI);
        url_add_parameter(&url, "ci", zCI);
      }
      db_finalize(&q);
      if( rid==0 ){
        style_header("No such file");
        @ File '%h(zName)' does not exist in this repository.
      }
    }else{
      style_header("No such artifact");
      @ Artifact '%h(zName)' does not exist in this repository.
    }
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
      db_column_text(&q,2),
      db_column_text(&q,3));
  }
  db_finalize(&q);
}

#if INTERFACE
/* 
** Description of a check-in relative to an earlier, tagged check-in.
*/
typedef struct CommitDescr {
  char *zRelTagname;        /* Tag name on the relative check-in */
  int nCommitsSince;        /* Number of commits since then */
  char *zCommitHash;        /* Hash of the described check-in */
  int isDirty;              /* Working directory has uncommitted changes */







|







3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
      db_column_text(&q,2),
      db_column_text(&q,3));
  }
  db_finalize(&q);
}

#if INTERFACE
/*
** Description of a check-in relative to an earlier, tagged check-in.
*/
typedef struct CommitDescr {
  char *zRelTagname;        /* Tag name on the relative check-in */
  int nCommitsSince;        /* Number of commits since then */
  char *zCommitHash;        /* Hash of the described check-in */
  int isDirty;              /* Working directory has uncommitted changes */

Changes to src/lookslike.c.

458
459
460
461
462
463
464


















  fossil_print("Has flag LOOK_LONG: %s\n",(lookFlags&LOOK_LONG)?"yes":"no");
  fossil_print("Has flag LOOK_INVALID: %s\n",
               (lookFlags&LOOK_INVALID)?"yes":"no");
  fossil_print("Has flag LOOK_ODD: %s\n",(lookFlags&LOOK_ODD)?"yes":"no");
  fossil_print("Has flag LOOK_SHORT: %s\n",(lookFlags&LOOK_SHORT)?"yes":"no");
  blob_reset(&blob);
}

























>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
  fossil_print("Has flag LOOK_LONG: %s\n",(lookFlags&LOOK_LONG)?"yes":"no");
  fossil_print("Has flag LOOK_INVALID: %s\n",
               (lookFlags&LOOK_INVALID)?"yes":"no");
  fossil_print("Has flag LOOK_ODD: %s\n",(lookFlags&LOOK_ODD)?"yes":"no");
  fossil_print("Has flag LOOK_SHORT: %s\n",(lookFlags&LOOK_SHORT)?"yes":"no");
  blob_reset(&blob);
}

/*
** Returns true if the given text contains certain keywords or
** punctuation which indicate that it might be SQL. This is only a
** high-level check, not intended to be used for any application-level
** logic other than in defense against spiders in limited contexts.
*/
int might_be_sql(const char *zTxt){
  if( zTxt==0 || zTxt[0]==0 ) return 0;
#define L(GLOB) 0==sqlite3_strlike("%" GLOB "%",zTxt, '%')
  return L(";") || L("'")
    || L("select") || L("order") || L("drop")
    || L(" and ") || L(" or ")
    /* ^^^^^ noting that \n and \t should also be checked */
    || L("null") || L("delete") || L("update")
    || L("waitfor");
#undef L
}