Cette version du service Knock Knock utilise l'opttion SSL de Ncat (NetCat du package Nmap) et un serveur SSH pour l'ouverture de session final. Il ne se content pas d'ouvrir un port. De plus tout les ports par défaut sont fermés et ouvert un à un. De plus Ncat n'autorise qu'une connexion et uniquement au client.
0x01. KK.CONF
# # Configuration # # Key to validate session KEY1="Ca5f523dFFE46C_fa0a96d6dfFb2B95FD058230B87afec6e" KEY2="144d7Dcc8AeC89b58D710+8Fa7ffe75Cc1d1ADA33d113368" KEY3="5AaddF32BFA3B63De2F16dfaDE50B=ebBaBbcE60DDe3aFb7" # SSH reference file CONF_SSHD_REF="kk.ssh.conf.ref" CONF_SSHD="kk.ssh.conf" # SSH daemon + SSH conf file DAEMON="/usr/sbin/sshd -D -d -e -f "$CONF_SSHD"" DAEMON_PROCNAME="sshd" CLIENT="/usr/bin/ssh" # Time to wait before considering a SSH client WAIT_FOR_SSH_CLIENT=30 # Log file LOG="kk.log" # Port to send data for next sessions PORT_CONF="50000" # Session port range MIN_PORT1=5 # 59999 >= port1 >= 50000 MIN_PORT2=5 # 59999 >= port2 >= 50000 MIN_PORT3=5 # 59999 >= port3 >= 50000 MIN_PORTSSH=5 # 59999 >= portssh >= 50000 # # Programs path # iptables=/sbin/iptables ncat=/usr/bin/ncat
0x02. KK.SSH.CONF.REF
Port %PORT% Protocol 2 UsePrivilegeSeparation yes KeyRegenerationInterval 3600 ServerKeyBits 1024 SyslogFacility AUTH LogLevel INFO StrictModes yes PubkeyAuthentication yes IgnoreRhosts yes RhostsRSAAuthentication no HostbasedAuthentication no PermitEmptyPasswords no ChallengeResponseAuthentication no X11Forwarding yes X11DisplayOffset 10 PrintMotd no PrintLastLog yes TCPKeepAlive yes AcceptEnv LANG LC_* Subsystem sftp /usr/lib/openssh/sftp-server UsePAM yes
0x03. KK.SERVER.SH
#!/bin/bash # # Configuration # source kk.conf # Assume iptables rule is OK, print only ncat result # Allow only for client and port open_listen() { client="$1" port="$2" sleep 1 ( ${iptables} -I INPUT -p tcp -s $client --dport $port -j ACCEPT ) >/dev/null 2>&1 ${ncat} --allow $client --ssl -lp $port } # Delete iptables rule with port and IP close_port() { client="$1" port="$2" ( $iptables -D INPUT -p tcp -s $client --dport $port -j ACCEPT ) >/dev/null 2>&1 } # This function may be overwritten to use another daemon # You should bind a crypted shell (cryptcat?) on port # SSH is "naturally" protected, audited and make crypted traffic configure_server() { client="$1" port="$2" ( ${iptables} -D INPUT -p tcp -s $client --dport $port -j ACCEPT ) >/dev/null 2>&1 ( ${iptables} -I INPUT -p tcp -s $client --dport $port -j ACCEPT ) >/dev/null 2>&1 cat "$CONF_SSHD_REF"|sed "s/%PORT%/$port/1" > "$CONF_SSHD" $DAEMON >"$LOG" 2>&1 & sleep $WAIT_FOR_SSH_CLIENT while true do w | grep "$client" >/dev/null 2>&1 && sleep 1.5 || break sleep 1 done killall "$DAEMON_PROCNAME" >>"$LOG" 2>&1 } # Be a daemon while true do # At first generate random port for sessions PORTS="$MIN_PORT1$(((RANDOM%8000)+2000));$MIN_PORT2$(((RANDOM%8000)+2000));$MIN_PORT3$(((RANDOM%8000)+2000));$MIN_PORTSSH$(((RANDOM%8000)+2000))" # Separate knock knock session and daemon port PORT1=$(echo $PORTS|cut -d';' -f1) PORT2=$(echo $PORTS|cut -d';' -f2) PORT3=$(echo $PORTS|cut -d';' -f3) PORTDAEMON=$(echo $PORTS|cut -d';' -f4) # Display used ports echo -e "\\n[+] Listening PORTS : $PORTS" # Allow connection to get session configuration $iptables -I INPUT -p tcp --dport $PORT_CONF -j ACCEPT CLIENT=$(echo $PORTS|ncat -v --ssl -lp $PORT_CONF 2>&1|grep 'Connection from '|head -n1|awk '{ print $4 }'|cut -d'.' -f1,2,3,4) echo "[-] New client : $CLIENT" $iptables -D INPUT -p tcp --dport $PORT_CONF -j ACCEPT [ -z "$CLIENT" ] && continue # Open 1st session... echo -ne "\\n[+] Listening on $PORT1 ..." res1=$(open_listen "$CLIENT" "$PORT1") # ...get and compare key #1... if [ "$res1" = "$KEY1" ]; then echo "OK!" close_port "$CLIENT" "$PORT1" echo -ne "[+] Listening on $PORT2 ..." res2=$(open_listen "$CLIENT" "$PORT2") if [ "$res2" = "$KEY2" ]; then echo "OK!" close_port "$CLIENT" "$PORT2" echo -ne "[+] Listening on $PORT3 ..." res3=$(open_listen "$CLIENT" "$PORT3") if [ "$res3" = "$KEY3" ]; then # ...if all keys are OK, then run daemon echo "OK!" close_port "$CLIENT" "$PORT3" echo -e "\\n[+] Opening session for $CLIENT" configure_server "$CLIENT" "$PORTDAEMON" close_port "$CLIENT" "$PORTDAEMON" else echo "Failed." fi else echo "Failed." fi else echo "Failed." fi done
0x04. KK.CLIENT.SH
#!/bin/sh # # Connect on host and via ssh user # user="$1" host="$2" # # Configuration # source kk.conf # # Get port sequence # PORTS=$(echo |ncat --ssl $host $PORT_CONF) echo -e "\\n[-] Got ports: $PORTS" PORT1=$(echo $PORTS|cut -d';' -f1) PORT2=$(echo $PORTS|cut -d';' -f2) PORT3=$(echo $PORTS|cut -d';' -f3) PORTSSH=$(echo $PORTS|cut -d';' -f4) # # Function to open port one by one, exit if fail # toctoc() { hst="$1" prt="$2" key="$3" iky="$4" [ $# -eq 5 ] && wit="$5" sleep $wit ; echo "$key"|ncat --ssl $hst $prt ; err=$? [ "$err" = "0" ] && printf "\\n[v] Door #$iky (%-5s) : Open!" "$prt" [ "$err" = "1" ] && printf "\\n[x] Door #$iky (%-5s) : Closed." "$prt" [ "$err" != "0" ] && exit $err } # # Make the sequence # toctoc "$host" "$PORT1" "$KEY1" 1 $WAIT_BETWEEN_TWO_SEQUENCE toctoc "$host" "$PORT2" "$KEY2" 2 $WAIT_BETWEEN_TWO_SEQUENCE toctoc "$host" "$PORT3" "$KEY3" 3 $WAIT_BETWEEN_TWO_SEQUENCE # If we are always in script, then all sequence are done. # We are able to open SSH session printf "\\n\\n[-] Got session from knockknock server\\n\\n" # Wait for SSH loading sleep $WAIT_SSH_TO_BE_READY # And then connect ssh "$user"@"$host" -p "$PORTSSH" # Print some return printf "\\n\\n"
=> Écrit par : Nicolas, le 04 août 2015