I've been tasked with updating a website that was developed in 2003-2004 before Cross-Site Request Forgery (CSRF or XSRF) was really well known to be an issue. The system is currently built on mod_perl2 and HTML::Mason (Mason 1, not 2), and it uses Apache2::AuthCookieDBI for user authentication. I'm sure it was state-of-the-art back in 2003-2004, but the basic building blocks haven't been updated since then. A recent security audit revealed that most of this site's CGIs are vulnerable to CSRF, and I need to fix it.
Switching to a completely different framework/middleware like CGI::Application, Dancer, Catalyst, or Plack would take too much effort, I think. And everyone is happy with how the site works currently, so avoiding any user-visible changes would be preferable.
So what's the best way to incorporate CSRF protection into a site that uses mod_perl, Mason, and Apache2::AuthCookieDBI (or Apache::AuthCookie in general)? Has anyone done anything like this?
MasonX::Request::WithApacheSession looks promising, but Apache::Session doesn't appear to be updated as frequently as CGI::Session or as well regarded, I think. There's also Apache::SessionManager, but it hasn't been updated since 2004. A lot of these modules seem to overlap conceptually with Apache::AuthCookie. It appears I'd be almost generating two session IDs if I go with one of these approaches in addition to using Apache::AuthCookieDBI. Can I reuse the AuthCookieDBI ticket as the session ID with any of these modules?
Or should I just roll my own class to generate a random, one-time-use-only, expirable token, stick it in just the forms that have consequences as a hidden parameter, and store the token in the server-side database? I don't want to reinvent the wheel, but there is similar code already in this project for handling password resets which I could potentially generalize and refactor, so I'm very tempted to go this route. The problem with that is that it's not a comprehensive solution, so it would require identification and modification of the vulnerable forms that modify the database and there's always the possibility I could miss a form. Even if I don't, some future web developer might add a new form without thinking it through.
Thanks for any advice!
Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
Read Where should I post X? if you're not absolutely sure you're posting in the right place.
Please read these before you post! —
Posts may use any of the Perl Monks Approved HTML tags:
You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
- a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
Link using PerlMonks shortcuts! What shortcuts can I use for linking?
See Writeup Formatting Tips and other pages linked from there for more info.
| & || & |
| < || < |
| > || > |
| [ || [ |
| ] || ] ||