├── .gitignore ├── LICENSE ├── README.md └── winshock_test.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 ANEXIA Internetdienstleistungs GmbH 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | winshock-test 2 | ============= 3 | 4 | Bash script that tests if a system is Winshock (MS14-066) vulnerable. 5 | 6 | This script was developed by the emergency response team at [ANEXIA](http://www.anexia-wwc.com). 7 | 8 | Important 9 | --------- 10 | 11 | winshock_test.sh does behavioural analysis based upon the available SSL ciphers. 12 | If you either do not have direct access to the target system due to SSL-offloading in any form or manually modified the available SSL ciphers the script will 13 | be giving **false positives**. 14 | 15 | 16 | Disclaimer 17 | ---------- 18 | 19 | This script does in no way try to exploit the vulnerability described in MS14-066. 20 | It merely checks for hints on whether the target system has been patched or not. 21 | For details, have a look at the script itself or read the short 'How it works' 22 | part of this document below. 23 | 24 | Usage 25 | ----- 26 | 27 | ```shell 28 | ./winshock_test.sh 10.0.0.1 3389 29 | ./winshock_test.sh 10.0.0.2 443 30 | ``` 31 | 32 | Be sure to use a port on which a service is listening for SSL connections, 33 | which you can actually connect to. If the script takes long to complete, 34 | chances are good that either no service is listening on that port or 35 | a firewall is blocking access to that port. 36 | 37 | The examples above use the default RDP and HTTPS ports for those checks. 38 | 39 | Also, please ensure you are connecting directly to the target system. A 40 | load balancer or any other form of SSL-offloading may impact the results 41 | and may generate false-positives or false-negatives. 42 | 43 | 44 | How it works 45 | ------------ 46 | 47 | MS14-066 introduced four new SSL ciphers, so a check can be made if 48 | the target system supports those previously unsupported ciphers. 49 | winshock_test.sh uses this fact by simply checking if those ciphers are 50 | supported by the target system or not. If they are supported, the patches 51 | have been applied. 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /winshock_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # winshock_test.sh 4 | # 5 | # This script tries to determine whether the target system has the 6 | # winshock (MS14-066) patches applied or not. 7 | # This is done by checking if the SSL ciphers introduced by MS14-066 are 8 | # available on the system. 9 | # 10 | # 11 | # Authors: 12 | # Stephan Peijnik 13 | # 14 | # The MIT License (MIT) 15 | # 16 | # Copyright (c) 2014 ANEXIA Internetdienstleistungs GmbH 17 | # 18 | # Permission is hereby granted, free of charge, to any person obtaining a copy 19 | # of this software and associated documentation files (the "Software"), to deal 20 | # in the Software without restriction, including without limitation the rights 21 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | # copies of the Software, and to permit persons to whom the Software is 23 | # furnished to do so, subject to the following conditions: 24 | # 25 | # The above copyright notice and this permission notice shall be included in all 26 | # copies or substantial portions of the Software. 27 | # 28 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 31 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 33 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34 | # SOFTWARE. 35 | 36 | VERSION=0.2.1 37 | HOST=$1 38 | PORT=${2:-443} 39 | 40 | if [ -z "$HOST" -o -z "$PORT" ] 41 | then 42 | echo "Usage: $0 host [port]" 43 | echo "port defaults to 443." 44 | exit 1 45 | fi 46 | 47 | echo "Checking if script is up-to-date..." 48 | REMOTE_VERSION=$(curl -k https://raw.githubusercontent.com/anexia-it/winshock-test/master/winshock_test.sh 2>/dev/null | grep '^VERSION=' | sed -e 's/^VERSION=//g') 49 | 50 | if [[ "$REMOTE_VERSION" != "$VERSION" ]] 51 | then 52 | echo -e "\033[91mYou are running an outdated version of this script." 53 | echo "The most recent version is $REMOTE_VERSION." 54 | echo -e "It is highly recommended to update your script first.\033[0m" 55 | read -p "Do you want to continue? (y/N) " -n 1 -r 56 | if [[ ! "$REPLY" =~ ^[Yy]$ ]] 57 | then 58 | exit 2 59 | fi 60 | else 61 | echo "Script is up-to-date." 62 | fi 63 | 64 | echo -e "\n\033[91m" 65 | cat <&1 >/dev/null 121 | then 122 | echo -e "\033[91mNO (OpenSSL does not support $c cipher.)\033[0m" 123 | echo -e "\033[91mAborting." 124 | exit 5 125 | fi 126 | done 127 | 128 | echo -e "\033[92mYES\033[0m" 129 | 130 | SERVER=$HOST:$PORT 131 | 132 | echo -e "\n\033[94mTesting ${SERVER} for availability of SSL ciphers added in MS14-066...\033[0m" 133 | 134 | patched="no" 135 | for cipher in ${MS14_066_CIPHERS} 136 | do 137 | echo -en "Testing cipher ${cipher}: " 138 | result=$(echo -n | openssl s_client -cipher "$cipher" -connect $SERVER 2>&1) 139 | if [[ "$result" =~ "connect:errno=" ]] 140 | then 141 | err=$(echo $result | grep ^connect: \ 142 | | sed -e 's/connect:errno=.*//g' -e 's/connect: //g') 143 | echo -e "\033[93mConnection error: $err" 144 | echo -e "Aborting checks.\033[0m" 145 | exit 1 146 | elif [[ "$result" =~ "SSL23_GET_SERVER_HELLO:unknown protocol" ]] 147 | then 148 | echo -e "\033[93mNo SSL/TLS support on target port." 149 | echo -e "Aborting checks.\033[0m" 150 | exit 1 151 | elif [[ "$result" =~ "SSL_CTX_set_cipher_list:no cipher match" ]] 152 | then 153 | echo -e "\033[93mYour version of OpenSSL is not supported." 154 | echo -e "Aborting checks.\033[39m" 155 | exit 1 156 | elif [[ "$result" =~ "Cipher is ${cipher}" || "$result" =~ "Cipher : ${cipher}" ]] 157 | then 158 | echo -e "\033[92mSUPPORTED\033[0m" 159 | if [[ "$patched" == "no" ]] 160 | then 161 | patched="yes" 162 | fi 163 | else 164 | echo -e "\033[91mUNSUPPORTED\033[0m" 165 | fi 166 | done 167 | 168 | windows_server_2012_or_later="no" 169 | windows_server_2012_r2="no" 170 | iis_detected="no" 171 | # added by @stoep: check whether a 443 port runs IIS 172 | if [[ "$PORT" == "443" ]] 173 | then 174 | iis=$(curl -k -I https://$SERVER 2> /dev/null | grep "Server" ) 175 | echo -n "Testing if IIS is running on port 443: " 176 | if [[ $iis == *Microsoft-IIS* ]] 177 | then 178 | iis_version=$(echo $iis | sed -e 's|Server: Microsoft-IIS/||g') 179 | iis_detected="yes" 180 | echo -e "\033[92mYES - Version ${iis_version}\033[0m" 181 | if [[ $iis_version == *8.5* ]] 182 | then 183 | echo -e "\033[91mWindows Server 2012 R2 detected. Results of this script will be inconclusive.\033[0m" 184 | windows_server_2012_or_later="yes" 185 | windows_server_2012_r2="yes" 186 | elif [[ $iis_version == *8.0* ]] 187 | then 188 | windows_server_2012_or_later="yes" 189 | windows_server_2012_r2="no" 190 | fi 191 | else 192 | echo -e "\033[91mNO\033[0m" 193 | fi 194 | fi 195 | 196 | # Check if Windows Server 2012 or later is running on the remote system... 197 | if [[ "$windows_server_2012_or_later" == "no" && "$iis_detected" == "no" ]] 198 | then 199 | echo -e "\033[94mChecking if target system is running Windows Server 2012 or later...\033[0m" 200 | for cipher in ${WINDOWS_SERVER_2012R2_CIPHERS} 201 | do 202 | echo -en "Testing cipher ${cipher}: " 203 | result=$(echo -n | openssl s_client -cipher "$cipher" -connect $SERVER 2>&1) 204 | if [[ "$result" =~ "connect:errno=" ]] 205 | then 206 | err=$(echo $result | grep ^connect: \ 207 | | sed -e 's/connect:errno=.*//g' -e 's/connect: //g') 208 | echo -e "\033[93mConnection error: $err" 209 | echo -e "Aborting checks.\033[0m" 210 | exit 1 211 | elif [[ "$result" =~ "SSL23_GET_SERVER_HELLO:unknown protocol" ]] 212 | then 213 | echo -e "\033[93mNo SSL/TLS support on target port." 214 | echo -e "Aborting checks.\033[0m" 215 | exit 1 216 | elif [[ "$result" =~ "Cipher is ${cipher}" || "$result" =~ "Cipher : ${cipher}" ]] 217 | then 218 | echo -e "\033[92mSUPPORTED\033[0m" 219 | if [[ "$windows_server_2012_or_later" == "no" ]] 220 | then 221 | windows_server_2012_or_later="yes" 222 | break 223 | fi 224 | else 225 | echo -e "\033[91mUNSUPPORTED\033[0m" 226 | fi 227 | done 228 | fi 229 | 230 | if [[ "$patched" == "yes" && "$windows_server_2012_or_later" == "no" ]] 231 | then 232 | patched="\033[92mYES\033[0m" 233 | elif [[ "$patched" == "yes" ]] 234 | then 235 | patched="\033[93mUNKNOWN" 236 | if [[ "$windows_server_2012_r2" == "yes" ]] 237 | then 238 | patched="$patched: Windows Server 2012 R2 detected." 239 | else 240 | patched="$patched: Windows Server 2012 or later detected." 241 | fi 242 | else 243 | patched="\033[91mNO\033[0m" 244 | fi 245 | 246 | echo -e "\033[94m$SERVER is patched: $patched\033[0m" 247 | echo -e "\n\033[93m" 248 | cat <