1CGI::Application::PlugiUns:e:rLiCnoknItnrtiebgurtieCtdGyI(P:3e:)rAlppDloiccuamteinotna:t:iPolnugin::LinkIntegrity(3)
2
3
4
6 CGI::Application::Plugin::LinkIntegrity - Make tamper-resisistent links
7 in CGI::Application
8
10 Version 0.06
11
13 In your application:
14
15 use base 'CGI::Application';
16 use CGI::Application::Plugin::LinkIntegrity;
17
18 sub setup {
19 my $self = shift;
20 $self->link_integrity_config(
21 secret => 'some secret string known only to you and me',
22 );
23 }
24
25 sub account_info {
26 my $self = shift;
27
28 my $account_id = get_user_account_id();
29
30 my $template = $self->load_tmpl('account.html');
31
32 $template->param(
33 'balance' => $self->link("/account.cgi?rm=balance&acct_id=$account_id");
34 'transfer' => $self->link("/account.cgi?rm=transfer&acct_id=$account_id");
35 'withdrawal' => $self->link("/account.cgi?rm=withdrawl&acct_id=$account_id");
36 );
37 }
38
39 In your template:
40
41 <h1>Welcome to The Faceless Banking Corp.</h1>
42 <h3>Actions:</h3>
43 <br /><a href="<TMPL_VAR NAME="balance">">Show Balance</a>
44 <br /><a href="<TMPL_VAR NAME="transfer">">Make a Transfer</a>
45 <br /><a href="<TMPL_VAR NAME="withdrawal">">Get Cash</a>
46
47 This will send the following HTML to the browser:
48
49 <h1>Welcome to The Faceless Banking Corp.</h1>
50 <h3>Actions:</h3>
51 <br /><a href="/account.cgi?rm=balance&acct_id=73&_checksum=1d7c4b82d075785de04fa6b98b572691">Show Balance</a>
52 <br /><a href="/account.cgi?rm=transfer&acct_id=73&_checksum=d41d8cd98f00b204e9800998ecf8427e">Make a Transfer</a>
53 <br /><a href="/account.cgi?rm=withdrawl&acct_id=73&_checksum=3c5ad17bdeef3c4281abd39c6386cfd6">Get Cash</a>
54
55 The URLs created are now tamper-resistent. If the user changes
56 "acct_id" from 73 to 74, the "_checksum" will not match, and the system
57 will treat it as an intrusion attempt.
58
59 Calling link and self_link directly from the template
60 If you use "Template::Toolkit|Template" or
61 "HTML::Template::Plugin::Dot", you can pass the "CGI::Application"
62 $self object into the template and call "link" and "self_link" directly
63 from the template. In your app:
64
65 $template->param(
66 'app' => $self,
67 'name' => 'gordon',
68 'email' => 'gordon@example.com',
69 );
70
71 And in your template you can use
72
73 # Template::Toolkit syntax
74 <a href="[% app.self_link('name', name, 'email', email %]">...</a>
75
76 # HTML::Template::Plugin::Dot syntax
77 <a href="<TMPL_VAR NAME="app.self_link('name', name, 'email', email">">...</a>
78
79 # Petal syntax
80 <a href="http://www.example.com"
81 tal:attributes="href app/self_link('name', name, 'email', email)">...</a>
82
83 Note that in the parameters of the call to << link >>, items enclosed
84 in quotes are treated as literal parameters and barewords are treated
85 as template params. So 'email' is the literal string, and "email" is
86 the template paramter named email (in this case 'gordon@example.com').
87
89 "CGI::Application::Plugin::LinkIntegrity" lets you create tamper-
90 resistent links within your CGI::Application project. When you create
91 an URL with "link", a "_checksum" is added to the URL:
92
93 my $link = $self->link("/account.cgi?rm=balance&acct_id=73");
94 print $link; # /account.cgi?rm=balance&acct_id=73&_checksum=1d7c4b82d075785de04fa6b98b572691
95
96 The checksum is a (cryptographic) hash of the URL, plus a secret string
97 known only to the server.
98
99 If the user attempts to change part of the URL (e.g. a query string
100 parameter, or the PATH_INFO), then the checksum will not match. The
101 run mode will be changed to "link_tampered", and the "invalid_checksum"
102 hook will be called.
103
104 You can define the "link_tampered" run mode yourself, or you can use
105 the default "link_tampered" run mode built into
106 CGI::Application::Plugin::LinkIntegrity.
107
108 You can disable link checking during development by passing a true
109 value to the "disable" parameter of "$self->link_integrity_config".
110
112 link_integrity_config
113 Configure the CGI::Application::Plugin::LinkIntegrity. Usually, it
114 makes sense to configure this in the "setup" method of your
115 application's base class:
116
117 use CGI::Application::Plugin::LinkIntegrity;
118 use base 'CGI::Application';
119 package My::Project;
120
121 sub setup {
122 my $self = shift;
123
124 $self->run_modes(['bad_user_no_biscuit']);
125 $self->link_integrity_config(
126 secret => 'some secret string known only to you and me',
127 link_tampered_run_mode => 'bad_user_no_biscuit',
128 digest_module => 'Digest::MD5',
129 disable => 1,
130 );
131 }
132
133 Or you can pull in this configuration info from a config file. For
134 instance, with using CGI::Application::Config::Context:
135
136 use CGI::Application::Plugin::LinkIntegrity;
137 use CGI::Application::Plugin::Config::Context;
138
139 use base 'CGI::Application';
140 package My::Project;
141
142 sub setup {
143 my $self = shift;
144
145 $self->conf->init(
146 file => 'app.conf',
147 driver => 'ConfigGeneral',
148 );
149
150 my $config = $self->conf->context;
151
152 $self->link_integrity_config(
153 $config->{'LinkIntegrity'},
154 additional_data => sub {
155 my $self = shift;
156 return $self->session->id;
157 },
158 );
159
160 my $link_tampered_rm = $config->{'LinkIntegrity'}{'link_tampered_run_mode'} || 'link_tampered';
161
162 $self->run_modes([$link_tampered_rm]);
163 }
164
165 Then in your configuration file:
166
167 <LinkIntegrity>
168 secret = some REALLY secret string
169 link_tampered_run_mode = bad_user_no_biscuit
170 hash_algorithm = SHA1
171 disable = 1
172 </LinkIntegrity>
173
174 This strategy allows you to enable and disable link checking on the fly
175 by changing the value of "disable" in the config file.
176
177 The following configuration parameters are available:
178
179 secret
180 A string known only to your application. At a commandline, you can
181 generate a secret string with md5:
182
183 $ perl -MDigest::MD5 -le"print Digest::MD5::md5_hex($$, time, rand(42));"
184
185 Or you can use Data::UUID:
186
187 $ perl -MData::UUID -le"$ug = new Data::UUID; $uuid = $ug->create; print $ug->to_string($uuid)"
188
189 If someone knows your secret string, then they can generate their
190 own checksums on arbitrary data that will always pass the integrity
191 check in your application. That's a Bad Thing, so don't let other
192 people know your secret string, and don't use the default secret
193 string if you can help it.
194
195 additional_data
196 You can pass constant additional data to the checksum generator for
197 every link.
198
199 $self->link_integrity_config(
200 secret => 'really secret',
201 additional_data => 'some other secret data',
202 }
203
204 For instance, to stop one user from following a second user's link,
205 you can add a user-specific component to the session, such as the
206 user's session id:
207
208 $self->link_integrity_config(
209 secret => 'really secret',
210 additional_data => sub {
211 my $self = shift;
212 return $self->session->id;
213 }
214 }
215
216 You can pass a string instead of a subroutine. But in the case of
217 the user's session, a subroutine is useful so that you get the
218 value of the user's session at the time when the checksum is
219 generated, not at the time when the link integrity system is
220 configured.
221
222 checksum_param
223 The name of the checksum parameter, which is added to the query
224 string and contains the cryptographic checksum of link. By default,
225 this parameter is named "_checksum".
226
227 link_tampered_run_mode
228 The run mode to go to when it has been detected that the user has
229 tampered with the link. The default is "link_tampered".
230
231 See "The link_tampered Run Mode", below.
232
233 digest_module
234 Which digest module to use to create the checksum. Typically, this
235 will be either "Digest::MD5" or "Digest::SHA1". However any module
236 supported by "Digest::HMAC" will work.
237
238 The default "digest_module" is "Digest::MD5".
239
240 checksum_generator
241 If you want to provide a custom subroutine to make your own
242 checksums, you can define your own subroutine do it via the
243 "make_checksum" param. Here's an example of one that uses
244 Digest::SHA2:
245
246 $self->link_integrity_config(
247 checksum_generator => sub {
248 my ($url, $secret) = @_;
249 require Digest::SHA2;
250
251 my $ctx = Digest::SHA2->new();
252 $ctx->add($url . $secret);
253
254 return $ctx->hexdigest;
255 },
256 );
257
258 disable
259 You can disable link checking entirely by setting "disable" to a
260 true value. This can be useful when you are developing or
261 debugging the application and you want the ability to tweak URL
262 params without getting busted.
263
264 link
265 Create a link, and add a checksum to it.
266
267 You can add parameters to the link directly in the URL:
268
269 my $link = $self->link('/cgi-bin/app.cgi?var=value&var2=value2');
270
271 Or you can add them as a hash of parameters after the URL:
272
273 my $link = $self->link(
274 '/cgi-bin/app.cgi',
275 'param1' => 'value',
276 'param2' => 'value2',
277 );
278
279 self_link
280 Make a link to the current application, with optional parameters, and
281 add a checksum to the URL.
282
283 my $link = $self->self_link(
284 'param1' => 'value1',
285 'param2' => 'value2',
286 );
287
288 "self_link" preserves the value of the current application's
289 "PATH_INFO". For instance if the current URL is:
290
291 /cgi-bin/app.cgi/some/path?foo=bar # PATH_INFO is 'some/path'
292
293 Calling:
294
295 $self->self_link('bar' => 'baz');
296
297 Will produce the URL:
298
299 /cgi-bin/app.cgi/some/path?bar=baz
300
301 If you want to remove the "PATH_INFO" value or replace it with a new
302 value, use path_link.
303
304 path_link
305 Calling "path_link" is the same as calling "self_link", except the
306 current value of "PATH_INFO" can be replaced.
307
308 my $link = $self->path_link(
309 '/new/path',
310 'param1' => 'value1',
311 'param2' => 'value2',
312 );
313
314 For instance if the current URL is:
315
316 /cgi-bin/app.cgi/some/path?foo=bar # PATH_INFO is 'some/path'
317
318 Calling:
319
320 $self->path_link('/new/path');
321
322 Will produce the URL:
323
324 /cgi-bin/app.cgi/new/path?foo=bar
325
326 If you want to remove "PATH_INFO" entirely, call one of the following:
327
328 $self->path_link;
329 $self->path_link(undef, 'param1' => 'val1', 'param2 => 'val2' ...);
330 $self->path_link('', 'param1' => 'val1', 'param2 => 'val2' ...);
331
332 If you want to keep the existing "PATH_INFO" that was passed to the
333 current application, use self_link instead.
334
336 The link_tampered Run Mode
337 Your application is redirected to this run mode when it has been
338 detected that the user has tampered with the link. You can change the
339 name of this run mode by changing the value of the
340 "link_tampered_runmode" param to "link_integrity_config".
341
342 CGI::Application::Plugin::LinkIntegrity provides a default
343 "link_tampered" run mode, which just displays a page with some stern
344 warning text.
345
346 You can define your own as follows:
347
348 sub link_tampered {
349 my $self = shift;
350 my $template = $self->load_template('stern_talking_to');
351 return $template->output;
352 }
353
355 When a link is followed that doesn't match the checksum, the
356 "invalid_checksum" hook is called. You can add a callback to this hook
357 to do some cleanup such as deleting the user's session. For instance:
358
359 sub setup {
360 my $self = shift;
361 $self->add_callback('invalid_checksum' => \&bad_user);
362 }
363
364 sub bad_user {
365 my $self = shift;
366
367 # The user has been messing with the URLs, possibly trying to
368 # break into the system. We don't tolerate this behaviour.
369 # So we delete the user's session:
370
371 $self->session->delete;
372 }
373
375 Michael Graham, "<mag-perl@occamstoothbrush.com>"
376
378 This module was based on the checksum feature originally built into
379 Richard Dice's CGI::Application::Framework.
380
382 Please report any bugs or feature requests to
383 "bug-cgi-application-plugin-linkintegrity@rt.cpan.org", or through the
384 web interface at <http://rt.cpan.org>. I will be notified, and then
385 you'll automatically be notified of progress on your bug as I make
386 changes.
387
389 Copyright 2005 Michael Graham, All Rights Reserved.
390
391 This program is free software; you can redistribute it and/or modify it
392 under the same terms as Perl itself.
393
394
395
396perl v5.12.2 201C0G-I1:1:-A1p0plication::Plugin::LinkIntegrity(3)