Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | More intensive use of the Synchronizer Token Pattern for CSRF defense. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | csrf-defense-enhancement |
| Files: | files | file ages | folders |
| SHA3-256: |
0a66be2b7545262a62ec8f45ce82a6ff |
| User & Date: | drh 2023-09-18 15:10:48.882 |
Context
|
2023-09-18
| ||
| 15:24 | Fix forum-post approval buttons so that they send the CSRF token. ... (check-in: bf9974cf8d user: drh tags: csrf-defense-enhancement) | |
| 15:10 | More intensive use of the Synchronizer Token Pattern for CSRF defense. ... (check-in: 0a66be2b75 user: drh tags: csrf-defense-enhancement) | |
| 14:32 | Strengthen CSRF requirements for the skin editor. ... (check-in: 6912636dc3 user: drh tags: csrf-defense-enhancement) | |
Changes
Changes to src/alerts.c.
| ︙ | ︙ | |||
1543 1544 1545 1546 1547 1548 1549 |
register_page();
return;
}
style_set_current_feature("alerts");
alert_submenu_common();
needCaptcha = !login_is_individual();
if( P("submit")
| | | 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 |
register_page();
return;
}
style_set_current_feature("alerts");
alert_submenu_common();
needCaptcha = !login_is_individual();
if( P("submit")
&& cgi_csrf_safe(2)
&& subscribe_error_check(&eErr,&zErr,needCaptcha)
){
/* A validated request for a new subscription has been received. */
char ssub[20];
const char *zEAddr = P("e");
const char *zCode; /* New subscriber code (in hex) */
int nsub = 0;
|
| ︙ | ︙ | |||
1854 1855 1856 1857 1858 1859 1860 |
}
if( sid==0 ){
db_commit_transaction();
cgi_redirect("subscribe");
/*NOTREACHED*/
}
alert_submenu_common();
| | | 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 |
}
if( sid==0 ){
db_commit_transaction();
cgi_redirect("subscribe");
/*NOTREACHED*/
}
alert_submenu_common();
if( P("submit")!=0 && cgi_csrf_safe(2) ){
char newSsub[10];
int nsub = 0;
Blob update;
sdonotcall = PB("sdonotcall");
sdigest = PB("sdigest");
semail = P("semail");
|
| ︙ | ︙ | |||
1916 1917 1918 1919 1920 1921 1922 |
db_unprotect(PROTECT_READONLY);
db_multi_exec(
"UPDATE subscriber SET lastContact=now()/86400"
" WHERE subscriberId=%d", sid
);
db_protect_pop();
}
| | | 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 |
db_unprotect(PROTECT_READONLY);
db_multi_exec(
"UPDATE subscriber SET lastContact=now()/86400"
" WHERE subscriberId=%d", sid
);
db_protect_pop();
}
if( P("delete")!=0 && cgi_csrf_safe(2) ){
if( !PB("dodelete") ){
eErr = 9;
zErr = mprintf("Select this checkbox and press \"Unsubscribe\" again to"
" unsubscribe");
}else{
alert_unsubscribe(sid);
db_commit_transaction();
|
| ︙ | ︙ | |||
2267 2268 2269 2270 2271 2272 2273 |
return;
}
style_set_current_feature("alerts");
zEAddr = PD("e","");
dx = atoi(PD("dx","0"));
| | | 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 |
return;
}
style_set_current_feature("alerts");
zEAddr = PD("e","");
dx = atoi(PD("dx","0"));
bSubmit = P("submit")!=0 && P("e")!=0 && cgi_csrf_safe(2);
if( bSubmit ){
if( !captcha_is_correct(1) ){
eErr = 2;
zErr = mprintf("enter the security code shown below");
bSubmit = 0;
}
}
|
| ︙ | ︙ | |||
3298 3299 3300 3301 3302 3303 3304 |
style_finish_page();
return;
}
if( P("submit")!=0
&& P("subject")!=0
&& P("msg")!=0
&& P("from")!=0
| | | 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 |
style_finish_page();
return;
}
if( P("submit")!=0
&& P("subject")!=0
&& P("msg")!=0
&& P("from")!=0
&& cgi_csrf_safe(2)
&& captcha_is_correct(0)
){
Blob hdr, body;
AlertSender *pSender = alert_sender_new(0,0);
blob_init(&hdr, 0, 0);
blob_appendf(&hdr, "To: <%s>\r\nSubject: %s administrator message\r\n",
zAdminEmail, db_get("email-subname","Fossil Repo"));
|
| ︙ | ︙ | |||
3475 3476 3477 3478 3479 3480 3481 |
style_set_current_feature("alerts");
if( fossil_strcmp(P("name"),"test1")==0 ){
/* Visit the /announce/test1 page to see the CGI variables */
zAction = "announce/test1";
@ <p style='border: 1px solid black; padding: 1ex;'>
cgi_print_all(0, 0, 0);
@ </p>
| | | 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 |
style_set_current_feature("alerts");
if( fossil_strcmp(P("name"),"test1")==0 ){
/* Visit the /announce/test1 page to see the CGI variables */
zAction = "announce/test1";
@ <p style='border: 1px solid black; padding: 1ex;'>
cgi_print_all(0, 0, 0);
@ </p>
}else if( P("submit")!=0 && cgi_csrf_safe(2) ){
char *zErr = alert_send_announcement();
style_header("Announcement Sent");
if( zErr ){
@ <h1>Internal Error</h1>
@ <p>The following error was reported by the system:
@ <blockquote><pre>
@ %h(zErr)
|
| ︙ | ︙ | |||
3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 |
@ <a href="https://fossil-scm.org/fossil/doc/trunk/www/alerts.md">set up</a>
@ for this repository.</p>
return;
}
style_header("Send Announcement");
@ <form method="POST" action="%R/%s(zAction)">
@ <table class="subscribe">
if( g.perm.Admin ){
int aa = PB("aa");
int all = PB("all");
int aMod = PB("mods");
const char *aack = aa ? "checked" : "";
const char *allck = all ? "checked" : "";
| > | 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 |
@ <a href="https://fossil-scm.org/fossil/doc/trunk/www/alerts.md">set up</a>
@ for this repository.</p>
return;
}
style_header("Send Announcement");
@ <form method="POST" action="%R/%s(zAction)">
login_insert_csrf_secret();
@ <table class="subscribe">
if( g.perm.Admin ){
int aa = PB("aa");
int all = PB("all");
int aMod = PB("mods");
const char *aack = aa ? "checked" : "";
const char *allck = all ? "checked" : "";
|
| ︙ | ︙ |
Changes to src/forum.c.
| ︙ | ︙ | |||
1537 1538 1539 1540 1541 1542 1543 |
const char *zContent = PDT("content","");
login_check_credentials();
if( !g.perm.WrForum ){
login_needed(g.anon.WrForum);
return;
}
| | > | 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 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 |
const char *zContent = PDT("content","");
login_check_credentials();
if( !g.perm.WrForum ){
login_needed(g.anon.WrForum);
return;
}
if( P("submit") && cgi_csrf_safe(2) ){
if( forum_post(zTitle, 0, 0, 0, zMimetype, zContent,
forum_post_flags()) ) return;
}
if( P("preview") && !whitespace_only(zContent) ){
@ <h1>Preview:</h1>
forum_render(zTitle, zMimetype, zContent, "forumEdit", 1);
}
style_set_current_feature("forum");
style_header("New Forum Thread");
@ <form action="%R/forume1" method="POST">
@ <h1>New Thread:</h1>
forum_from_line();
forum_post_widget(zTitle, zMimetype, zContent);
@ <input type="submit" name="preview" value="Preview">
if( P("preview") && !whitespace_only(zContent) ){
@ <input type="submit" name="submit" value="Submit">
}else{
@ <input type="submit" name="submit" value="Submit" disabled>
}
forum_render_debug_options();
login_insert_csrf_secret();
@ </form>
forum_emit_js();
style_finish_page();
}
/*
** WEBPAGE: forume2
|
| ︙ | ︙ | |||
1609 1610 1611 1612 1613 1614 1615 |
if( P("cancel") ){
cgi_redirectf("%R/forumpost/%S",zFpid);
return;
}
bPreview = P("preview")!=0;
bReply = P("reply")!=0;
iClosed = forum_rid_is_closed(fpid, 1);
| | | 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 |
if( P("cancel") ){
cgi_redirectf("%R/forumpost/%S",zFpid);
return;
}
bPreview = P("preview")!=0;
bReply = P("reply")!=0;
iClosed = forum_rid_is_closed(fpid, 1);
isCsrfSafe = cgi_csrf_safe(2);
bPrivate = content_is_private(fpid);
bSameUser = login_is_individual()
&& fossil_strcmp(pPost->zUser, g.zLogin)==0;
if( isCsrfSafe && (g.perm.ModForum || (bPrivate && bSameUser)) ){
if( g.perm.ModForum && P("approve") ){
const char *zUserToTrust;
moderation_approve('f', fpid);
|
| ︙ | ︙ | |||
1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 |
style_header("Delete %s", zTitle ? "Post" : "Reply");
@ <h1>Original Post:</h1>
forum_render(pPost->zThreadTitle, pPost->zMimetype, pPost->zWiki,
"forumEdit", 1);
@ <h1>Change Into:</h1>
forum_render(zTitle, zMimetype, zContent,"forumEdit", 1);
@ <form action="%R/forume2" method="POST">
@ <input type="hidden" name="fpid" value="%h(P("fpid"))">
@ <input type="hidden" name="nullout" value="1">
@ <input type="hidden" name="mimetype" value="%h(zMimetype)">
@ <input type="hidden" name="content" value="%h(zContent)">
if( zTitle ){
@ <input aria-label="Title" type="hidden" name="title" value="%h(zTitle)">
}
| > | 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 |
style_header("Delete %s", zTitle ? "Post" : "Reply");
@ <h1>Original Post:</h1>
forum_render(pPost->zThreadTitle, pPost->zMimetype, pPost->zWiki,
"forumEdit", 1);
@ <h1>Change Into:</h1>
forum_render(zTitle, zMimetype, zContent,"forumEdit", 1);
@ <form action="%R/forume2" method="POST">
login_insert_csrf_secret();
@ <input type="hidden" name="fpid" value="%h(P("fpid"))">
@ <input type="hidden" name="nullout" value="1">
@ <input type="hidden" name="mimetype" value="%h(zMimetype)">
@ <input type="hidden" name="content" value="%h(zContent)">
if( zTitle ){
@ <input aria-label="Title" type="hidden" name="title" value="%h(zTitle)">
}
|
| ︙ | ︙ | |||
1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 |
"forumEdit", 1);
if( bPreview ){
@ <h2>Preview of Edited Post:</h2>
forum_render(zTitle, zMimetype, zContent,"forumEdit", 1);
}
@ <h2>Revised Message:</h2>
@ <form action="%R/forume2" method="POST">
@ <input type="hidden" name="fpid" value="%h(P("fpid"))">
@ <input type="hidden" name="edit" value="1">
forum_from_line();
forum_post_widget(zTitle, zMimetype, zContent);
}else{
/* Reply */
char *zDisplayName;
| > | 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 |
"forumEdit", 1);
if( bPreview ){
@ <h2>Preview of Edited Post:</h2>
forum_render(zTitle, zMimetype, zContent,"forumEdit", 1);
}
@ <h2>Revised Message:</h2>
@ <form action="%R/forume2" method="POST">
login_insert_csrf_secret();
@ <input type="hidden" name="fpid" value="%h(P("fpid"))">
@ <input type="hidden" name="edit" value="1">
forum_from_line();
forum_post_widget(zTitle, zMimetype, zContent);
}else{
/* Reply */
char *zDisplayName;
|
| ︙ | ︙ | |||
1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 |
@ <input type="submit" name="cancel" value="Cancel">
if( (bPreview && !whitespace_only(zContent)) || isDelete ){
if( !iClosed || g.perm.Admin ) {
@ <input type="submit" name="submit" value="Submit">
}
}
forum_render_debug_options();
@ </form>
forum_emit_js();
style_finish_page();
}
/*
** WEBPAGE: setup_forum
| > | 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 |
@ <input type="submit" name="cancel" value="Cancel">
if( (bPreview && !whitespace_only(zContent)) || isDelete ){
if( !iClosed || g.perm.Admin ) {
@ <input type="submit" name="submit" value="Submit">
}
}
forum_render_debug_options();
login_insert_csrf_secret();
@ </form>
forum_emit_js();
style_finish_page();
}
/*
** WEBPAGE: setup_forum
|
| ︙ | ︙ |
Changes to src/interwiki.c.
| ︙ | ︙ | |||
312 313 314 315 316 317 318 |
char *zErr = 0;
login_check_credentials();
if( !g.perm.Read && !g.perm.RdWiki && ~g.perm.RdTkt ){
login_needed(0);
return;
}
| | | 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
char *zErr = 0;
login_check_credentials();
if( !g.perm.Read && !g.perm.RdWiki && ~g.perm.RdTkt ){
login_needed(0);
return;
}
if( g.perm.Setup && P("submit")!=0 && cgi_csrf_safe(2) ){
zTag = PT("tag");
zBase = PT("base");
zHash = PT("hash");
zWiki = PT("wiki");
if( zTag==0 || zTag[0]==0 || !interwiki_valid_name(zTag) ){
zErr = mprintf("Not a valid interwiki tag name: \"%s\"", zTag?zTag : "");
}else if( zBase==0 || zBase[0]==0 ){
|
| ︙ | ︙ |
Changes to src/login.c.
| ︙ | ︙ | |||
1980 1981 1982 1983 1984 1985 1986 |
zUserID = PDT("u","");
zPasswd = PDT("p","");
zConfirm = PDT("cp","");
zEAddr = PDT("ea","");
zDName = PDT("dn","");
/* Verify user imputs */
| | | 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 |
zUserID = PDT("u","");
zPasswd = PDT("p","");
zConfirm = PDT("cp","");
zEAddr = PDT("ea","");
zDName = PDT("dn","");
/* Verify user imputs */
if( P("new")==0 || !cgi_csrf_safe(2) ){
/* This is not a valid form submission. Fall through into
** the form display */
}else if( (captchaIsCorrect = captcha_is_correct(1))==0 ){
iErrLine = 6;
zErr = "Incorrect CAPTCHA";
}else if( strlen(zUserID)<6 ){
iErrLine = 1;
|
| ︙ | ︙ | |||
2258 2259 2260 2261 2262 2263 2264 |
@ with the project administrator.
style_finish_page();
return;
}
zEAddr = PDT("ea","");
/* Verify user imputs */
| | | 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 |
@ with the project administrator.
style_finish_page();
return;
}
zEAddr = PDT("ea","");
/* Verify user imputs */
if( !cgi_csrf_safe(2) || P("reqpwreset")==0 ){
/* This is the initial display of the form. No processing or error
** checking is to be done. Fall through into the form display
*/
}else if( (captchaIsCorrect = captcha_is_correct(1))==0 ){
iErrLine = 2;
zErr = "Incorrect CAPTCHA";
}else if( zEAddr[0]==0 ){
|
| ︙ | ︙ |
Changes to src/security_audit.c.
| ︙ | ︙ | |||
793 794 795 796 797 798 799 |
@ the "fossil http" or "fossil server" commands then add
@ a command-line option "--errorlog <i>FILENAME</i>" to that
@ command.
@ </ol>
style_finish_page();
return;
}
| | > | 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 |
@ the "fossil http" or "fossil server" commands then add
@ a command-line option "--errorlog <i>FILENAME</i>" to that
@ command.
@ </ol>
style_finish_page();
return;
}
if( P("truncate1") && cgi_csrf_safe(2) ){
fclose(fopen(g.zErrlog,"w"));
}
if( P("download") ){
Blob log;
blob_read_from_file(&log, g.zErrlog, ExtFILE);
cgi_set_content_type("text/plain");
cgi_set_content(&log);
return;
}
szFile = file_size(g.zErrlog, ExtFILE);
if( P("truncate") ){
@ <form action="%R/errorlog" method="POST">
login_insert_csrf_secret();
@ <p>Confirm that you want to truncate the %,lld(szFile)-byte error log:
@ <input type="submit" name="truncate1" value="Confirm">
@ <input type="submit" name="cancel" value="Cancel">
@ </form>
style_finish_page();
return;
}
|
| ︙ | ︙ |
Changes to src/setup.c.
| ︙ | ︙ | |||
1452 1453 1454 1455 1456 1457 1458 |
void setup_adunit(void){
login_check_credentials();
if( !g.perm.Admin ){
login_needed(0);
return;
}
db_begin_transaction();
| | | 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 |
void setup_adunit(void){
login_check_credentials();
if( !g.perm.Admin ){
login_needed(0);
return;
}
db_begin_transaction();
if( P("clear")!=0 && cgi_csrf_safe(2) ){
db_unprotect(PROTECT_CONFIG);
db_multi_exec("DELETE FROM config WHERE name GLOB 'adunit*'");
db_protect_pop();
cgi_replace_parameter("adunit","");
cgi_replace_parameter("adright","");
setup_incr_cfgcnt();
}
|
| ︙ | ︙ | |||
1554 1555 1556 1557 1558 1559 1560 |
}
login_check_credentials();
if( !g.perm.Admin ){
login_needed(0);
return;
}
db_begin_transaction();
| | | 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 |
}
login_check_credentials();
if( !g.perm.Admin ){
login_needed(0);
return;
}
db_begin_transaction();
if( !cgi_csrf_safe(2) ){
/* Allow no state changes if not safe from CSRF */
}else if( P("setlogo")!=0 && zLogoMime && zLogoMime[0] && szLogoImg>0 ){
Blob img;
Stmt ins;
blob_init(&img, aLogoImg, szLogoImg);
db_unprotect(PROTECT_CONFIG);
db_prepare(&ins,
|
| ︙ | ︙ | |||
1763 1764 1765 1766 1767 1768 1769 |
int go = P("go")!=0;
login_check_credentials();
if( !g.perm.Setup ){
login_needed(0);
return;
}
add_content_sql_commands(g.db);
| | | 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 |
int go = P("go")!=0;
login_check_credentials();
if( !g.perm.Setup ){
login_needed(0);
return;
}
add_content_sql_commands(g.db);
zQ = cgi_csrf_safe(2) ? P("q") : 0;
style_set_current_feature("setup");
style_header("Raw SQL Commands");
@ <p><b>Caution:</b> There are no restrictions on the SQL that can be
@ run by this page. You can do serious and irrepairable damage to the
@ repository. Proceed with extreme caution.</p>
@
#if 0
|
| ︙ | ︙ | |||
2120 2121 2122 2123 2124 2125 2126 |
*/
static void setup_update_url_alias(
Blob *pSql,
const char *zOldName,
const char *zNewName,
const char *zValue
){
| | | 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 |
*/
static void setup_update_url_alias(
Blob *pSql,
const char *zOldName,
const char *zNewName,
const char *zValue
){
if( !cgi_csrf_safe(2) ) return;
if( zNewName[0]==0 || zValue[0]==0 ){
if( zOldName[0] ){
blob_append_sql(pSql,
"DELETE FROM config WHERE name='walias:%q';\n",
zOldName);
}
return;
|
| ︙ | ︙ |
Changes to src/setupuser.c.
| ︙ | ︙ | |||
340 341 342 343 344 345 346 |
if( P("can") ){
/* User pressed the cancel button */
cgi_redirect(cgi_referer("setup_ulist"));
return;
}
/* Check for requests to delete the user */
| | | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 |
if( P("can") ){
/* User pressed the cancel button */
cgi_redirect(cgi_referer("setup_ulist"));
return;
}
/* Check for requests to delete the user */
if( P("delete") && cgi_csrf_safe(2) ){
int n;
if( P("verifydelete") ){
/* Verified delete user request */
db_unprotect(PROTECT_USER);
if( alert_tables_exist() ){
/* Also delete any subscriptions associated with this user */
db_multi_exec("DELETE FROM subscriber WHERE suname="
|
| ︙ | ︙ |
Changes to src/style.c.
| ︙ | ︙ | |||
1458 1459 1460 1461 1462 1463 1464 |
@ anonymous-adds = %s(find_anon_capabilities(zCap))<br>
}
@ g.zRepositoryName = %h(g.zRepositoryName)<br>
@ load_average() = %f(load_average())<br>
#ifndef _WIN32
@ RSS = %.2f(fossil_rss()/1000000.0) MB</br>
#endif
| | > > > > > > > > > > > > > > > > > > > | 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 |
@ anonymous-adds = %s(find_anon_capabilities(zCap))<br>
}
@ g.zRepositoryName = %h(g.zRepositoryName)<br>
@ load_average() = %f(load_average())<br>
#ifndef _WIN32
@ RSS = %.2f(fossil_rss()/1000000.0) MB</br>
#endif
(void)cgi_csrf_safe(2);
switch( g.okCsrf ){
case 1: {
@ CSRF safety = Same origin<br>
break;
}
case 2: {
@ CSRF safety = Same origin, POST<br>
break;
}
case 3: {
@ CSRF safety = Same origin, POST, CSRF token<br>
break;
}
default: {
@ CSRF safety = unsafe<br>
break;
}
}
@ fossil_exe_id() = %h(fossil_exe_id())<br>
if( g.perm.Admin ){
int k;
for(k=0; g.argvOrig[k]; k++){
Blob t;
blob_init(&t, 0, 0);
blob_append_escaped_arg(&t, g.argvOrig[k], 0);
|
| ︙ | ︙ |