I’ve been catching up on various security-related articles that I’ve been meaning to read, and the following article was on the list http://www.itnews.com.au/News/73635,google-shares-its-security-secrets.aspx about Google’s “security secrets.”
Quoting from the article:
“In order to keep its products safe, Google has adopted a philosophy of 'security as a cultural value'. The programme includes mandatory security training for developers, a set of in-house security libraries, and code reviews both by Google developers and outside security researchers."
I think it is great that Google has a security program they are willing to talk about and I could not agree more with the ‘security as a cultural value’ philosophy. But isn’t there something really fundamental missing here? Design? There is a lot more to software engineering other than coding and testing.
The SDL has a very large set of implementation-related requirements, but there are many design-related requirements also.
Computer security experts have known since the early 1970s that you have to get the design right; and our experiences with the SDL over the last 5 years have taught us that you need to consider security and privacy (but remember, you have to ship too!) very early in the design phase and have a consistent end-to-end process if you truly hope to reduce vulnerabilities and create more secure software. This is how the SDL is helping to create ‘security as a cultural value’ at Microsoft.
We’ve seen a general trend downward in security vulnerabilities in Microsoft products, and the IBM X-Force 2008 mid-year report backs the assertion that we’re making progress; according to the report Microsoft’s share of total vulnerabilities decreased from 3.7% in 2007 (1st place) to 2.5% (that’s 2.5% for all Microsoft products; a more appropriate comparison might be Windows vs Linux vs Mac OSX, or SQL Server vs Oracle vs DB2) in the first 6 months of 2008 (3rd place.) This is an encouraging signal that the SDL is working on a large scale… of course, it might also show that vulnerability researchers are moving to easier targets, which, to me shows the SDL is working too.
What do you think?
A group of MIT students made news last week with their discovery of insecurities in Boston's "Charlie" transit fare payment system [pdf]. The three students, Zack Anderson, R.J. Ryan and Alessandro Chiesa, were working on an undergraduate research project for Ron Rivest. They had planned to present their findings at the DEFCON conference last weekend, but were prevented from doing so after the transit authority obtained a restraining order against them in federal court.
The court sets a dangerous standard here, with implications well beyond MIT and Boston. It suggests that advances in security research can be suppressed for the convenience of vendors and users of flawed systems. It will, of course, backfire, with the details of the weaknesses (and their exploitation) inevitably leaking into the underground. Worse, the incident sends an insidious message to the research community: warning vendors or users before publishing a security problem is risky and invites a gag order from a court. The ironic -- and terribly unfortunate -- effect will be to discourage precisely the responsible behavior that the court and the MBTA seek to promote. The lesson seems to be that the students would have been better off had they simply gone ahaed without warning, effectively blindsiding the very people they were trying to help.
The Electronic Frontier Foundation is representing the students, and as part of their case I (along with a number of other academic researchers) signed a letter [pdf] urging the judge to reverse his order.
Update 8/13/08: Steve Bellovin blogs about the case here.
Adam Shostack here. I'm working on a paper about "Experiences Threat Modeling at Microsoft" for an academic workshop on security modeling. I have some content that I think is pretty good, but I realize that I don't know all the questions that readers might have.
So, what questions should I try to answer in such a paper? What would you like to know about? No promises that I'll have anything intelligent to say, but I'd love to know the questions you're asking. So please. Ask away!
I got a lot of interesting comments from my TechEd 2008 presentation entitled, "How To Review Your Code And Test For Security Bugs," but the most comments and questions were reserved for fuzz testing; I was blown away by the number of people who thought fuzz testing was hard, or that you only left fuzz testing to ‘leet hackers.
During the presentation I mentioned in some depth how to perform fuzz testing, and what parts of an application should be fuzz testing targets. I also introduced an idea (that's not new) to help people who have never performed fuzz testing begin fuzz testing with very little cost and friction. The idea is to add a small layer of code to an application to automatically mutate untrusted data as it comes into an application; I called that code layer "a layer of hurt."
Before I continue, I want to point out that fuzzing is an SDL requirement, but the idea in this blog post is not an SDL requirement, it's just another way to help meet SDL fuzzing requirements.
Adding a layer of hurt, as shown in the picture below, is pretty simple as it involves adding code to an application to tweak data as it comes into an application. You can work out where to place the fuzzing code by looking at your threat models to see where data crosses trust boundaries. You could also simply grep the code looking for APIs that read data, for example:
You get the picture.
The fuzzing code should appear right after the API that reads that data.
For example, C or C++ code that reads from a UDP socket and then fuzzes the data before it's consumed by the rest of the application might look like this:
char RecvBuf[1024];
int BufLen = sizeof(RecvBuf);
int result = recvfrom(
RecvSocket,
RecvBuf,
BufLen,
0,
(SOCKADDR *)&SenderAddr,
&SenderAddrSize);
#ifdef _FUZZ
Fuzz(RecvBuf,&BufLen);
#endif
Or, in C#, code that reads from an untrusted file:
FileStream fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
uint len = (uint)(fileStream.Length);
byte[] fileData = new byte[fileStream.Length];
fileStream.Read(fileData, 0, (int)len);
fileStream.Close();
#if _FUZZ_
Malform pain = new Malform();
fileData = pain.Fuzz(fileData);
#endif
In both code examples, Fuzz() mutates the incoming data. In the C++ case, the fuzzing code looks like this:
void Fuzz(_Inout_bytecap_(*pcbBuf) char *pBuf,
_Inout_ size_t *pcbBuf) {
if (!pcbBuf || !pBuf || !*pcbBuff || *pBuf) return;
if ((rand() % 100) > 5) return; // fuzz about 5% of Buffers
size_t cLoop = 1 + (rand() % 4);
for (size_t j = 0; j < cLoop; j++) {
size_t i=0,
iLow = rand() % *pcbBuf,
iHigh = 1+rand() % *pcbBuf,
iIter = 1+rand() % 8;
if (iLow > iHigh)
{size_t t=iHigh; iHigh=iLow; iLow=t;}
char ch=0;
switch(rand() % 9) {
case 0 : // reset upper bits
for (i=iLow; i < iHigh; i++)
pBuf[i] &= 0x7F;
break;
case 1 : // set upper bits
for (i=iLow; i < iHigh; i++)
pBuf[i] |= 0x80;
break;
case 2 : // toggle all bits
for (i=iLow; i < iHigh; i++)
pBuf[i] ^= 0xFF;
break;
case 3 : // set to random chars
for (i=iLow; i < iHigh; i++)
pBuf[i] = (char)(rand() % 256);
break;
case 4 : // set NULL chars to (possibly) non-NULL
for (i=iLow; i < iHigh; i++)
if (!pBuf[i])
pBuf[i] = (char)(rand() % 256);
break;
case 5 : // swap adjacent bytes
for (i=iLow; i < __max(iHigh-1,iLow); i+= iIter)
{char t=pBuf[i]; pBuf[i] = pBuf[i+1]; pBuf[i+1]=t;}
break;
case 6 : // set to random chars every n-bytes
for (i=iLow; i < __max(iHigh-1,iLow); i+= iIter)
pBuf[i] = (char)(rand()%256);
break;
case 7 : // set bytes to one random char
ch=(char)(rand() % 256);
for (i=iLow; i < iHigh; i++)
pBuf[i] = ch;
break;
default: // truncate stream
*pcbBuf = iHigh;
break;
}
}
}
The sample C# and C++ fuzzing code is available as a ZIP file at the end of this post.
This code is an example of dumb-fuzzing, which is fuzzing with little or no regard for the data structure being manipulated. If you've never performed any kind of fuzz testing in the past, then you will probably find bugs with this simple fuzzing technique. Once you have weeded out the low-hanging bugs, you may need to turn your attention to smarter fuzzers. For example, in theory, this code would find few if any bugs in a PNG parser, because PNG files have a built in check-sum, so if you fuzz a PNG file, you'd have to recalculate the checksum to get decent code coverage.
When I showed this code during my presentation, I urged people to add it to their applications today if they currently don't do fuzz testing, and simply run their applications through their normal testing processes. Within three days of my presentation I received emails from people saying they had found bugs. I have no doubt others did too.
One of the comments I made during the session was,"If you can't spend the time on great fuzzing, fuzz anyway" and adding a "layer of hurt" is a reasonable start.
Please feel free to sound off if you have ideas to help improve the code and let us know what you think, either through email or comments to this post.