mining ruby gem vulnerabilities for fun and no profit
TRANSCRIPT
Mining Ruby Gem Vulnerabilities for Fun and No Profit
Larry W. Cashdollar
v0.6
Who Am I• Employed at Akamai Technologies• Hobbyist Vulnerability Researcher• 75+ CVEs• Unix Administrator • Penetration Tester Back in Late 90s• Twitter @_larry0• Enjoy Writing and Breaking Code
Agenda• Why Ruby Gems• Gem Pros/Cons• What Vulnerabilities Did I Mine• How Did I Look for Them• Automation• Crowd Sourcing• Other Areas to Mine• Improvements
The Story• Vulnerability Research Like Wading Through
Molasses*• Discover a Vulnerability Once Every Two Months?• I Wanted MOAR FASTER!• I Don’t Write Ruby
* at least for me
Why Gems
• Large Code Base• Lots of New Developers• No One Else Was Really Looking• Popularity
Pros/Cons
• Con– I don’t write Ruby… yet– True PoC Requires a Full Project
• Pro – Lots of Ruby Gem Code to Look At!– Developers New to Secure Coding Practices– Easily Download Gem Code
Ruby Gem Stats
• 3,812,982,562 Downloads• 90,120 Gems Cut Since July 2009
Simple Vulnerabilities and Easy to Find
• Insecure use of /tmp or /var/tmp• Command Injection• Clear Text User/Password Credentials• API Keys• Credentials Exposed to Process Table
The Process
10. Download A Gem20. Unpackage30. Examine40. Log50. GOTO 10
How to Look?
• Lots of Code to Dig Through• Use Tools Readily Available
– find– grep– awk– sed
Searching via Command Line
$ wget http://www.rubygems.org/gems/ftpd-1.0.1.gem$ mv ftpd-1.0.1.gem ftpd-1.0.1.tgz$ tar -zxvf ftpd-1.0.1.tgz$ cd ftpd-1.0.1$ find . -name “*.rb” –exec grep –l system {} \; > list$ for x in `cat list`; do echo “#######[$x]######”; egrep –nC3 system {} \; done > ~/results/cmd.log
Automation
• Download All the Gems!• Search Code for Possible Vulns• Sort and Categorize For Later
The Script
• Shell Script On github• Scrapes rubygems.org• Uses curl/grep/find/awk/sed • It’s an Abomination
#!/bin/sh#ruby gem scraper, grab all the gems to hAck#Larry Cashdollar, @_larry0 2/17/2015
echo "[+] Scraping rubygems.org for all $1 Gems";echo "[+] Cleaning up files";
WPATH=workdirOUTPATH=outdir
rm -rf working.$1echo "[+] Getting number of pages for letter $1";
wget https://rubygems.org/gems?letter=$1 -O $1.max
NUM=`cat $1.max | grep Next | awk -F\= '{print $36}' | awk -F\" '{print $1}'`
#will give us number of pages in Cxecho "[+] Number of pages :"$NUM
echo "[+] Downloading all $1 gems"
for x in `seq 1 $NUM`; do wget -nv https://rubygems.org/gems?letter=$1\&page=$x -O $1.$x.list ; done
echo "[+] Creating package list"
cat $1.*.list |grep "href=\"/gems/" | awk -F= '{print $3}' | sed -e 's/\/gems\///g' | sed -e 's/\"//g' | sed -e 's/>//' > main_pkg_list.$1echo "[+] Downloading all packages pages for parsing"
mkdir working.$1
for x in `cat main_pkg_list.$1`; do wget -nv https://rubygems.org/gems/$x -O working.$1/$x ; done
cd working.$1
LIST=`ls|wc -l`
echo "[+] Creating download script for $LIST gems."echo "#!/bin/sh" > download.sh.tmpfor x in `ls`; do cat $x |grep Download | awk -F\" '{print "wget -nv https://rubygems.org"$4}'; done >> download.sh.tmpcat download.sh.tmp | sort -u > download.shmkdir data.$1mv download.sh data.$1cd data.$1chmod 755 download.shecho "[+] Downloading gems.."./download.shecho "[+] Renaming files from .gem to .tar"
for x in `ls|grep gem`; do echo -n "mv $x "; echo "$x" | sed -e 's/.gem/.tar/'; done > rename
sh renamerm renameecho "[+] Unpacking"for x in `ls *.tar`; do echo $x | sed -e 's/.tar//'| xargs mkdir ; done
for x in `ls |grep -v .tar` ; do echo "- Working on $x";tar -xmf $x.tar -C $x ; done
for x in `ls|grep -v .tar`; do echo "- Unpacking $x"; tar -zxmf $x/data.tar.gz -C $x; done
echo "[+] Generating file lists of potential targets"
cd $WPATH/working.$1/data.$1echo "************************************************************"pwdecho "************************************************************"
find . -name *.rb -exec grep -l "\`#{command}\`" {} \; > cmdfile.$1.log find . -name *.rb -exec egrep -l "api_key|apikey" {} \; > api_key.$1.log find . -name *.rb -exec egrep -l "\`*\`" {} \; > backtick.$1.logfind . -name *.rb -exec egrep -l "system\(|system\s\(" {} \; > system.$1.logfind . -name *.rb -exec egrep -l '%x[\{\(\[]' {} \; > x_percent.$1.log find . -name *.rb -exec grep -l "/tmp" {} \; > tmpfile.$1.log
echo "[+] Looking for (basic) command exec vulnerabilities."#we are only finding a few of them, see http://tech.natemurray.com/2007/03/ruby-shell-commands.htmlfor x in `cat cmdfile.$1.log`; do echo "+--------------------[$x]-------------------+"; grep -nC3 "\`#{command}\`" $x; echo "+---------------------------------------------------------------------+"; done > command.$1.log.txt
for x in `cat x_percent.$1.log`; do echo "+--------------------[$x]-------------------+"; egrep -nC3 '%x[\{\(\[]' $x; echo "+---------------------------------------------------------------------+"; done > x_percent.$1.log.txt
for x in `cat backtick.$1.log`; do echo "+--------------------[$x]-------------------+"; egrep -nC3 "\`*\`" $x; echo "+---------------------------------------------------------------------+"; done > backtick.$1.log.txt
for x in `cat system.$1.log`; do echo "+--------------------[$x]-------------------+"; egrep -nC3 "system\(|system\s\(" $x; echo "+---------------------------------------------------------------------+"; done > system.$1.log.txt
echo "[+] Looking for /tmp file vulnerabilities."
for x in `cat tmpfile.$1.log`; do echo "+--------------------[$x]-------------------+"; grep -nC3 "/tmp" $x; echo "+---------------------------------------------------------------------+"; done > tmpfile.$1.log.txt
echo "[+] Looking for API key exposure vulnerabilities."
for x in `cat api_key.$1.log`; do echo "+--------------------[$x]-------------------+"; egrep -nC3 "api_key|apikey" $x; echo "+---------------------------------------------------------------------+"; done > api_key.$1.log.txt
cp command.$1.log.txt $OUTPATH/$1-command.txtcp tmpfile.$1.log.txt $OUTPATH/$1-tmpfile.txtcp x_percent.$1.log.txt $OUTPATH/$1-xexec.txtcp api_key.$1.log.txt $OUTPATH/$1-apikey.txtcp backtick.$1.log.txt $OUTPATH/$1-backtick.txtcp system.$1.log.txt $OUTPATH/$1-system.txt
cd $WPATH
echo "[+] Done"
Automation
• Pump Everything into MySQL Database• 6000 Entries• At Least 5000 obvious False Positives• FAIL
Crowd Source
• Created User Web Interface • Flag Finds as FP, Confirmed, Needs
Attention, Unknown• Invited a Few Friends
Dependencies
• https://www.ruby-toolbox.com
Going Sour
• Grave Yard of Code• < 1000 downloads• No Response from Gem Author• Pull Requests go un-Pulled• Dreaming about Ruby Code
Other Programming Languages?
• Perl Modules?• PHP Pear Packages?• Joomla! and WordPress
– Themes– Plugins
Improvements
• RFI,LFI,SQLi,XSS,CSRF?• Gem Auditing Project? • Use rubygems.org API?• Reduce FPs
– Better Regular Expressions– Parse .rb scripts, create lookup tables/symbol
tables for variables and code flow
My Github Junk• https://github.com/lcashdol/rci-info• https://github.com/lcashdol/rubygem_miner• https://github.com/lcashdol/wpthemedownloader• https://github.com/lcashdol/wpplugindownloader
WWW• http://www.vapid.dhs.org