No es una respuesta directa sobre el almacenamiento de las contraseñas, pero generalmente uso al menos dos conexiones de bases de datos cuando construyo aplicaciones web: una se usa el 99% del tiempo para actividades relacionadas con el usuario, con privilegios restringidos, y la otra se usa para la funcionalidad 'admin' (eliminar usuarios, etc.).
En algunos casos, cuando estoy instalando el paquete de otra persona, instalaré dos instancias ... una instancia pública que solo tiene acceso a la base de datos para hacer el tipo de usuario general, y una segunda instancia que está restringida por IP a mi subred local (posiblemente incluso en una máquina diferente) que debe usarse para cualquier tipo de actividad 'admin'. Ninguno de los dos tiene acceso para modificar tablas, etc., sin embargo ... Prefiero entrar a través de las herramientas de base de datos nativas que permitir que la aplicación web ejecute sus propias tareas de actualización que no han sido examinadas.
Sin embargo, puede llevarlo aún más lejos y agregar más conexiones específicamente para tareas determinadas ... para que las tareas de creación de usuarios y administración de contraseñas pasen por un usuario que tenga privilegios adicionales en las tablas de usuarios, el inicio de sesión tiene privilegios de base de datos para autenticar y no mucho más etc.
De esta manera, si hay un ataque de inyección sql, en la mayoría de las páginas web realmente no puede hacer nada significativo: no puede ver el hash de la contraseña, no puede agregar un nuevo usuario administrador (no es que puedan hacerlo) de todos modos), etc. Todavía no ayudará si logran obtener un shell en su máquina, pero los ralentizará.