HTTP Response Header: Content-Disposition

For the longest time, I always wondered how WordPress.org always served the current version of wordpress from a file named “latest.tar.gz”, and whenever I downloaded it with a browser (such as Firefox), my browser would always save it as something like “wordpress-3.5.2.tar.gz” instead. This never happened when I would retrieve the file using “wget”. I never really bothered looking into it much.

Just tonight I stumbled across it while downloading a driver for a USB wireless adapter that I have.

It’s all in the “Content-Disposition” header, which can contain an optional “filename” field tagged on to the end. The “filename” field is just a suggestion to the browser for a filename to save the file as. It’s not mandatory, and apparently “wget” doesn’t give a hoot about it. Well, I don’t like my packages having filenames like “dl.php”, so I dug in a bit and learned what made this happen.

(I need to rename “dl.php” to something else, and I wanted to find the suggested filename.)

Here’s a sample of what the Content-Disposition HTTP response header may look like when downloading a file with a suggested filename:


Content-Disposition: attachment;filename=Package-2013_07_08.dmg

Password Policy

Hackers/crackers use modern GPUs (and possibly ASICs) to brute-force passwords. The old-school password policies from the early 2000’s really shouldn’t apply now, because to a computer, it’s irrelevant which characters are which. Computers can run through the entire UTF-8 charset in fractions of a second, and they’ll eventually guess a short password whether or not it contains a mix of character types (upper, lower, numbers, special, etc).

I’m tired of seeing password policies like this (I saw this when trying to change one of my passwords today):

We require that your new password contain the following:

2 upper case letters
2 lower case letter
2 numbers
2 special characters (examples: !@#$%^&*)

This leads to a false sense of security on both the part of users and the site operators.

Anyone still using/enforcing/advocating this kind of password policy needs to read this (I promise it’s very short).

It doesn’t have to be that complicated. I’ve boiled it down to a 2-step process:

  1. enforce a minimum password (or passphrase) length, such as 25+ characters
  2. hash the password using bcrypt or scrypt and store only the hash

Obviously basic steps should be taken, such as preventing passwords from being transmitted in plaintext, but the 2 measures above will prevent 99% of passwords from being cracked.

Remove Ubuntu/Debian version from sshd server string

For security reasons, I don’t like that “Debian/Ubuntu” shows up on my sshd server string.

You can see the sshd server identification string by telnetting to port 22.


$ telnet ngmarley.com 22
Trying 106.187.97.211...
Connected to ngmarley.com.
Escape character is '^]'.
SSH-2.0-OpenSSH_6.0p1 Debian-3ubuntu1
^]
telnet> quit
Connection closed.

It’s very simple to just remove the “Debian…” part off the end.

Just edit /etc/ssh/sshd_config and append

DebianBanner no

to it.

Then re-start your sshd:


service ssh restart

… and now verify that it’s gone:


$ telnet ngmarley.com 22
Trying 106.187.97.211...
Connected to ngmarley.com.
Escape character is '^]'.
SSH-2.0-OpenSSH_6.0p1
^]
telnet> quit
Connection closed.

Disable “Speed Dial” Feature in Firefox 13

When you open a new tab in Firefox 13, you see a preview grid of most-visited web pages or something. Maybe. I’m not sure where that list comes from. Doesn’t matter, I don’t like it. There’s no way to disable it in the Firefox preferences, so you have to tweak the config settings to disable it.

I don’t know what the guys at Mozilla were thinking when they added this not-so-optional “feature”. Someone suggested they were trying to win… “The Most Retarded New Features Competition”. I would change that to “The Most Superfluous New Features Competition”.

To disable it:

1. Type about:config in the address bar.

2. Search for “browser.newtab.url”, and change the value to “about:blank”.

That’s it.

OSX – How to change the root user’s shell.

Or the default shell of any user for that matter. I don’t know if this is recommended or not, but changing from /bin/sh to /bin/bash will enable tab-completion, and since I’m a lazy admin that’s what I’ll do. (Plus, less keystrokes = longer hardware life for my keyboard.)

This command will display the user’s default shell (replace root with desired username):
rivendell:~ root# dscl . -read /Users/root UserShell

Now change the shell (in this case to /bin/bash):
rivendell:~ root# dscl . -change /Users/root UserShell /bin/sh /bin/bash

Make sure it was changed:

rivendell:~ root# dscl . -read /Users/root UserShell
UserShell: /bin/bash
rivendell:~ root# echo $0
-sh
rivendell:~ root# su -
rivendell:~ root# echo $0
-bash

Analysis of a Chinese Phishing Scam – Global Payments, Inc.

This post will be of particular interest to customers of Global Payments, Inc. I received an email which seemingly came from them, asking for account login details. Since I don’t have an account with them (and before this morning didn’t know who they were), I did some detective work. It turns out to be a phishing scam.

phish·ing/ˈfiSHiNG/
Noun:
The fraudulent practice of sending e-mails purporting to be from legitimate companies in order to induce individuals to reveal personal or confidential information, such as such as credit card numbers or passwords by directing a user to a fake email message or website.

Do not trust any emails coming from the domain “global-paymts.com”, e.g. “virtualT@global-paymts.com”. This is not the company “Global Payments, Inc.” (which itself is a valid company), but a phishing scam intended to get you to enter your real payment processor login data, which the scammers will then use to access your real account and take all your real monies.

A Google search did not turn anything up, so I did a little investigating myself. The HTML form in the email accepts your login info and sends it to a script at the fjnusoft.com domain. A “whois” search reveals that this is a Chinese domain:

Domain Name.......... fjnusoft.com
  Creation Date........ 2007-04-08 11:12:47
  Registration Date.... 2007-04-08 11:12:47
  Expiry Date.......... 2016-04-08 11:12:47
  Organisation Name.... fu jianshida ruanjian
  Organisation Address. fujianshifandaxue ruanjianrencaipeiyangjidi
  Organisation Address.
  Organisation Address. fuzhou
  Organisation Address. 350000
  Organisation Address. FJ
  Organisation Address. CN

Admin Name........... lu qixue
  Admin Address........ fujianshifandaxue ruanjianrencaipeiyangjidi
  Admin Address........
  Admin Address........ fuzhou
  Admin Address........ 350000
  Admin Address........ FJ
  Admin Address........ CN
  Admin Email.......... lqx@fjnusoft.com
  Admin Phone.......... +86.59187248372
  Admin Fax............ +86.59183560708

Tech Name............ jinfeng wang
  Tech Address......... BeiGuo East Residential District 26-102
  Tech Address.........
  Tech Address......... Nantong
  Tech Address......... 226001
  Tech Address......... JS
  Tech Address......... CN
  Tech Email........... sales@dns99.net
  Tech Phone........... +86.51385292710
  Tech Fax............. +86.51385292710

Bill Name............ jinfeng wang
  Bill Address......... BeiGuo East Residential District 26-102
  Bill Address.........
  Bill Address......... Nantong
  Bill Address......... 226001
  Bill Address......... JS
  Bill Address......... CN
  Bill Email........... lqx@fjnusoft.com
  Bill Phone........... +86.51385292710
  Bill Fax............. +86.51385292710
  Name Server.......... ns1.dns.com.cn
  Name Server.......... ns2.dns.com.cn

Below is the email I received. Note that I use mutt, a text-based email reader. If you are reading your email on a web browser and are hit with this scam email, the text of the message will be the same as below but you will probably see the HTML form and some image(s).

From: "GlobalPayments, Inc" 
To: contact@ngmarley.com
Subject: Account Update

[-- Attachment #1 --]
[-- Type: text/plain, Encoding: 7bit, Size: 0.2K --]

Dear GlobalPayments Customer,

Because we registrated to many frauds we decided to lock your Virtual Terminal account.
To unlock it please download the file attached to this e-mail and update your login info.

2012 Copyright Global Payments ,Inc.


[-- Attachment #2: Login_myvirtualmerchant.html --]
[-- Type: application/html, Encoding: 7bit, Size: 2.2K --]

[-- application/html is unsupported (use 'v' to view this part) --]

[-- Attachment #3 --]
[-- Type: text/plain, Encoding: 7bit, Size: 0K --]

update: Apparently the company Global Payments, Inc. are aware of this scam, as they have an alert on their homepage and a link to a more detailed alert/disclaimer here: http://www.globalpaymentsinc.com/Alert.html

Convert .m4a files to .mp3 format (with tags)

A Perl utility I wrote to convert .m4a files to .mp3 format. It will also pull the tags over from m4a format. If there are no m4a tags, the script will die. (But of course you can just comment that part out.)

Here is the direct link to the script: m4a2mp3.pl

Note: I’ve updated the code to reflect my more current programming style. If I had time to re-do this, I’d have used IPC::Open3 or something else for IPC, instead of the system call used.


#! /usr/bin/perl
#
# name: m4a2mp3.pl
# description: Convert m4a file to mp3 format. Attempts to convert tags.
# developer: Nathan G. Marley
# date: 2011Sep10
# ========================================================================

use strict;
use warnings;
use feature qw(say);
use Carp;
use MP4::Info;
use MP3::Tag;
use Getopt::Long;

if ( !@ARGV ) {
croak("usage: $0 <...>\n");
}

my @m4atags = qw ( YEAR ARTIST GENRE TRACKNUM TIME
TITLE ALBUM ENCODING BITRATE );

sub main {

for my $file ( @ARGV ) {
my $m4atags = get_m4a_tags( $file );
my $mp3file = convert_m4a_2_mp3( $file );
my $rc = tag_mp3_file( $mp3file , $m4atags );
}

}

main();

sub get_m4a_tags {
my $filename = shift;
my $taginfo;

my $tag = get_mp4tag($filename)
or carp("No TAG info");

for my $t ( @m4atags ) {
$taginfo->{ $t } = $tag->{$t};
}

return $taginfo;
}

sub convert_m4a_2_mp3 {
my $m4afile = shift;
my $mp3file;

($mp3file = $m4afile) =~ s/\.m4a$/.mp3/;

if ( -e $mp3file ) {
carp("error: MP3 file '$mp3file' already exists.");
return;
}

my $faad_opts = "-q -o -";
my $lame_opts = "-S -v -V 0";
my $cmd = "faad $faad_opts \"$m4afile\" | lame $lame_opts - \"$mp3file\"";

my $rc = system($cmd) >> 8;
if ( 0 != $rc ) {
croak("error: Couldn't convert m4a file to mp3 format");
}

return $mp3file;
}

sub tag_mp3_file {
my ( $mp3file , $tags ) = (@_)[0,1];

my $mp3 = MP3::Tag->new($mp3file);

# scan file for existing tags
$mp3->get_tags;

if (exists $mp3->{ID3v1}) {
$mp3->{ID3v1}->remove_tag;
$mp3->new_tag("ID3v1");
}

if (exists $mp3->{ID3v2}) {
$mp3->{ID3v2}->remove_tag;
$mp3->new_tag("ID3v2");
}

$mp3->title_set ( $tags->{TITLE} );
$mp3->artist_set( $tags->{ARTIST} );
$mp3->album_set ( $tags->{ALBUM} );
$mp3->year_set ( $tags->{YEAR} );
$mp3->genre_set ( $tags->{GENRE} );
$mp3->track_set ( $tags->{TRACKNUM} );

$mp3->update_tags(); # Commit to file
$mp3->close();

return;
}

Facebook account deletion link

In case anyone is looking for it:

https://www.facebook.com/help/contact.php?show_form=delete_account

This is the official Facebook delete account link. You can permanently delete your account by visiting this & entering your password & a (Re-)Capcha.

Be aware that it will be gone forever — this doesn’t just de-activate it. For now, there is still a 14-day grace period, so if you log back in within 14 days, the account deletion request will be cancelled.

spicnspan.pl – “clean up” text files

At times I get tired of editing code with tabs. And by “at times”, I mean every time. I hate tabs in code. I hate trailing spaces in code too (makes it more difficult to navigate using vi/vim). And more than anything, I hate Windows CR/LF (carraige return/line feed) line terminator characters.

So I wrote a script to take care of it. I call it “spicnspan”. To use: spicnspan

Simple enough.

This script:

  • Converts all tab chars in a text file to 4 spaces.
  • Converts Windows-style CR/LF line terminators to UNIX newline chars (0x0a).
  • Removes trailing spaces.

If I were to re-code this, I would allow for multiple filenames on the command-line. I would also make separate smaller functions, one each for:

1. Slurping the file data
2. “Fix” ing (i.e. remove spaces, etc) the file data
3. Writing the file back to disk.

This is done now. The code below has been updated to reflect these changes, as well as the direct link.

Here’s a direct link to the code (save as .pl on your computer, or whatever you want if you have a real OS):

spicnspan


#! /usr/bin/perl
#
# name: spicnspan
# description: Removes tab chars (converts to 4 spaces) & trailing spaces
# from code.
# developer: Nathan G. Marley
# date: 2010Ene19
#
# change history:
# ========================================================================
# description: change description placeholder
# developer: developer name goes here
# date: YYYYMmmDD
# ========================================================================

use strict;
use Data::Dumper;
use File::Basename;
use Carp;

# boilerplate
my $progname = basename($0);
my $usage = "usage: $progname ...";

# main section
foreach my $filename ( @ARGV ) {

# slurp file data
my $indata = &slurp_file( $filename );

# clean file data
my $outdata = &scrub_data( $indata );

# write file data to disk
&write_file( $filename, $outdata );

}

# subroutines...

sub slurp_file() {
my $codefile = shift;
my $data;

if ( ! -f $codefile ) {
print STDERR "error: '$codefile' doesn't exist or not a regular file.\n";
}

open(IN, "< $codefile") or die "Can't open '$codefile': $!"; { local undef $/; $data = ; }
close(IN);

return $data;
}

sub scrub_data() {
my $indata = shift;
my $outdata = $indata;

# strip Windows-style linefeeds
$outdata =~ s%\x0d%%g;

# convert all tabs to 4 space chars
$outdata =~ s%\t% %g;

# remove any trailing spaces
$outdata =~ s% +\n%\n%g;

return $outdata;
}

sub write_file( $codefile, $outdata ) {
my ( $codefile , $outdata ) = (@_)[0,1];
open(OUT, "> $codefile") or die "Can't open '$codefile' for writing: $!";
print OUT $outdata;
close(OUT);
}

CPAN changing permissions on OSX

some Perl code
some Perl code

If you are looking for a Perl module to interface with Amazon’s S3 hosting service, do not use the Net::Amazon::S3 module. It has an unrealistically huge list of modules on which it’s dependent (one of which is more like a framework — a pain in itself) and you’ll likely never get it installed. The Amazon::S3 module by Timothy Appnel installs without a hitch, and it was based on an earlier version of the Net::Amazon::S3 module.

So apparently something in CPAN on OSX 10.6 (Perl version 5.10.0) causes it to change permissions of the /usr/bin/cpan script, not only removing the executable bit for all, but also setting the write bit (not good).

This results in the common “permission denied” message when someone trys to run CPAN to install some Perl modules:


[root@lorien ~]# cpan
-bash: /usr/bin/cpan: Permission denied

For the uninitiated, this permission change will render your CPAN installation completely vulnerable to anyone who logs in (or breaks in) to the system, even standard “normal” user accounts.

You can run this find statement to show all files in a directory (including subdirectories) that are world-writeable:
find . -perm -o+w

In the example below, I’ve paired this with the “exec” argument using ‘ls’ to show the permissions and inode number of each file.


[root@lorien bin]# find . -perm -o+w -exec ls -ldi {} \;
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./c2ph
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./corelist
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./cpan
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./cpan2dist
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./cpanp
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./cpanp-run-perl
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./dprofpp
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./enc2xs
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./find2perl
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./h2ph
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./h2xs
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./libnetcfg
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./perlbug
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./perlcc
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./perldoc
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./perlivp
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./perlthanks
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./piconv
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./pl2pm
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./pod2html
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./pod2latex
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./pod2man
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./pod2text
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./pod2usage
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./podchecker
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./podselect
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./psed
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./pstruct
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./ptar
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./ptardiff
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./s2p
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./shasum
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./splain
2491453 -rw-rw-rw- 34 root wheel 807 2009-06-24 02:42 ./xsubpp

As you can see from the output, there are a lot of files that were affected, but you can also see from the inode number that they are all hard links to the same file (good in this case). So, we fix the permissions on one file and we fix them all.


[root@lorien bin]# chmod 0755 cpan
[root@lorien bin]# ls -ld cpan
-rwxr-xr-x 34 root wheel 807 2009-06-24 02:42 cpan
[root@lorien bin]# find . -perm -o+w -exec ls -ldi {} \;
[root@lorien bin]#

Life is good again. (Note: this will fix the problems, but not the root cause. I’m too lazy to start looking into CPAN itself to find the root cause, so… I’ll leave it to the smart guys who actually write the code for CPAN to figure that one out.)

And in case you are wondering, yes, my computer’s name is Lorien. What can I say? I’m a LotR nerd. Not too unusual for us techie types.