shm
2014-06-25 07:35:12 UTC
Hello,
bozohttpd currently checks password using strcmp, which may leak information
about compared data, my patch [1] introduces following countermeasures:
- username / password is now compared using introduced timing safe function
(which run time depends on the known string)
- remove username/password from the memory as it's no longer needed
- avoid username leak by checking all records in the auth file (previously
when we found valid username but user sent invalid password we break from
the loop, so other records from the .htpassword weren't checked, thus an
attacker basing on response time could be able to figure out if username
exists) by checking all records in the file.
This might sounds a bit paranoid, but I've got real world example that the
problem really exists:
192.168.1.105 is a bozohttpd (built from HEAD):
executed by: : /usr/libexec/httpd -d -c cgi-bin -bf -X -I 8080 .
192.168.1.105
***@netbsd-dev ~/www $ cat .htpasswd
bla:$sha1$22983$EVXICHNn$wnulZLsEKwnbZTwGRD0vi/8n5rzP
test:$sha1$22983$EVXICHNn$wnulZLsEKwnbZTwGRD0vi/8n5rzP
test2:$sha1$22983$EVXICHNn$wnulZLsEKwnbZTwGRD0vi/8n5rzP
test3:$sha1$22983$EVXICHNn$wnulZLsEKwnbZTwGRD0vi/8n5rzP
test4:$sha1$22983$EVXICHNn$wnulZLsEKwnbZTwGRD0vi/8n5rzP
test6:$sha1$22983$EVXICHNn$wnulZLsEKwnbZTwGRD0vi/8n5rzO
(password is bla)
Response times from the machine in the same LAN:
For non-existing user:
$ for ((i=0;i<100;i++)) ; do time curl
http://notexists:***@192.168.1.105:8080/ ; done 2> /dev/stdout | grep real |
sort | uniq -c
1 real 0m0.016s
1 real 0m0.017s
3 real 0m0.018s
13 real 0m0.019s
50 real 0m0.020s
4 real 0m0.021s
1 real 0m0.022s
1 real 0m0.023s
2 real 0m0.024s
5 real 0m0.025s
7 real 0m0.030s
3 real 0m0.031s
1 real 0m0.033s
1 real 0m0.034s
2 real 0m0.035s
2 real 0m0.036s
1 real 0m0.037s
1 real 0m0.040s
1 real 0m0.045s
For existing user:
$ for ((i=0;i<100;i++)) ; do time curl http://test3:***@192.168.1.105:8080/ ;
done 2> /dev/stdout | grep real | sort | uniq -c
2 real 0m0.086s
3 real 0m0.087s
3 real 0m0.088s
14 real 0m0.089s
43 real 0m0.090s
11 real 0m0.091s
2 real 0m0.092s
2 real 0m0.093s
2 real 0m0.094s
2 real 0m0.095s
3 real 0m0.096s
1 real 0m0.097s
1 real 0m0.098s
1 real 0m0.101s
1 real 0m0.102s
1 real 0m0.104s
5 real 0m0.106s
1 real 0m0.108s
1 real 0m0.115s
1 real 0m0.130s
For bozohttpd with my patch results are as follows:
For not-existing user:
***@selene ~ $ for ((i=0;i<100;i++)) ; do time curl
http://notexists:***@192.168.1.105:8080/ ; done 2> /dev/stdout | grep real |
sort | uniq -c
2 real 0m0.087s
3 real 0m0.088s
13 real 0m0.089s
51 real 0m0.090s
10 real 0m0.091s
2 real 0m0.093s
2 real 0m0.094s
2 real 0m0.095s
1 real 0m0.096s
1 real 0m0.097s
7 real 0m0.100s
1 real 0m0.102s
1 real 0m0.104s
1 real 0m0.106s
1 real 0m0.114s
1 real 0m0.115s
1 real 0m0.268s
For existing user:
***@selene ~ $ for ((i=0;i<100;i++)) ; do time curl
http://bla:***@192.168.1.105:8080/ ; done 2> /dev/stdout | grep real | sort |
uniq -c
1 real 0m0.087s
12 real 0m0.089s
54 real 0m0.090s
11 real 0m0.091s
2 real 0m0.092s
2 real 0m0.093s
1 real 0m0.094s
2 real 0m0.096s
5 real 0m0.100s
2 real 0m0.101s
1 real 0m0.104s
5 real 0m0.105s
1 real 0m0.115s
1 real 0m0.120s
----
Do you have any thoughts on this? I'd like to commit [1], if there is no
objections.
Kind Regards,
shm@
[1] http://netbsd.org/~shm/patches/bozohttpd/consttime_auth-bozo.diff
bozohttpd currently checks password using strcmp, which may leak information
about compared data, my patch [1] introduces following countermeasures:
- username / password is now compared using introduced timing safe function
(which run time depends on the known string)
- remove username/password from the memory as it's no longer needed
- avoid username leak by checking all records in the auth file (previously
when we found valid username but user sent invalid password we break from
the loop, so other records from the .htpassword weren't checked, thus an
attacker basing on response time could be able to figure out if username
exists) by checking all records in the file.
This might sounds a bit paranoid, but I've got real world example that the
problem really exists:
192.168.1.105 is a bozohttpd (built from HEAD):
executed by: : /usr/libexec/httpd -d -c cgi-bin -bf -X -I 8080 .
192.168.1.105
***@netbsd-dev ~/www $ cat .htpasswd
bla:$sha1$22983$EVXICHNn$wnulZLsEKwnbZTwGRD0vi/8n5rzP
test:$sha1$22983$EVXICHNn$wnulZLsEKwnbZTwGRD0vi/8n5rzP
test2:$sha1$22983$EVXICHNn$wnulZLsEKwnbZTwGRD0vi/8n5rzP
test3:$sha1$22983$EVXICHNn$wnulZLsEKwnbZTwGRD0vi/8n5rzP
test4:$sha1$22983$EVXICHNn$wnulZLsEKwnbZTwGRD0vi/8n5rzP
test6:$sha1$22983$EVXICHNn$wnulZLsEKwnbZTwGRD0vi/8n5rzO
(password is bla)
Response times from the machine in the same LAN:
For non-existing user:
$ for ((i=0;i<100;i++)) ; do time curl
http://notexists:***@192.168.1.105:8080/ ; done 2> /dev/stdout | grep real |
sort | uniq -c
1 real 0m0.016s
1 real 0m0.017s
3 real 0m0.018s
13 real 0m0.019s
50 real 0m0.020s
4 real 0m0.021s
1 real 0m0.022s
1 real 0m0.023s
2 real 0m0.024s
5 real 0m0.025s
7 real 0m0.030s
3 real 0m0.031s
1 real 0m0.033s
1 real 0m0.034s
2 real 0m0.035s
2 real 0m0.036s
1 real 0m0.037s
1 real 0m0.040s
1 real 0m0.045s
For existing user:
$ for ((i=0;i<100;i++)) ; do time curl http://test3:***@192.168.1.105:8080/ ;
done 2> /dev/stdout | grep real | sort | uniq -c
2 real 0m0.086s
3 real 0m0.087s
3 real 0m0.088s
14 real 0m0.089s
43 real 0m0.090s
11 real 0m0.091s
2 real 0m0.092s
2 real 0m0.093s
2 real 0m0.094s
2 real 0m0.095s
3 real 0m0.096s
1 real 0m0.097s
1 real 0m0.098s
1 real 0m0.101s
1 real 0m0.102s
1 real 0m0.104s
5 real 0m0.106s
1 real 0m0.108s
1 real 0m0.115s
1 real 0m0.130s
For bozohttpd with my patch results are as follows:
For not-existing user:
***@selene ~ $ for ((i=0;i<100;i++)) ; do time curl
http://notexists:***@192.168.1.105:8080/ ; done 2> /dev/stdout | grep real |
sort | uniq -c
2 real 0m0.087s
3 real 0m0.088s
13 real 0m0.089s
51 real 0m0.090s
10 real 0m0.091s
2 real 0m0.093s
2 real 0m0.094s
2 real 0m0.095s
1 real 0m0.096s
1 real 0m0.097s
7 real 0m0.100s
1 real 0m0.102s
1 real 0m0.104s
1 real 0m0.106s
1 real 0m0.114s
1 real 0m0.115s
1 real 0m0.268s
For existing user:
***@selene ~ $ for ((i=0;i<100;i++)) ; do time curl
http://bla:***@192.168.1.105:8080/ ; done 2> /dev/stdout | grep real | sort |
uniq -c
1 real 0m0.087s
12 real 0m0.089s
54 real 0m0.090s
11 real 0m0.091s
2 real 0m0.092s
2 real 0m0.093s
1 real 0m0.094s
2 real 0m0.096s
5 real 0m0.100s
2 real 0m0.101s
1 real 0m0.104s
5 real 0m0.105s
1 real 0m0.115s
1 real 0m0.120s
----
Do you have any thoughts on this? I'd like to commit [1], if there is no
objections.
Kind Regards,
shm@
[1] http://netbsd.org/~shm/patches/bozohttpd/consttime_auth-bozo.diff