Hi.
In general there are serval different handling-methods for such things. (i dont know all ogf them/cannot explain all of them - so other users may add more and different hints and informations.)
→ How do I store passwords securely? I hear there’s a function called password_hash() but I’m not sure which settings to use for maximum protection.
… In old times we stored a passwd in md5 hash , then we used sha1, later some combined them as sha1(md5($passwd)) … Today there are some common hashes, who can be used - depends how hard you wnat to encrypt this password to a hash. Since php5 there are the function “password_hash()” implemented directly into php. It uses a one-way algo and with the “password_default” it’'s strong enough for common web-logins. (It is about to have a hash, who cannot reverse-engeneered to the plain text password or it takes ages even with best hardware/preformance to do it. Thats why the users password should be stron too, as stronger the password so harder it is to reverse-engeneer it with thing like brute-force, if hashes from database got stolen.)
→ How can I keep track of users who are logged in without anyone messing with it? Are there ways to prevent hackers from stealing someone’s session?
… there also are different methods. My personal preference is, to check the combination of session id and adjectives of the remote host/users thing (like remote IP and/or remote used browser). to be sure, the user is the known user absolutly. (If this combination dont match the user gets auto-loggedout.)
(If someone have to complain, Yes, i’m oldschool coder in PHP
)
→ Two-factor authentication sounds like a good idea. How can I add that extra layer of security to my app? Are there any tools or libraries that can help?
… i dont know the solutions for this thing, never used …
→ How do I protect my app from common attacks like hackers injecting weird code or trying to trick users into clicking bad stuff?
… 1st rule, safe clean code. You have to know what you do and whrere the code may be insecure. (almost at points of userinputs in any kind)
… Then there are some general methods you can prevent to get global scanners/attackers their hands on your app/webpage, because most are scanning/attacking the hosts of the IP-Adresses directly. Configure your ebserver setup in a way, your app/page is ONLY reachabe by the defined adress, not by the IP of the server. More things to think about are fail2ban at the server, who blocks bad things found in logfiles (correct configured), and others additionals like cloudflare proxy. (some people say you dont have to care for such things like scanner blocking, as long your code is safe, yes. But explaining it here in detail would be to much at this point.)
Hacks , injection atempts and so on, you’re never be 100% safe as long you dont know your code is 100% bullet proof. (So its a very good step to ask for here, but hard to awnswer outside of “make bulletproof-proof code”.) There are a wide range of possibilitys, to hack in different ways and to do somthing against it, also in different ways. (escapes, sql-safe strings, anti-de-escapes, aliasing of input-values, and so on)
Aliasing of input values is a good start. You dont set the values at frontend/userside directly, you set aliases - sample: input value 1, 2, 3, 4 (like in a select box) and pickup it from the post and compare in php, if 1 this action , if 2 this action … else logout (… because there only can be 1,2, 3, 4, all other input values at this point are “hacked”, “modded” in the webpage at users side, means the user/cleint try to compromise the input fields.)
Other random inputs like username i check twice and compare. (post stringlength of this input have to be the stringlength and the content of the final filtered and protected/escaped absolute string, who are used to put in the database)
In “old times” alot users/coders did another “mistake” too because it was “common” They picked up the username at login, asked the database for the dataset of just this username from input. Thats the wrong way. Correct way: you create the hash from the given password and search for the dataset of this hash in the database. This prevents absolute from using user-inputs into the database at login point. There are no way to have a succesful injection attempt in any way. (Another method is a salten hash. Like the Joke: "I have “FA - the username and the password!”
Means us simply use the username as “salt” Yes, uncommon way, but works
)
To prevent users clicking wired given URLs from other users content there are one way: dont auto-convert strings who may be an adress to http links, leave them as plain text.
→ What are some good practices for managing user accounts? Things like resetting passwords, locking them out after too many tries, and maybe even email verification?
… There also are serval methods and levels to do it. In General i always have an extra “admin”-page/system (not implemented in the system the user get their hands on) where i manage the useraccounts and settings. Ofcourse extra protected (2 passwords) and other toys (extra subdomian, extra firewalled access, and so on)
→ Are there any guides or resources that teach you how to securely handle user logins in PHP? Examples of how others have done it would be awesome!
… at me, no. I always developed, thinked, rethinked, proofed and finally coded this things individual handmaded by myself.