Fossil SCM
Further improvements to the attack-spider detection mechanism.
Commit
eb7fad0cd3621013177ec8a4604c60bddc5dcb8a22de216718d19aebff5f7b95
Parent
00ae2391e4c7dea…
2 files changed
+2
-2
+11
-4
+2
-2
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -1516,11 +1516,11 @@ | ||
| 1516 | 1516 | Blob content = empty_blob; |
| 1517 | 1517 | |
| 1518 | 1518 | cgi_set_content(&content); |
| 1519 | 1519 | style_set_current_feature("test"); |
| 1520 | 1520 | style_header("Malicious Query Detected"); |
| 1521 | - @ <h2>Begone, Hacker!</h2> | |
| 1521 | + @ <h2>Begone, Fiend!</h2> | |
| 1522 | 1522 | @ <p>This page was generated because Fossil believes it has |
| 1523 | 1523 | @ detected an SQL injection attack. If you believe you are seeing |
| 1524 | 1524 | @ this in error, contact the developers on the Fossil-SCM Forum. Type |
| 1525 | 1525 | @ "fossil-scm forum" into any search engine to locate the Fossil-SCM Forum. |
| 1526 | 1526 | style_finish_page(); |
| @@ -1529,11 +1529,11 @@ | ||
| 1529 | 1529 | exit(0); |
| 1530 | 1530 | } |
| 1531 | 1531 | |
| 1532 | 1532 | /* |
| 1533 | 1533 | ** If looks_like_sql_injection() returns true for the given string, calls |
| 1534 | -** cgi_begin_spider() and does not return, else this function has no | |
| 1534 | +** cgi_begone_spider() and does not return, else this function has no | |
| 1535 | 1535 | ** side effects. The range of checks performed by this function may |
| 1536 | 1536 | ** be extended in the future. |
| 1537 | 1537 | ** |
| 1538 | 1538 | ** Checks are omitted for any logged-in user. |
| 1539 | 1539 | ** |
| 1540 | 1540 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1516,11 +1516,11 @@ | |
| 1516 | Blob content = empty_blob; |
| 1517 | |
| 1518 | cgi_set_content(&content); |
| 1519 | style_set_current_feature("test"); |
| 1520 | style_header("Malicious Query Detected"); |
| 1521 | @ <h2>Begone, Hacker!</h2> |
| 1522 | @ <p>This page was generated because Fossil believes it has |
| 1523 | @ detected an SQL injection attack. If you believe you are seeing |
| 1524 | @ this in error, contact the developers on the Fossil-SCM Forum. Type |
| 1525 | @ "fossil-scm forum" into any search engine to locate the Fossil-SCM Forum. |
| 1526 | style_finish_page(); |
| @@ -1529,11 +1529,11 @@ | |
| 1529 | exit(0); |
| 1530 | } |
| 1531 | |
| 1532 | /* |
| 1533 | ** If looks_like_sql_injection() returns true for the given string, calls |
| 1534 | ** cgi_begin_spider() and does not return, else this function has no |
| 1535 | ** side effects. The range of checks performed by this function may |
| 1536 | ** be extended in the future. |
| 1537 | ** |
| 1538 | ** Checks are omitted for any logged-in user. |
| 1539 | ** |
| 1540 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1516,11 +1516,11 @@ | |
| 1516 | Blob content = empty_blob; |
| 1517 | |
| 1518 | cgi_set_content(&content); |
| 1519 | style_set_current_feature("test"); |
| 1520 | style_header("Malicious Query Detected"); |
| 1521 | @ <h2>Begone, Fiend!</h2> |
| 1522 | @ <p>This page was generated because Fossil believes it has |
| 1523 | @ detected an SQL injection attack. If you believe you are seeing |
| 1524 | @ this in error, contact the developers on the Fossil-SCM Forum. Type |
| 1525 | @ "fossil-scm forum" into any search engine to locate the Fossil-SCM Forum. |
| 1526 | style_finish_page(); |
| @@ -1529,11 +1529,11 @@ | |
| 1529 | exit(0); |
| 1530 | } |
| 1531 | |
| 1532 | /* |
| 1533 | ** If looks_like_sql_injection() returns true for the given string, calls |
| 1534 | ** cgi_begone_spider() and does not return, else this function has no |
| 1535 | ** side effects. The range of checks performed by this function may |
| 1536 | ** be extended in the future. |
| 1537 | ** |
| 1538 | ** Checks are omitted for any logged-in user. |
| 1539 | ** |
| 1540 |
+11
-4
| --- src/lookslike.c | ||
| +++ src/lookslike.c | ||
| @@ -467,28 +467,35 @@ | ||
| 467 | 467 | ** Return true if z[i] is the whole word given by zWord |
| 468 | 468 | */ |
| 469 | 469 | static int isWholeWord(const char *z, unsigned int i, const char *zWord, int n){ |
| 470 | 470 | if( i>0 && fossil_isalnum(z[i-1]) ) return 0; |
| 471 | 471 | if( sqlite3_strnicmp(z+i, zWord, n)!=0 ) return 0; |
| 472 | - if( z[i+n]!=0&& fossil_isalnum(z[i+n]) ) return 0; | |
| 472 | + if( fossil_isalnum(z[i+n]) ) return 0; | |
| 473 | 473 | return 1; |
| 474 | 474 | } |
| 475 | 475 | |
| 476 | 476 | /* |
| 477 | 477 | ** Returns true if the given text contains certain keywords or |
| 478 | -** punctuation which indicate that it might be SQL. This is only a | |
| 479 | -** high-level check, not intended to be used for any application-level | |
| 480 | -** logic other than in defense against spiders in limited contexts. | |
| 478 | +** punctuation which indicate that it might be an SQL injection attempt | |
| 479 | +** or some other kind of mischief. | |
| 480 | +** | |
| 481 | +** This is not a defense against vulnerabilities in the Fossil code. | |
| 482 | +** Rather, this is part of an effort to do early detection of malicious | |
| 483 | +** spiders to avoid them using up too many CPU cycles. | |
| 481 | 484 | */ |
| 482 | 485 | int looks_like_sql_injection(const char *zTxt){ |
| 483 | 486 | unsigned int i; |
| 484 | 487 | if( zTxt==0 ) return 0; |
| 485 | 488 | for(i=0; zTxt[i]; i++){ |
| 486 | 489 | switch( zTxt[i] ){ |
| 487 | 490 | case ';': |
| 488 | 491 | case '\'': |
| 489 | 492 | return 1; |
| 493 | + case '/': /* 0123456789 123456789 */ | |
| 494 | + if( strncmp(zTxt+i+1, "/wp-content/plugins/", 20)==0 ) return 1; | |
| 495 | + if( strncmp(zTxt+i+1, "/wp-admin/admin-ajax", 20)==0 ) return 1; | |
| 496 | + break; | |
| 490 | 497 | case 'a': |
| 491 | 498 | case 'A': |
| 492 | 499 | if( isWholeWord(zTxt, i, "and", 3) ) return 1; |
| 493 | 500 | break; |
| 494 | 501 | case 'n': |
| 495 | 502 |
| --- src/lookslike.c | |
| +++ src/lookslike.c | |
| @@ -467,28 +467,35 @@ | |
| 467 | ** Return true if z[i] is the whole word given by zWord |
| 468 | */ |
| 469 | static int isWholeWord(const char *z, unsigned int i, const char *zWord, int n){ |
| 470 | if( i>0 && fossil_isalnum(z[i-1]) ) return 0; |
| 471 | if( sqlite3_strnicmp(z+i, zWord, n)!=0 ) return 0; |
| 472 | if( z[i+n]!=0&& fossil_isalnum(z[i+n]) ) return 0; |
| 473 | return 1; |
| 474 | } |
| 475 | |
| 476 | /* |
| 477 | ** Returns true if the given text contains certain keywords or |
| 478 | ** punctuation which indicate that it might be SQL. This is only a |
| 479 | ** high-level check, not intended to be used for any application-level |
| 480 | ** logic other than in defense against spiders in limited contexts. |
| 481 | */ |
| 482 | int looks_like_sql_injection(const char *zTxt){ |
| 483 | unsigned int i; |
| 484 | if( zTxt==0 ) return 0; |
| 485 | for(i=0; zTxt[i]; i++){ |
| 486 | switch( zTxt[i] ){ |
| 487 | case ';': |
| 488 | case '\'': |
| 489 | return 1; |
| 490 | case 'a': |
| 491 | case 'A': |
| 492 | if( isWholeWord(zTxt, i, "and", 3) ) return 1; |
| 493 | break; |
| 494 | case 'n': |
| 495 |
| --- src/lookslike.c | |
| +++ src/lookslike.c | |
| @@ -467,28 +467,35 @@ | |
| 467 | ** Return true if z[i] is the whole word given by zWord |
| 468 | */ |
| 469 | static int isWholeWord(const char *z, unsigned int i, const char *zWord, int n){ |
| 470 | if( i>0 && fossil_isalnum(z[i-1]) ) return 0; |
| 471 | if( sqlite3_strnicmp(z+i, zWord, n)!=0 ) return 0; |
| 472 | if( fossil_isalnum(z[i+n]) ) return 0; |
| 473 | return 1; |
| 474 | } |
| 475 | |
| 476 | /* |
| 477 | ** Returns true if the given text contains certain keywords or |
| 478 | ** punctuation which indicate that it might be an SQL injection attempt |
| 479 | ** or some other kind of mischief. |
| 480 | ** |
| 481 | ** This is not a defense against vulnerabilities in the Fossil code. |
| 482 | ** Rather, this is part of an effort to do early detection of malicious |
| 483 | ** spiders to avoid them using up too many CPU cycles. |
| 484 | */ |
| 485 | int looks_like_sql_injection(const char *zTxt){ |
| 486 | unsigned int i; |
| 487 | if( zTxt==0 ) return 0; |
| 488 | for(i=0; zTxt[i]; i++){ |
| 489 | switch( zTxt[i] ){ |
| 490 | case ';': |
| 491 | case '\'': |
| 492 | return 1; |
| 493 | case '/': /* 0123456789 123456789 */ |
| 494 | if( strncmp(zTxt+i+1, "/wp-content/plugins/", 20)==0 ) return 1; |
| 495 | if( strncmp(zTxt+i+1, "/wp-admin/admin-ajax", 20)==0 ) return 1; |
| 496 | break; |
| 497 | case 'a': |
| 498 | case 'A': |
| 499 | if( isWholeWord(zTxt, i, "and", 3) ) return 1; |
| 500 | break; |
| 501 | case 'n': |
| 502 |