Category Archives: Uncategorized

Override Jenkins stage Function

Recently, I needed a mechanism to identify, as part of a try/catch block, which stage in a Jenkins Groovy Scripted Pipeline was the last to execute before the catch block was called.

Jenkins does not currently store details about the last stage to run outside of the context of that specific stage. So, in other words env.STAGE_NAME is valid with a particular stage("I'm a stage"){ //valid here} block, but not in, say, a catch(Exception e) { // where was I called from? } block.

To get around this, I found a few examples, and cobbled together something that I believe will provide future functionality. I present to you the extensibleContextStage:

// Jenkins groovy stages are somewhat lacking in their ability to persist 
// context state beyond the lifespan of the stage
// For example, to obtain the name of the last stage to run, 
// one needs to store the name in an ENV varialble (JENKINS 48315)
// https://issues.jenkins-ci.org/browse/JENKINS-48315

// We can create an extensible stage to provide attitional context to the pipeline
// about the state of the currently running stage.

// This also provides a capability to extend pre- and post- stage operations

// Idea / base code borrowed from https://stackoverflow.com/a/51081177/11125318
// and from https://issues.jenkins-ci.org/browse/JENKINS-48315?focusedCommentId=321366&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-321366

def call(name, Closure closure) {
    env.BUILD_LAST_STAGE_STARTED = name
    try {
        stage(name) {
            def result = closure.call()
            return result
        }
        env.BUILD_LAST_STAGE_SUCCEEDED = name
    }
    catch(Exception ex) {
        env.BUILD_LAST_STAGE_FAILED = name
        throw ex;
    }
}

This is a drop-in replacement for stage(string name){ closure} blocks in a Jenkins Groovy Scripted Pipeline, but with the added benefit of additional environment variables:

  • env.BUILD_LAST_STAGE_STARTED
  • env.BUILD_LAST_STAGE_SUCCEEDED
  • env.BUILD_LAST_STAGE_FAILED

So, as a full example, one can now do this (which was previously awkward):


try {
    extensibleContextStage("Do some things")
    {
        //whatever
    }
    extensibleContextStage("Do some More things")
    {
       throw new Exception("MAYHEM!")
    }
    extensibleContextStage("Do some final things")
    {
        //whatever
    }
}
catch(Exception e){
    // at this point, with normal stage, we wouldn't know where MAYHEM came from,
    // but with extensibleContextStage, we can look at either
    // env.BUILD_LAST_STAGE_FAILED or  env.BUILD_LAST_STAGE_STARTED
    // to know that "Do some More things" was the offendign stage.
    // this is super handy to send "helpful" notifications to slack/email
}

I hope this helps someone (if even my future self)

Windows 10 Password Recovery

DISCLAIMER: DO NOT EXECUTE THIS PROCESS WITHOUT EXPLICIT APPROVAL FROM THE SYSTEM OWNERS.  I AM NOT ENDORSING OR APPROVING ANY ILLEGAL ACTIVITY WHICH COULD BE ACCOMPLISHED FOLLOWING THESE STEPS

An older friend forgot his computer password; asked me for help.

I booted the machine, and saw an email address where the Windows 10 username normally would be;  my first thought was “oh, great; this is a Microsoft Online  joined computer, password recovery probably won’t happen”

I did a little research, and found some evidence that suggests my seemingly outdated knowledge about passwords being stored in the SAM seems to still stand.  However, Windows 10 Anniversary Update changed the encryption algorithm used on the SAM: https://twitter.com/gentilkiwi/status/762465220132384770

This algorithm change broke my normal tool (OPHCRACK), since it was unable to read the NTLM hashes from the SAM.  SAM encryption caused OPHCRACK to incorrectly read every account hash as 31d6cfe0d16ae931b73c59d7e0c089c0.  So, I copied the SAM and SYSTEM files (at C:\Windows\System32\config) from the target machine to my desktop for additional processing.

Mimikatz has a module `lsadump::sam` which accepts parameters for offline SYSTEM and SAM decryption.  Easy command line:

lsadump::sam /system:c:\users\charles\documents\system /sam:c:\users\charles\documents\sam

This returned decrypted NTLM hashes for easy cracking.

I decided to try a new tool here to crack the plain text password from the NTLM hashes: Hashcat.  There’s a Windows 64bit compiled version (I know, I know don’t run random binaries…) which made it easy to get cracking quickly.

I copied the hash from the output of Mimikaz into a text file called hashes.txt and ran the command

.\hashcat64.exe -m 1000 -a 3 -O -o pass1.txt .\hashes.hash

My 10 year old computer cracked the Microsoft Online account NTLM Windows 10 password hash in ~8 minutes. It was two dictionary words and a two-digit number for a total of 8 characters.  I was using brute-force in this scenario, so the fact that dictionary words were used is of no consequence.  Had I been using a dictionary, the attack would have likely concluded sooner.

Just for fun, I generated a new NTLM hash, but replacing vowels with numbers (i with 1 and the e with 3 and so fourth), the attack took the same amount of time.


import hashlib
print hashlib.new('MD4', 'password'.encode('utf-16le')).hexdigest()

Moral of the story:  USE STRONG PASSWORDS AND A PASSWORD MANAGER

Let’s Encrypt Setup

The “Let’s Encrypt” setup process is very painless – Just clone a Git repo, run a comand, and edit some apache config files.

  1. sudo apt-get install git
  2.  sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt
  3. cd /opt/letsencrypt
  4. ./letsencrypt-auto –apache -d ccrossan.com -d www.ccrossan.com
  5. edit the sites-enabled config files so that the appropriate virtual host uses the correct ssl certs.
  6. delete the newly generated ssl.conf file
  7. restart apache
  8. [Optional] Set up Cron for auto-renew
  9. sudo crontab -e
  10. 30 2 * * 1 /opt/letsencrypt/letsencrypt-auto renew >> /var/log/le-renew.log

 

These commands taken from the DigitalOcean Let’s Encrypt Setup Guide