Just a quick little collection of useful code snippets when dealing with certificates.
Some of these don’t really need to be in their own methods but it helps for clarification.
Namespaces for Everything
using System.Security.Cryptography.X509Certificates;
using System.Security;
Save Certificate to Store
// Nothing fancy here. Just a helper method to parse strings.
private StoreName parseStoreName(string name)
{
return (StoreName)Enum.Parse(typeof(StoreName), name);
}
// Same here
private StoreLocation parseStoreLocation(string location)
{
return (StoreLocation)Enum.Parse(typeof(StoreLocation), location);
}
private void saveCertToStore(X509Certificate2 x509Certificate2, StoreName storeName, StoreLocation storeLocation)
{
X509Store store = new X509Store(storeName, storeLocation);
store.Open(OpenFlags.ReadWrite);
store.Add(x509Certificate2);
store.Close();
}
Create Certificate from byte[] array
private X509Certificate2 CreateCertificateFromByteArray(byte[] certFile)
{
return new X509Certificate2(certFile);
// will throw exception if certificate has private key
}
The comment says that it will throw an exception if the certificate has a private
key because the private key has a password associated with it. If you don't pass the
password as a parameter it will throw a System.Security.Cryptography.CryptographicException
exception.
Get Certificate from Store by Thumbprint
private bool FindCertInStore(
string thumbprint,
StoreName storeName,
StoreLocation storeLocation,
out X509Certificate2 theCert)
{
theCert = null;
X509Store store = new X509Store(storeName, storeLocation);
try
{
store.Open(OpenFlags.ReadWrite);
string thumbprintFixed = thumbprint.Replace(" ", "").ToUpperInvariant();
foreach (var cert in store.Certificates)
{
if (cert.Thumbprint.ToUpperInvariant().Equals(thumbprintFixed))
{
theCert = cert;
return true;
}
}
return false;
}
finally
{
store.Close();
}
}
Have fun!
The other day I had the opportunity to take part in an interesting meeting with Microsoft.
The discussion was security, and the meeting members were 20 or so IT Pro’s, developers,
and managers from various Fortune 500 companies in the GTA. It was not a sales call.
Throughout the day, Microsofties Rob Labbe and Mohammad Akif went into significant
detail about the current threat landscape facing all technology vendors and departments.
There was one point that was paramount. Security is not all about technology.
Security is about the policies implemented at the human level. Blinky-lighted devices
look cool, but in the end, they will not likely add value to protecting your network.
Here in lies the problem. Not too many people realize this -- hence the purpose of
the meeting.
Towards the end of the meeting, as we were all letting the presentations sink in,
I asked a relatively simple question:
What resources are out there for new/young people entering the security field?
The response was pretty much exactly what I was (unfortunately) expecting: notta.
Security it seems is mostly a self-taught topic. Yes there are some programs at schools
out there, but they tend to be academic – naturally. By this I mean that there is
no fluidity in discussion. It’s as if you are studying a snapshot of the IT landscape
that was taken 18 months ago. Most security experts will tell you the landscape changes
daily, if not multiple times a day. Therefore we need to keep up on the changes in
security, and any teacher will tell you, it’s impossible in an academic situation.
Keeping up to date with security is a manual process. You follow blogs, you subscribe
to newsgroups and mailing lists, your company gets hacked by a new form of attack,
etc., and in the end you have a reasonable idea of what is out there yesterday. And
you know what? This is just the attack vectors! You need to follow a whole new set
of blogs and mailing lists to understand how to mitigate such attacks. That sucks.
Another issue is the ramp up to being able to follow daily updates. Security is tough
when starting out. It involves so many different processes at so many different levels
of the application interactions that eyes glaze over at the thought of learning the
ins and outs of security.
So here we have two core problems with security:
-
Security changes daily – it’s hard to keep up
-
It’s scary when you are new at this
Let’s start by addressing the second issue. Security is a scary topic, but let’s breaks
it down into its core components.
-
Security is about keeping data away from those who shouldn’t see it
-
Security is about keeping data available for those who need to see it
At its core, security is simple. It starts getting tricky when you jump into the semantics
of how to implement the core. So let’s address this too.
A properly working system will do what you intended it to do at a systematic level:
calculate numbers, view customer information, launch a missile, etc. This is a fundamental
tenant of application development. Security is about understanding the unintended
consequences of what a user can do with that system.
These consequences are of the like:
-
SQL Injection
-
Cross Site Scripting attacks
-
Cross Site Forgery attacks
-
Buffer overflow attacks
-
Breaking encryption schemes
-
Session hijacking
-
etc.
Once you understand that these types of attacks can exist, everything is just semantics
from this point on. These semantics are along the line of figuring out best practices
for system designs, and that’s really just a matter of studying.
Security is about understanding that anything is possible. Once you understand attacks
can happen, you learn how they can happen. Then you learn how to prevent them from
happening. To use a phrase I really hate using, security is about thinking outside
the box.
Most developers do the least amount of work possible to build an application. I am
terribly guilty of this. In doing so however, there is a very high likelihood that
I didn’t consider what else can be done with the same code. Making this consideration
is (again, lame phrase) thinking outside the box.
It is in following this consideration that I can develop a secure system.
So… policies?
At the end of the day however, I am a lazy developer. I will still do as little
work as possible to get the system working, and frankly, this is not conducive to
creating a secure system.
The only way to really make this work is to implement security policies that force
certain considerations to be made. Each system is different, and each organization
is different. There is no single policy that will cover the scope of all systems
for all organizations, but a policy is simple.
A policy is a rule that must be followed, and in this case, we are talking about a
development rule. This can include requiring certain types of tests while developing,
or following a specific development model like the Security Development Lifecycle.
It is with these policies that we can govern the creation of secure systems.
Policies create an organization-level standard. Standards are the backbone of
security.
These standards fall under the category of semantics, mentioned earlier. Given
that, I propose an idea for learning security.
-
Understand the core ideology of security – mentioned above
-
Understand that policies drive security
-
Jump head first into the semantics starting with security models
The downside is that you will never understand everything there is to know about security.
No one will.
Perhaps its not that flawed of an idea.
Good enough is sometimes not good enough. I’ve been doing a lot of thinking
lately (well, I’m always thinking), and security has been an issue that has come up
a lot. Frankly, I’m a two-bit software developer. I know my code isn’t
the best, nor the most secure. I use strong passwords, encrypt my sensitive
data, and try to limit access to the applications for those who need to use it.
In theory this works. Problem is, it’s a lame theory. There are so many
unknown factors that have to be taken into account. Often times they aren’t.
When I go to build an application I spend time designing it and architecting it.
This is usually the case for most developers. What I’ve noticed though, is that
I don’t spend time securing it. I can’t.
Imagine building a house. You put locks on the doors, bars on the windows, and
someone breaks in. Why? Because someone left the key in the door.
You can’t build against that. You just can’t.
You can follow the Security
Development Lifecycle, which I recommend to each every single developer I meet.
There are tons of resources available.
But it can only go so far. It’s designed more for being part of the iterative
processes, not the architecture. Or at least, that’s how most people interpret
it.
So?
My last post talked about Single
Sign-On (SSO). It’s a great sellable feature for any product. What most
people don’t realize though is the inherent security benefit to it. With it,
that means one less password to remember, one less password that could get intercepted,
one less password to change every month. This is a fundamental architectural
issue. But at the same time, it’s common sense.
What is sometimes the simplest idea, is usually the correct solution
What the hell does that mean? It means keep it simple. Security is simple.
Keep data from prying eyes, and keep it from getting lost. This is common sense.
Security is not difficult to comprehend. It becomes difficult when academics
get involved. Spouting theories and methodologies scares people into thinking
security is extremely difficult to implement. It’s not!
Follow the Data
Understanding the flow of data is crucial in properly architecting an application.
It’s crucial in properly securing an application as well. SSO
is a perfect example of this.
The SSO feature in Office SharePoint Server 2007 maps user credentials to back-end
data systems. Using SSO, you can access data from server computers and services that
are external to Office SharePoint Server 2007. From within Office SharePoint Server
2007 Web Parts, you can view, create, and change this data. The SSO feature ensures
that:
It makes perfect sense. It’s simple when you think about, and it affects every
subsystem of SharePoint. Make security a feature.
The
Windows Live team announced a
few months ago that their Live ID service will be a new provider for the OpenID system.
The Live team was quoted:
Beginning today, Windows Live™ ID is publicly committing to support the OpenID digital
identity framework with the announcement of the public availability of a Community
Technology Preview (CTP) of the Windows Live ID OpenID Provider.
You will soon be able to use your Windows Live ID account to sign in to any OpenID
Web site.
I saw the potential in OpenID a while ago, long before I heard about Microsoft’s intentions.
The only problem was that I didn’t really find a good way to implement such a system
on my website. Not only that, I didn’t really have a purpose for doing such
a thing. The only reason anyone would need to log into the site would be to
administer it. And seeing as I’m the only person who could log in, there was
never a need.
Then a brilliant idea hit me. Let users create accounts to make comment posting
easier. Originally, a user would leave a comment, and I would log in to verify
comments, at which point the comment would actually show up. Sometimes I wouldn’t
log in for a couple days, which meant no comments. So now, if a user wants to
post a comment, all they have to do is log in with their openID, and the comment will
appear.
Implementing OpenID
I used the ExtremeSwank OpenID
Consumer for ASP.NET 2.0. The beauty of this framework is that all I have
to do is drop a control on a webform and OpenID functionality is there. The
control handles all the communications, and when the authenticating site returns it’s
data, you access the data through the control’s properties. To handle the authentication
on my end, I tied the values returned from the control into my already in place Forms
Authentication mechanism:
if (!(OpenIDControl1.UserObject
== null)) { if (Membership.GetUser(OpenIDControl1.UserObject.Identity)
== null) { string email = OpenIDControl1.UserObject
.GetValue(SimpleRegistrationFields.Email); string username
= ""; if (HttpContext.Current.User.Identity
!= null) { username = HttpContext.Current.User.Identity.Name;
} else { username = OpenIDControl1.UserObject.Identity; }
MembershipCreateStatus membershipStatus; MembershipUser user = Membership.CreateUser(
username, RandomString(12, false), email, "This
is an OpenID Account. You should log in with your OpenID", RandomString(12, false), true, out membershipStatus
); if (membershipStatus != MembershipCreateStatus.Success)
{ lblError.Text
= "Cannot create account for OpenID Account: "
+ membershipStatus.ToString(); } } }
That’s all there is to it.