Trying Out Beef Jerky

My brother-in-law gave me a taste of some of his homemade beef jerky a couple weekends ago, and it was fantastic! Apparently it was also easy to make. Easy, delicious, I’m gonna try it! He used a dehydrator, but I plan to use a smoker to keep my wife’s dehydrator from getting strong flavors stuck in it.

Jason’s Recommended Starting Recipe

I got a 2.5 lbs bottom round steak, sliced it thin, then started it in the marinade below at 2130. I plan to marinade for over 12 hours, then smoke the slices at 175℉ for 4 hours or so.

1 1/3 cup Worcestershire sauce
1 tsp paprika
1 tsp black pepper
2 tsp cayenne pepper
1 tsp garlic powder
1 tsp onion powder

I intended to use 1 Tbsp of paprika as in the recipe, and purposely left out the brown sugar for the first time.

1450: I dried the meat slices on paper towel, then put it on the smoker. The smoke holes are fully open to increase air flow and aid drying (not sure if this will really make a difference), the water pan is not even in the smoker, and the wood is hickory.

I’ll keep hickory in there for the first two hours, at least, then I suspect the meat will be as smoky as it can get. After that, I’m using the smoker like a low temperature oven.

That’s really why this method should be comprable to the recipe’s oven method. This is an electric smoker, and it can maintain temperatures up to 275℉, so 175℉ will not be a problem. Plus, the exhaust goes directly outside, so the house doesn’t smell like Worcestershire sauce for a week.

The meat took up all the smoker rack space except half of the bottom one. I’m pretty happy with how thin I got it.

1900: jerky is done! Final weight is only 11 oz! It is down to 27% of original weight.

I’ll freeze half.

The result should cost $1.59 per ounce, just in meat cost, since the original meat was $7 per pound. Normally jerky is $2.50 per ounce. While $1 per ounce is a good mark-up (and of course they aren’t buying their meat from the supermarket), it’s not preposterous. Meat seriously shrinks from water loss.

Changes for next time – maybe more flavorful if possible. Less spicy for sure (this is probably too spicy for Sarah). More spices though, and maybe a little salt. Same thickness cut I think – as thin as I could get it with the knife while being consistent.

Writing About Writing Secure Shell Scripts

I recently read this cautionary tale about shell scripts. https://www.linuxjournal.com/content/writing-secure-shell-scripts

It’s cautionary in two ways: it is intended to cause shell programmers caution, and I caution against you taking the article too seriously.

One of the biggest threats to the shell in memory was the Shellshock vulnerability. This wasn’t typically a direct threat to shell scripts, but one caused by a bug in a shell, and by other programs exposing parts of the shell to external input, often in unexpected and unlikely places.

That kind of topic is not what the Linux Journal article is about.

Instead, it provides three cautions to people writing shell scripts:

  • Know the utilities you invoke: fully specify program paths so you don’t accidentally run something out of /tmp
  • Don’t store passwords in scripts: find your own other solution, good luck sucker!
  • Beware of invoking anything the user inputs: with examples that work on no modern Linux

These are all fine recommendations, but are made in terrible ways.

Know the Utilities You Invoke

The author provides an example where a user drops a malicious “ls” script in /tmp, then scripts execute it because they do not completely specify the path of ls. The author’s recommendation is to completely specify all paths. The problems with this are two-fold…

First, to execute a program in a directory that isn’t in your path, you must specify the path of that program. If it’s your current directory, that’s just a “./”, but it still must be present. If you have “.” in your path, as the article suggests, then you have made a configuration error that can easily cause you unexpected behavior at best, and the precise security vulnerability mentioned in the article at worst.

The correct remediation for this issue is to not put “.” in your path.

The second problem with the article’s recommendation is that many programs are not in a set location on the system, and some even move around over time (decades). Many claim that the “/bin”, “/usr/bin”, “/usr/local/bin” system is set, sensible, and regular. This is not the case in practice. Usage varies between distros, and even between versions of distros. A system update can move the location of a program in the worst case. This isn’t a problem if the new location is in your path, you’ll still execute the right thing. Unless you fully specified the old location in all your scripts.

This isn’t to say that you can’t usually specify the full location. And specifying the full path might provide a greater security guarantee. However, the author’s recommendation has some practical downsides, and anyway don’t put “.” in your path!

The great /usr merge makes fully specifying paths more practical.

Don’t Store Passwords in Scripts

This is 100% correct. Anyone with read access to your scripts or your git repo or your backups can pull those passwords right out. The problem with this section of the article is that it doesn’t provide any practical solutions. Anybody that has been doing shell scripting for a time will have run into the password problem, and lots of us have just crammed the password in the script or in a readable file at some point.

There are other better solutions!

First though, another wrong way to do it: specifying passwords on the command line or in environment variables. Don’t do this either! It often seems a better solution than dropping it in the code, but both solutions still expose passwords in many ways.

If your need is for SSH (or related) authentication, consider requiring the script user to type in the password. The password is a way to ensure the user actually has permission to use the resource you’re automating access to.

Often, scripts need to run without user interaction though, so entering a password is not feasible in those cases.

Then you need to limit the damage someone malicious can do if they gain access to the target system. Consider setting up a specific user on the target system that has permissions limited to only what is required for the automated actions. Setup key-based access to that target account, don’t specify a key file password, and don’t provide the target account an actual system password. Place the key file in a location only accessible to the users that should be able to execute the script (maybe you need a custom user or group here, too) and give the file only the minimum required permissions. Now, in your script, invoke SSH, or SCP, etc. with that key file specified.

Using SSH-Agent is probably an even better solution: https://www.akadia.com/services/ssh_agent.html

What if it’s not SSH that you’re sending a password to, what if it’s sudo? I think we’ve all wanted to do this at some point, I confess that I have.

Don’t do it though!

Change your sudo configuration so that for the specific command you need a specific user to run, it doesn’t require a password! Then lock access to that user down some. Even in this case, you’re probably causing problems you don’t expect. Imagine if the target executable has a vulnerability… Now you’re opening the aperture for privilege escalation. A better solution is to change permissions to allow specific users access to the specific resources required, then reduce others’ access to those user accounts.

What if you need to script password sending to telnet or ftp? I don’t have great solutions at hand for you. At some point you may need to put passwords and usernames in files, then limit access to those files, and have your script grab the file contents.

Beware of Invoking Anything the User Inputs

The author suggests that a specific setup and command line can cause, “quite dire consequences.” Try this command for yourself though, after changing the “rm” command to something benign like a version of “ls”.

You didn’t get the output the author suggested you might? That’s because this isn’t really a problem the way he states it.

Oh, the author’s “eval” version might work, but when have you ever written code like that? Please say you haven’t.

It’s definitely possible to accidentally provide ways for users to cause command injection – it’s a very common class of vulnerabilities. Scrubbing the input, as the article author suggests, is a common solution.

One recommendation the author should have made more clear is that when scrubbing input you should permit only data that fits a minimalist whitelist. Don’t try to look for bad characters, like you would with a blacklist… Instead, fail on any characters that aren’t in your specific small set.

More often though, the use case for shell scripts is in accepting input from users already on your system. In this case, the recommendations in the article are lacking.

My main recommendation is to avoid permitting users to run anything as a higher level user, or as a different user at all. If users can only execute scripts as themselves, and the script doesn’t grab extra permissions like via SSH, any commands the user might try to get the script to run would also run with the user’s permissions. Therefore, it’s a thing they could’ve done themselves.

If there are shared resources the script needs that the user shouldn’t normally have, perhaps use sudo within the script to grab/use those resources then drop permissions (as would happen if a separate program did the permissioned work, then ended). Alternatively, create another user with only minimal permissions, including those shared resources, then have the script run as that user.

If the script does have to get extra permissions, like through SSH, avoid sending user input there, or sanitize it with a whitelist (worst case). When I say SSH provides extra permissions, I mean that it does so by providing access to another computer, and potentially another user.

You should try to avoid writing code that eval’s user input, or potentially places it on the command line as multiple arguments, and you should try to sanitize input when you have to take a risk… But the best solution is to design the environment so that even when you inevitably mess up it’s not that big a deal.

Conclusion

Good points Dave, but the recommendations are lacking.

The Apple article he links has better recommendations, and solid examples. It points out that older Bash versions were vulnerable to one of Dave’s examples that I poo-pooed. However, there are many problems with running older Bash versions (you wondered why I mentioned Shellshock?)… Don’t do that anymore. The Apple example also has a great hidden eval command in there – echoing user input to a file then executing the file is essentially eval. Avoid.

Brisket and Salmon Again

I ran out of brisket too quickly last time…  It makes a fantastic sandwich with Philly Cream Cheese (strangely enough).  Then I eat a bunch of salmon on bagels, with Philly Cream Cheese…  The discovery that it’s the right cheese for both sandwiches has made shopping easier.

The brisket is 15.5 lbs, $2.99 per pound.  Salmon is 6 lbs, didn’t get the price before tossing the package.  We have to move in July and I hope I can keep up this hobby at the next stop in life.

1700 30 Dec: Fish begins brining.

2120: Brisket is on the smoker at 225℉, vent half open, fat cap up.  Next temp check should be 8 hours from now at 0520.  Used 4 Tbsp salt, 4 Tbsp pepper, 2 Tbsp garlic powder on the brisket.  I forgot to put water in the tray…  Let’s see what happens.

0520: 163 and 162, next check 0720

0720: 176 and 173…  I missed the crutch temp, but things seem to be proceeding well…  I cranked up the temp to 250.

0920: 193 and 188, smelling real good now…

0940: Fish started drying.

1040: 200 and 201.

1140: 207 and 204.  Close enough!  Meat came off, and I cleaned up the grates to put the fish on.

1210: Fish is on at 120.

1610: Fish is done, right on time.  Final temps were just above 140.

Everything was great, some of the skinny parts of the flat were dry, but not much…  The bark was fantastic.  Crisp, flavorful…  Some parts of the flat were more like roast beef than the brisket normally is.  I think I should try it unwrapped again, but maybe trim less fat on the flat and turn the temp up an hour sooner and see what changes.  Right now though, wrapped seems the way to go.

The water tray was almost full with grease by the end, I think next time I’ll put water in, but don’t think it makes a difference.

Brisket and Salmon!


Just got married, just got honeymooned, just got back to work…  Time for some food!

17 lbs brisket, $61, 6 lbs salmon $9 per pound.  Using the same recipe as usual.

2120: Brisket went on the smoker.  4.5 Tbsp salt, 4.5 Tbsp pepper, 2.25 Tbsp garlic powder.

2200: Fish is brining.

0530: Brisket at 165 and 166.  Crutched it, and turned temperature up to 250.  Also, moved fish to drying.

0845: Brisket at 202 and 189.

0930: Took the flat off, it was done, at 208.

1130: I’ve checked the point temperature periodically this whole time, and it has slowly risen to 201.  I’ll take it off after making coffee.

1145: Point was at 201, close enough, took it off then cleaned the smoker grates and water tray, and removed and chunks.  Set it to reheat to 120.

1230: Fish is on!

1630: All done, delicious.

Next time I need to make sure I slice across the grain.  I mistook the direction of the grain in some of the brisket, I need to double check that next time.  Otherwise I think it all turned out fantastically.