#!/bin/bash
#
# $Id: permtree,v 0.11 2009/11/21 07:36:15 stef Exp $
#
# Takes a directory tree (copy of webroot) as input and generates lists
# of permutations of each possible path. Intended to be used when
# searching for "hidden" files and directories in web applications. 
#
# Copyright (c) 2009, Stefan Pettersson, http://www.bigpointyteeth.se/
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

IFS=
PATH="/bin:/usr/bin:/usr/local/bin"
me=$(basename $0)

error() { echo "$me: $1" 1>&2; }

if test -z $2; then
    echo "usage: $me <webroot> <base name>"
    exit 1
fi

trap "error 'user abort'; exit 1" 1 2 3 15

dir=$1
base=$2
glob="${base}-*.txt"

# output file names
treefile=${base}-tree.txt
filesfile=${base}-files.txt
dirsfile=${base}-dirs.txt
pfilesfile=${base}-perm-files.txt
pdirsfile=${base}-perm-dirs.txt
pcurlfilesconf=${base}-curl-perm-files.conf
pcurldirsconf=${base}-curl-perm-dirs.conf

# check if dir exists
if test ! -d $dir; then
    error "directory '$dir' does not exist"
    exit 1
fi

# enter the working directory
cd $dir

# check if any of the output files already exists
for file in $treefile $filesfile $dirsfile $pfilesfile $pdirsfile $pcurlfilesconf $pcurldirsconf; do
    if test -f $file; then
        error "file '$file' already exists"
        exit 1
    fi
done

# show a tree structure representing the directory tree
tree -aF --dirsfirst -I "$glob" > $treefile

# generate a list of all absolute paths in the webroot
tree -aifF --dirsfirst -I "$glob" | cut -c 2- | egrep "^/" | egrep -v "/$" > $filesfile

# generate a list of all absolute paths to directories in webroot
tree -aifF -I "$glob" | cut -c 2- | egrep "/$" > $dirsfile

# first we mangle all the file names
cat $filesfile | while read line; do
    # break the absolute path into pieces
    dn=$(dirname $line)
    bn=$(basename $line)
    # split the file name across the last dot
    nam=$(echo $bn | awk -F . '{if (NF>1) NF=NF-1; OFS="."; print}')
    ext=$(echo $bn | awk -F . '{print $NF}')

cat << EOF | sed 's/\/\//\//g' >> $pfilesfile 
$dn/$nam
$dn/${nam}1.$ext
$dn/${nam}2.$ext
$dn/${nam}.1.$ext
$dn/${nam}.2.$ext
$dn/${nam}-1.$ext
$dn/${nam}-2.$ext
$dn/${nam}_1.$ext
$dn/${nam}_2.$ext
$dn/$bn.bak
$dn/$bn.backup
$dn/$bn.old
$dn/$bn.new
$dn/$bn.test
$dn/$bn-bak
$dn/$bn-backup
$dn/$bn-old
$dn/$bn-new
$dn/$bn-test
$dn/$nam.bak
$dn/$nam.backup
$dn/$nam.old
$dn/$nam.new
$dn/$nam.test
$dn/$nam.bak.$ext
$dn/$nam.backup.$ext
$dn/$nam.old.$ext
$dn/$nam.new.$ext
$dn/$nam.test.$ext
$dn/$nam-bak.$ext
$dn/$nam-backup.$ext
$dn/$nam-old.$ext
$dn/$nam-new.$ext
$dn/$nam-test.$ext
$dn/${nam}_bak.$ext
$dn/${nam}_backup.$ext
$dn/${nam}_old.$ext
$dn/${nam}_new.$ext
$dn/${nam}_test.$ext
$dn/$nam.txt
$dn/_$bn
$dn/.$bn
$dn/${bn}_
$dn/${nam}_.$ext
$dn/$bn.swp
$dn/$bn.gz
$dn/$bn~
$dn/$bn.1
$dn/$bn.2
$dn/Copy of $bn
$dn/$nam - Copy.$ext
$dn/Kopia av $bn
$dn/$nam - Kopia.$ext
EOF
done

# let's take on the directory names
cat $dirsfile | while read line; do

    # if there is only one "/" we're in the root, skip that
    if test $line == "/"; then
        continue
    fi

    # break the absolute path into pieces
    dn=$(dirname $line)
    bn=$(basename $line)

cat << EOF | sed 's/\/\//\//g' >> $pdirsfile
$dn/${bn}1
$dn/${bn}2
$dn/$bn.1
$dn/$bn.2
$dn/$bn-1
$dn/$bn-2
$dn/${bn}_1
$dn/${bn}_2
$dn/$bn.bak
$dn/$bn.new
$dn/$bn.old
$dn/$bn.backup
$dn/$bn.test
$dn/$bn-bak
$dn/$bn-new
$dn/$bn-old
$dn/$bn-backup
$dn/$bn-test
$dn/${bn}_bak
$dn/${bn}_new
$dn/${bn}_old
$dn/${bn}_backup
$dn/${bn}_test
$dn/new$bn
$dn/old$bn
$dn/backup$bn
$dn/test$bn
$dn/new_$bn
$dn/old_$bn
$dn/backup_$bn
$dn/test_$bn
$dn/new-$bn
$dn/old-$bn
$dn/backup-$bn
$dn/test-$bn
$dn/new $bn
$dn/old $bn
$dn/backup $bn
$dn/test $bn
$dn/$bn.zip
$dn/$bn.rar
$dn/$bn.tar.gz
$dn/$bn.tgz
$dn/$bn.7za
$dn/old$bn.zip
$dn/old$bn.rar
$dn/old$bn.tar.gz
$dn/old$bn.tgz
$dn/old_$bn.zip
$dn/old_$bn.rar
$dn/old_$bn.tar.gz
$dn/old_$bn.tgz
$dn/backup_$bn.zip
$dn/backup_$bn.rar
$dn/backup_$bn.tar.gz
$dn/backup_$bn.tgz
$dn/${bn}_backup.zip
$dn/${bn}_backup.rar
$dn/${bn}_backup.tar.gz
$dn/${bn}_backup.tgz
$dn/_$bn
$dn/${bn}_
$dn/Copy of $bn
$dn/$bn - Copy
$dn/Kopia av $bn
$dn/$bn - Kopia
EOF
done

# generate curl configuration files for testing file permutations
echo -e 'include\nsilent\nuser-agent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"\nwrite-out = "%{http_code}\\t%{size_download}\\t%{num_redirects}\\t%{url_effective}\\t%{redirect_url}\\n"' > $pcurlfilesconf
while read line; do
    path=$(echo $line | sed -e 's/%/%25/g' -e 's/ /+/g' -e 's/\&/%26/g' -e 's/+/%2b/g' -e 's/?/%3f/g')
    # XXX if you are aware of a better way to discard the contents of the responses
    # than inserting an "output" line for every url, please tell me
    echo -e "output = temp\nurl = <URL>$path" >> $pcurlfilesconf
done < $pfilesfile

# generate curl configuration files for testing directory permutations
echo -e 'include\nsilent\nuser-agent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"\nwrite-out = "%{http_code}\\t%{size_download}\\t%{num_redirects}\\t%{url_effective}\\t%{redirect_url}\\n"' > $pcurldirsconf
while read line; do
    path=$(echo $line | sed -e 's/%/%25/g' -e 's/ /+/g' -e 's/\&/%26/g' -e 's/+/%2b/g' -e 's/?/%3f/g')
    # XXX if you are aware of a better way to discard the contents of the responses
    # than inserting an "output" line for every url, please tell me
    echo -e "output = temp\nurl = <URL>$path" >> $pcurldirsconf
done < $pdirsfile

wc -l $dirsfile $pdirsfile $filesfile $pfilesfile | grep -v " total"

exit 0

# eof
