Bitcoin Forum
November 16, 2024, 12:06:07 AM *
News: Latest Bitcoin Core release: 28.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Secure coding best practices?  (Read 1114 times)
cjp (OP)
Full Member
***
Offline Offline

Activity: 210
Merit: 124



View Profile WWW
February 06, 2013, 07:43:50 PM
 #1

I am starting a Bitcoin-related coding project, and since it's dealing with Bitcoin transactions, it can become an interesting target for hackers. I'd like to do everything I can to make my code hacker-proof. I guess that in the Bitcoin developer community I'm not the only one who has to deal with this, so I want to ask: does anyone have a list of rules to follow when writing secure code?

My current project is written in C++ (without Boost), but in the future I'm interested in Java too.

So far, I've come up with the following list:
  • Know how to code. Don't make bugs, test everything, keep your code easy to understand etc.
  • Know the language you're using, and follow its best practices, in order to avoid bugs and keep your code readable.
  • Don't make any assumptions about input data. Do a complete validation on input, especially input from untrusted sources.
  • When using libraries, only use ones you trust.
  • Have clearly defined (and secure) behavior for all error situations (invalid input, out of memory, failing library call etc.)
  • When using cryptography, stick to existing practices as much as possible. Whenever you do things differently, make a detailed analysis of your design. Know the properties of the cryptographic primitives you're using. Use existing encryption and hashing primitives if you're not a cryptography professor (or equivalent).

Right now, my most important questions are:
  • How to use OpenSSL the right way for setting up a TLS connection. It's going to be a new protocol, so there's no need for backward compatibility with old insecure SSL/TLS protocol versions. It's P2P, so there's no clear client/server hierarchy, but obviously there's one peer that offers a connection and another peer that connects to it. I might want to use alternative key authentication mechanisms besides CA's; I'm mostly thinking about namecoin for that purpose, but web-of-trust or user-defined (ssh-style) are also options.
  • How to do error handling. It seems right now that every three lines of code or so can potentially create an error, and I want a convenient way to deal with them. Is it a good/secure idea to use exceptions for this in C++? The most basic error handling would be to log the error and exit: that would allow a DoS attack but at least that's not the worst possible consequence of an attack. For errors in incoming data, I'd have to write friendlier exception handlers, to prevent DoS.

Donate to: 1KNgGhVJx4yKupWicMenyg6SLoS68nA6S8
http://cornwarecjp.github.io/amiko-pay/
misterbigg
Legendary
*
Offline Offline

Activity: 1064
Merit: 1001



View Profile
February 06, 2013, 07:45:51 PM
 #2

http://www.atsec.com/downloads/pdf/secure-coding-guidelines.pdf
mjc
Hero Member
*****
Offline Offline

Activity: 588
Merit: 500


Available on Kindle


View Profile WWW
February 07, 2013, 04:48:21 AM
 #3

Check out OWASP https://www.owasp.org this will provide you with web application secure coding best practices and libraries that you can use.

Robert C Seacord had the bible of C Secure coding, which is still applicable to C++.

Kindle : Bitcoin Step by Step (2nd Ed) : http://www.amazon.com/Bitcoin-Step-by-ebook/dp/B00A1CUQQU
Kindle : Bitcoin Mining Step by Step : http://www.amazon.com/Bitcoin-Step-by-ebook/dp/B00A1CUQQU
Facebook :  https://www.facebook.com/BitcoinStepByStep     Twitter : @BitcoinSbS
Mike Hearn
Legendary
*
expert
Offline Offline

Activity: 1526
Merit: 1134


View Profile
February 09, 2013, 10:33:43 AM
 #4

My list:

Prefer managed languages. Although they can be constraining, languages like Java or C# are significantly harder to shoot yourself in the foot with. I've got nothing against C++, enjoy working with it (it's my primary language at work), and it's possible to write C++ securely - see how Satoshi did it for an example. But it's not easy, which is why Kaminsky was so surprised when he saw it had been done.

Don't try to reimplement Bitcoin. Seriously. It's tough, I should know Wink Either find a way to use Satoshis code, or consider taking a chance with bitcoinj. Bitcoinj can be used from C++ by the way, check out the native branch in the git repo to see how it's done using GCJ/CNI.

Minimize your surface area for attack - run your production code on a computer that doesn't do anything else. Use key-based SSH auth only, no passwords. Don't host it with cheap VPS providers that may be an avenue for attack, either prefer a physical box in a nearby datacenter you can drive to, or use VPS providers but hide the core of your app behind a Tor hidden service so nobody except you knows where to find it.

Consider sandboxing different parts of the app and using RPC between them. I wrote my degree thesis on this topic. Tools like SELinux or AppArmor can be used to constrain hackers if they do manage to break in via a vulnerable component. So learn about them and see how to use them. Managed platforms have another advantage here because they usually have convenient (but language specific) RPC mechanisms built in so communicating between sandboxed components is easy. But if your entire app is written in one language it doesn't matter. For C++ you could use ZeroC ICE or just use a custom protocol.

Use assertions liberally. It's better to crash the app and have some downtime than let it enter an undefined state that could be exploited. That said, obviously assertions are only to be used for internal state that should never be corrupted, it's not appropriate for transient conditions like bad input from the network. Once again, managed languages win. Exceptions in C++ are very hard to do right because it's much harder to write exception safe code when doing manual memory management. Exception-safety is rarely considered, in my experience, but it's important. In a language like C++ it can lead to memory corruption if you get it wrong, and that is often the start of an exploit. With garbage collection it's much easier.

TLS is a good choice for secure communications but as you obviously already know, it's not that useful in a P2P scenario because you (almost by definition) don't know who you are talking to. Make sure you really understand why you want to use encryption there, something that is willing to communicate with anything doesn't benefit much from encrypting that communication.
cjp (OP)
Full Member
***
Offline Offline

Activity: 210
Merit: 124



View Profile WWW
February 11, 2013, 07:05:02 PM
 #5

Thanks for all the replies. I'll definitely use the ATSEC and OWASP links a couple of times during development and testing.

I think Mike Hearn's list is useful. When applying it to my project I have the following replies:
  • I've started using C++. I feel confident using C++ and I know I can make reliable C++ code; the only thing new for this project is the large focus on security. I have the impression it's easier to make cross-platform portable C++ code that doesn't require things like a Java runtime or Python interpreter. Many "managed" languages come with huge standard libraries with their own security vulnerabilities. I suppose only the parts I'm actually using really matter, but I'm not really sure about that. About garbage collection: doesn't that make the state of your software unpredictable? Maybe garbage collection is OK as long as your destructors don't do too important things?
  • I won't re-implement Bitcoin; I plan to use it through the RPC interface.
  • I'm not even close yet to the deployment stage, but thanks already for the sysadmin advice about hosting etc.. During application development, I intend to keep the application lean-and-mean; if it gets bulky I will consider splitting it up so that different parts can be run isolated and with minimum privileges.
  • Right now I have a habit of carefully documenting each method and function, where I list e.g. all requirements on input objects and things it promises about output objects; I also mention whether some requirement is checked or not checked. Obviously, checked is preferred.
  • Right now, my default behavior in case of errors is "log the error message and terminate the application". Obviously, when verifying untrusted input, default behavior should be different (e.g. "reply with error message, close the connection and clean up") to prevent DoS attacks.
  • I decided to use exceptions in C++for error handling: I have the impression the cleaner, smaller code is worth the effort of making everything exception safe. I have the impression that the things you need to do for exception safety are already good practice anyway. The downside is of course that new developers also have to have "C++ exception skills"; right now I'm making decisions based on my own skill level.
  • My application is only P2P in the sense that all participants have the same role, and form an arbitrarily shaped network. The difference with most P2P networks is that in my case, participants choose carefully who they are talking to. Consider it to be a sort of a dark-net, if you wish. In my case, TLS is only used to protect confidentiality; integrity is ensured with other cryptographical measures.

Donate to: 1KNgGhVJx4yKupWicMenyg6SLoS68nA6S8
http://cornwarecjp.github.io/amiko-pay/
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!