Fossil SCM
Improvements to the algorithm for detecting likely SQL injection text.
Commit
5d6efeee477ff3087811df663a34e551982f09b34b2bee51fe8a11d129d3879d
Parent
ef1702fde39616e…
1 file changed
+10
-4
+10
-4
| --- src/lookslike.c | ||
| +++ src/lookslike.c | ||
| @@ -462,16 +462,20 @@ | ||
| 462 | 462 | fossil_print("Has flag LOOK_SHORT: %s\n",(lookFlags&LOOK_SHORT)?"yes":"no"); |
| 463 | 463 | blob_reset(&blob); |
| 464 | 464 | } |
| 465 | 465 | |
| 466 | 466 | /* |
| 467 | -** Return true if z[i] is the whole word given by zWord | |
| 467 | +** Return true if z[i] is the whole word given by zWord in a context that | |
| 468 | +** might be an attempted SQL injection. | |
| 468 | 469 | */ |
| 469 | 470 | 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( i==0 ) return 0; | |
| 471 | 472 | if( sqlite3_strnicmp(z+i, zWord, n)!=0 ) return 0; |
| 472 | - if( z[i+n]!=0 && !fossil_isspace(z[i+n]) ) return 0; | |
| 473 | + if( fossil_isalnum(z[i-1]) ) return 0; | |
| 474 | + if( fossil_isalnum(z[i+n]) ) return 0; | |
| 475 | + if( strchr("-)_", z[i-1])!=0 ) return 0; | |
| 476 | + if( strchr("(_", z[i+n])!=0 ) return 0; | |
| 473 | 477 | return 1; |
| 474 | 478 | } |
| 475 | 479 | |
| 476 | 480 | /* |
| 477 | 481 | ** Returns true if the given text contains certain keywords or |
| @@ -502,11 +506,13 @@ | ||
| 502 | 506 | case 'N': |
| 503 | 507 | if( isWholeWord(zTxt, i, "null", 4) ) return 1; |
| 504 | 508 | break; |
| 505 | 509 | case 'o': |
| 506 | 510 | case 'O': |
| 507 | - if( isWholeWord(zTxt, i, "order", 5) ) return 1; | |
| 511 | + if( isWholeWord(zTxt, i, "order", 5) && fossil_isspace(zTxt[i+5]) ){ | |
| 512 | + return 1; | |
| 513 | + } | |
| 508 | 514 | if( isWholeWord(zTxt, i, "or", 2) ) return 1; |
| 509 | 515 | break; |
| 510 | 516 | case 's': |
| 511 | 517 | case 'S': |
| 512 | 518 | if( isWholeWord(zTxt, i, "select", 6) ) return 1; |
| 513 | 519 |
| --- src/lookslike.c | |
| +++ src/lookslike.c | |
| @@ -462,16 +462,20 @@ | |
| 462 | fossil_print("Has flag LOOK_SHORT: %s\n",(lookFlags&LOOK_SHORT)?"yes":"no"); |
| 463 | blob_reset(&blob); |
| 464 | } |
| 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 |
| @@ -502,11 +506,13 @@ | |
| 502 | case 'N': |
| 503 | if( isWholeWord(zTxt, i, "null", 4) ) return 1; |
| 504 | break; |
| 505 | case 'o': |
| 506 | case 'O': |
| 507 | if( isWholeWord(zTxt, i, "order", 5) ) return 1; |
| 508 | if( isWholeWord(zTxt, i, "or", 2) ) return 1; |
| 509 | break; |
| 510 | case 's': |
| 511 | case 'S': |
| 512 | if( isWholeWord(zTxt, i, "select", 6) ) return 1; |
| 513 |
| --- src/lookslike.c | |
| +++ src/lookslike.c | |
| @@ -462,16 +462,20 @@ | |
| 462 | fossil_print("Has flag LOOK_SHORT: %s\n",(lookFlags&LOOK_SHORT)?"yes":"no"); |
| 463 | blob_reset(&blob); |
| 464 | } |
| 465 | |
| 466 | /* |
| 467 | ** Return true if z[i] is the whole word given by zWord in a context that |
| 468 | ** might be an attempted SQL injection. |
| 469 | */ |
| 470 | static int isWholeWord(const char *z, unsigned int i, const char *zWord, int n){ |
| 471 | if( i==0 ) return 0; |
| 472 | if( sqlite3_strnicmp(z+i, zWord, n)!=0 ) return 0; |
| 473 | if( fossil_isalnum(z[i-1]) ) return 0; |
| 474 | if( fossil_isalnum(z[i+n]) ) return 0; |
| 475 | if( strchr("-)_", z[i-1])!=0 ) return 0; |
| 476 | if( strchr("(_", z[i+n])!=0 ) return 0; |
| 477 | return 1; |
| 478 | } |
| 479 | |
| 480 | /* |
| 481 | ** Returns true if the given text contains certain keywords or |
| @@ -502,11 +506,13 @@ | |
| 506 | case 'N': |
| 507 | if( isWholeWord(zTxt, i, "null", 4) ) return 1; |
| 508 | break; |
| 509 | case 'o': |
| 510 | case 'O': |
| 511 | if( isWholeWord(zTxt, i, "order", 5) && fossil_isspace(zTxt[i+5]) ){ |
| 512 | return 1; |
| 513 | } |
| 514 | if( isWholeWord(zTxt, i, "or", 2) ) return 1; |
| 515 | break; |
| 516 | case 's': |
| 517 | case 'S': |
| 518 | if( isWholeWord(zTxt, i, "select", 6) ) return 1; |
| 519 |