Skip to content

Commit

Permalink
Didn't work with <form action="http://{http_host}/api" ...
Browse files Browse the repository at this point in the history
More tests.
  • Loading branch information
Rintaro Ishizaki committed Feb 7, 2011
1 parent fafd2d4 commit 7cc4f95
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 36 deletions.
2 changes: 1 addition & 1 deletion lib/Plack/Middleware/CSRFBlock.pm
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ sub call {
if(
lc($tag) ne 'form' or
lc($attr->{'method'}) ne 'post' or
($attr->{'action'} =~ m{^https?://([^/])+/} and $1 ne $http_host)
($attr->{'action'} =~ m{^https?://([^/:]+)[/:]} and $1 ne $http_host)
) {
return;
}
Expand Down
131 changes: 96 additions & 35 deletions t/01_basic.t
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,47 @@ my $form = <<FORM;
<head><title>the form</title></head>
<body>
<form action="/post" method="post">
<input type="text" />
<input type="text" name="name" />
<input type="submit" />
</form>
</body>
</html>
FORM

my $form_outside = <<FORM;
<html>
<head><title>the form</title></head>
<body>
<form action="http://example.com/post" method="post">
<input type="text" name="name" />
<input type="submit" />
</form>
<form action="http://example.com:80/post" method="post">
<input type="text" name="text" />
<input type="submit" />
</form>
</body>
</html>
FORM

my $form_localhost = <<FORM;
<html>
<head><title>the form</title></head>
<body>
<form action="http://localhost/post" method="post">
<input type="text" name="name" />
<input type="submit" />
</form>
</body>
</html>
FORM

my $form_localhost_port = <<FORM;
<html>
<head><title>the form</title></head>
<body>
<form action="http://localhost:80/post" method="post">
<input type="text" name="name" />
<input type="submit" />
</form>
</body>
Expand All @@ -35,6 +75,10 @@ my $mapped = builder {
mount "/form/html-charset" => sub { [ 200, [ 'Content-Type' => 'text/html; charset=UTF-8' ], [ $form ] ] };
mount "/form/xhtml-charset" => sub { [ 200, [ 'Content-Type' => 'application/xhtml+xml; charset=UTF-8' ], [ $form ] ] };
mount "/form/text-charset" => sub { [ 200, [ 'Content-Type' => 'text/plain; charset=UTF-8' ], [ $form ] ] };

mount "/form/html-outside" => sub { [ 200, [ 'Content-Type' => 'text/html' ], [ $form_outside ] ] };
mount "/form/html-localhost" => sub { [ 200, [ 'Content-Type' => 'text/html' ], [ $form_localhost ] ] };
mount "/form/html-localhost-port" => sub { [ 200, [ 'Content-Type' => 'text/html' ], [ $form_localhost_port ] ] };
};

# normal input
Expand Down Expand Up @@ -75,78 +119,94 @@ test_psgi app => $app, client => sub {
ok($sid);

$res = $cb->(POST "http://localhost/post", [name => 'Plack'], Cookie => "sid=$sid");
is $res->code, 403;
is $res->code, 403, 'Forbidden for CSRF';
$res = $cb->(POST "http://localhost/post", [SEC => '1234567890123456', name => 'Plack'], Cookie => "sid=$sid");
is $res->code, 403;
is $res->code, 403, 'Forbidden for faked token';

$res = $cb->(GET "http://localhost/form/html", Cookie => "sid=$sid");
is $res->code, 200;
ok $res->content =~ /<input type="hidden" name="SEC" value="([0-9a-f]{16})" \/>/;
is $res->code, 200, 'form /form/html';
ok $res->content =~ /<input type="hidden" name="SEC" value="([0-9a-f]{16})" \/>/, 'form_has_token /form/html';
my $token = $1;

$res = $cb->(GET "http://localhost/form/html-charset", Cookie => "sid=$sid");
is $res->code, 200;
ok $res->content =~ /<input type="hidden" name="SEC" value="([0-9a-f]{16})" \/>/;
is $1, $token;
is $res->code, 200, 'form /form/html-charset';
ok $res->content =~ /<input type="hidden" name="SEC" value="([0-9a-f]{16})" \/>/, 'form_has_token /form/html-charset';
is $1, $token, 'same token for same sid';

$res = $cb->(GET "http://localhost/form/html-outside", Cookie => "sid=$sid");
is $res->code, 200, 'form /form/html-outside';
ok $res->content !~ /<input type="hidden" name="SEC" value="([0-9a-f]{16})" \/>/, 'form_has_not_token /form/html-outside';

$res = $cb->(GET "http://localhost/form/html-localhost", Cookie => "sid=$sid");
is $res->code, 200, 'form /form/html-localhost';
ok $res->content =~ /<input type="hidden" name="SEC" value="([0-9a-f]{16})" \/>/, 'form_has_token /form/html-localhost';
is $1, $token, 'same token for same sid again';

$res = $cb->(GET "http://localhost/form/html-localhost-port", Cookie => "sid=$sid");
is $res->code, 200, 'form /form/html-localhost-port';
ok $res->content =~ /<input type="hidden" name="SEC" value="([0-9a-f]{16})" \/>/, 'form_has_token /form/html-localhost-port';
is $1, $token, 'same token for same sid again2';

# application/x-www-form-urlencoded
$res = $cb->(POST "http://localhost/post",
[SEC => $token, name => 'Plack'],
Cookie => "sid=$sid",
'Content-Type' => 'application/x-www-form-urlencoded'
);
is $res->code, 200;
is $res->content, 'Hello Plack';
is $res->code, 200, 'correct token returns 200';
is $res->content, 'Hello Plack', 'name param';

$res = $cb->(POST "http://localhost/post",
[SEC => $token, x => 'x' x 20000, name => 'Plack'],
Cookie => "sid=$sid",
'Content-Type' => 'application/x-www-form-urlencoded'
);
is $res->code, 200;
is $res->content, 'Hello Plack';
is $res->code, 200, 'correnct token returns 200 / long body';
is $res->content, 'Hello Plack', 'name param / long body';

# multipart/form-data
$res = $cb->(POST "http://localhost/post",
[SEC => $token, name => 'Plack'],
Cookie => "sid=$sid",
'Content-Type' => 'multipart/form-data'
);
is $res->code, 200;
is $res->content, 'Hello Plack';
is $res->code, 200, 'correct token returns 200 / multipart/form-data';
is $res->content, 'Hello Plack', 'name param / multipart/form-data';

$res = $cb->(POST "http://localhost/post",
[SEC => $token, x => 'x' x 20000, name => 'Plack'],
Cookie => "sid=$sid",
'Content-Type' => 'multipart/form-data'
);
is $res->code, 200;
is $res->content, 'Hello Plack';
is $res->code, 200, 'correct token returns 200 / long body / multipart/form-data';
is $res->content, 'Hello Plack', 'name param / long body / multipart/form-data';

# application/x-www-form-urlencoded; charset=UTF-8
$res = $cb->(POST "http://localhost/post",
[SEC => $token, name => 'Plack'],
Cookie => "sid=$sid",
'Content-Type' => 'application/x-www-form-urlencoded; chartset=UTF-8'
);
is $res->code, 200;
is $res->content, 'Hello Plack';
is $res->code, 200, 'correct token returns 200 / charset';
is $res->content, 'Hello Plack', 'name param / charset';

$res = $cb->(POST "http://localhost/post",
[SEC => $token, x => 'x' x 20000, name => 'Plack'],
Cookie => "sid=$sid",
'Content-Type' => 'application/x-www-form-urlencoded; chartset=UTF-8'
);
is $res->code, 200;
is $res->content, 'Hello Plack';
is $res->code, 200, 'correct token returns 200 / long body / charset';
is $res->content, 'Hello Plack', 'name param / long body /charset';

# multipart/form-data; charset=UTF-8
$res = $cb->(POST "http://localhost/post",
[SEC => $token, name => 'Plack'],
Cookie => "sid=$sid",
'Content-Type' => 'multipart/form-data; chartset=UTF-8'
);
is $res->code, 200;
is $res->content, 'Hello Plack';
is $res->code, 200, 'correct token returns 200 / long body / multipart/form-data / charset';
is $res->content, 'Hello Plack', 'name param / long body / multipart/form-data / charset';

$res = $cb->(POST "http://localhost/post",
[SEC => $token, x => 'x' x 20000, name => 'Plack'],
Cookie => "sid=$sid",
Expand All @@ -155,15 +215,16 @@ test_psgi app => $app, client => sub {
is $res->code, 200;
is $res->content, 'Hello Plack';

# supported content-type
$res = $cb->(GET "http://localhost/form/xhtml", Cookie => "sid=$sid");
like $res->content, qr/<input type="hidden" name="SEC" value="$token" \/>/;
like $res->content, qr/<input type="hidden" name="SEC" value="$token" \/>/, 'xhtml form has token';
$res = $cb->(GET "http://localhost/form/text", Cookie => "sid=$sid");
unlike $res->content, qr/<input type="hidden" name="SEC" value="$token" \/>/;
unlike $res->content, qr/<input type="hidden" name="SEC" value="$token" \/>/, 'text form has not token';

$res = $cb->(GET "http://localhost/form/xhtml-charset", Cookie => "sid=$sid");
like $res->content, qr/<input type="hidden" name="SEC" value="$token" \/>/;
like $res->content, qr/<input type="hidden" name="SEC" value="$token" \/>/, 'xhtml-charset form has token';
$res = $cb->(GET "http://localhost/form/text-charset", Cookie => "sid=$sid");
unlike $res->content, qr/<input type="hidden" name="SEC" value="$token" \/>/;
unlike $res->content, qr/<input type="hidden" name="SEC" value="$token" \/>/, 'text-charset form has token';
};

}; # for my $app ($app1,$app2)
Expand All @@ -190,7 +251,7 @@ test_psgi app => $app3, client => sub {
my $cb = shift;

my $res = $cb->(GET "http://localhost/form/xhtml");
is $res->code, 200;
is $res->code, 200, 'w/param form';

my $h_cookie = $res->header('Set-Cookie');
$h_cookie =~ /sid=([^; ]+)/;
Expand All @@ -199,25 +260,25 @@ test_psgi app => $app3, client => sub {
ok $res->content =~ /<input type="hidden" name="TKN" value="([0-9a-f]{8})" \/>/;
my $token = $1;
$res = $cb->(POST "http://localhost/post", [TKN => $token, name => 'Plack'], Cookie => "sid=$sid");
is $res->code, 200;
is $res->code, 200, 'w/param:onetime token use firsttime';
$res = $cb->(POST "http://localhost/post", [TKN => $token, name => 'Plack'], Cookie => "sid=$sid");
is $res->code, 404;
is $res->content, 'csrf';
is $res->code, 404, 'w/param:onetime second token use';
is $res->content, 'csrf', 'w/param:blocked custom blocked app';

for(1..2) {
$res = $cb->(GET "http://localhost/form/xhtml", Cookie => "sid=$sid");
is $res->code, 200;
is $res->code, 200, 'w/param form again';
ok $res->content =~ /<input type="hidden" name="TKN" value="([0-9a-f]{8})" \/>/;
isnt $1, $token;
isnt $1, $token, 'w/param:onetime token changed';
$token = $1;

$res = $cb->(POST "http://localhost/post", [TKN => $token, name => 'Plack'], Cookie => "sid=$sid");
is $res->code, 200;
is $res->code, 200, 'w/param:onetime new token used';
}

$res = $cb->(POST "http://localhost/post", [TKN => $token, name => 'Plack'], Cookie => "sid=$sid");
is $res->code, 404;
is $res->content, 'csrf';
is $res->code, 404, 'w/param:onetime second token use again';
is $res->content, 'csrf', 'w/param:blocked custom blocked app again';
};


Expand Down

0 comments on commit 7cc4f95

Please sign in to comment.