It is the unfortunate truth that there will never be a way to truly fix latency issues. The most we can do is make it unexploitable / fair and try to hide it with some magic tricks.
Exploitability / Fairness
One of the most common tricks in the hackers book is to play with their network latency. To cut a long message short, I’ll say this: each player should be disadvantaged by only their own latency. Any damage or loss to players should not be dependent upon another player’s latency, or else a hacker can use this against other players. In your problem, this means that whatever logic decides if a hit took place or not cannot compensate by the latency of the person who shot. If so, then it is exploitable. I’d also add that this check cannot be done on the client shooting (for obvious reasons) or on the client being hit (an exploiter would never admit to being hit). That leaves that this check must be done on the server.
The server is also the most fair place to determine hits because its game world or normally between the game world of the attacker when they shot the bullet and the game world of the victim when they are hit. Each player is also only disadvantaged by their own latency. A hacker having high latency means that they must lead their shots more; a victim with high latency cannot pull a Neo, break all the known laws of physics, and dodge flying bullets.
A server can handle a couple bullets. If not, then you can apply some optimizations. Trying to pre-optimize in this case will lead to a bad design decision. The server can handle the cost of running this critical game logic, and it doesn’t need to be handed off to a client.
The Black Magic
It is unfortunate that players with more latency will see "rubber banding". If each client is in charge of their own position, this rubber banding is almost always twice as large. If the server is in charge then rubber banding is cut in half and it is more fair, but the person moving has to interpolate. I've written a lot about client interpolation, you can find all of it by searching "client interpolation" on my profile.
Each client can with its own latency extrapolate where players are going to actually be at a given moment. This provides a more accurate representation of the game world and reduces the problem of missing shots when it looks like they should have hit to moments when the victim had just moved and the server found out but the shooter hasn’t. There is no way to fix this without introducing exploits. The shooter must be disadvantaged by their latency or else you are giving them leeway they can use to their advantage. Likewise, a player will be hit when it looks like they shouldn’t have been when they had just moved but the server hasn’t found out yet. If you trust the client to tell you where they are, then they can pull a Neo at any time. In addition, the victim is being disadvantaged by their own latency to the server. Compensation will also give them leeway to exploit.
To sum it up, the best you can to is extrapolate the positions of other players and interpolate the client’s position. Running the checks on the server is the only fair place. Any other way is prone to exploitation.