[Lesson] Basic Computer Security

Discussion in 'Resources' started by N3X15, May 16, 2011.

Thread Status:
Not open for further replies.
  1. Offline

    N3X15

    Lately, there's been a lot of programs released with poor security measures, so I'm releasing this so that everyone can learn how to make safe, reasonably secure applications. This is by no means comprehensive, but it's needed.

    LESSON ONE: Client/Server Security

    Bukkit and its host of plugins is a client/server architecture. This means that Minecraft (the client) connects to Bukkit (the server). As you are developing plugins that interface with the server, the most important thing to remember in this situation is that you can never reasonably assume that the client is going to be predictable, send valid information, etc. In short, NEVER, EVER TRUST THE CLIENT. Check that the requests and data the client sends are valid and in the appropriate sequence, and do not make any assumptions. Faulty assumptions caused several varieties of exploits on the minecraft server (such as sending invalid location updates to cause server crashes).

    For those of you who are creating java-based webservers and other socket listeners, this is doubly important, as you are not relying on Minecraft's built-in security systems. If you are opening HTTP streams, DO NOT USE JAVASCRIPT FOR AUTHENTICATION. Javascript is run on the client browser, and users can disable javascript and completely bypass any authentication scheme you build into the page. All authentication must be done on the server in your plugin.

    LESSON TWO: Password Storage Practices

    Many plugins store passwords to allow users to authenticate themselves and gain access to restricted areas or materials. Some plugins also store these passwords incorrectly. Even encrypting the passwords with AES or some other reversible encryption scheme is wrong.

    Passwords can be encrypted with a one-way hash algorithm (such as MD5 or SHA-512) that ensures that the passwords cannot be decrypted. A string that has been through the hashing algorithm is known as a hash, and the hashing process cannot be reversed. You may be asking, "Well, if that's the case, how am I supposed to check the supplied password against the stored password for authentication?"

    Let's assume that you have a function named checkPassword(String myPassword) in a class that corresponds to a chest, and a file on your hard drive that stores the correct password.
    1. When the password is first assigned, hash the password using your chosen hashing algorithm (SHA-512 is recommended, as MD5 has been cracked in some cases) and save the hash to the file.
    2. To check a password, load the hash from the file, and then also hash the incoming password and compare the two hashes. If they are equal, then the user has supplied the correct password.
    In pseudocode:
    Code:
    public class MyStuff {
      ...
    
       public void setPassword(String newPassword) {
          String newhash = SHA512(newPassword);
          storeHash(newhash);
       }
    
       public boolean checkPassword(String password) {
          return (SHA512(password) == getStoredHash());
       }
    }
    An even safer approach would be to create a random string (called a "salt") every time a new password is assigned, and prepend the password with the salt before hashing it (a practice called salting the hash). You would also salt any passwords you need to check.

    Code:
    public class MyStuff {
      ...
      private String salt=randomString();
    
       public void setPassword(String newPassword) {
          String newhash = SHA512(salt+newPassword);
          storeHash(newhash);
          storeSalt(salt);
       }
    
       public boolean checkPassword(String password) {
          salt=getStoredSalt();
          return (SHA512(salt+password) == getStoredHash());
       }
    }
    Salting hashes makes it more difficult to brute-force passwords.

    LESSON THREE: SQL Input

    Lots of nasty things can be done if you directly append user input to SQL statements, such as dropping tables, changing table contents, bypassing authentication, etc. Use prepared statements. Since this forum uses a variety of languages in addition to Java, I'll leave it up to you to find the documentation.
     
    Chlikikijleelgus and rakiru like this.
  2. Offline

    pyromanic

    Great post! I'll definitely be looking into the SHA512 encryption method.

    Properly parsing numerical values and escaping single quotes in strings before use can prevent those 'nasty' things you speak of when appending SQL statements. There are some occasions where I would rather append strings than use prepared statements to reduce the amount of code. I don't much like java prepared statements anyway. :D
     
  3. Offline

    desht

    Do a google search for 'bobby tables' and then realise that there is never an excuse for not using prepared SQL statements.
     
Thread Status:
Not open for further replies.

Share This Page