| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package LWP::Auth_UA; |
|
2
|
|
|
|
|
|
|
$REVISION=q$Revision: 1.5 $ ; $VERSION = sprintf ( "%d.%02d", $REVISION =~ /(\d+).(\d+)/ ); |
|
3
|
2
|
|
|
2
|
|
174541
|
use LWP::UserAgent; |
|
|
2
|
|
|
|
|
151861
|
|
|
|
2
|
|
|
|
|
86
|
|
|
4
|
|
|
|
|
|
|
@ISA=qw(LWP::UserAgent); |
|
5
|
|
|
|
|
|
|
|
|
6
|
2
|
|
|
2
|
|
21
|
use strict; |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
59
|
|
|
7
|
2
|
|
|
2
|
|
10
|
use warnings; |
|
|
2
|
|
|
|
|
6
|
|
|
|
2
|
|
|
|
|
571
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 NAME |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
LWP::Auth_UA.pm - a user agent which knows some authorisation tokens |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
use LWP::Auth_UA.pm |
|
16
|
|
|
|
|
|
|
credentials ( { |
|
17
|
|
|
|
|
|
|
my_realm => { uri_re => "https://myhost.example.com", |
|
18
|
|
|
|
|
|
|
credential => "my_secret" } |
|
19
|
|
|
|
|
|
|
} ); |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
$ua = LWP::Auth_UA->new; |
|
22
|
|
|
|
|
|
|
$request = HTTP::Request->new('GET', 'file://localhost/etc/motd'); |
|
23
|
|
|
|
|
|
|
$response = $ua->request($request); |
|
24
|
|
|
|
|
|
|
etc... |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
This is a LWP user agent which is almost identical to the normal user |
|
29
|
|
|
|
|
|
|
agent (LWP::UserAgent) except that if it reaches a situation where it |
|
30
|
|
|
|
|
|
|
needs an authentication token then it will send a token which it has |
|
31
|
|
|
|
|
|
|
stored. |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
Storing authentication tokens in a file is inherently a security |
|
34
|
|
|
|
|
|
|
issue. This risk may, however, not be much higher than the one that |
|
35
|
|
|
|
|
|
|
you are currently carrying, so this can be useful. |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
This page describes how this works and how to ensure that the security |
|
38
|
|
|
|
|
|
|
risks you are taking on are not greater than are acceptable to you. |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
As with the rest of LinkController, there is no warantee. If you have |
|
41
|
|
|
|
|
|
|
an environment in which this might be a problem, you should definitely |
|
42
|
|
|
|
|
|
|
find someone to look over your installation and ensure that everything |
|
43
|
|
|
|
|
|
|
is done correctly. Of course, this is true of every piece of software |
|
44
|
|
|
|
|
|
|
you install. |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=head1 SECURITY RISKS |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
The fundamental security problem with this system is that the |
|
49
|
|
|
|
|
|
|
authentication token must be stored somewhere where the program can |
|
50
|
|
|
|
|
|
|
access it. This is because link-controller has to send the actual |
|
51
|
|
|
|
|
|
|
authentication token over the link to authenticate. Since it's very |
|
52
|
|
|
|
|
|
|
easy to monitor the inputs and outputs of a program, it's very easy to |
|
53
|
|
|
|
|
|
|
monitor this password. |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
This applies even if we keep the password in some encrypted form, |
|
56
|
|
|
|
|
|
|
since we then have to store the decryption key in the program which |
|
57
|
|
|
|
|
|
|
can then be found and used to decrypt the key. |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
So there are only two possible defenses: |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=over 4 |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=item * |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
make sure that the program data remains secret |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=item * |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
make sure that the passwords the program has can't do any real damage |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=back |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
We demand permissions on our files which protect against accidental |
|
74
|
|
|
|
|
|
|
disclosure by encouraging the user to be more secure. |
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
Making sure that the program can't do any damage is normally achieved |
|
77
|
|
|
|
|
|
|
by giving it a dedicated account which has only read only privilages |
|
78
|
|
|
|
|
|
|
and, preferably, can only use it's privilages from a specified system |
|
79
|
|
|
|
|
|
|
which will be the host on which the link checking is run. |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=head2 Accidental Sending of Tokens |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
Another authentication risk is that the system will send it to a |
|
84
|
|
|
|
|
|
|
server which is trying to trick it. This is again difficult to |
|
85
|
|
|
|
|
|
|
protect against. The only solution in this case is to ensure that the |
|
86
|
|
|
|
|
|
|
regular expression used for limiting the URI matches only host names |
|
87
|
|
|
|
|
|
|
which are under the control of the body responsible for handing out |
|
88
|
|
|
|
|
|
|
the authentication token. |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
The security of this system is not of course perfect. If we can |
|
91
|
|
|
|
|
|
|
pretend to be the host that we are meant to send the authentication |
|
92
|
|
|
|
|
|
|
token to then we will can trick the user agent into sending the token. |
|
93
|
|
|
|
|
|
|
Remember that the hostname being used is the one in the URL we are |
|
94
|
|
|
|
|
|
|
trying to examine, so the protection against this is having a secure |
|
95
|
|
|
|
|
|
|
and correct DNS system and ensuring that we have a secure IP |
|
96
|
|
|
|
|
|
|
connection to the end host. |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=head2 Sending of Tokens over Insecure protocols |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
If an insecure protocol like HTTP is used for sending an |
|
101
|
|
|
|
|
|
|
authentication token, then it is possible for someone to listen to the |
|
102
|
|
|
|
|
|
|
transaction and record the token for later use. |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
The protection against this is to switch over to only using secure |
|
105
|
|
|
|
|
|
|
protocols and hard wire the protocol name into the URI regular expression. |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=cut |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub get_basic_credentials { |
|
110
|
4
|
|
|
4
|
1
|
353889
|
my $self=shift; |
|
111
|
4
|
|
|
|
|
8
|
my $realm=shift; |
|
112
|
4
|
|
|
|
|
6
|
my $uri=shift; |
|
113
|
4
|
|
|
|
|
6
|
my $proxy=shift; |
|
114
|
4
|
|
|
|
|
8
|
my $credentials=$self->{"Auth_UA-credentials"}; |
|
115
|
4
|
100
|
|
|
|
15
|
return undef unless defined $credentials; |
|
116
|
3
|
|
|
|
|
5
|
my $rec=$credentials->{$realm}; |
|
117
|
3
|
100
|
|
|
|
9
|
return undef unless defined $rec; |
|
118
|
2
|
|
|
|
|
4
|
my $re=$rec->{uri_re}; |
|
119
|
2
|
100
|
|
|
|
24
|
return undef unless $uri =~ m/$re/; |
|
120
|
1
|
|
|
|
|
5
|
return $rec->{credential} |
|
121
|
|
|
|
|
|
|
} |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub auth_ua_credentials { |
|
124
|
1
|
|
|
1
|
0
|
4595
|
my $self=shift; |
|
125
|
1
|
50
|
|
|
|
7
|
return $self->{"Auth_UA-credentials"} unless @_; |
|
126
|
1
|
|
|
|
|
3
|
my $cred=shift; |
|
127
|
1
|
|
|
|
|
3
|
$self->{"Auth_UA-credentials"} = $cred; |
|
128
|
1
|
|
|
|
|
3
|
return $cred; |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
sub delete_brain_dead_credentials { |
|
132
|
1
|
|
|
1
|
0
|
20
|
my $self=shift; |
|
133
|
1
|
|
|
|
|
2
|
my $cred=shift; |
|
134
|
1
|
50
|
|
|
|
5
|
$cred=$self->{"Auth_UA-credentials"} unless defined $cred; |
|
135
|
1
|
50
|
|
|
|
4
|
return undef unless defined $cred; |
|
136
|
1
|
|
|
|
|
6
|
foreach my $key ( keys %$cred ) { |
|
137
|
2
|
|
|
|
|
5
|
my $rec=$cred->{$key}; |
|
138
|
2
|
|
|
|
|
4
|
my $re=$rec->{uri_re}; |
|
139
|
|
|
|
|
|
|
( "http://3133t3hax0rs.rhere.com" =~ m/$re/ |
|
140
|
|
|
|
|
|
|
or "http://3133t3hax0rs.rhere.com/secretstuff/www.goodplace.com/" =~ m/$re/ ) |
|
141
|
2
|
100
|
66
|
|
|
56
|
and do { |
|
142
|
1
|
|
|
|
|
16
|
warn "Deleting credential with dangerous URI RE $re in Auth_UE for real $key"; |
|
143
|
1
|
|
|
|
|
9
|
delete $cred->{$key}; |
|
144
|
|
|
|
|
|
|
}; |
|
145
|
|
|
|
|
|
|
} |
|
146
|
1
|
|
|
|
|
4
|
return $cred; |
|
147
|
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
# sub aua_load_credentials { |
|
151
|
|
|
|
|
|
|
# my $self=shift; |
|
152
|
|
|
|
|
|
|
# my $file=$self->{Auth_UA-authfile}; |
|
153
|
|
|
|
|
|
|
# open my $cred, $file; |
|
154
|
|
|
|
|
|
|
# while ( <$cred> ) { |
|
155
|
|
|
|
|
|
|
# my ($realm, $auth, $uri_re) = m/ |
|
156
|
|
|
|
|
|
|
# }; |
|
157
|
|
|
|
|
|
|
# } |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# sub aua_authfile { |
|
160
|
|
|
|
|
|
|
# my $self=shift; |
|
161
|
|
|
|
|
|
|
# return $self->{Auth_UA-authfile} unless @_; |
|
162
|
|
|
|
|
|
|
# $self->{Auth_UA-authfile} = shift; |
|
163
|
|
|
|
|
|
|
# } |