前言
在開始本文之前,先來介紹一下相關(guān)內(nèi)容,大家都知道一些防護(hù)SSRF漏洞的代碼一般使用正則來判斷訪問IP是否為內(nèi)部IP,比如下面這段網(wǎng)上比較常見的正則:
1
2
3
4
5
|
if re.match(r "^192\.168(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){2}$" , ip_address) or \ re.match(r "^172\.([1][6-9]|[2]\d|3[01])(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){2}$" , ip_address) or \ re.match(r "^10(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){3}$" , ip_address): raise Execption( "inner ip" ) |
很明顯這個(gè)正則有很多問題,可以有多種方式繞過,比如
1. 利用八進(jìn)制IP地址繞過
2. 利用十六進(jìn)制IP地址繞過
3. 利用十進(jìn)制的IP地址繞過
4. 各種進(jìn)制組合形成的IP繞過
一般我們常見都是10進(jìn)制表示的IP,其實(shí)系統(tǒng)是可以識(shí)別其他進(jìn)制表示的IP,比如8進(jìn)制,16進(jìn)制,或者它們的組合
所以,我們在測試系統(tǒng)是否有SSRF漏洞的時(shí)候,有時(shí)候需要嘗試各種進(jìn)制的IP組合,看看是否能繞過系統(tǒng)的防護(hù),于是就有了本文的這個(gè)小程序,用于自動(dòng)生成各種進(jìn)制形式的IP,以幫助我們進(jìn)行安全測試,下面話不多說了,來一起看看詳細(xì)的介紹:
實(shí)例源碼
程序代碼
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
|
#!/usr/bin/env python # -*- coding:utf8 -*- """ 各種進(jìn)制的IP表示及其它們的組合 """ import socket import struct import itertools def ip_split_by_comma_oct(ip): """ :param ip: :return: """ parsed_result = set () ip_split = str (ip).split( '.' ) ip_split_oct = [ oct ( int (_)) for _ in ip_split] parsed_result.add( '.' .join(ip_split_oct)) return parsed_result def ip_split_by_comma_hex(ip): """ :param ip: :return: """ parsed_result = set () ip_split = str (ip).split( '.' ) ip_split_hex = [ hex ( int (_)) for _ in ip_split] parsed_result.add( '.' .join(ip_split_hex)) return parsed_result def combination_oct_int_ip(ip): """ :param ip: :return: """ result = set () parsed_result = set () ip_split = str (ip).split( '.' ) oct_2 = list (itertools.combinations([ 0 , 1 , 2 , 3 ], 2 )) oct_3 = list (itertools.combinations([ 0 , 1 , 2 , 3 ], 3 )) for n, _ in enumerate (ip_split): _tmp = oct ( int (_)) _delete = ip_split[:n] + ip_split[n + 1 :] _delete.insert(n, _tmp) result.add( tuple (_delete)) for _ in oct_2: _tmp_ip = ip_split[:] _tmp1 = oct ( int (ip_split[_[ 0 ]])) _tmp2 = oct ( int (ip_split[_[ 1 ]])) del _tmp_ip[_[ 0 ]] del _tmp_ip[_[ 1 ] - 1 ] _tmp_ip.insert(_[ 0 ], _tmp1) _tmp_ip.insert(_[ 1 ], _tmp2) result.add( tuple (_tmp_ip)) for _ in oct_3: _tmp_ip = ip_split[:] _tmp1 = oct ( int (ip_split[_[ 0 ]])) _tmp2 = oct ( int (ip_split[_[ 1 ]])) _tmp3 = oct ( int (ip_split[_[ 2 ]])) del _tmp_ip[_[ 0 ]] del _tmp_ip[_[ 1 ] - 1 ] del _tmp_ip[_[ 2 ] - 2 ] _tmp_ip.insert(_[ 0 ], _tmp1) _tmp_ip.insert(_[ 1 ], _tmp2) _tmp_ip.insert(_[ 2 ], _tmp3) result.add( tuple (_tmp_ip)) for _ in result: parsed_result.add( '.' .join(_)) return parsed_result def combination_hex_int_ip(ip): """ :param ip: :return: """ result = set () parsed_result = set () ip_split = str (ip).split( '.' ) hex_2 = list (itertools.combinations([ 0 , 1 , 2 , 3 ], 2 )) hex_3 = list (itertools.combinations([ 0 , 1 , 2 , 3 ], 3 )) for n, _ in enumerate (ip_split): _tmp = hex ( int (_)) _delete = ip_split[:n] + ip_split[n + 1 :] _delete.insert(n, _tmp) result.add( tuple (_delete)) for _ in hex_2: _tmp_ip = ip_split[:] _tmp1 = hex ( int (ip_split[_[ 0 ]])) _tmp2 = hex ( int (ip_split[_[ 1 ]])) del _tmp_ip[_[ 0 ]] del _tmp_ip[_[ 1 ] - 1 ] _tmp_ip.insert(_[ 0 ], _tmp1) _tmp_ip.insert(_[ 1 ], _tmp2) result.add( tuple (_tmp_ip)) for _ in hex_3: _tmp_ip = ip_split[:] _tmp1 = hex ( int (ip_split[_[ 0 ]])) _tmp2 = hex ( int (ip_split[_[ 1 ]])) _tmp3 = hex ( int (ip_split[_[ 2 ]])) del _tmp_ip[_[ 0 ]] del _tmp_ip[_[ 1 ] - 1 ] del _tmp_ip[_[ 2 ] - 2 ] _tmp_ip.insert(_[ 0 ], _tmp1) _tmp_ip.insert(_[ 1 ], _tmp2) _tmp_ip.insert(_[ 2 ], _tmp3) result.add( tuple (_tmp_ip)) for _ in result: parsed_result.add( '.' .join(_)) return parsed_result def combination_hex_int_oct_ip(ip): """ :param ip: :return: """ result = set () parsed_result = set () ip_split = str (ip).split( '.' ) hex_3 = list (itertools.combinations([ 0 , 1 , 2 , 3 ], 3 )) for n1, n2, n3 in hex_3: _tmp_ip = ip_split[:] _tmp_2 = oct ( int (_tmp_ip[n2])) _tmp_3 = hex ( int (_tmp_ip[n3])) del _tmp_ip[n2] del _tmp_ip[n3 - 1 ] _tmp_ip.insert(n2, _tmp_2) _tmp_ip.insert(n3, _tmp_3) result.add( tuple (_tmp_ip)) for _ in result: parsed_result.add( '.' .join(_)) return parsed_result if __name__ = = '__main__' : ip = '10.1.100.1' ip_int = struct.unpack( '!L' , socket.inet_aton(ip))[ 0 ] ip_oct_no_comma = oct (ip_int) ip_hex_no_comma = hex (ip_int) ip_oct_by_comma = ip_split_by_comma_oct(ip) ip_hex_by_comma = ip_split_by_comma_hex(ip) all_result = ip_oct_by_comma | ip_hex_by_comma | combination_oct_int_ip(ip) | combination_hex_int_ip(ip) | combination_hex_int_oct_ip(ip) for _ip in all_result: print _ip |
代碼很容易看懂,首先生成純8進(jìn)制表示的IP、純16進(jìn)制表示的IP,然后在分別生成10進(jìn)制和8進(jìn)制混合組成的IP,16進(jìn)制和10進(jìn)制混合組成的IP, 16進(jìn)制8進(jìn)制10進(jìn)制混合組成的IP,最后輸出各種組合的結(jié)果
在使用其他腳本或者工具遍歷測試這個(gè)腳本的結(jié)果,看看是否能繞過SSRF的防護(hù)
部分截圖:
比如生成10.1.100.1 這個(gè)IP的其他各種進(jìn)制形式:
總結(jié)
工具雖然簡單,但卻能給我們的滲透測試帶來方便,其實(shí)工作中有很多可以總結(jié)沉淀的地方,都可以形成工具化,不僅能方便以后工作,還能有助于我們知識(shí)的沉淀,加快我們自身實(shí)力提升。也希望大家以后也能多多分享。
好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對(duì)服務(wù)器之家的支持。
原文鏈接:http://www.freebuf.com/sectool/140982.html