Age | Commit message (Collapse) | Author | Files | Lines |
|
Previously the website was connected to the database with a "database
owner" user, which has far too many permissions. Now there's a special
vndb_site user with only the necessary permissions. The primary
reason to do this is to decrease the impact if the site process is
compromised. E.g. it's now no longer possible to delete or modify old
entry revisions. An attacker can still do a lot of damage, however.
Additionally (and this was the main reason to implement this change in
the first place), the user sessions, passwords and email data is now not
easily accessible anymore. Hopefully, the new user management
abstractions will prevent email and password dumps in case of an SQL
injection or RCE vulnerability in the site code. Of course, this only
works if my implementation is fully correct and there's no privilige
escalation vulnerability somewhere.
Furthermore, changing your password now invalidates any existing
sessions, and the password reset function is disabled for 'usermods'
(because usermods can list email addresses from the database, and the
password reset function could still allow an attacker to gain access to
anyone's account).
I also changed the format of the password reset tokens, as they totally
don't need to be salted.
|
|
With some related edits in other parts of the code, mostly due to
interface changes to htmlRevision() and htmlFormError().
Trivial replacements were automated by a super awesome script.
|
|
|
|
They had to be deleted from the database at some point, otherwise we
still have thousands of easily-cracked password hashes in the database.
Note that I could have opted to use scrypt on top of the sha256 hashes
so the passwords would remain secure without needing to reset
everything, but doing that after one year of switching to scrypt is
likely not worth it. Everyone who still actively uses his account has
already been converted to scrypt, everyone else should just reset their
password whevener they decide to come back.
|
|
|
|
|
|
This ensures that, if an attacker evers gets read access to the
database, he will not be able to compromise any accounts. SHA-1 suffices
here, because the data being hashed is a random 20 byte string. The
search space is so damn large that you can't sanely brute force it, nor
are rainbow tables any use at that scale.
They're not salted. The password reset tokens are also hashed in the
database and do include salt, but I've no idea why we did that.
|
|
I increased the N parameter to approximate about 500ms to generate the
hash. This is quite a paranoid setting for a website, but login attempts
are throttled so there's not much of a DoS factor. (Alright, password
changing feature isn't throttled so the DoS factor still exists. But
really, there's some pages with longer page generation times anyway.)
I did lower the size of the salt a bit (Crypt::ScryptKDF uses 256 bits
by default), because 64 bits of randomness should have low enough chance
of collision with only ~100k users (even with a million users,
seriously).
|
|
|
|
It doesn't make a whole lot to separate the hashed password and the salt
from each other, you need both to do anything with them, and from the
database perspective they're both completely opaque strings only usable
for direct comparison with other hashed strings.
This change is mostly as preparation for switching to a proper key
derivation function (sha256 isn't...) and to add support for longer
and/or binary salt.
Because the passwd field now needs to be interpreted in Perl, it's being
passed around as a binary string rather than a hex-encoded value.
API login is broken in this commit. I'll get to that.
|
|
|
|
formcode is strengthened by including the IP (-prefix) into the hash,
ensuring that the code can't be obtained by someone on a different
network.
I also removed the login form of every page. Felt kinda pointless.
|
|
Rather than setting an automatically password, reset the password and
send an email with a secure token instead. The password can then be set
again using this token.
This doesn't really have an advantage at this point, just makes the
interface and code more consistent when I update the registration code
to do something similar.
|
|
Users who haven't logged in since 2009-08-09 will find that their
passwords have been reset. They need to use the password recovery
feature before logging in again.
|
|
This is far more flexible.
|
|
Way more convenient. This also fixes several bugs with the previous
commit, since the cookie_prefix wasn't used for *all* cookies. Since it
is now, the 'l10n' cookie now also respects the configured prefix, which
means some people will have to set their default language again.
Configuration changes: 'cookie_domain' option has been removed, the
'cookie_defaults' option of TUWF should now be used.
|
|
Configuration change: Make sure you more the cookie_prefix option from
%S to %O. (It's now a TUWF option rather than a VNDB one)
|
|
There may still be some bugs present and I've only converted the points
where TUWF is incompatible with YAWF. The new TUWF features are not in
use yet, I'll do that later on.
Note that, in order to run the new code, TUWF must be installed on your
system. The configuration for the TransAdmin plugin has also changed.
Other than that there shouldn't be any issues.
|
|
|
|
And renamed notify_dbedit to notify_nodbedit, since the default is to
provide a notify on a database edit.
Also fixed a few bugs along the way.
|
|
Will convert the other preferences later.
|
|
|
|
This replaces the "cookie_auth" setting, and applies to all cookies in
use by VNDB.
|
|
Now it's finally possible to run multiple VNDB's with different
databases on the same domain without constantly getting logged out.
|
|
An expiration date doesn't make much sense if it's both not used and if
it can't be configured by the user, so just make this a timestamp to
indicate when the session has been added, which, while still not really
used, is more valuable.
|
|
If we're going to automatically remove older sessions, it would make
more sense to remove unused sessions, rather than old sessions that are
still in use. But we first need to keep track of when a session has last
been used to do so...
|
|
The current setup should be able to handle all kinds of notifications,
though only PMs are implemented at this point. More to come.
|
|
Caused by $self->{_auth} being set to an empty string when the uid part
of the cookie doesn't match, and authCan() not properly checking for a
positive value of $self->{_auth}
|
|
This one query is a bit faster than the two queries executed seperately, and
with a query that is executed on each pageview it does matter.
Ideally, the dbUserMessageCount() is cached and fetched with the same query,
this should save another 1-2ms. But this is probably not worth the extra code
it would require.
|
|
Most of the columns are only used in some rare situations, so fetching
all that information is unecessary. To fetch this information, a
what => 'extended'
is now required. This change should be most noticable for the user list
(now less than half of the previous data is fetched from the database).
|
|
This way the counter resets itself immediately when opening the unread
thread page, which is more intuitive.
|
|
User ranks are easy... but the language names are used everywhere!
|
|
Anything fetched from the DB to Perl should be converted to a UNIX
timestamp, and everything that goes from Perl to the DB should be
converted from a UNIX timestamp to a timestamptz data type.
Also, when creating a session, don't rely on the fact that the
expiration default happens to be the same as the cookie expiration time
calculated in Perl. It's cleaner to calculate the date at one place and
then use that everywhere else.
|
|
For consistency, it's best to do everything related to hashes in
hexadecimal notation in Perl.
|
|
This forces $salt and $pass to be 'downgraded' to byte strings in case
we are given unicode strings (i.e. when fetched from database or YAWF).
This, in turn, prevents global_salt from 'upgrading', which allows
binary data to be used for this string.
|
|
This fixes a 500 error when the cookie was longer than 40 bytes but the
characters after the 40th byte aren't a number. (i.e. the cookies of the
previous auth system)
This will also purge the cookie from the user's browser when
dbSessionCheck() returns false. (There's no sense in keeping it in such
a case)
|
|
Conflicts:
util/dump.sql
util/updates/update_2.6.sql
Also updated ChangeLog and made some tiny style changes.
|
|
-- Updated SQL files to reflect column type change.
-- Subroutine dbSessionAdd rewritten to accept an expiration
timestap as an optional third argument.
|
|
|
|
|
|
-- Changed the way cookie data is handled and removed the need for Crypt::Lite
-- Removed "cookie_key" configuration setting for Crypt::Lite
|
|
This commit is tested to work.
|
|
-- Removed _authGenerateSalt in favor of a one-liner in authPreparePassword.
-- Fixed a self-inflicted "WTF" mistake in authInit caused by a stray paste.
|
|
-- Changed the way cookies are handled to a database-backed system
-- Changed the password hashing algorithm used
-- Introduced a dual-salt method for increasing password encryption strength
|
|
This is more of a test of the new git environment than anything else.
|
|
This adds a small performance penalty, but should make it a lot easier
for people to notice that someone is asking for his/her attention.
Ideally, this count would be the number of *unread* *posts*, rather than
*total* number of *threads*, but we don't store read the state (yet).
|
|
DB/{Votes,VNList,WishList}.pm into ULists.pm
|
|
and login form
|
|
|
|
...this is basically everything we're going to rewrite
|