blob: 4e8ea99166e0dc31f569d22fc1fae7da63db8ca9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
#!/bin/sh
#
# ensure we never fallback from a signed to a unsigned repo
#
# hash checks are done in
#
set -e
simulate_mitm_and_inject_evil_package()
{
rm -f $APTARCHIVE/dists/unstable/InRelease
rm -f $APTARCHIVE/dists/unstable/Release.gpg
inject_evil_package
}
inject_evil_package()
{
cat > $APTARCHIVE/dists/unstable/main/binary-i386/Packages <<EOF
Package: evil
Installed-Size: 29
Maintainer: Joe Sixpack <joe@example.org>
Architecture: all
Version: 1.0
Filename: pool/evil_1.0_all.deb
Size: 1270
Description: an autogenerated evil package
EOF
# avoid ims hit
touch -d '+1hour' aptarchive/dists/unstable/main/binary-i386/Packages
}
assert_update_is_refused_and_last_good_state_used()
{
testequal "E: The repository 'file: unstable Release.gpg' is no longer signed." aptget update -qq
assert_repo_is_intact
}
assert_repo_is_intact()
{
testequal "foo/unstable 2.0 all" apt list -q
testsuccess "" aptget install -y -s foo
testfailure "" aptget install -y evil
LISTDIR=rootdir/var/lib/apt/lists
if ! ( ls $LISTDIR/*InRelease >/dev/null 2>&1 ||
ls $LISTDIR/*Release.gpg >/dev/null 2>&1 ); then
echo "Can not find InRelease/Release.gpg in $(ls $LISTDIR)"
msgfail
fi
}
setupaptarchive_with_lists_clean()
{
setupaptarchive --no-update
rm -f rootdir/var/lib/apt/lists/_*
#rm -rf rootdir/var/lib/apt/lists
}
test_from_inrelease_to_unsigned()
{
# setup archive with InRelease file
setupaptarchive_with_lists_clean
testsuccess aptget update
simulate_mitm_and_inject_evil_package
assert_update_is_refused_and_last_good_state_used
}
test_from_release_gpg_to_unsigned()
{
# setup archive with Release/Release.gpg (but no InRelease)
setupaptarchive_with_lists_clean
rm $APTARCHIVE/dists/unstable/InRelease
testsuccess aptget update
simulate_mitm_and_inject_evil_package
assert_update_is_refused_and_last_good_state_used
}
test_cve_2012_0214()
{
# see https://bugs.launchpad.net/ubuntu/+source/apt/+bug/947108
#
# it was possible to MITM the download so that InRelease/Release.gpg
# are not delivered (404) and a altered Release file was send
#
# apt left the old InRelease file in /var/lib/apt/lists and downloaded
# the unauthenticated Release file too giving the false impression that
# Release was authenticated
#
# Note that this is pretty much impossible nowdays because:
# a) InRelease is left as is, not split to InRelease/Release as it was
# in the old days
# b) we refuse to go from signed->unsigned
#
# Still worth having a regression test the simulates the condition
# setup archive with InRelease
setupaptarchive_with_lists_clean
testsuccess aptget update
# do what CVE-2012-0214 did
rm $APTARCHIVE/dists/unstable/InRelease
rm $APTARCHIVE/dists/unstable/Release.gpg
inject_evil_package
# build valid Release file
aptftparchive -qq release ./aptarchive > aptarchive/dists/unstable/Release
assert_update_is_refused_and_last_good_state_used
# ensure there is no _Release file downloaded
testfailure ls rootdir/var/lib/apt/lists/*_Release
}
test_subvert_inrelease()
{
# setup archive with InRelease
setupaptarchive_with_lists_clean
testsuccess aptget update
# replace InRelease with something else
mv $APTARCHIVE/dists/unstable/Release $APTARCHIVE/dists/unstable/InRelease
testequal "W: Failed to fetch file:${APTARCHIVE}/dists/unstable/InRelease Does not start with a cleartext signature
E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq
# ensure we keep the repo
assert_repo_is_intact
}
test_inrelease_to_invalid_inrelease()
{
# setup archive with InRelease
setupaptarchive_with_lists_clean
testsuccess aptget update
# now remove InRelease and subvert Release do no longer verify
sed -i 's/Codename.*/Codename: evil!'/ $APTARCHIVE/dists/unstable/InRelease
inject_evil_package
testequal "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: file: unstable InRelease: The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) <joe@example.org>
W: Failed to fetch file:${APTARCHIVE}/dists/unstable/InRelease
W: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq
# ensure we keep the repo
assert_repo_is_intact
testfailure grep "evil" rootdir/var/lib/apt/lists/*InRelease
}
test_release_gpg_to_invalid_release_release_gpg()
{
# setup archive with InRelease
setupaptarchive_with_lists_clean
rm $APTARCHIVE/dists/unstable/InRelease
testsuccess aptget update
# now subvert Release do no longer verify
echo "Some evil data" >> $APTARCHIVE/dists/unstable/Release
inject_evil_package
testequal "E: The repository 'file: unstable Release.gpg' is no longer signed." aptget update -qq
assert_repo_is_intact
testfailure grep "evil" rootdir/var/lib/apt/lists/*Release
}
TESTDIR=$(readlink -f $(dirname $0))
. $TESTDIR/framework
setupenvironment
configarchitecture "i386"
# a "normal" package with source and binary
buildsimplenativepackage 'foo' 'all' '2.0'
# setup the archive and ensure we have a single package that installs fine
setupaptarchive
APTARCHIVE=$(readlink -f ./aptarchive)
assert_repo_is_intact
# test the various cases where a repo may go from signed->unsigned
msgmsg "test_from_inrelease_to_unsigned"
test_from_inrelease_to_unsigned
msgmsg "test_from_release_gpg_to_unsigned"
test_from_release_gpg_to_unsigned
# ensure we do not regress on CVE-2012-0214
msgmsg "test_cve_2012_0214"
test_cve_2012_0214
# ensure InRelase can not be subverted
msgmsg "test_subvert_inrelease"
test_subvert_inrelease
# ensure we revert to last good state if InRelease does not verify
msgmsg "test_inrelease_to_invalid_inrelease"
test_inrelease_to_invalid_inrelease
# ensure we revert to last good state if Release/Release.gpg does not verify
msgmsg "test_release_gpg_to_invalid_release_release_gpg"
test_release_gpg_to_invalid_release_release_gpg
|