From 130cd2711b06cc8ba4b98b9c5aa78bf873412a5d Mon Sep 17 00:00:00 2001 From: Adrien Bourmault Date: Wed, 4 May 2022 14:44:59 +0200 Subject: [PATCH] Initial commit --- captcha.sh | 181 +++++++++++++++++++++++++++++ exemples/CALCUL.png | Bin 0 -> 7143 bytes exemples/NOTIN.png | Bin 0 -> 4810 bytes exemples/REPLACE.png | Bin 0 -> 5664 bytes exemples/REVERSE.png | Bin 0 -> 7430 bytes exemples/REVERSE2.png | Bin 0 -> 7024 bytes experimental.sh | 231 ++++++++++++++++++++++++++++++++++++++ get_validated_captchas.sh | 23 ++++ readme.md | 43 +++++++ savecaptcha.sh | 18 +++ 10 files changed, 496 insertions(+) create mode 100755 captcha.sh create mode 100644 exemples/CALCUL.png create mode 100644 exemples/NOTIN.png create mode 100644 exemples/REPLACE.png create mode 100644 exemples/REVERSE.png create mode 100644 exemples/REVERSE2.png create mode 100755 experimental.sh create mode 100755 get_validated_captchas.sh create mode 100644 readme.md create mode 100755 savecaptcha.sh diff --git a/captcha.sh b/captcha.sh new file mode 100755 index 0000000..8800e74 --- /dev/null +++ b/captcha.sh @@ -0,0 +1,181 @@ +#!/bin/bash + +# Copyright © 2021 Adrien Bourmault (neox@a-lec.org) +# Copyright © 2021 Echolib (echolib@dismail.de) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This script is an example captcha script. +# It takes the text to recognize in the captcha image as a parameter. +# It return the image binary as a result. ejabberd support PNG, JPEG and GIF. + +# The whole idea of the captcha script is to let server admins adapt it to +# their own needs. The goal is to be able to make the captcha generation as +# unique as possible, to make the captcha challenge difficult to bypass by +# a bot. +# Server admins are thus supposed to write and use their own captcha generators. + +# This script relies on ImageMagick. +# It is NOT compliant with ImageMagick forks like GraphicsMagick. + +INPUT=$1 +LENINPUT=${#INPUT} +DIGITS=(zéros uns deux trois quatres cinqs six septs huits neufs dix) +DIGIT=(zéro un deux trois quatre cinq six sept huit neuf dix) + + +# **************************************************************************** +# +# Tools +# +# **************************************************************************** + + +# Loops 10 times (should be enough) to check if a TARGET number is in INPUT +GENERATE__NOTIN() { +for i in {1..10} +do + FALSENBR=`seq 1 9 | sort -R | head -n 1` + ! [[ $INPUT =~ $FALSENBR ]] \ + && break +done +} + + +# **************************************************************************** +# +# Captcha shapes +# +# **************************************************************************** + + +# REPLACEs a random number in INPUT by another one randomized +REPLACE() { +NAME="REPLACE" +PLACE=`seq 1 6 | sort -R | head -n 1` +TARGET=`echo "$INPUT" | head -c $PLACE | tail -c 1` + +GENERATE__NOTIN +NAME+="-$FALSENBR-$TARGET" +NEWINPUT=${INPUT//$TARGET/$FALSENBR} +INSTRUCTIONS1="Recopiez ce nombre" +INSTRUCTIONS2="en changeant les ${DIGITS[FALSENBR]} en ${DIGITS[TARGET]}" +} + + +# REVERSEs INPUT. Ask to Add first or last number in random. +REVERSE() { +NAME="REVERSE" +RFL=`seq 1 2 | sort -R | head -n 1` # Rand First (1) or Last (2) +ADDNBR=${DIGITS[ADDNBR]} + +for ((i=$LENINPUT-1;i>=0;i--)) +do + NEWINPUT="$NEWINPUT${INPUT:$i:1}" +done + +if (( $RFL == 1 ));then + ADDNBR="${INPUT:0:1}" + NAME+="_FIRST" + NEWINPUT=${NEWINPUT:0:$LENINPUT-1} # Do not show first INPUT NBR + INSTRUCTIONS1="Écrivez le chiffre ${DIGIT[$ADDNBR]} puis le nombre " + INSTRUCTIONS2="en recopiant de DROITE à GAUCHE ←" +else + ADDNBR="${INPUT:$LENINPUT-1:1}" + NAME+="_LAST" + NEWINPUT=${NEWINPUT:1:$LENINPUT-1} # Do not show last INPUT NBR + INSTRUCTIONS1="Recopiez de DROITE à GAUCHE ←" + INSTRUCTIONS2="et terminez par le chiffre ${DIGIT[$ADDNBR]}" +fi +NAME+="-$ADDNBR" +} + + +# Add FALSE NBR to INPUT at three randomized place +NOTIN() { +NAME="NOTIN" +GENERATE__NOTIN +PLACE=(`seq 0 $((LENINPUT-1)) | sort -R | head -n 3 | sort -n`) +for i in `seq 0 $((LENINPUT-1))` +do + (( $i == ${PLACE[0]} )) \ + && NEWINPUT+="$FALSENBR" + (( $i == ${PLACE[1]} )) \ + && NEWINPUT+="$FALSENBR" + (( $i == ${PLACE[2]} )) \ + && NEWINPUT+="$FALSENBR" + NEWINPUT="$NEWINPUT${INPUT:$i:1}" +done +NAME+="-$FALSENBR" +INSTRUCTIONS1="Recopiez ce nombre sans les ${DIGITS[FALSENBR]}" +} + + +# Take a random NBR from INPUT. Calculate X +CALCUL() { +PLACE=`seq 1 $((LENINPUT)) | sort -R | head -n 1` +TARGET=`echo "$INPUT" | head -c $PLACE | tail -c 1` +NEWINPUT=${INPUT//$TARGET/X} + +RC=`seq 1 2 | sort -R | head -n 1` # 1 = - | 2 = + +if (( $RC == 1 ));then + FALSENBR=`seq $TARGET 10 | sort -R | head -n 1` + RESUME=$(( FALSENBR - TARGET )) + INSTRUCTIONS1="Calculez: ${DIGIT[FALSENBR]} moins ${DIGIT[RESUME]} et copiez" + NAME="CALCULM-$FALSENBR-$RESUME" +else + FALSENBR=`seq 1 4 | sort -R | head -n 1` + if (( $FALSENBR <= $TARGET ));then + RESULT=$(( TARGET + FALSENBR )) + RESUME=$(( TARGET - FALSENBR )) + INSTRUCTIONS1="Calculez: ${DIGIT[FALSENBR]} plus ${DIGIT[RESUME]} et copiez" + NAME="CALCULP-$FALSENBR-$RESUME" + else + RESULT=$(( FALSENBR - TARGET )) + RESUME=$(( TARGET - RESULT )) + INSTRUCTIONS1="Calculez: ${DIGIT[RESULT]} plus ${DIGIT[RESUME]} et copiez" + NAME="CALCULP-$RESULT-$RESUME" + fi +fi +INSTRUCTIONS2="en remplaçant chaque X par la somme" +} + + +# **************************************************************************** +# +# Random captcha shape choice (aka main) +# +# **************************************************************************** + +MODULES=(CALCUL NOTIN REPLACE REVERSE) +RMODULE=`seq 0 $(( ${#MODULES[@]} - 1)) | sort -R | head -n 1` +eval "${MODULES[RMODULE]}" + +TEXT="$NEWINPUT" +CHAPRILURI=/var/lib/ejabberd/chapril_captchas/$(date "+%Y-%m-%d-%H%M%S")_${NAME}_${INPUT}.png + +convert -size 300x70 xc:none -pointsize 20 \ + \( -clone 0 -fill black \ + -stroke black -strokewidth 1 \ + -font Helvetica-Narrow -annotate "0x0+0+0" "\n $INSTRUCTIONS1" \ + -font Helvetica-Bold -annotate "0x0+0+22" "\n $TEXT" \ + -font Helvetica-Narrow -annotate "0x0+0+44" "\n $INSTRUCTIONS2" \ + -roll +$ROLL_X+0 \ + -wave "$WAVE1_AMPLITUDE"x"$WAVE1_LENGTH" \ + -roll -$ROLL_X+0 \) \ + -flatten -crop 300x70 +repage -quality 500 \ + -depth 11 png:"$CHAPRILURI" + +convert -size 300x70 xc:none -pointsize 20 \ + \( -clone 0 -fill black \ + -stroke black -strokewidth 1 \ + -font Helvetica-Narrow -annotate "0x0+0+0" "\n $INSTRUCTIONS1" \ + -font Helvetica-Bold -annotate "0x0+0+22" "\n $TEXT" \ + -font Helvetica-Narrow -annotate "0x0+0+44" "\n $INSTRUCTIONS2" \ + -roll +$ROLL_X+0 \ + -wave "$WAVE1_AMPLITUDE"x"$WAVE1_LENGTH" \ + -roll -$ROLL_X+0 \) \ + -flatten -crop 300x70 +repage -quality 500 -depth 11 png:- diff --git a/exemples/CALCUL.png b/exemples/CALCUL.png new file mode 100644 index 0000000000000000000000000000000000000000..09032e1ba430c054ca01d4f245b026db5fd36e97 GIT binary patch literal 7143 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 bvvIUT{Qn&)1{!E@8~~b+p^#E_%kcjN%@+8A literal 0 HcmV?d00001 diff --git a/exemples/NOTIN.png b/exemples/NOTIN.png new file mode 100644 index 0000000000000000000000000000000000000000..fdfaf1a11df94b23b41c27785bfe5de6372ee3aa GIT binary patch literal 4810 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 ZLcJsYZ$g-VBI1MqFfp_MV{W;}{|Cb9Xf6N% literal 0 HcmV?d00001 diff --git a/exemples/REPLACE.png b/exemples/REPLACE.png new file mode 100644 index 0000000000000000000000000000000000000000..a87c3c9af3912babedef407b7c212339dc4974de GIT binary patch literal 5664 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 PFaQj6jdUvSz$5+(y`|ze literal 0 HcmV?d00001 diff --git a/exemples/REVERSE.png b/exemples/REVERSE.png new file mode 100644 index 0000000000000000000000000000000000000000..0ac19951652e753e2c852520e444f5271f67859a GIT binary patch literal 7430 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%0Av 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 +do + NEWINPUT="$NEWINPUT${INPUT:$i:1}" +done + +if (( $RFL == 1 ));then + ADDNBR="${INPUT:0:1}" + NAME+="_FIRST" + NEWINPUT=${NEWINPUT:0:$LENINPUT-1} # Do not show first INPUT NBR + INSTRUCTIONS1="Écrivez le chiffre ${DIGIT[$ADDNBR]}" + INSTRUCTIONS2="et recopiez de DROITE à GAUCHE ←" +else + ADDNBR="${INPUT:$LENINPUT-1:1}" + NAME+="_LAST" + NEWINPUT=${NEWINPUT:1:$LENINPUT-1} # Do not show last INPUT NBR + INSTRUCTIONS1="Recopiez de DROITE à GAUCHE ←" + INSTRUCTIONS2="et terminez par le chiffre ${DIGIT[$ADDNBR]}" +fi +NAME+="-$ADDNBR" +} + + +# Add FALSE NBR to INPUT at three randomized place +NOTIN() { +NAME="NOTIN" +GENERATE__NOTIN +PLACE=(`seq 0 $((LENINPUT-1)) | sort -R | head -n 3 | sort -n`) +for i in `seq 0 $((LENINPUT-1))` +do + (( $i == ${PLACE[0]} )) \ + && NEWINPUT+="$FALSENBR" + (( $i == ${PLACE[1]} )) \ + && NEWINPUT+="$FALSENBR" + (( $i == ${PLACE[2]} )) \ + && NEWINPUT+="$FALSENBR" + NEWINPUT="$NEWINPUT${INPUT:$i:1}" +done +NAME+="-$FALSENBR" +INSTRUCTIONS1="Recopiez ce nombre sans les ${DIGITS[FALSENBR]}" +} + + +# Take a random NBR from INPUT. Calculate X +CALCUL() { +PLACE=`seq 1 $((LENINPUT)) | sort -R | head -n 1` +TARGET=`echo "$INPUT" | head -c $PLACE | tail -c 1` +NEWINPUT=${INPUT//$TARGET/X} + +RC=`seq 1 2 | sort -R | head -n 1` # 1 = - | 2 = + +if (( $RC == 1 ));then + FALSENBR=`seq $TARGET 10 | sort -R | head -n 1` + RESUME=$(( FALSENBR - TARGET )) + INSTRUCTIONS1="Calculez: ${DIGIT[FALSENBR]} moins ${DIGIT[RESUME]} et copiez" + NAME="CALCULM-$FALSENBR-$RESUME" +else + FALSENBR=`seq 1 4 | sort -R | head -n 1` + if (( $FALSENBR <= $TARGET ));then + RESULT=$(( TARGET + FALSENBR )) + RESUME=$(( TARGET - FALSENBR )) + INSTRUCTIONS1="Calculez: ${DIGIT[FALSENBR]} plus ${DIGIT[RESUME]} et copiez" + NAME="CALCULP-$FALSENBR-$RESUME" + else + RESULT=$(( FALSENBR - TARGET )) + RESUME=$(( TARGET - RESULT )) + INSTRUCTIONS1="Calculez: ${DIGIT[RESULT]} plus ${DIGIT[RESUME]} et copiez" + NAME="CALCULP-$RESULT-$RESUME" + fi +fi +INSTRUCTIONS2="en remplaçant chaque X par la somme" +} + +# Sum 2 LAST numbers. Hide LAST or BEFORE LAST +CALCEND() { +END1=${INPUT:$LENINPUT-2:1} +END2=${INPUT:$LENINPUT-1:1} +ENDS=$(( END1 + END2 )) +REND=`seq 1 2 | sort -R | head -n 1` +if (( $REND == 1 ));then + # Hide LAST + NEWINPUT=${INPUT:0:LENINPUT-1}X + NAME="END-${END1}X" +else + # Hide BEFORE LAST + NEWINPUT=${INPUT:0:LENINPUT-2}X$END2 + NAME="END-X$END2" +fi +INSTRUCTIONS1="La somme des 2 derniers chiffres est $ENDS" +INSTRUCTIONS2="Copiez en remplaçant X par sa valeur" +} + +# Replace 2 X (smaller > bigger | bigger > smaller) +LEMO() { +MAXNBR=${INPUT:0:1} +MINNBR=${INPUT:0:1} +for i in `seq 1 $((LENINPUT-1))` +do + (( ${INPUT:$i:1} > $MAXNBR )) \ + && MAXNBR=${INPUT:$i:1} + (( ${INPUT:$i:1} < $MINNBR )) \ + && MINNBR=${INPUT:$i:1} +done + +for i in `seq 0 $((LENINPUT-1))` +do + if (( ${INPUT:$i:1} == $MINNBR ));then + INSTRUCTIONS1="Remplacez les X par ${DIGIT[MAXNBR]} et ${DIGIT[MINNBR]}" + INSTRUCTIONS2="! le plus PETIT en premier" + NAME="LEMO-$MINNBR-$MAXNBR" + break + elif (( ${INPUT:$i:1} == $MAXNBR ));then + INSTRUCTIONS1="Remplacez les X par ${DIGIT[MINNBR]} et ${DIGIT[MAXNBR]}" + INSTRUCTIONS2="! Le plus GRAND en premier" + NAME="LEMO-$MAXNBR-$MINNBR" + break + fi +done + +NEWINPUT=`echo $INPUT | sed "s/$MINNBR/X/"` +NEWINPUT=`echo $NEWINPUT | sed "s/$MAXNBR/X/"` +} + +# **************************************************************************** +# +# Random captcha shape choice (aka main) +# +# **************************************************************************** + +MODULES=(CALCUL CALCEND LEMO NOTIN REPLACE REVERSE) +RMODULE=`seq 0 $(( ${#MODULES[@]} - 1)) | sort -R | head -n 1` +eval "${MODULES[RMODULE]}" + +TEXT="$NEWINPUT" +DATE="$(date "+%Y-%m-%d-%H%M%S")" +CHAPRILURI=/var/lib/ejabberd/chapril_captchas/${DATE}_${NAME}_${INPUT}.png + +convert -size 300x70 xc:none -pointsize 20 \ + \( -clone 0 -fill black \ + -stroke black -strokewidth 1 \ + -font Helvetica-Narrow -annotate "0x0+0+0" "\n $INSTRUCTIONS1" \ + -font Helvetica-Bold -annotate "0x0+0+22" "\n $TEXT" \ + -font Helvetica-Narrow -annotate "0x0+0+44" "\n $INSTRUCTIONS2" \ + -roll +$ROLL_X+0 \ + -wave "$WAVE1_AMPLITUDE"x"$WAVE1_LENGTH" \ + -roll -$ROLL_X+0 \) \ + -flatten -crop 300x70 +repage -quality 500 \ + -depth 11 png:"$CHAPRILURI" + +convert -size 300x70 xc:none -pointsize 20 \ + \( -clone 0 -fill black \ + -stroke black -strokewidth 1 \ + -font Helvetica-Narrow -annotate "0x0+0+0" "\n $INSTRUCTIONS1" \ + -font Helvetica-Bold -annotate "0x0+0+22" "\n $TEXT" \ + -font Helvetica-Narrow -annotate "0x0+0+44" "\n $INSTRUCTIONS2" \ + -roll +$ROLL_X+0 \ + -wave "$WAVE1_AMPLITUDE"x"$WAVE1_LENGTH" \ + -roll -$ROLL_X+0 \) \ + -flatten -crop 300x70 +repage -quality 500 -depth 11 png:- diff --git a/get_validated_captchas.sh b/get_validated_captchas.sh new file mode 100755 index 0000000..968d497 --- /dev/null +++ b/get_validated_captchas.sh @@ -0,0 +1,23 @@ +#! /bin/bash + +dates=$(zcat /var/log/ejabberd/ejabberd* 2> /dev/null | grep "was registered" \ + | cut -d[ -f 1 | cut -c 1-16) + +SAVEIFS=$IFS # Save current IFS +IFS=$'\n' # Change IFS to new line + +dates=($dates) # Split to array +IFS=$SAVEIFS # Restore IFS + +greppattern="" + +for (( i=0; i<${#dates[@]}; i++ )) +do + greppattern="$greppattern -e \"$(echo ${dates[$i]})\"" +done + +#echo -e ${greppattern} + +grepcommand="ls -lt --full-time /var/lib/ejabberd/chapril_captchas | grep $greppattern | cut -d ' ' -f 9" + +eval $grepcommand diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..46a529e --- /dev/null +++ b/readme.md @@ -0,0 +1,43 @@ +# Méthodes de génération de captcha pour ejabberd 2x.x + +## Réalisées dans le cadre du service XMPP du Chapril + +### Concept + +L'idée derrière ces méthodes de captchas est d'abord la simplicité de lecture pour l'utilisateur: +- Pas de déformation du texte +- Pas de coloration du texte +- Ecrit en français sous la forme d'une consigne se voulant "simple" tout en étant difficile à attaquer par force brute par un bot +- Compatible avec le système de génération de captcha de ejabberd (la XEP 0158) + +### Exemples + +Différentes méthodes sont utilisées. + +#### Remplacement (REPLACE) + +Une seule forme est disponible: + +![Exemple de remplacement](exemples/REPLACE.png) + +#### Inversion (REVERSE) + +Deux formes sont disponibles: + +![Premier exemple d'inversion](exemples/REVERSE.png) + +ou encore + +![Premier exemple d'inversion](exemples/REVERSE2.png) + +#### Intrus (NOTIN) + +Une seule forme est disponible: + +![Exemple d'intrus](exemples/NOTIN.png) + +#### Calcul (CALCUL) + +Une seule forme est disponible: + +![Exemple de calcul](exemples/CALCUL.png) \ No newline at end of file diff --git a/savecaptcha.sh b/savecaptcha.sh new file mode 100755 index 0000000..a1f196f --- /dev/null +++ b/savecaptcha.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# This script relies on ImageMagick. +# It is NOT compliant with ImageMagick forks like GraphicsMagick. + +RAND_ANGLE=$1 +RAND_ITALIC=$2 +INPUT=$3 +SOLUTION=$4 + +convert -size 300x60 xc:none -pointsize 20 \ + \( -clone 0 -fill black \ + -stroke black -strokewidth 1 \ + -annotate "${RAND_ANGLE}x${RAND_ITALIC}+0+0" "\n $INPUT" \ + -roll +$ROLL_X+0 \ + -wave "$WAVE1_AMPLITUDE"x"$WAVE1_LENGTH" \ + -roll -$ROLL_X+0 \) \ + -flatten -crop 300x60 +repage -quality 500 -depth 11 png:"/var/tmp/captcha/${SOLUTION}_$(date "+%Y-%m-%d-%H%M%S").png"