Puppet: Error 400 on SERVER: undefined method `empty?’ for nil:NilClass

I received this error after making some changes to a Hiera config and the referenced “dev-server” role.

Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Error from DataBinding 'hiera' while looking up 'role::dev-server::use_ssl': undefined method `empty?' for nil:NilClass on node servername.local

Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run

It turns out this is a vague syntax error. Checking the following has worked for me:

  • Ensuring the syntax of your Hiera YAML or JSON file is correct. Check for trailing commas in JSON, or misplaced colons. (“foo:bar”, “foo::bar:”, “foo:::bar”, etc.)
  • The variable name is unique. In one case, “dev-server::use_ssl” was configuring a child resource with the same “use_ssl” property/param/variable.
  • There are no empty YAML or JSON files in your hieradata directory. I think I’ve had a similar issue with temp files (*~)
  • If you’ve modified your hiera.yaml to add a new hierarchy or something, restart Puppet.
Puppet: Error 400 on SERVER: undefined method `empty?’ for nil:NilClass

CryptoPHP – A WordPress backdoor in social.png


This is a series of posts on CryptoPHP, a PHP backdoor used for spamming and blackhat SEO. It seems to come bundled with certain copies of WordPress themes from unofficial sites and resides in a file named “social.png”. It comes installed with a list of email addresses and domains to contact and communicates with a C2 server using cURL and OpenSSL for encryption. Its main purpose appears to be to facilitate the display of links and other content, sent from the C2 server. When the script determines that a web crawler (e.g., GoogleBot), and not a real user, is viewing the site, it injects links to third-party sites in hopes of being indexed.


CryptoPHP communicates with external servers, requiring multiple external requests. You may see the following symptoms:

  • WordPress is slow to load, especially during the first pageview
  • Error messages in your server log, possibly due to failed requests.
  • Error messages from IDS/IPS or other security software (e.g., Suhosin) indicating that someone is making calls to exec and eval.


A few days ago, I noticed that a WordPress installation was running extremely slowly. After enabling xhprof and profiling the index page, I noticed that a single method (RoQfzgyhgTpMgdUIktgNdYvKE) was taking around 160 seconds to run. The method name (others in the stack were similarly named) and the 23 calls to curl_exec came off as immediately suspicious. I used grep to search for the file and found it under the themes folder as images/social.png.

This file was included at the bottom of a theme file, causing it to be executed on each page load.

<?php include_once(‘images/social.png’); ?>

Opening social.png in a text editor reveals obfuscated and minified code. While it looks like a mess, it’s simply renamed variables and functions with whitespace removed, and can be undone rather easily with the “Find/Replace All” feature of your favorite text editor.

Obfuscated CryptoPHP


How to Remove CryptoPHP or social.png

In the limited tests that I’ve done, the offending file – social.png – is the only file that is malicious. It seems to be added to the images/ directory in themes downloaded from unofficial sources. Another line in the main theme files (index.php, header.php or footer.php) includes the file.

While nothing in the file itself indicates that personal or sensitive data is being transmitted back to the server, the file allows its controllers to send commands to it. These commands are then executed by the eval and exec commands in PHP. It is theoretically possible for content, account information, etc. to be transmitted back to the controlling server.

Since the WordPress instance I was using was running on localhost, it would have been unreachable by the controlling servers. It could still phone home and download commands, but could not be controlled directly.  However, due to the possibility of sensitive data being stolen, and the evidence of storing information in the database, I’d recommend a complete re-install of WordPress and changing your admin password(s).

Coming Soon

  • Encryption methods (including a script to decrypt database contents)
  • Detailed/technical review
CryptoPHP – A WordPress backdoor in social.png

What is Google foo.bar?

A week or two ago, the following popped up on my screen during a search for a Python-related topic:

You're speaking our language. Up for a challenge?

I had seen this before after our CTO got the same mysterious message a few months ago. We initially thought it was another one of Google’s Easter eggs, but a quick search revealed that everyone from HN and Reddit to Business Insider seems to think it’s a recruiting move by the search giant. (A similar program was rumored to be a search for cryptoanalyists, but turned out to be related to The Imitation Game, so who knows?)

Update: it is recruiting portal. Both of us were contacted by Google and interviewed on-site. The actual interview is under NDA, but I’ll post more about the interview process itself later.

The first time around, we discovered that replicating the query doesn’t necessarily trigger an invite, and visiting the URL without an invite doesn’t work. It was suggested that the invites are sent to a subset of users who have enabled search history. When I got the invite a week or two ago, I registered and then hit the “Back” button. The query string was preserved, so we tried an experiment: Is the invite based on a tagged query string, or the result of some back-end processing? After sending the URL to a couple of coworkers who had not received an invite after searching the same query, they tried accessing the URL directly. We learned two things:

  1. Both of them subsequently received an invite.
  2. One of them hit “refresh” as the animation began to show the box, and no invite was shown upon refresh. Opening the link in an Incognito window gave him a second chance.

The most likely scenario is that certain queries redirect to the results page with a query string, which triggers the message. Since neither of the other developers write lots of Python, but still got an invite after visiting the link, it’s likely that Google doesn’t validate invitee status. I doubt this is a simple oversight, and more likely indicates one of two things:

  1. Invitees are not on some sort of pre-selected list; and/or
  2. Google isn’t worried about additional invitees.

The latter was proven when the program displayed a “refer a friend” link. Assuming the recruitment theory is correct, it’s likely that Google is operating under the assumption that high-quality developers will refer other high-quality developers. I don’t know for sure, but this is probably a valid assumption.

To clarify some of the speculation, I was asked if I’d like a Google recruiter to contact me after completing the first six challenges.

Well, there goes that theory.

Others have asked Google directly about the program, and received a Python snippet that prints “glhf” in response – essentially “no comment”.

A Quick Tour

The pseudo-terminal responds to *nix commands like ls, cat and less and features its own editor. Listing the directory shows a textfile

Contents of start_here.txt
Contents of start_here.txt

The help menu offers several possible commands:


The levels consist of at least 5! challenges, split into 5 levels where each level n has challenges. Challenges fall into one of five categories, or tags.
Google Foobar Tags

Unfortunately, there has only been one crypto challenge available so far, and I haven’t been able to score a low_level challenge.  Most of the challenges I’ve completed so far involve one-off applications of computer science problems – like whiteboard interview questions with a twist. Additionally, there are constraints on execution time and memory use, which prevent some naive implementations from passing the test cases. This speaks to the needs of a company like Google who requires, or at least desires, efficient implementations rather than generic Algorithms 101 approaches.

I’ll be posting my solutions to GitHub shortly, along with some explanations here.

What is Google foo.bar?

Pennsylvania Adopts Critical Care Transport Scope

Today, Pennsylvania announced the scope of practice and medication list for Critical Care Emergency Medical Service Providers. Unfortunately, all of the skills and medications listed apply to interfacility transports and/or must be performed in the physical presence of a PHRN/PHPE/PHP.

Critical Care Scope of Practice

Category Skill Critical Care Transport Provider (Paramedic, PHRN, PHPE or PHP)
8 Airway/ventilation/oxygenation Chest tube thoracostomy, monitoring of existing tube in a closed system (for example water seal or suction) Yes1
9 Airway/ventilation/oxygenation Chest tube thoracostomy, acute insertion Yes2
12 Airway/ventilation/oxygenation Biphasic positive airway pressure (BiPAP) for patients acutely on BiPAP for <48 hours Yes1
24 Airway/ventilation/oxygenation Endotracheal Intubation—paralytic assisted, rapid sequence induction (RSI) Yes2
25 Airway/ventilation/oxygenation Ventilation—Maintenance of previously initiated neuromuscular blockade Yes1
28 Airway/ventilation/oxygenation Laryngeal mask airway (LMA) Yes1
49 Airway/ventilation/oxygenation Ventilators, transport—single or multi-modal, with or without blender, using volume control mode only, on patients >1 year of age with no anticipated need to actively titrate ventilator settings during transport. Yes1
64 Cardiovascular/circulation Transvenous or Epicardial pacing, Management of Yes2
66 Cardiovascular/circulation Hemodynamic monitoring/assist (pulmonary artery catheter, central venous pressure) Yes2
67 Cardiovascular/circulation Intra-aortic balloon pump or invasive cardiac assist device or extracorporeal membrane oxygenation—monitoring/assist Yes2
69 Cardiovascular/circulation Thrombolytic therapy—initiation Yes2
70 Cardiovascular/circulation Thrombolytic therapy—monitoring Yes2
77 IV Initiation/maintenance/fluids Sub-cutaneous indwelling catheters—access of existing catheters Yes1
79 IV Initiation/maintenance/fluids Venous central line (blood sampling)—obtaining Yes1
81 IV Initiation/maintenance/fluids Arterial line—monitoring Yes1
82 IV Initiation/maintenance/fluids Blood products—initiation and continued administration Yes2
94 Medication administration routes Enteral Feeding Devices, Management of Yes1
103 Medications Medications for Critical Care Transport Providers as published in Pennsylvania Bulletin by the Department Yes1
105 Medications Over-the-counter (OTC) medications (Note: aspirin and glucose covered elsewhere) Yes1
112 Patient Assessment/management Portable blood analysis devices, use of (glucometer covered elsewhere) Yes1
121 Patient Assessment/management Intracranial pressure monitoring/assist Yes2
126 Patient Assessment/management Urinary catheterization Yes1

Yes—The skill is in the scope of practice for paramedics, PHRNs, PHPEs and PHPs who are authorized to function for an EMS agency that has been licensed as a CCT ambulance service. (Emphasis added)

1. Paramedics, PHRNs, PHPEs and PHPs who are authorized to function for an EMS agency that has been licensed as a CCT ambulance service may only perform or assist with these skills during interfacility transport with a CCT ambulance. (Emphasis added)

2. Paramedics who are authorized to function for an EMS agency that has been licensed as a CCT ambulance service may assist a PHRN, PHPE or PHP with this skill only during interfacility transport with a CCT ambulance and when in the direct physical presence of, and supervised by, the higher level provider. (Emphasis added)


Critical Care Medication List

  1. Abciximab2
  2. Albumin1,2
  3. Anti-Coagulants/Anti-Platelets: All Types (Not otherwise specified)1,2
  4. Anti-Emetics: All Types (Not otherwise specified)1.2
  5. Anti-Hypertensives: All Types (Not otherwise specified)2
  6. Antivenom1,2
  7. Atenolol1,2
  8. Barbiturates2
  9. Bivalirudin2
  10. Blood Products2
  11. Clopidogrel2
  12. Dextran1,2
  13. Digoxin2
  14. Dilaudid2
  15. Eptifibatide2
  16. Esmolol2
  17. Fibrinolytics/Thrombolytics: All Types2
  18. Glucocorticoids/Mineralcorticoids1,2
  19. Heparin2
  20. Hespan1,2
  21. Hydralazine1,2
  22. Hydroxocobalamin1,2
  23. Insulin2
  24. Ketamine1,2
  25. Ketorolac1,2
  26. Labetolol1,2
  27. Mannitol2
  28. Metaproterenol1,2
  29. Metoprolol1,2
  30. Milrinone1,2
  31. Non-Depolarizing Agents1,2
  32. Norepinephrine2
  33. Other Non-Benzodiazepine Anti-Convulsants2
  34. Phenylephrine2
  35. Phenytoin/Phosphenytoin1,2
  36. Plasmanate1,2
  37. Potassium Chloride2
  38. Propofol1,2
  39. Propranolol1,2
  40. Prostaglandins: All Types2
  41. Quinidine Sulfate/Gluconate2
  42. Romazicon2
  43. Succinylcholine2
  44. Theophylline1,2
  45. Tirofiban2
  46. Tocolytics: All Types (Not otherwise specified)2
  47. Total Parenteral Nutrition2

1. Paramedics who are authorized to function for an EMS agency that has been licensed as a CCT ambulance service are restricted to the maintenance and monitoring of medication administration that is initiated at the sending medical facility. (Emphasis added)

2. Paramedics who are authorized to function for an EMS agency that has been licensed as a CCT ambulance service may only administer the medication in the direct physical presence of, and supervised by, a PHRN, PHPE or PHP. (Emphasis added)


Pennsylvania Adopts Critical Care Transport Scope

Visual Binary File Analysis with Python

Update: Added a colorize function:

With colorize

Here’s a quick Python script to visualize binary data. In the grayscale example, each pixel is the color of the bit value (0x00 – 0xFF). The same method is used for colorization, except the bit value is used to provide hue and value values for HSV colorspace (saturation is fixed at 0.99).

The cols parameter is the width of the image to be generated (in pixels). By default, the script generates a couple of different sizes. The height is calculated based on the width. Patterns tend to be clearer when the column width is a multiple of 8 (16, 32, 64, 128…), though that could depend on the format and type of data in the file.

As an example, here are some images from a 256-byte file generated with the following Python program:

with open('foo.txt', 'wb') as fd:
    for i in range(256):

Bytes in range(0,256)


./process_dir.py <dirname> <cols>

The program will generate images for each of the binaries in the specified directory, create an “index.html” file and attempt to launch it in the browser.


The generated image on the left is from a PNG file. A dark patch in the beginning with a mostly-uniform distribution is consistent with file headers followed by image data.

The image to the right is an OpenOffice Writer file. The striped area indicates a repeating pattern of bytes, which often separates the metadata header and content in word processor files. The example screenshot shows an image generated from a compiled binary.

This can also be used to visually approximate the amount of entropy in a file. A high-entropy file would have a uniform byte distribution, thus occupying all of the available colorspace. I’ll include a histogram function later. This would show the frequency distribution of the bytes as well.

Compare the outputs of the following files:

  • An MP3 file
  • /dev/urandom
  • A TrueCrypt container (AES with RIPEMD-160)
  • A plain text file
MP3 File
MP3 File
Data from /dev/urandom
TrueCrypt container

Visual Binary File Analysis with Python

InfoSec Institute – CTF Level 12

This is a walkthrough of InfoSec Institute’s CTF challenge, Level 12.

As I mentioned in some of the other walkthroughs, the first step is to look through the source code for anything that’s out of place. After that, I typically evaluate the headers and other responses (with Chrome’s developer tools) and proceed from there. Anything that the site loads will be revealed in the “Network” tab, so it’s a pretty good source of information that’s always available.

In this level, the file “design.css” was out of place. Viewing the contents showed an invalid CSS statement:

This is not a color

In CSS, colors are typically specified with their hexidecimal value. (There are a couple of other acceptable formats, but that’s irrelevant for now)

Load that string into a Python interpreter, and use the built-in “decode” function. Pretty intuitive, yeah?

The flag also states the obvious.

InfoSec Institute – CTF Level 12

InfoSec Institute – CTF Level 11

This is a walkthrough for InfoSec Institute’s CTF Challenge, Level 11.

The only immediate difference between this and level 10 is the addition of a grainy PHP logo.


Grainy images are one indicator of steganography, so I proceeded along the route of checking for readable strings. Using the strings command again revealed the flag instantly (but read on!). However, opening it in emacs revealed that it was in the header of the image file.

Raw data

This is hardly the same as steganography, which hides the message in the image data. This flag is hidden in the image’s EXIF (Exchangable Image Format) data, which provides metadata about the image. If you have exiftool installed (apt-get install exiftool, IIRC), you can get the same information:

exiftool php-logo-virus.jpg | grep -i infosec

Exiftool Output

The “document name” field contains the string, plus two additional bytes. If you had trouble viewing the image properties, it was likely because the viewer wasn’t prepared for the extra bytes at the end of the string. Remember, the “strings” command only reveals printable characters.

Raw data

Depending on whether or not the flag includes the extra bytes, there are two options:




Bytes 240 and 206 are outside of the printable range, and not valid Unicode, as they’re missing the BOM. The control characters correspond to the end of the field, which is NUL-terminated. These characters are present because of the way emacs is forced to display something, but you can see the true value with a hex editor. I used hexedit in the following screenshot:

Hex Editor View

The additional unprintable characters are in red and NUL bytes in yellow.  Since the bytes are part of the field (as far as any EXIF parser is concerned), these bytes are part of the field. That leaves us with bytes A0 86 01 unaccounted for.

Note: Your raw data may differ from mine, due to endianness. If your hex editor displayed this, it’s correct, but you’ll notice each pair is switched.

          6e69 6f66 6573 5f63 6c66 6761
7369 615f 5248 6330 6f44 4c76 6433 6433
3579 6279 7832 5a73 4a58 617a 6b32 5975
3832 6475 7357 6176 3157 5a68 5632 597a
3969 6277 6433 636c 4e6e 6173 5257 586c
7832 5a76 3932 6266 4647 5a79 5532 5a75
6c32 a06d 0186 0000 0100

Before we cross over the threshold into text-encoding hell, extended ASCII sets, control characters, and all the levels dedicated specifically to Unicode, let’s take a step back. (Sorry guys, I only led you down this road to take a look at the actual contents of the field!)

Occam’s razor says the field was obfuscated to prevent what I’ll dub a “View Properties Attack”, and we’re dealing with a printable-characters-only string. This is a n00bs challenge, afterall.

Although it lacks the characteristic ending equals signs of a base64-encoded string, the flag we have does contain a valid base64 string. (The ending == signs are for padding, and not always present.)

Decoding that string yields the following URL:


Which links to the following image:



  • infosec_flagis_\x61\x48\x52\x30\x63\x44\x6F\x76\x4C\x33\x64\x33\x64\x79\x35\x79\x62\x32\x78\x73\x5A\x58\x4A\x7A\x61\x32\x6B\x75\x59\x32\x38\x75\x64\x57\x73\x76\x61\x57\x31\x68\x5A\x32\x56\x7A\x59\x69\x39\x77\x62\x33\x64\x6C\x63\x6E\x4E\x73\x61\x57\x52\x6C\x58\x32\x78\x76\x5A\x32\x39\x66\x62\x47\x46\x79\x5A\x32\x55\x75\x5A\x32\x6C\x6D\xA0\x86\x01
  • infosec_flagis_aHR0cDovL3d3dy5yb2xsZXJza2kuY28udWsvaW1hZ2VzYi9wb3dlcnNsaWRlX2xvZ29fbGFyZ2UuZ2lm
  • infosec_flagis_http://www.rollerski.co.uk/imagesb/powerslide_logo_large.gif
  • infosec_flagis_powerslide



InfoSec Institute – CTF Level 11

InfoSec Institute – CTF Level 9

This is a walkthrough for InfoSec Institute’s CTF challenge, Level 9.

The challenge presents with a login screen for a Cisco Intrusion Detection System (IDS). I tried a few typical username/password combinations (root/root, admin/password, etc) before googling “Cisco IDS default password”.


Sure enough, ‘root’/’attack’ worked, and the flag was given in a popup box:Infosec_flagis_?

At first glance, this looks like the string presented in their Level 4 CTF challenge, but the character spacing is all wrong. We already determined that they’re using the format “infosec_flagis_?????”, and they’re unlikely to change the grouping since it helps identify the flag in a CTF event.

The flag is presented in plaintext, but reversed. To undo this, use the “rev” command in Linux, which reverses a string passed into it:

echo "ssaptluafed_sigalf_cesofni" | rev

Answer: infosec_flagis_defaultpass

InfoSec Institute – CTF Level 9

InfoSec Institute – CTF Level 8

This is a walkthrough on Level 8 of InfoSec Institute’s CTF challenge. The challenge begins by asking if you’d like to download “app.exe”. Since I’m not about to run an untrusted *.exe file (and I’m on Linux anyway), I decided to open it up in emacs. The flags follow a common format, so performing a string search can’t hurt:

Screenshot from 2015-03-22 17:21:41

Well, that was easy.

This can also be done with the strings command, which prints strings of printable characters. Binary files do have quite a few readable characters, so combining strings with grep shouldn’t hurt (the -i flag means case-insensitive search):

strings app.exe | grep -i infosec

Gives the output:

Screenshot from 2015-03-22 17:27:40




InfoSec Institute – CTF Level 8