Fossil SCM
Improve the error log message for 418 responses so that it includes the name of the offending query parameter. Require whitespace around keywords when trying to detect SQL.
Commit
ef1702fde39616ec00b6536277f11ad65fb6e2526a4abada6ee2c7e33e022f82
Parent
f39c878fe196db9…
2 files changed
+7
-7
+2
-2
+7
-7
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -1533,11 +1533,11 @@ | ||
| 1533 | 1533 | } |
| 1534 | 1534 | |
| 1535 | 1535 | /* |
| 1536 | 1536 | ** Renders the "begone, spider" page and exits. |
| 1537 | 1537 | */ |
| 1538 | -static void cgi_begone_spider(void){ | |
| 1538 | +static void cgi_begone_spider(const char *zName){ | |
| 1539 | 1539 | Blob content = empty_blob; |
| 1540 | 1540 | cgi_set_content(&content); |
| 1541 | 1541 | style_set_current_feature("test"); |
| 1542 | 1542 | style_submenu_enable(0); |
| 1543 | 1543 | style_header("Malicious Query Detected"); |
| @@ -1547,13 +1547,13 @@ | ||
| 1547 | 1547 | @ |
| 1548 | 1548 | @ <p>If you believe you are innocent and have reached this page in error, |
| 1549 | 1549 | @ contact the Fossil developers on the Fossil-SCM Forum. Type |
| 1550 | 1550 | @ "fossil-scm forum" into any search engine to locate the Fossil-SCM Forum. |
| 1551 | 1551 | style_finish_page(); |
| 1552 | - cgi_set_status(418,"I'm a teapot"); | |
| 1552 | + cgi_set_status(418,"I'm a teapotgrep "); | |
| 1553 | 1553 | cgi_reply(); |
| 1554 | - fossil_errorlog("possible hack attempt - 418 response"); | |
| 1554 | + fossil_errorlog("possible hack attempt - 418 response on \"%s\"", zName); | |
| 1555 | 1555 | exit(0); |
| 1556 | 1556 | } |
| 1557 | 1557 | |
| 1558 | 1558 | /* |
| 1559 | 1559 | ** If looks_like_sql_injection() returns true for the given string, calls |
| @@ -1569,13 +1569,13 @@ | ||
| 1569 | 1569 | ** the server with dozens or hundreds of SQL injection attempts per second |
| 1570 | 1570 | ** against pages (such as /vdiff) that are expensive to compute. In other |
| 1571 | 1571 | ** words, this is an effort to reduce the CPU load imposed by malicious |
| 1572 | 1572 | ** spiders. It is not an effect defense against SQL injection vulnerabilities. |
| 1573 | 1573 | */ |
| 1574 | -void cgi_value_spider_check(const char *zTxt){ | |
| 1574 | +void cgi_value_spider_check(const char *zTxt, const char *zName){ | |
| 1575 | 1575 | if( g.zLogin==0 && looks_like_sql_injection(zTxt) ){ |
| 1576 | - cgi_begone_spider(); | |
| 1576 | + cgi_begone_spider(zName); | |
| 1577 | 1577 | } |
| 1578 | 1578 | } |
| 1579 | 1579 | |
| 1580 | 1580 | /* |
| 1581 | 1581 | ** A variant of cgi_parameter() with the same semantics except that if |
| @@ -1584,11 +1584,11 @@ | ||
| 1584 | 1584 | */ |
| 1585 | 1585 | const char *cgi_parameter_nosql(const char *zName, const char *zDefault){ |
| 1586 | 1586 | const char *zTxt = cgi_parameter(zName, zDefault); |
| 1587 | 1587 | |
| 1588 | 1588 | if( zTxt!=zDefault ){ |
| 1589 | - cgi_value_spider_check(zTxt); | |
| 1589 | + cgi_value_spider_check(zTxt, zName); | |
| 1590 | 1590 | } |
| 1591 | 1591 | return zTxt; |
| 1592 | 1592 | } |
| 1593 | 1593 | |
| 1594 | 1594 | /* |
| @@ -2744,9 +2744,9 @@ | ||
| 2744 | 2744 | int i; |
| 2745 | 2745 | for(i = 0; i < nUsedQP; ++i){ |
| 2746 | 2746 | pParam = &aParamQP[i]; |
| 2747 | 2747 | if(0 == pParam->isFetched |
| 2748 | 2748 | && fossil_islower(pParam->zName[0])){ |
| 2749 | - cgi_value_spider_check(pParam->zValue); | |
| 2749 | + cgi_value_spider_check(pParam->zValue, pParam->zName); | |
| 2750 | 2750 | } |
| 2751 | 2751 | } |
| 2752 | 2752 | } |
| 2753 | 2753 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1533,11 +1533,11 @@ | |
| 1533 | } |
| 1534 | |
| 1535 | /* |
| 1536 | ** Renders the "begone, spider" page and exits. |
| 1537 | */ |
| 1538 | static void cgi_begone_spider(void){ |
| 1539 | Blob content = empty_blob; |
| 1540 | cgi_set_content(&content); |
| 1541 | style_set_current_feature("test"); |
| 1542 | style_submenu_enable(0); |
| 1543 | style_header("Malicious Query Detected"); |
| @@ -1547,13 +1547,13 @@ | |
| 1547 | @ |
| 1548 | @ <p>If you believe you are innocent and have reached this page in error, |
| 1549 | @ contact the Fossil developers on the Fossil-SCM Forum. Type |
| 1550 | @ "fossil-scm forum" into any search engine to locate the Fossil-SCM Forum. |
| 1551 | style_finish_page(); |
| 1552 | cgi_set_status(418,"I'm a teapot"); |
| 1553 | cgi_reply(); |
| 1554 | fossil_errorlog("possible hack attempt - 418 response"); |
| 1555 | exit(0); |
| 1556 | } |
| 1557 | |
| 1558 | /* |
| 1559 | ** If looks_like_sql_injection() returns true for the given string, calls |
| @@ -1569,13 +1569,13 @@ | |
| 1569 | ** the server with dozens or hundreds of SQL injection attempts per second |
| 1570 | ** against pages (such as /vdiff) that are expensive to compute. In other |
| 1571 | ** words, this is an effort to reduce the CPU load imposed by malicious |
| 1572 | ** spiders. It is not an effect defense against SQL injection vulnerabilities. |
| 1573 | */ |
| 1574 | void cgi_value_spider_check(const char *zTxt){ |
| 1575 | if( g.zLogin==0 && looks_like_sql_injection(zTxt) ){ |
| 1576 | cgi_begone_spider(); |
| 1577 | } |
| 1578 | } |
| 1579 | |
| 1580 | /* |
| 1581 | ** A variant of cgi_parameter() with the same semantics except that if |
| @@ -1584,11 +1584,11 @@ | |
| 1584 | */ |
| 1585 | const char *cgi_parameter_nosql(const char *zName, const char *zDefault){ |
| 1586 | const char *zTxt = cgi_parameter(zName, zDefault); |
| 1587 | |
| 1588 | if( zTxt!=zDefault ){ |
| 1589 | cgi_value_spider_check(zTxt); |
| 1590 | } |
| 1591 | return zTxt; |
| 1592 | } |
| 1593 | |
| 1594 | /* |
| @@ -2744,9 +2744,9 @@ | |
| 2744 | int i; |
| 2745 | for(i = 0; i < nUsedQP; ++i){ |
| 2746 | pParam = &aParamQP[i]; |
| 2747 | if(0 == pParam->isFetched |
| 2748 | && fossil_islower(pParam->zName[0])){ |
| 2749 | cgi_value_spider_check(pParam->zValue); |
| 2750 | } |
| 2751 | } |
| 2752 | } |
| 2753 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1533,11 +1533,11 @@ | |
| 1533 | } |
| 1534 | |
| 1535 | /* |
| 1536 | ** Renders the "begone, spider" page and exits. |
| 1537 | */ |
| 1538 | static void cgi_begone_spider(const char *zName){ |
| 1539 | Blob content = empty_blob; |
| 1540 | cgi_set_content(&content); |
| 1541 | style_set_current_feature("test"); |
| 1542 | style_submenu_enable(0); |
| 1543 | style_header("Malicious Query Detected"); |
| @@ -1547,13 +1547,13 @@ | |
| 1547 | @ |
| 1548 | @ <p>If you believe you are innocent and have reached this page in error, |
| 1549 | @ contact the Fossil developers on the Fossil-SCM Forum. Type |
| 1550 | @ "fossil-scm forum" into any search engine to locate the Fossil-SCM Forum. |
| 1551 | style_finish_page(); |
| 1552 | cgi_set_status(418,"I'm a teapotgrep "); |
| 1553 | cgi_reply(); |
| 1554 | fossil_errorlog("possible hack attempt - 418 response on \"%s\"", zName); |
| 1555 | exit(0); |
| 1556 | } |
| 1557 | |
| 1558 | /* |
| 1559 | ** If looks_like_sql_injection() returns true for the given string, calls |
| @@ -1569,13 +1569,13 @@ | |
| 1569 | ** the server with dozens or hundreds of SQL injection attempts per second |
| 1570 | ** against pages (such as /vdiff) that are expensive to compute. In other |
| 1571 | ** words, this is an effort to reduce the CPU load imposed by malicious |
| 1572 | ** spiders. It is not an effect defense against SQL injection vulnerabilities. |
| 1573 | */ |
| 1574 | void cgi_value_spider_check(const char *zTxt, const char *zName){ |
| 1575 | if( g.zLogin==0 && looks_like_sql_injection(zTxt) ){ |
| 1576 | cgi_begone_spider(zName); |
| 1577 | } |
| 1578 | } |
| 1579 | |
| 1580 | /* |
| 1581 | ** A variant of cgi_parameter() with the same semantics except that if |
| @@ -1584,11 +1584,11 @@ | |
| 1584 | */ |
| 1585 | const char *cgi_parameter_nosql(const char *zName, const char *zDefault){ |
| 1586 | const char *zTxt = cgi_parameter(zName, zDefault); |
| 1587 | |
| 1588 | if( zTxt!=zDefault ){ |
| 1589 | cgi_value_spider_check(zTxt, zName); |
| 1590 | } |
| 1591 | return zTxt; |
| 1592 | } |
| 1593 | |
| 1594 | /* |
| @@ -2744,9 +2744,9 @@ | |
| 2744 | int i; |
| 2745 | for(i = 0; i < nUsedQP; ++i){ |
| 2746 | pParam = &aParamQP[i]; |
| 2747 | if(0 == pParam->isFetched |
| 2748 | && fossil_islower(pParam->zName[0])){ |
| 2749 | cgi_value_spider_check(pParam->zValue, pParam->zName); |
| 2750 | } |
| 2751 | } |
| 2752 | } |
| 2753 |
+2
-2
| --- src/lookslike.c | ||
| +++ src/lookslike.c | ||
| @@ -465,13 +465,13 @@ | ||
| 465 | 465 | |
| 466 | 466 | /* |
| 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 | - if( i>0 && fossil_isalnum(z[i-1]) ) return 0; | |
| 470 | + if( i>0 && !fossil_isspace(z[i-1]) ) return 0; | |
| 471 | 471 | if( sqlite3_strnicmp(z+i, zWord, n)!=0 ) return 0; |
| 472 | - if( fossil_isalnum(z[i+n]) ) return 0; | |
| 472 | + if( z[i+n]!=0 && !fossil_isspace(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 | 478 |
| --- src/lookslike.c | |
| +++ src/lookslike.c | |
| @@ -465,13 +465,13 @@ | |
| 465 | |
| 466 | /* |
| 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 |
| --- src/lookslike.c | |
| +++ src/lookslike.c | |
| @@ -465,13 +465,13 @@ | |
| 465 | |
| 466 | /* |
| 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_isspace(z[i-1]) ) return 0; |
| 471 | if( sqlite3_strnicmp(z+i, zWord, n)!=0 ) return 0; |
| 472 | if( z[i+n]!=0 && !fossil_isspace(z[i+n]) ) return 0; |
| 473 | return 1; |
| 474 | } |
| 475 | |
| 476 | /* |
| 477 | ** Returns true if the given text contains certain keywords or |
| 478 |