Search Üner.com

Looking for something specific? Try the keyword search below (no query syntax or booleans allowed).

 

Most popular pages

Words for the wise

Random Oblique Strategy:

Random Turkish proverb:


Random, unique error tags

We have probably all seen these ridiculously informative error on Web pages before, like:

java.sql.SQLException: Column 'password_release' not found.
   at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.
      executeQueryWithCallback(MappedStatement.java:224)
   at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.
      executeQueryForList(MappedStatement.java:39)
   at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.
      queryForList(SqlMapExecutorDelegate.java:356)
   at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.
      queryForList(SqlMapExecutorDelegate.java:457)
   at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForList
      (SqlMapSessionImpl.java:128)
   at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForList
      (SqlMapClientImpl.java:24)
   at dmahk.apps.tradeit.frontend.dao.ibatis.impl.AdSearchDAOImpl
      .searchAdByCriterias(AdSearchDAOImpl.java:56.)
   .
   .
   .

And then you have fun doing SQL injections for the next 20 minutes until you get bored. Right? And we wonder why people do that. Than why do C, C++, Objective C, Python, Perl, and other developers do the same, especially given they have to work harder at it in some ways.

I came across an error while debugging an embedded driver the other day, and although I won't disclose the exact error and get everyone doing searches for it, but changing some of the text, it was essentially:

ERROR: CallFunctionTable Line 24 -- offset into table in r3 must be quad-word aligned header_Len = 33/32 function_p = 0x79808000

Well, looking at this very useful data, it took me all of about 5 seconds to see that someone was keeping a table of function pointers, and that by sending a header into this driver that was too long, i could do a trivial overflow into where it was looking for the index from the top of some table. Not five minutes later I had the driver calling arbitrary functions for me, and after some more digging, I am sure I could have done much worse.

What's my point? As a security - well, whatever I am - researcher, developer of secure code, ethical hacker, call it what you will, I simply grow weary of seeing people leave this level of detail in commercial code. There are a few things wrong here. Let's start with some obvious one:

There is an overflow condition because someone forgot to check the bounds on the header, and trusted user input not to be invalid. Simple fix. Now that they are aware of it, I am guessing they already fixed it, in fact.
They used an index into an array that came directly from user input. Again a problem with trusting user-input. Please take this in context, but users and their data are never to be trusted.
Then there is the error message itself, and that's what I really want to talk about.

What if I were to have seen something like:

ERROR: RhDFB6R2Mh

OK, as a developer that may or may not be enough information, but often, presenting the user with information about errors presents a security risk. Consider the following code snippet:

  1. nt *myInts = new (nothrow) int [256];
  2. if (!myInts == NULL)
  3. {
  4.     errorHandler("Some_random_fun");
  5. }
  6. else
  7. {
  8.     .
  9.     .
  10.     .
  11. }

Instead of all the data about the error, how about just calling a function, and passing in "Some_random_fun," where "Some_random_fun" := a string that will not appear anywhere else in the code, but means nothing to a user. For example, "RhDFB6R2Mh." This has a few advantages:

It leaves an attacker with little or no useful data (the fact that an error occurred at all could be useful, so I can't say no data at all). It's not an encrypted form of anything that can be reverse-engineered or analyzed. It's simply random text.

The user can still call tech support and say, "I got an error RhDFB6R2Mh. What do I do?" Tech support can have a nice unique key for these and look them up to help the poor user, and developers can even find them in the code with grep or spotlight with no problem.

If you used line numbers and modules, then someone changes the code, they moved the line. They may even have renamed the module. But had you been using a random error key, from a troubleshooting standpoint, you are still on solid ground.

The random keys can be generated with a custom tool (I'll share mine if you like) or you can even just use mktemp or a command line PRNG. All that matters is when you use it, you drop it in a database to make it unique (or use an algorithm like mine that encodes time and is guaranteed not to repeat within a certain number of years that are longer than I will be alive, and still generates a couple of these string per second).

There are, of course, many ways to expand on this idea, and I'll leave it up to you to fit it into your process and workflow. You could, for example, use a macro that outputs the file and line and other data for debug, and conditionally compile it out for a release.

My plea, o developer, is for you to stop using verbose, wonderfully informative error messages when the situation does not merit doing so. The less you give an attacker, the more secure your systems will be, and you will find, surprisingly I think, that developing using good security practices will have fringe benefits for quality control, test, and maintenance teams as well.