Someone sent me this a while back and I thought it was very good – posting here so others can benefit!
Every programmer has to have something to program, whether it’s work related, hobby related, for a friend, or even just a quick script for an automation. We will discuss hobby pro-gramming.
When sitting at home and pondering upon ideas to program you sometimes get stumped and feel halted. This is a term in the programming world called “coders block”, yes… exactly like a “writers block”. I can speak from experience and from other documentation on steps to overcome this block, I will try and combine the both.
The first thing to do is get focused, you don’t want to be distracted while trying to program. Keep your environment quiet or even put on some music to your liking that doesn’t get you singing along… the slightest things can get us side tracked and off course. A lot of coders create a coding play-list, like myself. Furthermore the time of day you chose to program is a big part as well. From experience I do not like to program when I get off work or get in from a long day, instead I like to program when I wake up after eating break-fast and have started a fresh day. So if you’re starting or working on a big project, try and schedule in worthy time to code. After you have got all this situated it is now time for step 2, finding something to program.
Remember that programming is an art and is only limited to your imagination and programming skills. If you have coders block try and create a list of situations you have encountered in which a tool did not exist for what was needed. Once you have thought of something don’t stop adding ideas, you can add several and the next time you are in need of something to program you can go back and find previous self suggestions.
If you still can’t think of anything, like a lot of us do time to time then just go search freshmeat.net and read the latest released projects and even search the previous released. Try and spawn a totally new idea. If a paper could help expand your imagination then no one would ever be in search of projects.
Once you have created an idea, the next step is to chose a programming language. I can not tell you what to chose, but when I chose a language I think of:
- How fast does the program need to be.
- How much data is actually user/client supplied.
- How much regular expression and parsing will it need.
- How secure does it need to be, (s*id/daemon?).
After I compile a list I go from there. I like to program in C when the software needs to be fast and secure, especially for daemon/client type software. I also like to program in Perl if the input is mainly user supplied and heavily based on parsing and regular expression or I’m racing a clock. I obviously do not know every programming and scripting language existent so it’s totally up to you and your preferences, my suggestions are not near any type of standard.
Once you have chose a programming language a lot of people like to gather all references needed, as in books and online technical documentation like RFC’s and such.
Once all if this has been gathered it is time to setup your programs operation outline and build a mental list of functions, modules?, objects, and techniques in which you intend to use. You now want to sketch down a design in which you intend to guide and follow while programming your project. Without a guide you might end up forgetting something and having to redesign your entire project. Always plan ahead and have an overall understanding of what is ahead of you.
It is now time to code… securely. I will now try and include guidelines which are needed to be followed in order to produce secure programs. I will focus on s*id and network applications. If you don’t know what a s*id application is, in short it is a program that requires different privileges (sometimes root) to do operations. An example would be /usr/bin/passwd which requires access to read and modify the passwd and or shadow file. When programming a s*id application you want to be positive that you handle these given privileges with extra care and contain them only when actively using them. You want to try and put these operations that need extra privileges in the beginning of your code so when they are finished you can drop these privileges right afterwards. This prevents any holes found in the source extending the privilege drop that an attacker may exploit from spilling those privileges. If these operations can be done sgid new group just as they can suid root, do not make it suid root. Remember the whole reason we are programming securely is to prevent bugs and mostly preventing an attacker from gaining privileges that he currently does not have, whether it’s a remote attack on a daemon like telnetd or a local attack on a program like su. If you’re coding a network daemon you want to make sure every single instruction, operation, and routine you use is fool-proof. Holes exploitable remotely are the worst to exist and the most dangerous.
Trust nothing and no one, ever. Trust should never be apart of your program. Picture everything as an enemy to break your program. You have to build a defeatless set of operations and routines, create a flawless and unbreakable structural design, and still contain full functionality. In C this is not even near an unreachable goal when utilizing the right functions and routines which are clearly at hand. I will now list some guidelines while programming:
- Preform bounds checking on everything.
- Become a semiotician and cross verify all syntactics.
- Watch carefully over the handling of command line arguments and bound everything.
- Verify all typecast variables.
- Verify system function arguments going outbound.
- Try and prevent from pulling arguments from the environment. If you have to, make triple sure that you preform bounds checking and monitor everywhere the variable can go. This is a major commonly known mistake.
- Don’t use functions that omit buffer bounds checking.
Example: – sprintf(), vprintf(), vsprintf(), etc.
– strcpy(), strcat().
– gets(), scanf(), sscanf(), etc.
- Make double sure all your variable sizes are calculated correctly.
- Don’t trust strings to be all null(‘\0’) terminated and remember strlen() does not include this null. In reality the string is always one byte larger.
- Don’t allow overwriting of the null terminated byte when using read() and fgets().
- If you must run operations via higher privileges, be carefull what your program is equipped with, like stated earlier… trust nothing. GTK+ for one has been an example recently shown to allow a library hijacking which was attackable via any s*id application which had GTK+ equipped while running in ‘higher privilege mode’.
- If outside “equipment” has to be used, I myself would audit it.
Execution via shell escapes – functions with suction.
- Do not use system(), popen(), or exec(). These methods are way too sketchy. Arbituary commands are commonly known to find their way to the arguments of these calls which escape the real intended usage and give an attacker easy access to gain shell access as a superuser. DO NOT USE THESE FUNCTIONS.
- Be sure you include full pathnames when using execl() and execvp(), these use $PATH if no ‘/’ is found.
- If they must be used for some twisted situation, make triple sure that you parse out any type of escaped shell escape characters (meta characters, etc).
- Make sure you include full pathnames to all outside programs being called. $PATH can be enabled to use ‘.’ (Trust no one). I would suggest creating your own $PATH and make sure you do not trail it with “:”, that includes ‘.’ in the paths.
Preventing race conditions.
- Do not use mktemp() when creating temp files, instead use mkstemp()/tmpfile().
- Use file locking for modified files. Leave yourself a recovery method in case of an emergency(crash, etc). Catch signals.
- When using open() to create a ‘new’ file, always use the O_EXCL and O_CREAT flags to cause failure if the file already exists.
- Also when manipulating a file always remember to utilize fchown(), fchmod(), and fstat() to prevent any type of race condition or an unexpected file replacement.
- Make sure a link does not exist with lstat().
- Make sure your sequence of operations are correct. ie. Don’t expect a file you just stat’d to be the same file 5 seconds later. (Trust no one).
Other sly tricks and misc things.
- Always check anything going to be created that is user supplied for meta characters… a filename, anything shell related, etc. (vital).
- Dynamically link all libraries, this will prevent any pseudo system libraries from being created and switched.
- Setup limit values so your program does not leave a corefile. Catch SIGABRT.
- In Perl try not to use `…` this too is a shell escape.
Implement logging / syslog’ing and debugging messages.
- Log the PID, time, user(*uid/*gid), and terminal.
- Log the command line arguments and cought attempts to breach your programs security.
- Do this while not flooding syslog.
- In the most vital positions of your programs you want to implement verbose messages. Also debugging messages are a big help when working on a huge project that starts to get confusing of what’s doing what and what is going where. Lots of debugging messages are very good. Create a ‘Debug mode’ in which you can turn on internally with a switch, debug=1, etc.
Release everything evil you have inside you.
- Try and BREAK, hurt, SMASH, trick, BEAT, and kill your program in any and every possible situation.
- Fix and secure what you’ve broken.
You can also go download several ‘lint’ programs which scan your source and often highlight subtle unforeseen problems. O`reilly has a book called ‘Checking C programs with lint’ which can be bought via http://www.oreilly.com/catalog/lint/.
After you have finished your project you want to make sure it is disposed of all bugs and errors. While you’re in the beta stages you want to allows friends or a selected few to ‘beta test’ this software and have a few more brains try and wreck it. When all seems well then it is up to you to release it.