Friday, 11 March 2011

A Few Hypercomplex Onions

C# Generic Limitations

The C# class Onion (listing below) allows experimentation with any of the Cayley-Dickson algebras mentioned in the previous related article, from the monodimensional reals, right up to the 512-dimensional austons :-) and beyond.

Modern professional libraries for this purpose still tend to be based on technologies like C++ templates, allowing for type variation in the underlying coefficients. And not just between a few integer and floating point types. For example, with careful design you can define your Biquaternion type as Quaternion<Complex>. But while elegant and fun to develop, these techniques don't port well to C#. There are several reasons for this, two of them being the comparitively restrictive natures of C# generics, and of C# operator overloading.

Introducing The Onion

The obvious alternative is to create a single class to represent a Cayley-Dickson number of any dimension. That's what Onion does. While it has a private array of double called Values, containing its real coefficients, it also makes essential use of the composition build model. Complex numbers can be treated as ordered pairs of real numbers; quaternions as ordered pairs of complex; octonions, pairs of quaternions; and so on. To support this model, an Onion has read only properties named A and B returning these two lower dimensional Onions.

These let the class encapsulate the Cayley-Dickson definition of a product. Take any two Onions, p and q, of the same dimensionality:
p = (a, b)
q = (c, d)
The Cayley-Dickson construction defines the product of these as
pq = (ac - d'b, da + bc')
where c' and d' represent the conjugates of c and d. Since all of a, b, c, d have lower dimension than p and q, we can apply this definition recursively until we reach the reals, which we already knew how to multiply together. The implementation of operator * is complicated by the need to handle input parameters p, q of different dimensionalities; in such cases, the "missing" component (b or d) is replaced by zero.

Onion Operators, Properties, Methods

Operators implemented in Onion include the unary +, -, and also ~, which returns the conjugate; the binary ==, !=, +, -, *, /, and also ^, which has an optimized override raising an Onion to a signed integral power. Finally, there is an implicit conversion operator from type double, which allows real values to be intermixed with Onions in arithmetic expressions.

Care and parentheses are recommended with ^. In normal C# usage, ^ represents the logical XOR operation, and so has an inappropriately low precedence for the present context (midway between logical OR and logical AND). Also, the exponentiation operator is frequently expected to be right-associative:
2 ^ 3 ^ 4 = 2 ^ (3 ^ 4) = 2 ^ 81 = 2,417,851,639,229,258,349,412,352
whereas without explicit parentheses, we get this instead:
2 ^ 3 ^ 4 = (2 ^ 3) ^ 4 = 8 ^ 4 = 4,096
Most other properties and methods are self-explanatory. Dim is the dimension of the Onion; Re and Im its real and imaginary parts; Norm its norm or modulus, Norm_2 the square of that; and Reciprocal - well, take a wild guess. There are static Exp and (natural) Log functions, added for the particular investigations I happened to be interested in at the time; and a useful ToString() override using 1 + 2i + 3j + 4ij notation, omitting redundant 0s and 1s. Note the use of ij in place of the conventional quaternion k here, as in my earlier article; if you want to change the basis representation, private method AppendDim is the place to visit.

It's a Reference Type but...

Onion isn't quite as dynamic as it appears. Every algebra that it can represent is closed. For example, starting with a bunch of complex numbers, there's no way that any sequence of additions, multiplications etc. can generate a quaternion. Also, I've made it immutable, because it's not a struct (does not have value copy semantics) and I didn't want multireferenced instances changing in unexpected ways.

There is an indexer, but that just gives read access to the coefficients. Once created, an Onion cannot change its value. Expressions such as z *= 2, rather than operating on z itself, replace it with a new Onion.

Examples

Here's some sample code showing verification of the "odd" results used in the previous article:
var i = new Onion(0, 1);
Onion p = i, z1 = (p ^ 2) + 1; // Caution! Operator ^ has a low precedence!
Console.WriteLine("(Complex numbers) When p = {0}, then p² + 1 = {1}.", p, z1);
// Output: (Complex numbers) When p = i, then p² + 1 = 0.

var j = new Onion(0, 0, 1);
Onion q = j, z2 = (p*q - q*p) ^ 2;
Console.WriteLine("(Quaternions) When p = {0} and q = {1}, then (pq - qp)² = {2}.", p, q, z2);
// Output: (Quaternions) When p = i and q = j, then (pq - qp)² = -4.

var k = new Onion(0, 0, 0, 0, 1);
Onion r = k, z3 = ((p*q)*r - p*(q*r)) ^ 2;
Console.WriteLine("(Octonions) When p = {0}, q = {1} and r = {2}, then ((pq)r - p(qr))² = {3}.", p, q, r, z3);
// Output: (Octonions) When p = i, q = j and r = k, then ((pq)r - p(qr))² = -4.

var l = new Onion(0, 0, 0, 0, 0, 0, 0, 0, 1);
p = i*j + k*l; // p ≠ 0
q = i*k + j*l; // q ≠ 0
var pq = p*q;
Console.WriteLine("(Sedenions) When p = {0} and q = {1}, then pq = {2};", p, q, pq);
// Output: (Sedenions) When p = ij + kl and q = ik + jl, then pq = 0;
Console.WriteLine("(p == 0) = {0}; (q == 0) = {1}; (pq == 0) = {2}.", p == 0, q == 0, pq == 0);
// Output: (p == 0) = False; (q == 0) = False; (pq == 0) = True.
Another example: here is the code fragment I used to generate the sedenion multiplication table (order = 4, dim = 16) in the previous article.
const int order = 4;
const int dim = 1 << order;
var values = new double[dim];
for (var row = 0; row < dim; row++)
{
values[row] = 1;
var p = new Onion(values);
values[row] = 0;
for (var col = 0; col < dim; col++)
{
values[col] = 1;
var q = new Onion(values);
values[col] = 0;
Console.Write(string.Format("{{0,{0}}}", order + 2), p*q);
}
Console.WriteLine();
}
Source Code

Okay, finally here's class Onion:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Onions
{
public class Onion
{
private double[] Values { get; set; }

public Onion(Onion x) : this(x.Values) { }

public Onion(Onion a, Onion b)
{
var dim = Math.Max(a.Dim, b.Dim);
Dim = dim*2;
a.Values.CopyTo(Values, 0);
b.Values.CopyTo(Values, dim);
}

public Onion(params double[] values)
{
var count = values.Count();
var dim = 1;
while (dim < count) dim <<= 1;
Dim = dim;
values.CopyTo(Values, 0);
}

private Onion(IEnumerable<double> values) : this(values.ToArray()) { }

public double this[int index] { get { return index < Dim ? Values[index] : 0; } }

public int Dim
{
get { return Values == null ? 0 : Values.Length; }
private set { if (Dim != value) Values = new double[value]; }
}

public Onion A { get { return new Onion(Values.Take(Dim/2)); } }

public Onion B { get { var dim = Dim/2; return new Onion(Values.Skip(dim).Take(dim)); } }

public double Re { get { return this[0]; } }

public Onion Im { get { return this - Re; } }

public double Norm { get { return Dim == 1 ? Math.Abs(Re) : Math.Sqrt(Norm_2); } }

private double Norm_2 { get { return Values.Sum(a => a*a); } }

public Onion Reciprocal { get { return Dim == 1 ? 1/this[0] : ~this/Norm_2; } }

public static implicit operator Onion(double value) { return new Onion(value); }

public static Onion operator +(Onion x) { return x; }

public static Onion operator -(Onion x) { return Operate(x, a => -a); }

public static Onion operator ~(Onion x) { return x.Dim == 1 ? x : new Onion(~x.A, -x.B); }

public static bool operator ==(Onion x, Onion y)
{
bool nullX = ReferenceEquals(null, x), nullY = ReferenceEquals(null, y);
return nullX || nullY ? nullX && nullY : x.Equals(y);
}

public static bool operator !=(Onion x, Onion y) { return !(x == y); }

public static Onion operator +(Onion x, Onion y) { return Operate(x, y, (a, b) => a + b); }

public static Onion operator -(Onion x, Onion y) { return Operate(x, y, (a, b) => a - b); }

public static Onion operator *(Onion x, Onion y)
{
int dimX = x.Dim, dimY = y.Dim;
if (dimX == 1) return dimY == 1 ? x[0]*y[0] : Operate(y, value => x[0]*value);
if (dimY == 1) return Operate(x, value => value*y[0]);
if (dimX < dimY) return new Onion(x*y.A, y.B*x);
if (dimX > dimY) return new Onion(x.A*y, x.B*~y);
Onion a = x.A, b = x.B, c = y.A, d = y.B;
return new Onion(a*c - ~d*b, d*a + b*~c);
}

public static Onion operator /(Onion x, Onion y) { return x*y.Reciprocal; }

public static Onion operator ^(Onion x, long y)
{
if (y < 0) return x.Reciprocal ^ -y;
Onion z = 1;
var power = x;
var unity = true;
for (long mask = 1; y > 0 && mask > 0; mask <<= 1)
{
if ((y & mask) != 0)
{
if (unity) { z = power; unity = false; }
else z *= power;
y &= ~mask;
}
if (mask > 0) power *= power;
}
return z;
}

public static Onion operator ^(Onion x, Onion y)
{
return Exp(Log(x)*y);
}

private static void AppendDim(StringBuilder result, int index)
{
for (int n = 0, keys = index, mask = 1; keys != 0 && mask > 0; n++, mask <<= 1)
if ((keys & mask) != 0)
{
result.Append((char)('i' + n));
keys &= ~mask;
}
}

public override bool Equals(object obj)
{
return
!ReferenceEquals(null, obj) &&
(ReferenceEquals(this, obj) || obj is Onion && Equals((Onion) obj));
}

private bool Equals(Onion other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
for (var n = 0; n < Math.Max(Dim, other.Dim); n++)
if (this[n] != other[n]) return false;
return true;
}

public static Onion Exp(Onion x)
{
var re = x.Re;
Onion z = Math.Exp(re);
if (x.Dim > 1)
{
var im = x.Im;
var angle = im.Norm;
if (angle != 0) z *= (Math.Cos(angle) + im*(Math.Sin(angle)/angle));
}
return z;
}

public override int GetHashCode()
{
return Values
.Select(value => value.GetHashCode())
.Aggregate((u, v) => u ^ v);
}

public static Onion Log(Onion x)
{
var norm = x.Norm;
Onion z = Math.Log(norm);
if (x.Dim > 1)
{
var im = x.Im;
var angle = im.Norm;
if (angle != 0) z += im*(Math.Acos(x.Re/norm)/angle);
}
return z;
}

private static Onion Operate(Onion x, Func<double, double> f)
{
var z = new Onion(x);
for (var n = 0; n < x.Dim; n++) z.Values[n] = f(z[n]);
return z;
}

private static Onion Operate(Onion x, Onion y, Func<double, double, double> f)
{
var dim = Math.Max(x.Dim, y.Dim);
var z = new Onion { Dim = dim };
for (var n = 0; n < dim; n++) z.Values[n] = f(x[n], y[n]);
return z;
}

public override string ToString()
{
var result = new StringBuilder();
var empty = true;
for (var n = 0; n < Dim; n++)
{
var value = this[n];
if (value == 0) continue;
if (empty)
{
if (value < 0) result.Append('-');
empty = false;
}
else result.Append(value < 0 ? " - " : " + ");
var absValue = Math.Abs(value);
if (n == 0 || absValue != 1) result.Append(absValue);
AppendDim(result, n);
}
if (empty) result.Append('0');
return result.ToString();
}
}
}
Happy hypercomplex numbering.

Wednesday, 9 March 2011

Security Testing Part 3 - The Attack Surface

More Than Just UI

From the viewpoint of focusing test effort and resources, one of the most useful outputs from thread modelling is its picture of the product's Attack Surface. This is based on the set of places where vulnerabilities might be exposed, and in some sense, the "cross-sectional exposure" of each to attackers.

The most obvious of these places is the vicinity of the UI. However, many other weak spots can often be identified by modelling the data flows present. The full set of loci appearing on any attack surface will depend upon the nature of the product, but might include such items as:
  • all UI controls;
  • file entry points;
  • registry entry points;
  • database accesses;
  • web interfaces;
  • interprocess calls;
  • remote process calls;
  • networking ports;
and many others.

A Word About Targeting

The significance of each depends not only on the nature of possible related vulnerabilities, but also on who can access each of these locations. For example, a TCP port might be sniffed by anyone, anywhere, while a named pipe may be accessible only to local administrators. That's what makes the term attack surface so apposite. Conceptually, the size of each site is multiplied by its accessibility, and the resulting areas summed into your security metrics.

Your time and resources are limited. Ideally, your test efforts should focus preferentially on the larger areas of this surface. That means knowing how to identify, measure and compare vulnerability exposures. Practice and real-world experience are the best teachers of these skills.

Exercise

Take a product you have worked on before, or are otherwise familiar with. Draw a diagram, showing all the points where data can cross "trust boundaries". Then for each of these, run down the STRIDE list, looking for potential vulnerabilities of each type:
Do that, and you've done (an admittedly quick-and-dirty) threat modelling. This is a hugely valuable process. Often just thinking about one particular vulnerability or threat will set you off on a voyage of discovery to more. Just remember, that's also exactly what your attackers are doing.


For Example...


We recently brainstormed the login UI of our flagship product, looking for credible spoofing, tampering, repudiation and elevation of privilege threats. But what we found instead, via the security "lock-out" feature (where a user's login would be disabled after three incorrect passwords), was a nifty denial of service attack. With that feature enabled, all I have to do is guess your password incorrectly three times (assuming your login name is in-the-clear), and presto, you are locked out: DoS, QED.

In mitigation: "But all I have to do is ask my administrator to reinstate me." Sure, your administrator. When she gets back from that meeting. By the way, what's her login name? It's "admin", isn't it? And that can't be changed, right? Wow, we're not exactly making it hard to guess!

SDL Resources (from MSDN Magazine Security Briefs)
Threat Models Improve Your Security Process - Michael Howard
Reinvigorate your Threat Modeling Process - Adam Shostack
Previously:
Part 1 - Overview
Part 2 - Lab Work

Tuesday, 8 March 2011

Contrafactuals

Say It Don't Spray It

Just saw a mock up of a PowerPoint presentation for a proposed new product. Although it was thrown together in that Lorem Ipsum fashion (don't you just love his dresses?), still it was amusing how the bullet points conspired by chance to tell the diametric opposite of the truth about this baby. Economic gains? In fact this solution would be more expensive than traditional ones. Reduced paperwork? More sort of increased, actually. Environmental impact? Do this one yourself...

Dilbert.com

Friday, 4 March 2011

A Few Hypercomplex Numbers

Adam's Apples

Adam learned to count sitting at home. Various number systems occurred to him, each one seeming to answer still more new questions...

Initially the natural numbers N (1, 2, 3 and their friends) arrived, letting him answer stuff like "How many apples should I bring home, to avoid an argument?" Later, zero was added, giving him the whole numbers, and answering "How many of a surplus does that leave for unexpected guests?" Then negative numbers extended this arrangement to the integers Z; now he could keep track of apple debts as well as stocks.

Naturally, all of this led to apple shortages, as others began to stockpile; soon he was looking at puzzles like "There's just one apple, and two of us; how many apples each can we have?" Hence the concept of a new type of number, expressed as a sequence of two or more other, pre-existing numbers: the ratios, or rational numbers Q, combining for example 1 and 2 into the single new number ½. Yet still he couldn't answer posers like "What length's the diagonal of my mile-square orchard?" Adding radicals like √2 to obtain the algebraic numbers, still he would find other measurements, like the circumference of a two- or three-inch diameter apple, impossible to pin down.

R - The Reals

For once he got lucky, and defined a (real) transcendental number as anything that wasn't already on the line! Finally, he had the continuum of the real numbers R stretching from -∞ on the left, past his nose, and onward to +∞ on the right. He even learned enough about projective geometry to include ∞ itself, when context called for such extremes.

Everything after N and up to this point was an attempt to solve an ever growing set of equations; to answer an ever expanding realm of questions. Suppose that x = 1. Then some of these questions were,
  • What's x - x? - Add zero; get the whole numbers.
  • What's x - 2? - Add negatives; get the integers Z.
  • What's x / (x+1)? - Add fractions; get the rationals Q.
  • What's y, if y² = x + 1? - Add radicals; get the algebraics.
  • What's an apple's circumference, if x is its diameter? - Add everything else on the line; get the reals R.
But damn, he thought, damn and stop me if you've heard this one before, but damn if it doesn't all go serpent shaped again, just as soon as I leave the familiar domain of apple accountancy! Here's one example still without an answer:
  • What's x, if x² + 1 = 0?
But all of that was quite some time ago. The answer lay nearby, but in another dimension; in this next domain...

C - The Complex Numbers

Just give this elusive result a whole new name, and call it a number. The new name is i; one example of a square root of minus one. Another such example is -i. Now, since i is a number, it can be multiplied it by any real number y; so doing produces an imaginary number, iy. Also, any real number x can then be added to this new thing, making a complex number, x + iy.

This new number i has effectively generated a second copy of the real number line. The new line is conventionally shown at right angles to the original, intersecting at zero in an Argand Diagram (see figure, from Wikipedia). The two lines define a complex plane. So whereas real numbers were represented by points on a line, these newfangled complex numbers are instead points on a plane.

Complex numbers have proved to be insanely useful in various mathematical, scientific and engineering disciplines. At their basics, complex addition and multiplication are used to represent and to compose together planar transformations. For example, multiplication by i results in a 90° anticlockwise rotation. So, how about adding more dimensions? Can we solve still more equations, by adding in still more crazy so-called numbers?

H - The Quaternions

What about this situation: find p and q, where
  • (pq - qp)² = -4
Obviously this equation has no solution in the real domain (where no square is negative), nor even the complex one. Multiplication of complex numbers is still commutative; for any real or complex p and q, we have (pq - qp) = 0, and that's never going to square to anything other than more zero. Yet believe it or not, if we now perform exactly the same trick as before, namely introducing a brand new square root of -1 into our system, then we can immediately find multiple solutions to this very odd equation.

The new guy is a completely independent square root of -1, distinct from both i and -i. Let's call him j. Now just as the real and imaginary lines generate the complex plane C, so too do i and j generate a plane. But multiplication in this plane is a little different from multiplication in C. To multiply i and j, you have to imagine the vector i "rotating" towards j, and by the rules of vector multiplication (the so-called cross product), generating a third vector ij orthogonal to both of these, perhaps in the direction that a right handed screw would be driven by such a rotation. But remember, the real line is already orthogonal to both i and j. This new vector ij can't be real; for then j himself would be merely imaginary to begin with, and not an entirely new kind of number after all.

No, i and j between them have to generate an entirely new direction ij, simultaneously orthogonal to both of these and to the real line. In fact this ij himself turns out to be yet another distinct square root of -1. As William Hamilton famously discovered in 1843: during the attempt to break out of two dimensions and into three, we're instead summarily deposited in the land of four! And by the preceding analogy with vector spaces, rotating in the opposite direction, notice this anticommutativity:
ji = -ij.
Numbers of the form a + bi + cj + dij (where a, b, c and d are real) are termed the quaternions, H. In general, if p and q are quaternions, then pq ≠ qp; they're not commutative.

Incidentally, don't take away the impression that these unit vectors, their products, and their negatives, are the only square roots of -1 in the new system. That may have been true in the complex domain, where only two numbers, the discrete ±i, held that distinction. But in the 3D vector subspace of the quaternions, i.e. the space remaining upon removal of the real axis, there's an uncountably infinite number of √-1. Every point on the surface of the unit sphere, a = 0, b² + c² + d² = 1, qualifies.

Returning to the equation at the head of this section, let's now set
p = i, q = j
then
(pq - qp)² = (ij - ji)² = (ij - (-ij))² = (2ij)² = 4(ij)² = 4(-1) = -4
So p = i, q = j is one solution to the very odd equation; and there are others.

Applications of the non-commutative quaternions were once much more numerous, but they have fallen out of favour, now displaced almost everywhere by matrix and vector algebras. Their one current party trick is modelling the camera in 3D computer games and other simulations, where they are less prone to the problems of interpolation and gimbal lock suffered by the alternatives. So we can at least claim them as a successful extension of the transformational complex numbers, from the plane into 3D and 4D spatial rotations (which are also non-commutative).

O - The Octonions

Now, what about this situation: find p, q and r, where
  • ((pq)r - p(qr))² = -4
Say what you will about the non-commutative quaternions, at least those guys associated, just like the complex and the real: for any p, q and r, we had ((pq)r - p(qr)) = 0. Please struggle to contain your amazement as I reveal to you now, that by the simple expedient of adding still another independent square root of -1 to our system, we can immediately find multiple solutions to this new and extremely odd equation.

The drill is the same as before. Our new root k is orthogonal to all of i, j, ij, and the real line. So too are his uninvited pals, namely ik, jk, and ijk. That's a total of eight independent dimensions (the number doubles with every brand new √-1 added). Seven of these are imaginary, so our basis includes seven square roots of -1. The seven points and directed lines of the Fano Plane (below) offer a mnemonic to help us multiply these. Example: the central vertical line tells us that
  • (jk)(ik) = ij, and (ik)(jk) = -ij;
  • (ik)(ij) = jk, and (ij)(ik) = -jk;
  • (ij)(jk) = ik, and (jk)(ij) = -ik; and so on.
The Fano Plane mnemonic for octonion multiplication

The bottom line in particular makes this statement of antiassociativity:
i(jk) = -(ij)k.
Numbers of the form a + bi + cj + dij + ek + fik + gjk + hijk (where a, b, c, d, e, f, g and h are real) are termed the octonions, O. In general, if p, q and r are octonions, then (pq)r ≠ p(qr); they're not associative. Returning to the equation at the head of this section, let's now set
p = i, q = j, r = k
then
((pq)r - p(qr))² = ((ij)k - i(jk))² =(ijk + ijk)² = (2ijk)² = 4(ijk)² = 4(-1) = -4
So p = i, q = j, r = k is one solution to the extremely odd equation; and there are others.

Applications of the non-associative octonions are currently quite rare. They are useful in investigating eight-dimensional transformations in general, and 8D rotations in particular. Some mathematicians (like John Baez and Ian Stewart) have recently begun to speculate that there might be a central role for the octonions in certain advanced physical theories.

S - The Sedenions

Now, what about this situation: find p and q, where
  • pq = 0, p ≠ 0, q ≠ 0.
In all of the number systems we've seen so far, if any two numbers p and q were nonzero, we could be sure that their product pq would also be nonzero; conversely, if a product was zero, then so too was at least one of its factors. But if we now add just one more square root of -1 to our evolving number system, we can immediately find multiple solutions to this new and pathologically odd equation.

Call the new root l. As usual he brings along an entourage of his pals, this time a further seven: il, jl, ijl, kl, ikl, jkl, and ijkl. So first, we need to go through the chore of working out the extension of the multiplication table from 8 to 16 dimensions. Here's the result (click for big):

The new 16-dimensional numbers are termed the sedenions, S. Notice that the top left quarter of the basis multiplication diagram contains the rules for octonions (previously shown encoded into a Fano Plane above); similarly in turn, the top left quarter of that contains the quaternions; the top left quarter of that, the complex numbers; and finally the top left quarter of that, the single cell "1", is of course the basis for the reals.

Returning to the equation at the head of this section, let's now set
p = ij + kl, q = ik + jl
then
pq = (ij + kl)(ik + jl) = ij(ik) + ij(jl) + kl(ik) + kl(jl) = -jk + il - il + jk = 0
So p = ij + kl, q = ik + jl is one solution to the pathologically odd equation; and there are others.

I'll not go into the 16-dimensional sedenions S any further - they are just a little too crazy! Technically, S and all subsequent extensions are no longer normed division algebras. There are only four of these, and we have already seen them all: they were R, C, H and O.

Incidentally, don't think of zero divisors as pathological in all number systems; it's just that they have no place in normed division algebras. For a particularly tame illustration, consider the integers modulo 12, as modelled by the numerals 0 to 11 on an analog clock face (if yours has 12 in place of 0, obviously you're not a C programmer). Define addition as clockwise progression, and multiplication as repeated addition. Then speaking modulo 12, we have
3 * 4 = 0.
Still Higher Dimensions

Just for fun, I can't resist mentioning the names of the next few algebras after S. These are:
  • the 32-dimensional trigintaduonions;
  • the 64-dimensional sexagintaquattuornions;
  • the 128-dimensional centumduodetrigintanions; and
  • the 256-dimensional ducentiquinquagintasexions.
In the unlikely event that any of these should darken your door again, let's hope they do so under the mercifully un-Latin alternative names proposed by Robert P.C. de Marrais and Tony Smith:
  • P - the pathions, from the 32 Paths of Kabbalah;
  • X - the chingons, from the 64 Hexagrams of the I Ching;
  • U - the routons, from Route 128 of the "Massachusetts Miracle"; and
  • V - the voudons, from the 256 deities of Voodoo's Ifa pantheon.
The number of crazy-looking equations soluble in each system also continues to rise. For example, there are nonzero routons whose squares are zero. There are nonzero voudons, having nonzero squares and cubes, yet whose fourth powers are zero. And so on.

Finally, I'd like to go on record here to propose the name austons for the next algebra in this series. Named of course for the capital city of the Lone Star State: area code 512. Sadly there's never likely to be any demand for these, as a certain Periodicity Theorem tells us that nothing new happens beyond the voudons.

Confessions

My aim in this article was to provide a contrast to the traditional presentation of these particular algebras, R, C, H, O and S, as a progression wherein "algebra gets a little bit worse with each step":
  • going from R to C, the property of ordering is lost;
  • going from C to H, commutativity is lost;
  • going from H to O, associativity is lost;
  • going from O to S, unique divisors, and our marbles, are lost.
Instead I've stressed what's gained with each step. Seeking out more and more equations to solve, building successively more powerful algebras, until eventually, there is nothing we can't do - and nothing we can!

During the exposition, I've taken various liberties with notation.
  • There is in fact no consensus as to whether the set of natural or whole numbers, both, or neither, contains zero. I've arbitrarily gone with N = {1, 2, 3, ...}.
  • Yes, my account of the "real line" misses completely the point of the continuum hypothesis. The reals weren't my principal target here.
  • k has traditionally been used, since the day and hour of William Hamilton's discovery of the quaternions, to represent ij, rather than the "next" new √-1 (the generator of the octonions). I play fast and loose with these bases, coming from a background in electrical engineering. Over there we live and breathe, eat and drink complex numbers; but we defiantly (and consistently) use j in place of i.
There are many more exotic number systems to be found. In fact, the schemes covered in this article, the first few Cayley-Dickson algebras, these are just some of the more popular (or better known) main line stations on a network also contaning biquaternions (like quaternions, but with complex instead of real coefficients - can, open! worms, everywhere!), exterior algebras, various split and conic hypercomplex numbers, and connecting even further out to some very weird places indeed.

Tuesday, 1 March 2011

Tweets - February 2011



Monday, 21 February 2011

Security Testing Part 2 - Lab Work

Jarlsberg Turns to Gruyere

As of July 13, 2010, the Google Codelab formerly known as Jarlsberg is now called Gruyere. This training aid is a knowingly vulnerable application, which can be used to learn and understand web vulnerabilities.
http://google-gruyere.appspot.com/
This is a particularly useful experience for test engineers, since one of its main aims is to simulate the activity of penetration testing - simulating attacks from malicious sources (known as Black Hat Hackers, or occasionally Crackers). The process involves an active analysis of the system for potential vulnerabilities resulting from poor or improper system configuration, from known and unknown hardware and software flaws, or from operational weaknesses in process and/or technical countermeasures.

Gruyere is excellent at what it does, in its tutorial-structured, hint-led way. The contents sidebar is the best reference to what classes and detailed subtypes of vulnerability are covered. Cross-Site Scripting, Script Inclusion and Request Forgery (XSS, XSSI, XSRF) are particularly well served, pardon the pun. Other inclusions include: data tampering, information disclosure, denial of service, remote code execution and elevation of privilege.

For each vulnerability, you assume the role of a black hat (malicious hacker) and uncover the related exploit. One particularly well realised aspect of this Codelab is the way in which you are encouraged - just like a real world security researcher - to combine approaches of both major kinds: black box (e.g. probe it with some bad input data) and white box (e.g. read its source code).

What Can't Gruyere Do?

There are some significant omissions. For starters, any popular C/C++ attack with "overflow" in the name. Gruyere is written in Python, which by design, prevents any attempt at reading and writing outwith an array's bounds. For that reason, the popular attack known as buffer overflow is not covered by this lab. Similarly, Python prohibits integer arithmetic overflow, and so Gruyere includes no examples of integer overflow exploits.

It is important to note that these observations do not guarantee the immunity of the website from such attacks. All applications are exposed to so-called platform vulnerabilities. These can be security weaknesses in the web browser or other client side code, or in the underlying Python runtime. The lab doesn't cover such issues, even though sometimes you might avoid platform vulnerabilities by making changes to the app, so as to alter its platform dependencies, or its resource usage.

By far the biggest omission from this lab has to be SQL Injection - for the admittedly very good reason, that Gruyere does not use SQL. Again, there are plenty of well researched cases elsewhere on the web. For example this very readable account by Steve Friedl is a model of clarity.

Microsoft 's extensive and very professionally produced Security Virtual Labs are also well worth a look. This one on SQL Injection Vulnerabilities can take up to 90 minutes to complete (the standard allowance for these labs). It requires JavaScript plus "IE6 or above"; and you'll have to install an ActiveX control to connect to and run the lab.

A Note On Scope

While security testing obviously needs to be targeted on a specific set of possible exploits, given the vulnerabilities and their mitigations in the application or system under test, the umbrella undertakings of security training, and more generally education, must entertain no such restrictions.

Take Banned APIs for example. These are closely related to the subject of buffer and integer overflows described above, and to other vulnerabilities specific to code in languages like C/C++ but not found for example in managed code. Why should a Test Department dealing with C# WinForms apps care about these? - Well, it could happen at any time, that the Development Department will decide to slip some C/C++ code, or a legacy library, into the mix. Maybe to avoid injecting a .NET or Windows Shell dependency somewhere. Suddenly, your attack surface quadruples. Shouldn't you be prepared for that? Certainly, to the extent that you should immediately and instinctively be at least aware of the implications of that change.

Another example. Why worry about XSS attacks, when no such vulnerabilities can be exploited, due to the particular nature of our app? - Because tomorrow, the Marketing Department will demand that lucrative third party ads be served up in IFrames beside your primary content. Next day, you could be serving malware as blithely as the BBC. Clearly, just-in-time training is woefully inappropriate here.

Finally, here is the definitive word on the issue from Michael Howard, architect of Microsoft's Security Development Lifecycle, and principal security program manager on their Trustworthy Computing (TwC) Security team. In his article The SDL and the CWE/SANS Top 25 Most Dangerous Programming Errors 2010, he writes:
Even CWE 98, "PHP File Inclusion," is covered by the SDL in our required security training classes, which is especially remarkable when you consider that virtually no PHP code is written at Microsoft!

The reason that we address issues like PHP file inclusion in the SDL is that we don't simply wait for new vulnerability taxonomies to be released and then rush to add mitigations to our security processes; rather, we structure the SDL to provide developers with fundamentally sound, secure programming practices. As a result, we cover not just the known vulnerabilities of today (like the Top 25) but also many of the unknown vulnerabilities that will be discovered tomorrow. The fact that all of the Top 25 are addressed by the SDL is a great validation, but it is the result of the content of our process and not the cause.
Now Hack!

Once you've read the introductory material, including the warning paraphrased in red below, you can start your Gruyere adventure here:
https://google-gruyere.appspot.com/start
One final thing, do remember to concentrate exclusively on the suggested attacks. Seriously. Any deviation from the vulnerability cases which Google have expressly authorized here could have dire consequences of almost unlimited badness for you.

Previously:
Part 1 - Overview