Sunday, April 25, 2021

How {goo,ba}d can a $20 smart watch be?

Back in December, I plunked $20 down (plus an additional $7 to cover tax and shipping) to preorder a new watch from Wyze (cleverly called: Wyze Watch). You might know Wyze from their inexpensive line of cameras, outlet controls, smart bulbs, and other internet-of-things devices. They make quite a few items and keep updating and adding new ones to their offerings. The watch caught my eye because it 1) was only $20 and 2) looked pretty decent (both physical design and features) for an inexpensive “smart watch”. I’ve been wearing the watch and using it regularly for over a month now, thought I’d write up a bit on it.


A couple of things to note up front.  The most recent “watch” I’ve worn regularly is a FitBit Alta, that is to say I haven’t had an Apple Watch or other smart watch to compare the Wyze Watch against. Additionally, I won’t be covering some areas of functionality because I don't own other Wyze products to test integrations with, nor did I enable the Android app permissions to access phone data/functionality (erring on the side of caution, as I’m not sure how well Wyze protects my data and how secure their app and watch are).


First impressions and beyond


The watch arrived in a nice little box with a USB (type A) charging cable and small Quick Start guide:


Simple, no frills...

The “watch end” of the charging cable is magnetized (sorta like MagSafe, but not reversible), and everything seemed intuitive to figure out for charging and basic usage.  There are also iOS and Android apps available to really get the most out of your purchase.  The watch body is gray aluminum, offered in two face sizes (44mm and 47mm; I bought the latter), and the default band is black silicone, though they have some others you can order (including a couple of leather variants):


From the front...


From the back...

The watch has only one button (along the right side of the face), which you can use to turn the display on or off (it also supports a “wake on raise” behavior which turns on the display for a couple of seconds when you raise your wrist to check the time).  The default screen on wake is the clock (which has a customizable "face" with many designs they offer, or you can use your own pictures with the time overlaid on top; the watch itself can only store three faces at any time, but it’s easy enough to download new ones from the app).  From the clock, you can swipe right to access your current daily activity data:


Datums...

Or, from the clock screen, swipe up to see battery life, screen brightness (3 levels, no “adaptive” option), do not disturb, and a “find my phone” option --lower right-- that will make your phone ring/vibrate if it’s within bluetooth range:


Settings...

And if you swipe left on the clock screen, you see the apps, which appear to be built-in with the firmware version (and the watch firmware is upgradeable via the app):


Apps...!

Some of the app highlights include getting your oxygen saturation levels and heart rate.


I found the Android app to be pretty user friendly.  Seems that it works with many other Wyze products, but all I have is the watch...


Main page, lists all your Wyze devices...


"Watch" page...


Data view in the app...

The app also supports a "find my watch" function, that will vibrate your watch if it's within bluetooth range (so listen closely!).

How's it holding up?


Wearing the watch and messing with it over a month now has surfaced some things I like and don't about it...

Pros

  • Affordable - $20!
  • Looks nice - the aluminum body and assembly seem to be solid and visually "works well" with the black silicone band.
  • Takes a beating - I've accidentally slammed this into hard countertops quite a few times now, neither the glass nor aluminum body show any evidence of these abuses.
  • Comfortable, considering the band is plastic-y - I'm not a huge fan of silicone bands on my wrist, but I find it to be not uncomfortable.

  • 7+ days between charges - that is with regular walks each day, and it recharges pretty quickly (caveat would be that I didn't test using it for email or text notifications and such)

  • Regular weekly email comms on status of preordered products - Wyze keep folks in the loop on how the preorders were coming along with once-a-week emails, was really nice.

Cons

  • When running an app, you can't get back to the clock without leaving the app (annoying).
  • Scrolling response via touch is a bit choppy.

Unknowns

  • Wyze privacy and security postures (both app and device) - I'd love to have tried the email/text/call notifications, but opted not to without having more data on how Wyze positions itself (and executes!) on privacy and security.
  • Integrations with other Wyze products - I didn't have any to test these capabilities with.
  • Accuracy of heart rate and oxygen saturation readings - I didn't have something "more authoritative" to check them against, and if you don't wear your band tight, these readings will lose accuracy.


All that to say...

For the money, it's quite a nice little watch if you want something that has good battery life, looks nice, and you don't need it to stream music (or other similar advanced features that more expensive smart watches can do).  In addition to app and watch unknowns around privacy and security, I'd be reluctant to put my faith into the oxygen saturation and heart rate reading accuracies without further vetting/testing.  But for my $20, it is a nice little watch (so far)...

Sunday, November 29, 2020

Open-source USB Duck-like Device

I thought it would be fun to wrangle together a device that acts similarly to the HAK5 USB Rubber Ducky (i.e. presents itself as a USB keyboard device and interacts with the target by sending rapid keystrokes), but is flexible w.r.t. abilities+implementation (and maybe cheaper!).  In addition to just scripting keystroke commands, my bigger goal was to be able to transfer files (payloads? ¯\_(ツ)_/¯) to targets, even if restrictions are in place (like USB mass storage devices being prohibited by a policy applied in the target OS).  Using a Raspberry Pi Zero (NOTE: I will include archive.org "wayback machine" snapshot links as wbm alongside all links here in an attempt to preserve-references-over-time for this post as much as possible) that I had lying around (a $15-or-less device to purchase online), an old microSD card, a leftover button, a tiny bit of solder, and a number of helpful guides/programs I found online, I cobbled something together:

Voila, end result...!

And when you connect it to a target computer/device's USB and press the button, it sends your data as keystrokes on a keyboard:

Animation from a macOS terminal...


Android phone Termux app screenshot of it working...

In this post, I'll cover all the steps I took to get this working and share some things I learned along the way, but I'll caveat here that this isn't the most polished-of-guides.  😅

Enjoy! 

Poking Around...

As mentioned above, I started with a RPi Zero (Raspberry Pi Zero) that I had handy and an 8GB microSD card that was unused at that moment.  I located this handy guide online (wbm) that helped carry me much of the way that I wanted to go with this, helping break down the following order of steps:
  1. setup the microSD card with a bootable Linux image
  2. install the microSD card into the RPi Zero, boot it, login, and update password and hostname
  3. setup the RPi for keystroke goodness
  4. setup for payload delivery
  5. add a button (optional!)
  6. use!
I should note that, alongside my RPi Zero, I used a MacBook Pro running macOS 10.15.7, which all my steps below are written to, but nothing should prevent anyone from achieving success using Linux or Windows.

MicroSD Setup

Before we can use the RPi Zero, we need to provide an operating system that it can boot and use.  You'll need a SD-to-USB card reader (or a built-in SD card reader) to accomplish this.  I followed this guide (wbm) to download and use Raspberry Pi Imager to install Linux-based Raspberry Pi OS Lite (used to be called Raspbian, for y'all fellow old timers...) on the microSD card, which went something like this under macOS:

Writing Pi OS to the microSD card...

Once the microSD had the OS saved and verified, close the app and do the following:
  1. unplug the SD-to-USB card reader (or remove the microSD card slot from the built-in reader)
  2. replug the SD-to-USB card reader back in (or reinsert the microSD card into the built-in slot)
  3. note that a new /Volumes/boot drive is now mounted (this is the SD card!)
Then, via a terminal window, follow step numbers 6 and 7 from this site (wbm) to enable both SSH and a working connection to your WPA2-secured local WiFi network when the RPi Zero boots up.  Once you've done those, cleanly unmount the drive with

diskutil eject /Volumes/boot

and remove the microSD.  The microSD now ready for the RPi Zero!

RPi Boot and Setup

Follow steps 9 through 11 from from this site (wbm) to get the RPi booted up, log in via ssh, and change the account password and hostname (which you'll find under the Network Settings option).  Then reboot, and you should be able to access your RPi from a terminal prompt with
ssh pi@<hostname>.local

using the updated password you set.  Neat! 

Create the Illusion

At this point, you have a nifty RPi Zero that you can ssh to over the wireless network.  Slick!  Now let's add the special sauce that will make the RPi appear as a USB keyboard HID (human interface device) to an unsuspecting target.

Follow steps 1 through 3 from this guide (wbm), which utilize gadget and "libcomposite" functionality of the Linux kernel to have the RPi appear as a USB keyboard device.  Now you have the base pieces in place for your RPi to appear as a keyboard.  Getting closer!

At this point, gracefully power your RPi down with:
pi@fakekeyboard:~ $ sudo poweroff
Then connect the RPi to your laptop/desktop via the RPi micro USB port labeled USB (see the diagram in section 4 of the guide you were just using).  This will allow your RPi to have the full USB connection (data lines and all) to your system.  Once the RPi boots up (~35 seconds), if you get a macOS (or other OS) dialog pop up saying "hey, this is a keyboard, I need you to press some keys so I can identify it", just "cancel" to close that dialog out (worked for me under macOS, and I never got that dialog again).

Someone wrote a nice little C-based util (wbm) called scan for taking stdin and creating "keystrokes" out of it.  We'll pull the code down to the RPi and compile it (helpfully, our necessary build tools are already installed with Pi OS).  In a terminal window, ssh into your RPi do the following:
pi@fakekeyboard:~ $ wget https://github.com/girst/hardpass-passwordmanager-mirror-of-git.gir.st/archive/master.zip 
pi@fakekeyboard:~ $ unzip master.zip 
pi@fakekeyboard:~ $ cd hardpass-passwordmanager-mirror-of-git.gir.st-master/send_hid/ 
pi@fakekeyboard:~/hardpass-passwordmanager-mirror-of-git.gir.st-master/send_hid $ make
At this point, you'll have an executable scan program.  Do the following to verify if your RPi can now send keystrokes:
pi@fakekeyboard:~ $ echo "whoami" | sudo ./scan /dev/hidg0 1 0
This command will send the string "whoami" (which happens to be a Linux command for identifying which user you are) to the scan utility, which will translate that into keystrokes.  If all goes according to plan, you'll see something like this after you run that one line above:
pi@fakekeyboard:~/hardpass-passwordmanager-mirror-of-git.gir.st-master/send_hid $ echo "whoami" | sudo ./scan /dev/hidg0 1 0
whoami  
pi@fakekeyboard:~/hardpass-passwordmanager-mirror-of-git.gir.st-master/send_hid $ whoami
pi

So our one line command successfully sent scan the string "whoami" to send as keystrokes, which it did in the middle line above, which resulted in the pi output at the end (telling us we are Linux user "pi" on the system).  Neato, we're a keyboard!!  :)

Completing the Buildout

As mentioned in the intro, my goal is to copy a file (possibly a binary file) to the target.  In order to support binary files, we need to ensure we're able to properly convey the data via our "keyboard" keystrokes.  I went with base64 encoding/decoding (wbm) to achieve this, as it encodes data into a limited number of keyboard-supported characters (wbm), specifically 64 total characters (plus '=' for padding, so really 65!).  So the idea is this:
  1. base64 encode the payload you want to deliver
  2. setup the RPi to send that encoded payload to the scan utility (just like we did with the 'echo' command in the previous section)
  3. try it out!

Encoding the Payload

Many *nix-like OSes have a utility present called base64 which is handy for encoding and decoding base64.  The OS running on your RPi has it, so we'll just decide which file we'd like as a payload and copy it over there:
scp <payload filename> pi@<hostname>.local:
Once copied over, ssh into your RPi and base64 encode your payload with the following command:
pi@fakekeyboard:~ $ base64 -w0 <payload filename> > payload.base64

This will give you a base64-encoded version of your file (named payload.base64), which also takes on an additional ~33% more bytes in size compared to the file size, just FWIW.

Setup to Send

Let's now setup the RPi to, on boot, send our payload as keystrokes and then power itself off.  We'll use the following short script to do accomplish this:
#!/usr/bin/env bash

SCAN_CMD='/home/pi/hardpass-passwordmanager-mirror-of-git.gir.st-master/send_hid/scan /dev/hidg0 1 0'

echo "cat << EOF > /tmp/payload.base64" | sudo ${SCAN_CMD}
cat /home/pi/payload.base64 | sudo ${SCAN_CMD}
echo | sudo ${SCAN_CMD}
echo "EOF" | sudo ${SCAN_CMD}

exit $?
You can copy-and-paste the above and save it to your RPi as filename gogokeystrokes.sh, or you can ssh into your RPi and run the following command to pull it directly from my GitHub gists (wbm):
pi@fakekeyboard:~ $ wget https://gist.githubusercontent.com/pbarry25/50b5c409cbb14791e239790cff30b0c4/raw/2d6b6c884849daf7a88a4e5c8f408bce51e34ad5/gogokeystrokes.sh
Also, don't forget to make it executable!
pi@fakekeyboard:~ $ chmod +x gogokeystrokes.sh 
Now let's set things up so that our payload keystrokes happen automatically once the RPi is plugged into the target, and let's also nicely shutdown the RPi to avoid potential corruption to the filesystem.  Edit the /etc/rc.local file on your RPi to add two lines before the final 'exit 0' line in the file:
sleep 15
if [ "X`who | /bin/sed -n '/^pi/p'`" = "X" ]; then /home/pi/gogokeystrokes.sh; poweroff; fi
This should leave you with an /etc/rc.local file that has the last handful of lines looking like:
/usr/bin/isticktoit_usb # libcomposite configuration

sleep 15
if [ "X`who | /bin/sed -n '/^pi/p'`" = "X" ]; then /home/pi/gogokeystrokes.sh; poweroff; fi

exit 0

These two lines we added will, at the final part of the RPi booting up, wait 15 seconds to see if anyone has logged into the RPi as the 'pi' user via ssh and, if no one has, then run our gogokeystrokes.sh script to send the payload via keystrokes and then power down the RPi.  This allows the RPi to automatically deliver our payload when inserted to a target, while still allowing us to quickly ssh into the RPi on bootup if we want to update the payload or make other changes.

At this point, we should be able to power off the RPi, unplug, and reinsert it to see it "do the keystrokes" that will create a new file called /tmp/payload.base64 of our payload, exactly as we'll want it to do when we insert it into our target device.  But there's a small problem...

A Small Fly in the Ointment

Well, two small flies, actually...  First, the code in scan doesn't handle more than 256 characters being read in, meaning base64 encoded payloads larger than 256 bytes are truncated down to 256 bytes.  Welp, not helpful.  Second, scan will send its keystrokes as fast as it can, which is 1) very well above what humans are capable of and 2) because of #1, some OSes will become unresponsive at those high keystroke rates.

We can mitigate both of these issues, respectively, in simple fashion by 1) increasing the read buffer size to something "large enough" for our payloads to fit in and 2) add a delay between keystrokes.  If you ssh into your RPi, you can pull a "patch" of these two changes I made via GitHub (wbm) to bump the input buffer size to 25,600 bytes and add a delay-between-keystrokes equivalent to typing 200 characters-per-second, which yields about 1Kb of encoded payload data "typed" in 5 seconds:
pi@fakekeyboard:~ $ wget https://gist.githubusercontent.com/pbarry25/cbae67450bb5ecd16a2f5f5f99e410e5/raw/ad7b86140c5e18dbe766801bb325fe270967b0eb/main.c.diff
You can then apply that patch and rebuild scan:
pi@fakekeyboard:~ $ patch -p1 < main.c.diff 
patching file hardpass-passwordmanager-mirror-of-git.gir.st-master/send_hid/main.c
pi@fakekeyboard:~ $ cd hardpass-passwordmanager-mirror-of-git.gir.st-master/send_hid/
pi@fakekeyboard:~/hardpass-passwordmanager-mirror-of-git.gir.st-master/send_hid $ make
gcc -std=c99 -Wall -Werror main.c scancodes.c -o scan
OK!  Now we're ready to do a quick local test that it's working.  Run the following:
pi@fakekeyboard:~/hardpass-passwordmanager-mirror-of-git.gir.st-master/send_hid $ ~/gogokeystrokes.sh
If it's working, you should see a bunch of phantom typing in your terminal window.  And once your encoded payload has been fully "typed" out, you should get your prompt back and the newly-delivered encoded payload should be at /tmp/payload.base64.  You can decode that base64 encoded file back to the original contents with:
pi@fakekeyboard:~ $ base64 -d /tmp/payload.base64 > payload
And payload should be identical to the file you encoded earlier!

Take it for a Spin!

Time to shine!  You can now power off your RPi:
pi@fakekeyboard:~ $ sudo poweroff
And go insert it into a target system (or into the system you've been working with it, that'll work fine, too...  :)  ).  The RPi should boot up, wait the 15 seconds and, when no ssh session for the 'pi' user appears, dump the payload keystrokes out, and power itself off.

NOTE: the full section above was written for targeting *nix-like terminals, particular the lines in gogokeystrokes.sh which use the cat command to write the encoded payload keystrokes to a file in /tmp, but you could easily target other OS terminals/shells/command-lines, OS "hot key" shortcuts, or other applications (anything that accepts keystrokes!).

For the Button Mashers Out There...

As an alternative to the above "delay-based delivery" of keystrokes, the RPi Zero has a number of general purpose input/output (GPIO) pins, making it handy to add something like a momentary switch (i.e. a button)!  You can find the pinout here (wbm), where you'll note that GPIO 3 (pin 5) hits kind of a sweet spot in that 1) it has a built-in pull-up resistor and 2) it is right next to a ground pin (pin 6).  Perfect!

I soldered a couple of header pins into those two pin location locations (of course you can skip this step if your RPi Zero came with this header populated):

GPIO and ground pins
Pins literally next to each other...!

I then attached (plugged in) a button salvaged from some other item/device (see pic at the top of this post).  Woo!  Now to connect it via software!

There's a handy python library for RPi GPIO support called GPIO Zero (wbm), and you can find some good examples here (wbm) on using it.

You can install GPIO Zero by ssh-ing into your RPi and running the following command (and answering 'Y' to allow it to install the packages, assuming everything looks correct):
pi@fakekeyboard:~ $ sudo apt install python3-gpiozero

Once installed, you can grab a little script from my GitHub gists (wbm) that we'll use to read the value of our button:

pi@fakekeyboard:~ $ wget https://gist.githubusercontent.com/pbarry25/9b2e316e2c9e0818e85bc5b24e5e1579/raw/c34b22275fbe902cb88de09a72d6ad050c4a0695/button-check.py

pi@fakekeyboard:~ $ chmod +x button-check.py 

This script will allowing us to initiate the payload keystroke delivery on button press!  Let's update our /etc/rc.local to use it instead of the delay-and-dump mechanism.  Edit the /etc/rc.local file on your RPi to remove the two lines we added in the section above, and add the following one line in their place, just before the final 'exit 0' line in the file:

/home/pi/button-check.py &

This should leave you with an /etc/rc.local file that has the last handful of lines looking like:

/usr/bin/isticktoit_usb # libcomposite configuration

/home/pi/button-check.py &

exit 0

 So, as the RPi is finishing up the boot process, it will run our button-check.py script as a background process.  That script will wait in a loop until the button is pressed, at which point it will playback the encoded payload as keystrokes followed by a shutdown of the RPi.  You can test it here by running the script directly and then pressing the button!

pi@fakekeyboard:~ $ ./button-check.py

If everything is working as expected, the script will detect your button press (NOTE: the script is only checking the button once per second, so you may need to press it for up to 1 second to be "detected"), send the keystrokes, and then powers off the RPi (NOTE: if this doesn't work, you might try rebooting your RPi and pressing the button once it has booted back up, as I can't recall if the GPIO Zero package/deps need a reboot).

At this point you should be good-to-go for "target practice"!

Parting Thoughts...

I found this project to be pretty fun, pretty quick (a few of evenings of poking around), inexpensive, and with the potential to grow it into something cooler.  A few things I thought of while working on this project that might be nice to improve/add/try:

  • reduce boot-up time (disabling unnecessary services from starting up, reducing/removing timeouts, etc.)
  • harden for abrupt poweroff (unplug) to remove need for clean poweroff
  • try other Vendor ID (VID) and Product ID (PID) combinations to try and avoid potential target OS "configure keyboard" pop-ups on device connect
  • update payloads to self-decode (and self-execute... ¯\_(ツ)_/¯ ), potentially using "hot key" shortcuts and/or control characters to open/navigate apps and/or the OS itself
  • improvements to the scan tool to better/more-flexibly support large amounts of incoming stdin data and adjustable delays between keystrokes
    • NOTE: on my MacBook, I see the 'hidd' process (responsible for handling keyboard and mouse events) leap to ~50% CPU with the RPi's scan cranking out keystrokes at 200 per second.  If I bump the RPi rate to 400 keystrokes per second, 'hidd' jumps to ~90% CPU and my whole UI starts lagging in responsiveness.
  • make the RPi enumerate as having multiple USB capabilities (composite!)
If you'd like more info/examples on Linux USB gadget and libcomposite capabilities, check out this post (wbm) which is a good (and short) read!  Cheers!

Saturday, March 31, 2018

Reflecting the Midpoint

This month marks an anniversary of sorts for me: 20 years of writing software as a full-time job.  Coincidentally, I'll also turn 45 this year.  Assuming the "usual path" toward retirement, these numbers mean I've got 20 years of coding "under my belt" and another 20 years ahead (notwithstanding a disruption from winning the lottery, changing careers, untimely death, etc.).  So I find myself at a career midpoint.  Huzzah.

Below are some partially-organized thoughts/musings/observations/whatever related to "tech work" that I've come to believe/understand over the years (subject to change in the future, of course).  FWIW, FYI, IMHO, YMMV, etc..  Enjoy (or don't, I can't force ya...!  :)  ).

ABL: Always Be Learning

Take a page from continuous integration and continuous delivery: strive to be a continuous learner.  May seem like an obvious goal/"good practice" to many, I'm sure.  But I've been at several places with folks who were "niche experts" in a very particular realm, who didn't feel the least bit obligated to broaden their knowledge.  When the layoffs came through, these folks suffered mightily finding their next gig.  Even if following the latest-and-hawtest tech frameworks/languages/tools/trends isn't your bag, just learning something different/new-to-you every once in a while can go a long way.  You might learn some stuff to make your current job easier, you'll definitely have new items for your resume (giving you new talking points for your next interview!), and, heck, you might even put yourself down a new career path!  As a related aside, I've found that jobs where I am surrounded by folks smarter than myself and/or are involved in other areas of tech outside of my personal career focus is a GREAT way to learn about new stuff without even trying.

Adapt or Die

By no means am I encouraging folks to blindly hop on the latest tech "hype train" barreling down the tracks (and there are just SO, so many hype trains these days...).  Rather, be open to new tools, new approaches, new processes, new ideas, new anything.  I love how git has made my world of code management so much richer than Subversion (or CVS, gag...) ever could.  And "pair programming" was something I only started trying 2 years ago, and now I "get it".  I'm a big fan of continuous integration as a best-practice and appreciate how much traction it's had over the last few years.  That said, I still use vi as my day-to-day editor (hey, it does syntax highlighting and I can work really fast in it!).  Clearly you don't have to drop all your "old" for "new", but don't shut-down or shut-out stuff just because it questions your understandings/beliefs in how things "should be" in your tech world.  It'll be a lot easier to pick up new skills (and land that next job!) if you keep your mind open to "new".

IMPOSTOR!

Ever feel like you've gotten a job you aren't really smart enough for?  Or promotion to a title you aren't qualified for?  Don't sweat it, most folks feel like an "impostor" at various points in their career (still happens to me at times!).  Take a deep breath, try your best, and be honest about things when they come up.  Did you get put on-the-spot by someone with a question about technology X (which you don't know anything about but feel like you should, since you were recently promoted to "Senior Software Developer")?  "Let me dig into that and get back to you."  Realize you aren't going to make next week's deadline because it's taken you longer on the deliverable due to ramp-up/learning effort?  Be honest with the boss/program-manager (and do so sooner-rather-than-later).  Loads of other folks feel like an impostor at times, you are definitely not alone.  Work to own those feelings and manage them.  (Note: this advice does NOT apply if you represented yourself in a fraudulent manner to attain your position; if that's the situation, then good luck with that...).

Look for the Silver Lining

I joined my first startup company in 2001.  The company was securing plenty of funding, the product was exciting, everything was coming up roses.  Employees were having water-cooler conversations about extravagant splurges they were considering once the company took off.  The company connected our managers to "wealth management" professionals for when the "ship came in".  It was an exciting and enthusiastic time.  Right up until it wasn't.  Funding dried up, mainly due to the product's lack of traction.  I survived five rounds of layoffs before I quit the company for another job (the sixth layoff round, which would have caught me, happened one month after my departure).  There was no huge payout, the exercised options were worthless.  We were bummed, our families were bummed.  Seemed like it was a "failure".  But something really cool had came out of this, something I wouldn't have considered had I not been through this experience: my former coworkers had, in an extremely brief period of time, become a sprawling network of folks at MANY tech companies all over town.  It took me a year or so to understand how awesome this really was (see the "It's More About People..." section below).  This "silver lining" has been hugely beneficial to my career over the years, I can attest to that.

It's More About People, Less About Companies

Metaphorically and physically, companies come and go.  To be blunt, companies don't GAF about you, it's the *people* at those companies who do (or don't) care about you.  It's been my experience that only a small number of people, statistically speaking, who you work with will ever really care about you to the point that they will go above-and-beyond when you need it.  Appreciate the heck out of those folks and do the work to keep those relationships active even after y'all no longer work together.  More broadly, it's worthwhile to provide appropriate care-and-feeding to your tech network.  It can be liking someone's post on social media, dropping someone a note, or meeting up for coffee or lunch.  Keeping connections current with folks you've enjoyed working alongside can help keep you in their mind (and vice versa) when a position opens up that might be a good fit (it also lets you "get a pulse" on what else is going on in tech around town).  Lastly, be a developer of people!  If you work with someone who has an appetite to learn something you know, share with them.  It's a great way to connect with folks, improve their skillset, and improve your own understanding of the subject.

Enjoy What You Do

As much as possible.  It's good for the company you work for, it's good for the people you work with, it's good for the people in your personal life, it's good for your mental well-being.  Not enjoying your current gig?  Is it something you can fix (or get fixed)?  Sometimes a change of project or transfer to another team might correct the issue.  Maybe some non-compete side work (consult your hiring agreement, of course) may ease the ennui.  Is the situation beyond (or "not worth") fixing?  Issues with upper management or being "at philosophical odds" with the company leadership/direction might mean time to look for another job.  While job searching and interviewing can be stressful, it affords an opportunity to meet new people and learn more about their company (and current projects/needs).  And landing a new job you're excited about is a huge attitude boost (duh)!

STFU Already...

Certainly I've made a few missteps on my path over the years, which I've tried to learn from (hence this post).  Take the above for whatever it's worth .  Living in an area flush with tech opportunities, I've had a pretty great ride so far.  Looking forward to the next 20 (or 25 or 30+) years of it!!

Saturday, July 8, 2017

AWS Lamba and My Amazingly Cheap Experiment

Earlier this year, I found myself in need of a little monitor.  To be more specific, there's this artistic fellow who puts "limited number/run" stuff up for sale on his website at seemingly random times.  And I've missed the opportunity to purchase some of his stuff because I didn't realize it was up for sale (bummer!).  So I wanted something automated to check his website frequently and alert me to any changes.  This situation looked like a great excuse for me to try out AWS' Lambda offering.

Enter the Lambda

Introduced in 2014, Wikipedia describes AWS Lambda as "an event-driven, serverless computing platform" which is a compute service "that runs code in response to events and automatically manages the compute resources required by that code".  Lambda is designed so that you don't have to provision it yourself (Amazon automagically handles where your code runs), billing you only for the time your Lambda function (i.e. code) takes to run.  Since its inception, Lambda has grown to support a number of different event triggers and interacts with many different AWS services.

In my case, I wanted something trigger by a timer that would go check the website and see if new items for sale had been listed.  And Amazon had a tutorial which got me 90% of the way there right out of the gate.  Perfect!

The Tutorial Flow

The lambda-canary "blueprints" AWS offers are Python code snippets which will go check a website and throw an error if there was a problem reaching or loading the website.  Using a periodic timer setup in AWS CloudWatch, the Python code is executed at whatever frequency you've selected.  If an error occurred reaching or loading the target website, the code will raise an exception.  This exception gets caught by CloudWatch monitoring, who will increment the "error" metric count, triggering an alarm you've set up for when errors >= 1.  And this alarm triggers the SNS alert you setup, so you get an email or text or however the SNS is configured to message you.  Not too shabby!  I tweaked the Python code a bit in my case to look for specific strings of text in the loaded webpage ("coming soon", "out of stock", etc.), and I was good to go!

The Cost

So having a little Lambda function to check a website every minute of every hour of every of every day of every week (etc.) turns out to be REALLY cheap.  Here's how billing during my first month of running looked:


To be fair, it did end up costing $0.02 for my first month of March (Amazon's mid-month forecast was off by a penny, dang!  :P  ), but has been usually $0.01 per month since.

Wrap it Up Already...

My experiment has been super cheap and really fun (and allowed me catch those artist's items I had been missing out on!).  I have some improvements I'd like to make, or course, but it's mind boggling to me just how inexpensive it is to run a task like this.  While Lambda won't lend itself well to some types of tasks, it does appear to be a very nice option for those it does!

Saturday, June 24, 2017

"I don't know that number..."

Miss the olden days of Caller ID, where a caller's number (with name!) would magically appear after the first ring or so?  I miss that feature when I get a call from a number that's not already in my contacts list (although I must admit that Google's Project Fi does a nice job on proving a name for some calls I receive that don't match existing numbers in my contacts list).

A friend of mine recently clued me into a cool online site for phone number lookup: https://www.twilio.com/lookup (Twilio actually provides many call-related services, lookup being just one of them)  You go the web site, plug in the phone number, and Twilio will attempt to tell you the name on the account, the carrier associated with that number, if the number is associated with a mobile or land line, the originating country for that number, and more:


It's worked pretty well for the handful of numbers I've tried so far.  And it seems they allow free lookups (at least a handful, anyway), but the paid model is a modest $0.01 per lookup (not shabby).

Saturday, June 17, 2017

Traveling Securely

With the summer break here, vacation time is kicking up.  Whether you're traveling across town or around the world, there are steps you can take to protect yourself and reduce your "attack surface" (i.e. the ways you are vulnerable).  Below are some suggestions  (not an exhaustive list here) for your consideration, applicable for both personal and work-related travel (and even your day-to-day when you're not traveling!).  Obviously I don't know everyone's needs/requirements, these are just some general thoughts.  And links-to or discussion-of specific products/services shouldn't be taken as an implicit endorsement, rather just as examples.  😊

Travel Light (a.k.a Don't Bring What You Don't Need)

This applies to both tech and non-tech items.  Don't need your checkbook?  Don't take it.  Not visiting the remote work office?  Leave your work ID and/or access badge(s) at home.  Passport not required?  (this one might be tricky these days...)  Don't pack it.  Not doing work while on vacation?  Leave the work laptop locked up at home or in your office desk.  Reducing the items you're carrying not only makes your bags lighter, it's "one less thing" to worry about losing or getting stolen (and the subsequent stress of phone calls and emails you'd be faced with making in such a circumstance).

Protecting What Comes With

This can be (and is!) a long list of stuff.  It'd be a lot for folks to follow every suggestion below, but the more you follow, the better-protected you'll be.  And this is not to suggest that the baddies out there will come at you from every possible angle (well, unless you're really that interesting of a person!  I, myself, am not...), but evil-doers just need one weak spot to get at ya...
  • update the OS, applications, and AntiVirus definitions on your devices before you go
    • keeping your laptop, phone, tablet, etc. devices updated will prevent folks from taking advantage of older bugs/vulnerabilities to gain access to your device
  • securely back up your data before you go
    • if a device gets stolen or seized by a government official, you'll still have a copy
  • only charge your devices from your own chargers and/or battery-packs
    • you'll avoid "juice jacking" this way, but if you absolutely must charge off something you don't own, use protection (or a cable you own that you are certain is a power-only --no data-- cable)
  • don't connect unknown devices to your devices
    • that USB drive you found on the hotel lobby floor doesn't contain anything worth the risk of infecting your laptop, trust me
  • securely delete sensitive data from portable data devices
    • don't leave that copy of your tax return sitting on your USB thumb drive
  • disable wireless technology that your devices aren't using (Bluetooth, WiFi, NFC, etc.)
    • the fewer you use, the fewer ways for an attacker to get at you
  • don't connect to unknown, unsecured/"open", or poorly secured networks
    • ideally use networks you know which are using WPA2 for security
  • connect to a VPN when using public, hotel, and airport networks
    • VPN offerings like Tunnel Bear are affordable and work on Windows, macOS, iOS, and Android
  • avoid logging into personal accounts from devices other than your own
    • keyloggers or credential stealing software might be present, but even a leftover cookie from forgetting to log out of your gmail is all someone needs
  • use multi-step authentication (good) or multi-factor authentication (better) for your device and online logins
  • ensure your stored data is encrypted
    • modern operating systems (both computer and phone/tablet) make this super easy to do, where you won't even notice the data is encrypted (but someone stealing your data will notice when they can't decrypt the data to read/use it)
  • store items which contain a passive RF component (e.g. U.S. passports, work badges, drivers licenses) or an RF transmitter (e.g. fobs for keyless push-button ignition vehicles) in a protective case/enclosure
  • keep an eye on your accounts that you're using for payment while traveling
    • if using credit or debit cards, beware of account-info-stealing skimmers and shimmers on ATMs, gas pumps, and the like
  • be aware of your surroundings when entering credentials or viewing sensitive information
    • is anyone looking over your shoulder, or maybe there's a camera installed somewhere (like in the shimmer article link above) 
  • always log out of online sites/services when you're done using them
    • in the event someone obtains your device, your logging out from these sites prevents them from accessing those accounts
  • always lock your device when not in use
    • it might be annoying to unlock that tablet every time you use it, but it will keep a thief from easily getting at your sensitive data
  • enable "find my device" capability on your devices
    • has helped find many stolen/lost devices over the years
  • enable "remotely wipe my device" capability on devices which contain sensitive/personal data (or have the credentials stored to access sensitive/personal data)
    • in the event you can't find the device (or it's not practical to try and retrieve it), use this tack to erase your data from the device so you don't worry about others getting ahold of your data

Protecting Your Person

Decidedly shorter list here (because I'm less knowledgeable in this area), but a few points for your consideration:
  • prefer "known secret" (e.g. password, drawing pattern, image sequence) credentials to biometric (e.g. fingerprint, face recognition) or device-based (e.g. USB/Bluetooth/NFC device possession)
    • while it is convenient to unlock your phone with your fingerprint, it is usually more difficult for the U.S. government to legally compel/force you to unlock a device if it is secured by "something you know" (e.g. a password, an unlock pattern, etc.) rather than "something you are" (biometric) or "something you have" (NFC keyfob)
  • carefully dispose of items containing sensitive/personal/account information
    • securely shred them or carry them home with you to securely dispose of later
  • know your rights

But All This Sounds Like a Hassle!

Yeah, it kind of does.  But it you choose a few items here to implement in your life and get use to them, then add a few more, get used to those, etc.,  hopefully they'll be second nature before you know it (and your data, devices, and life will be more secure!).  As the old adage goes: "an ounce of prevention is worth a pound of cure."  

Sunday, June 4, 2017

Firing Things Back Up...

This month marks one year that I've been back to working in the security space.  I've been having a ton of fun and constantly absorbing stuff (part of the "fun", yo), and also thinking on how I might share some of what I've learned in a consumer-friendly fashion.  So, hey, what about my dinky blog space I've been neglecting for years?!?  Sounds good!!!  :P

Starting today, I plan on posting somewhat-regular (not more often than weekly) entries on different aspects of security, with a particular focus on personal security.  Take note: I do NOT purport to be any sort expert, and anything offered here is strictly MY PERSONAL OPINION (and subject to change, particularly with the shifting landscape that security tends to be).  That said, I'm open to other's thoughts and questions folks might have, just hit me up in the comments!

Onward!