If you tell enough stories, perhaps the moral will show up.


The Future Still Isn't Right, pt II

And another thing. Spectacles. I had my eyes tested today and my prescription has shifted again. Fair enough, and I've opted to head off into the world of varifocals with a pair of single vision driving specs, and what's called occupational lenses which shade from VDU at the top down to reading at the bottom. There are three grades of optical efficiency to choose from, optional high index plastic to reduce the weight, optional quarterwave coating for transparency, and an (optional) hardness treatment. With correction and astigmatism in the basic prescription, the Dear only knows how many possible variations on the basic format that is.

During the test, I could opt to have my retina photographed for reference (for a tenner, how could I not?) and a chance to compare it with the lovely optometrist's album of interesting eyeballs. And the whole thing was conducted at a time and place to suit me. It was the very model of the modern custom shopping experience.

But if choice is the aim, why, for the love of every holy thing, do they only make spectacle frames in two sizes: too small, and much too fucking small? Am I the only person in the world with a head like a watermelon? I think not. And on that topic why is the choice limited to what they have in the shop on that day? Is it so impossible to record the relative location of ears, pupils and nose, and cut lenses to suit a pair of frames out of a catalogue? I want glasses like Michael Douglas in Falling Down: I need nerd authority, but yet again I've settled for some boring black metal frames that are barely willing to exist.

How sad.

Protect identity with a face blur: Fail

This story is so abominably sad that there's really no need to read it. All I want to do is note that in some cases, a face blur can still give important clues to identity.



Recently I wrote about the enumerate command that I use. I was looking at it just now because I wanted to enumerate one particular check across the whole domain: I wanted to report on the events that show a user being enrolled into local Administrators on their workstation -- and irregular admins generally.

This is a big deal for me -- has been for a long time, it's a big deal for more and more sites, and it should be for everyone. Admin privilege is the difference between spyware installing in a profile (and even now, most of them don't attempt to do this) and installing dangerously and ineradicably as a rootkit. Admin privilege is what allows  users to harm their builds with downloaded software or messing around with the branding or mapping. But alas, it's also the easy solution to a lot of problems and desktop team members -- admins themselves -- are often tempted to pass it on to a user in trouble so they can get on to the next call.

The control for this is to find out when it happens and follow up very promptly, next day, with the admin concerned. But you need to know it's happened, and the only ways I know how to tell it's happened are a) a listing of the group membership on every machine -- which doesn't, crucially, tell you when it was done, or b) the 536 message in the event log. So it's the message we want, provided we can pick and decode the content out of the rather unhelpful format. To hold the desktop team to account, we want to look at the new messages each day, making a nice report of all the suspect events.

We already have a tool -- enumerate -- which will run a command against every machine. So now we need a command that will append relevant log events on to a report. "But" I hear you cry, "but what about your RSA Envision log SELM appliance? Isn't that ideally suited to this task?" Well yes, my dears, it certainly is, but you see, it's licenced per event source. I have enough licences for all the infrastructure and about half of production servers, but none at all for workstations. We need something at a better price point, like free.

Microsoft is a better source of free (as in beer) software than you might expect, and they have the tool for this job: Logparser; motto: "the world is your database." In outline, Logparser converts and presents logs of many sorts and some odder stuff like registry and filesystem contents as queryable lists. The queries can be simple or complex: I started with

But you need to work a little harder to get a script parameterised enough to be enumerated across all domain members and produce a good outcome. The beauty of Logparser is that it's mature enough to deliver -- it really is a proper log analysis tool. I expected to write auxiliary scripts to break out the data, decode SIDs, accumulate the report as a CSV, and keep track of the last log read on each machine, but in fact all this can be done in Logparser script language or command line options.
-- admin.sql
-- Logparser query.
-- Accumulate events where a user has been made a member of admins or power users
-- You might want to enumerate this across the entire domain 
-- (omit domain controllers which have different messages)
-- Command would be like 
-- logparser 
--  -o:TSV -oSeparator:space -headers:OFF -fileMode:0 
--  -iCheckPoint:MYPC.lpc 
--  file:admin.sql?oFile=2009-10-18_AdminChanges+sMachine=MYPC
-- The checkpoint file is named for the machine, and output is appended to "today's" file.

-- Generating "hand" CSV rather than the CSV output type -- more flexible to do it in SELECT and USING
 -- the ms from the :ll aren't populated but it stops Excel dropping the seconds
 TO_STRING(TimeGenerated, '\"yyyy-MM-dd hh:mm:ss:ll\",')AS Date, 
 strcat(ComputerName,',') AS Computer,
 Resolve_SID (SID) AS Admin,
 Resolve_SID (SIDUser) AS User,   

-- Do the token parsing in USING: break the bits we want out of the -|%{SID}|... tokens in Strings
 Extract_Token(Strings,1,'|') AS SUr,  -- User SID
 Extract_Token(Strings,2,'|') AS GroupN, -- (Localised for free -- more friendly)
 Extract_Token(Strings,3,'|') AS GroupD, 
 Extract_Token(Strings,4,'|') AS SGp,  -- the Group SID 
 SUBSTR(SUr,2,SUB(STRLEN(SUr), 3)) AS SIDUser,  -- break raw User SID out of the %{SID}
 CASE EventID WHEN 636 THEN 'enrolled' WHEN 637 THEN 'removed' END AS Action, -- Friendly EventIDs
 -- Output like "into BUILTIN\Administrators"
   CASE EventID WHEN 636 THEN 'into ' WHEN 637 THEN 'from ' END, 
  STRCAT( '\\', GroupN)) AS Group
-- Need the -fileMode:0 (append) on the command line to avoid overwriting with each machine.
-- For a log for each machine then the command line above would let you use %Machine% in the name.

-- FROM the machine security log  --  This is -i:EVT. 
-- Don't use the SID resolve option because you may want to limit to particular built-in groups, but 
-- and S-1-5-32-544 is easier than working out internationalised versions of "Administrators"

 ((EventID=636) or (EventID=637)) and       -- 636 enroll, 637 remove
 (SID<>'S-1-5-18') and           -- Ignore actions by local System
 (                -- Ignore boring groups
  ((SGp = '%{S-1-5-32-544}') or (SGp = '%{S-1-5-32-547}')) -- Only want Admins or P Users
 -- Optionally don't report Domain admin (check your SID) being made admin, because it happens in every log!
 -- and 
 -- (SIDUser <> 'S-1-5-21-4163168572-49618088-4072775208-512') 

Remaining niggles are petty. some machines have corrupt SELs -- logparser fails at end of log, so it never writes a checkpoint so the entire file is processed every time. But this can be fixed by saving and emptying the offending log. And I suppose it would be nice if it enumerated the domain itself, but that doesn't trouble me.

Apparently V3 is due out. I cannot wait.



Just for fun, this is this is the exact text of a paragraph that Mrs U persuaded the more mad son to commit to Notepad:

On, 20th March 2010, I'm can Building the Farmhouse, I'm can Digging and Building the Pond for the Mallard Ducks and Ducklings, Runner Ducks and Ducklings, and Call Ducks and Ducklings, Khaki Campbell Ducks and Ducklings, and the Duck House, Muscovy Ducks and Ducklings. On, 11 April 2010, I'm Can Building the Dog Kennel with Mummy, Daddy, [LMS name], and [NMAAJSD name], and Take my Camera, Hammer, Drill, Spanner, and Tools, and the Bricks, and the Roof
The ducks are a long-lived interest, but this is mostly about Bob. Building is the thing: he's been talking about plans like these for a while and I think it's got worse since last weekend when we spent a happy session with hammer, screwdriver, assorted fasteners and some scrap wood.

If it all seems a tad ambitious, well yes. But it's not as bad as his plan for 2011 which is a DLR extension, or 2020 which is completion of the HS2 link. That's the trouble with Infrastructure projects -- they take so long.


Strange email a few days ago -- a casual note from one of the Exchange admins asking me to approve enabling a batch of accounts. Rather than just refuse it out of hand, I took a look at the list -- to find a mixed bag of service accounts and shared mailboxes.

For why? Well it appeared that they had been having difficulty archiving some boxes and noticed that the affected accounts were all disabled. Proof of a good reason? No. Plenty of other boxes are disabled -- our leavers process depends on archiving the boxes of disabled users, and shared box accounts are permanently disabled by policy.

I don't know how this will turn out, but it won't be fixed by the enable flag. I don't care, as the lesson I want to draw is a little different. Superstition in IT is one of the greatest impediments to security rectification.

If I had let that request go -- after all, what do I know about Exchange? and even if I was right, they might have learned something -- If I had followed a cautious "support the admins where you can" rule, a new superstitious belief would have been created. "If there's an archive problem, make sure the mailbox is enabled". And those boxes would never be disabled again -- after all, who goes looking for trouble? And we would have acquired a vast new list of unmanaged accounts for no purpose at all.

When I started, my first rectification was to get rid of the shared domain admin account. It was easy enough to issue DAs to colleagues who needed them, but the next stage, removing the shared account, was much harder. It was protected by superstition. Apparently, all sorts of stuff would break if I canned it or changed the password, it had been tried once and bad things happened, though nobody could remember what.

Now, that risk was real, given the usage of the account, but I knew the possibilities. It wasn't the replication account, it wasn't used to build images, and there were no services running under it (that one took a script to prove). So after a good deal of fruitless argument, I just did it -- our change control was weaker then. Nothing broke then and I suspect that what broke in the past was co-incidence

The point is that people who are out of their depth, even just a few inches, will clutch at the first turd that comes bobbing by, and once clutched, they'll never let it go. It's not a moral fault, it's a feature of human psychology, and no doubt in the wild it has survival value.

In Windows security, most people are just slightly out of their depth, even though it's pretty simple (apart from ACL inheritance, obviously.) Even though they could reach the truth with just a little effort, they don't. Instead they seize whatever comes first -- co-incidence or just wrong observation -- and their survivalist mind starts building superstition. It's my job to knock it down and I do. I don't like pretending to be authoritative, even though I took the training. But in a case like this, it's the only way forward. I declined the request, explained my reason as far as I could without accusing the team of crass irrationality, and left it at that. We'll see.


Bang per Buck

This is interesting. It's not a surprise that Iran wants to make a deal with a foreign oil major. No. The shock is the claim that a totally DIY nuclear programme, in the face of embargoes and secrecy, is cheaper than building out domestic oil production. That can't be good news.


I'm doing up a flat in the evenings, and there's enough work that I can't see an end to it. This morning I found myself peeping through the kitchen door on the off-chance that brownies had re-decorated or at least washed the greasy walls during the night. They hadn't.



The drought has parched the fields for months, and now the full moon light bleaches them bone white.

Fantasy Programming

I work at the command line, and I've never found a better place to do stuff in bulk. But since I've been dealing with dynamic networks of hundreds of PCs I've found that there's a tool missing from the utility set.

Windows is good for remote management -- better than people realise, but there's one thing it needs -- a decent network enumerator. What's that? It automates a task which crops up time and again -- running a command against a list of all the machines in a domain, or on a network, or subsets of those lists. I want to be able to type enumerate --domain MYDOMAIN.LOCAL --exclude "/(DC.*)|(PRNT.*)/" /cmd "mycommand %%Name%% %%Timestamp%% I think that's fairly clear: I want to enumerate the domain MYDOMAIN, exclude the DCs and those pesky HP print servers, and then, for each machine, run the command mycommand with the name of the machine and a timestamp on its command line.

I know that would be useful because I actually coded "enumerate" in Perl, and I use it a lot. But doing stuff in Perl has a limited future and I don't think there's really a pressing need to make it an editable script: the function seems rounded and complete -- not something that'll need continuous extension. So, as a first step to a .Net executable, here is my specification for the enumerate utility:


 Enumeration settings
 All these settings can be combined and repeated to build up a list of hosts.
 Each entry is expanded into FQDN and IP and de-duped on both, with the last entry taking precedence.
 [--domain DN] Add all members of domain DN to the list.
 [--IP N/L|IP1-IP2] Add all ip addresses in the specified subnet
      (omit network and BC) or the specified range to the list
 [--list H[, H]*] Add all the H's (names or IP addresses) to the list
 [--flist "path"] Add all the hosts in the text file at "path" 
      (one per line, leading "\\" optional, blank lines allowed, anything after white space on a line is comment)
 Logging settings
 [--job name] Log all dignostics to the file called TS_run_name and all command output to the file TS_out_name.

 Command Settings
 [--cmd "string" [--[no]ping] [--[no]browse] [--omit "regexp"] [--directory "path"] [--concurrent nnn]]
 Run the specified string in a cmd shell, for each enumerated target.
 Multiple --cmds are allowed.

 --directory : cd to "path" before running -- default is "."
 --[no]ping : ping the host -- don't run if no response. Default is --ping
 --[no]browse : attempt to Windows browse the host -- don't run if no response. Default: --nostart
 --omit : don't run if the enumerated name or IP matches the given regexp (no //). Default: --omit ""
 --concurrent nnn : Run no more than nnn instances of this --cmd setting concurrently. Default: --concurrent 1

 "string" is the command to run. Default is "echo %%Host%% %%IP%% %%TS%%"

 Variables in the command string are expanded:
 %%Host%% -- The enumerated FQDN or IP address if it can't be resolved
 %%IP%%   -- IP address -- skip if a name can't be resolved
 Times -- all suitable for use in file names:
 %%Date%% -- The date the run started in ISO yyyy-mm-dd format
 %%Time%% -- The time the run started as hh-mm-ss
 %%TS%%   -- Now as yyyymmddhhmmsscc
Now that's a utility.


Spam Counter - 2009 September: 818

More phishing than usual.