Security Mistakes Programmers Make

I think it's fair to assume most novice or even intermediate programmers are looking to just get the thing to work, compile without errors, to not crash and to do the job it was designed to do. So unfortunately most programmers are unaware of the common security risks we can unwittingly write into our code. In no particular order here are the security problems software developers should look out for.


Passwords in code
You would be surprised how often this happens. Application or PHP code is being developed as a prototype so a developer quickly hard codes the username and password into the code. Not much of a problem when the system is just being tested internally but when it gets rushed to market and the password remains your credentials are exposed.

Plain-text Passwords
It is disturbing how many website and applications store the users passwords as plain text possibly accessible via other security problems or accessible through physical access. Considering how many people use the same password for everything. One flawed application can expose everything their password is used on. You have a responsibility to protect it. So how do you know if the user has the correct password if you can access it directly. You encrypt the password with a one way scheme like MD5 and produce an unreadable hash and you store that. When the user logs in you encrypt their typed password and compare the two hashes.

Sending Plain-text
Network applications that send data over the network/internet in the clear expose the user and application to risk. The clearest example are websites that don't use https and send usernames and passwords  in the clear. A man and the middle attack using ARP cache poisoning or a WiFi honeypot can drive users internet traffic through the attackers computer at which point all the traffic becomes visible to them. Finding password=mySeceretPassword is trivial. It also make injecting packets and subverting the protocol much easier and makes it easier to profile users for later attacks.

Allowing SQL Injection
A lot of these problems come down to validating input. Of these kinds of problems SQL injection may be the most obvious. When a piece of software, be it a application, server or webpage using some form of SQL takes input from to be user to be used in an SQL statement that user input can contain SQL instructions that were not intended by the programmer. say for instance you have the statement:
"select * from users where userName = ' " . userName .  " ' ";
If userName contains the string;
anything ' or '1' = '1
Then the resulting sql statement would be;
select * from users where userName = ' anything ' or ' 1 ' = ' 1 '
Selecting all the users. Depending on where this mistake is made it could do anything from print all the user names and passwords on screen or log the attacker in as an administrator. You need to look out for this in user input, network input, config files and anywhere else you take in input.

Operating system instruction injection
Similar to SQL injections. Some programs use actual system command. For instance the programmer may have been trying to execute the command: cp [origin] [destination] and
the user entered the following.
Max's Super Backup Utility
From     [myPhoto.png]
To         [./myPhotoBAK.png && cp /etc/shadow ./httpDocs/shadow]
The user would have copied his photo but also copied shadow, the linux password file to where it can be grabbed from the net.

Allowing Format String Attacks
A format string comes into play when the developer has used a function that uses a variable number of arguments and sends unvalidated user input to these functions. Functions like printf(string, args...) do not have a set number of variables instead they load variables onto the stack and take variables from the stack based on characters defined in the string.
In the following example an application takes your name as an argument. 
char* password="this is a secret"; 
printf("Your name is: %s", name);
This might print: "Your name is: bob". What would then happen if Instead you use bob %s
your program might spit out.
Your name is: bobthis is a secret
printf prints "Your name is: " then finds %s and looks to the stack to find the string to print. Then it finds another %s and prints the another string from the stack.
An attacker could further use a series of '%x' characters to map the stack and find more information or can crash the application, map its memory and look at other variables in  memory.

Buffer overflow
User input could be argument a text field a file or data from the network. When a static amount of memory is allocated for this data, a buffer. That buffer can be filled. What happens if you add more to the buffer? It overflows the data spills into parts of memory where it doesn't belong.
This can be used to corrupt the memory, crash the application or to fool the software into executing an attackers instructions and possibly compromise your entire system.
As a programmer you need to either limit the amount of input taken or expand the amount of space available for the input.

Off by one
Off by one problems are common mistakes made by novice and even skilled programmers. they happen most commonly surrounding arrays. If an array is defined as:
int myArray[20];
And we try to define:
myArray[20] = 100;
Here we've made a subtle mistake that can easily sneak by. Our array goes from 0 to 19 much like the buffer overflow we have just written into another part of memory. Or in the following loop:
for(int i = 0; i <;= 20; i++)    
   myArray[i] = 100;
Because we used i &lt;= 20 instead of i &lt; 20 we have made the same mistake again.

Not validating client
This one should be obvious but it often omitted particularly on the network side. If a client is allowed to connect with out validation it may be able to access data for other users and manipulate the system. 

Not validating server
Many protocols validate client but many even competent protocol designers do not think to validate the server. A surprising example of this is the GSM mobile network. When a mobile phone it turned on it requests to connect to the mobile network through the nearest mobile transmitter. Your phone companies equipment sends the phone a challenge, a (pseudo)random number to encrypt. Your SIM card encrypts it using its internal key and the response is returned. If your encrypted response matches their encrypted version of your key your phone has validated itself and you are on the network.
      This is all very good practice. The actual key is never sent it's not ever accessible to the phone just the phone company and the SIM card. But what about the other end. If an attacker has access to the GSM equipment they can set up a false station and the phone will connect to it without question allowing attackers to snoop on your calls, texts and data as well as spoof callerID, message origin and redirect calls. The only thing preventing attacks like this from becoming more prevalent is the expense of the equipment.
      What's more a false SMB server or WEP router can gain encoded credentials from the client which can easily be cracked or used as is.


Weak encryption
The are some clever attack approaches that sidestep the encryption systems software uses, I'm not talking about those here. I know a little bit about encryption and code breaking but I am not a cryptographer and odds are neither are you. There are very strong algorithms out there like AES. They have been deigned by very smart people and tested by very smart people they're tried and true, Use them. Don't be like Adobe's scheme that was so simple it should be broken with a pen and paper. 

Socket hijacking.
Software uses a variety of ways to allow processes to communicate. Sockets are one way. In this scenario legitServer runs on IP * port 4242  and waits. An attacker starts evilServer listening to IP 192.168.1.2 port 4242 on same computer. Now a client tries to connect to 4242 what happens?
Well the socket favors the most specific socket listener. Because evilServer listens on a specific IP while legitServer listens on any the connection goes to evilServer which can now Deny services, steal credentials, do man in the middle attacks.
Try to bind to specific IP where possible.
   
Named Pipe Hijacking.
Used for inter process communication, usually but not always used within the system, pipes allow programs to communicate with each other.  A sever begins and creates a named pipe, a client starts and uses a named pipe with the same name now they can communicate.

But what if a malicious program creates a named pipe with the same name before the server. Then the legitimate server starts and tries to create a pipe with the same name. It doesn't fail but instead gets a handle to the existing pipe. From here the malicious application can impersonate the client and get privileges of the client eg. root/administrator. Deny service or snoop and subvert the communication.
Your server code should check if the pipe exists and as a client you can prevent the server from impersonation.

Downloading insecure code
You create a very fancy piece of software and you plan on maintaining it and keeping it up to date like a good programmer should. You decide it would be nicer for the user and
more practical to have it deal with updates automatically. Again all this is good. Keeping software up to date is great in general and for security.
    But if you are not checking the integrity of the code your well intentioned plan could prove to be a very nice backdoor for an attacker. Spoofing an update could add their code to yours and turn you software in a trojen complete with your seal of approval. 

Not updating 3rd party components
Some developers are very diligent in updating and maintaining there code but

overlook 3rd party software like openSSL zlib leaving them vulnerable to problems in older versions of the third party component. 

Path name traversal
More common with web based applications. Path name traversal allows an attacker access to parts of the file system you didn't intent. This example way seem simplistic but I actually saw a case of this just a few weeks ago. A friend directed me to his web page hosted at:
myFreindsCollege.edu/~myFriend/website.html
With his permition I just tried 
myFreindsCollege.edu/~myFriend/
And was dropped into his home directory containing Reports, Research material and a .xls file containing his details including his work, college and home email with passwords. Most of the time the programmer/admin have some deffence against this but it might be outsmarted with a few unicode value (eg. %2E).
Not just web developers need to pay attention. On Windows systems programs have a current working director that can be changed to allow DLL injection.

Cross site Scripting
Mainly a problem in web applications. Rich web pages are often built up in layers. PHP generates the HTML page filling it with information taken from an SQL database and Java script code is used to make web pages smarter. But what if someone could add their own javascript code to the page, Somethings it is possible.
   A prime example are forums. Users can add their option on a topic, it's saved and the next user gets a newly generated page containing the previous users' opinions. If not properly checked
the attacker can cause a large number of browsers to be used for their nefarious purposes. For an impressive demonstration of this technique used with Cross site request forgery take all look at Daniel McCarney's available on youtube.

Cross site request forgery
This attack needs to be know more. Some people have heard about it but it is generally regarded as a nuisance. It is often used with cross site scripting but it is not the same thing.
Cross site request forgery involves tricking a users browser into doing something is has authentication to do. The example often given is getting your page to request logout.php triggering the log out script. This could be done by including a IMG tag pointing to logout.php.
   That simple example often given leads people to believe it's just a nuisance, it isn't. using combinations of GET and POST's and using crosssite scripting as a vehical an attacker can build up complex attacks to direct a site to preform tasks only the user should be able to do; Change their passwords, email address, post messages, perhaps ever transfer money.
    Security researcher Daniel McCarney demonstrates how he used this technique on a Facebook-like social networking site. That upon viewing his page would force their browser to post the same script to their wall. When their friends see the page the script spreads to their pages adding a viral effect.
    To prevent this any POST messages should include a random value, a nonce. 

DLL Hijacking
Libraries are used to extent the functionality of your software. You may export functionality to a library or you may use someone elses library. Generally good practice but can open you up to a extremely serious security flaw also known as library spoofing.
The example used here is mainly a windows problem where they are known as DLL's. The trouble is how do you know you are loading the DLL you think you are loading. If you include myLibrary.dll. Which myLibrary is it:

C:\Program Files\mySoftware\myLibrary.dll
C:\Windows\system32\myLibrary.dll
C:\Windows\system\myLabrary.dll
C:\Windows\myLibrary.dll
\\attackerComputer\currentWorkingDirectory\myLibrary.dll

Your software will search for files in order until it finds a myLibrary.dll. Notice the last path is the Current Working Directory, in this case on a remote windows (SMB) share which could be anywhere in the world and there are many ways to change a programs current working directory. 
This is not the only way a malicious DLL can be loaded. Media software often searches for DLL's that allow them to play new codecs making them particularly susceptible. Ported software often still looks for library's from it's original platform. Any software using the Windows Foundation libraries ie. Created by visual studio is vulnerable while running on Windows XP.

I'll cover this topic more completely in another post but for now you should know. Try to use absolute paths where possible or try to keep your DLL's at the highest point in the search path you can. If you have DLL's that are regularly not found, try to clean them up.