Basically, your friend is right. But simply hashing the password on the client side is only just better than submitting it as plain text to the server. Someone, who can listen for your plain text passwords is certainly also able to listen for hashed passwords, and use these captured hashes him/herself to authenticate against your server.
For this matter, more secure authentication protocols usually jump through a number of hoops in order to make sure, that such a replay attack cannot work, usually, by allowing the client to select a bunch of random bits, which are hashed along with the password, and also submitted in the clear to the server.
On the server:
- generate a few bits of random
- send these bits (in clear text) to the client
On the client:
- generate a few random bits
- concatenate password, the server's random bits and the client random bits
- generate hash of the above
- submit random data (in clear text) and hash to the server
As the server knows its own random information as well as the client's random bits (it got them as clear text), it can perform essentially the same transformation. This protocol makes sure, that nobody listening in this conversation can use the information later to authenticate falsely using the information recorded (unless a very weak algorithm was used...), as long as both parties generate different "noise bits" each time, the hand shake is performed.
Edit All of this is error prone and tedious and somewhat hard to get right (read: secure). If ever possible, consider using authentication protocol implementations already written by knowledgeable people (unlike me! The above is only from memory of a book I read some time ago.) You really don't want to write this yourself usually.