The behavior you describe in the original post is not correct anymore. The current version 19.07 rc2, with busybox 1.31.1 (as of December 2019), has a crypt() function that behaves as expected for a *nix system: http://man7.org/linux/man-pages/man3/crypt.3.html
After disabling the hack and setting the default password algorithm to SHA256, the shadow file shows passwords correctly hashed and formatted. Luci, though, seems to have trouble checking passwords stored with the stronger hashing algorithms.
There is a significant increase in the security of password storage from MD5 to SHA256, and even more to SHA512. The latter is the current default in many systems today.
Given the current guidance for users to stop using routers with 4MB of flash memory, most, if not all routers should be able to handle either of the SHA algorithms, and it is really poor practice to keep an old and outdated hashing algorithm alive.
I created a separate post in the developer area, but we need to clear inaccurate information so that users don't get the wrong idea about password security.
This works as expected today and should be enabled by default. The SHA hack should be removed from the code, or at the very least, disabled by default.
On further inspection, the Luci issue is also shared by Dropbear, which leaves users unable to log in via SSH. However, the issue is not with either package above. The problem is due to uClibc not implementing SHA256/512, which both Luci and Dropbear depend on in order to verify logins.
Rebuilding the system with libc++ instead solved the issue, and surprisingly for me, did not increase the firmware size. My test was on a minimal system.
Thanks @shm0 for confirming this works in other routers.
I’m assuming you meant musl, as that is the standard C library used by OpenWrt at this time. So then it seems nothing of consequence has changed, correct?
I don't have the exact timeline, but I think that at some point busybox didn't have SHA implementations for password hashing. When they tried to implement them, they realized that their C library (uClibc) didn't have them either, so they built their own and forced their login routines to use the internal implementations. That works for logging in to busybox in a local terminal, but breaks SSH or any other remote login (i.e. Luci, in our case).
In the meantime, someone tried to implement the stronger passwords in OpenWrt, but realized that they did not work. They put in a patch that failed silently and downgraded security to DES, instead of MD5. I think that's the time when your first post in this thread was created. Later on, though, after some complaints, the patch was updated to fail, without downgrade. This the current state and a more graceful failure.
What I discovered now is that, if one disables the SHA patch and rebuilds busybox with libc++, everything works. Since I had a minimal system, with a bunch of disabled stuff, even in busybox, the final binaries are not bigger than the uClibc. I can't say that this will be the case for a fully blown system, where libc++ implementations might make a big difference in size.
So, to answer your question, I think something did change since the first post, and it is the default behavior now. The other change is that we now have evidence that it is possible to implement stronger password security, but may involve serious changes for a system with default configuration. It doesn't seem to be the case for a minimalistic system.
After the last change (in Jan 2019), there is also a menuconfig config option in master (and 19.07) to enable the SHA256 and SHA512 support with the standard musl libc.
So, I am not sure if one needs currently to do anything else than just toggle the config option for musl, select the desired hash option for busybox and re-compile everything. (Note that musl is in the toolchain, so make sure to recompile also it.) Using the correctly configured musl should also reflect to dropbox etc., I think.
Ps.
Master branch has busybox 1.31.1, but unlike you say, 19.07 has busybox 1.30.1.
Thanks for clarifying the timeline. And the master vs rc2 bit too. I never installed rc2, I've always started by cloning the master branch, [re]configuring and then [re]building. Shouldn't have assumed that master and rc2 were the same.
I am confused, though, about uClibc not being used for years. When I first run make menuconfig right after downloading the source, uClibc appears as the default C library. It was only until after I changed that to libc++ and rebuilt the toolchain that my OpenWrt started working as expected with SHA256. Is this just an out of sync config option in the master branch?
PS. Yes, the rebuilt toolchain fixed all my problems at once, Luci and Dropbear didn't have any issues handling stronger hashes.
Currently the available choices for the main C library are musl and glibc.
.config - OpenWrt Configuration
> Advanced configuration options (for developers) > Toolchain Options ────────
...
│ │ *** C Library *** │ │
│ │ C Library implementation (Use musl) ---> │ │
│ │ [ ] Include crypt() support for SHA256, SHA512 and Blowfish cip│ │
You are probably mixing C++ libraries (like libc++) to the main C library in your analysis. The C++ libraries have a minor role in things. (And there the uClibc++ is still is use).
I would think that this should be a 'default' I didn't know I had to go to the 'advanced' to enable the checksums. Thanks for the heads up though. Honestly, from a security perspective, if you they have your password file (physical access) its game over anyways.
Luci was broken with the 'defconfig' for x86_64. Hopefully someone will catch this and 'fix' in the next revision. Maybe sha256 should be a WORKING default?
I can confirm that sha256 indeed works if you choose 'advanced config' and 'enable crypt' as mentioned. I do think it should be a 'default' since the non-modifed config results in a brain-dead luci. Oh well.
I think switching from MD5 to SHA256/SHA512 is rather pointless.
It slows down password cracking by a small factor, but not by real
orders of magnitude,
That seems rather debatable as MD5 comes with fixed 64 rounds whilst SHA256|512 rounds are adjustable and even with the default of 5,000 rounds provides reasonable resistance. Increasing it to 15 <> 20 k makes it even difficult for quantum computing power.
Which leaves
been stripped from libc to cut down on useless bloat.
Note that authentication against such hashes will fail for rpcd (LuCI) and uhttpd basic auth (if using the $p$user notation) since those still use libc's crypt() function. Not sure about Dropbear / OpenSSH etc.