在渗透测试过程中,我们经常收集到很多用户的历史密码,部分用户的密码习惯是使用若干个相同的字符加上一些其他的字符,比如:
```
user01_history0:Passw0rd0
user01_history1:Password1
user01_history2:Password2
user01_history3:Passw0rd3
user02_history0:00P@ssw0rd
user02_history1:01P@ssw0rd
user02_history2:02P@ssw0rd
user02_history3:03P@ssw0rd
user02_history4:04P@ssw0rd
```
我们可以用算法来提取用户历史密码中的相同字符串,这里借鉴最长公共字符串问题(LCS) 的解决思路,查找出用户密码中的相同部分。代码如下:
```python
def common_string(password1, password2):
# 动态规划算法,计算2个密码的最大相同长度
x = len(password1)
y = len(password2)
longest_common = 0
result = []
# 使用字典作为矩阵
lcs_matrix = {}
# 算法复杂度O(N*M)
for i in range(x):
for j in range(y):
# 处理字符相同情况
if password1[i] == password2[j]:
if i == 0 or j == 0:
lcs_matrix[i,j] = 1
# lcs_matrix[i,j]的值等于矩阵坐标 i,j 左上角的值加1
# 0 | 0 0 | 0
# ---|--- ===> ---|---
# 0 | 0 0 | 1
else:
lcs_matrix[i,j] = lcs_matrix[i - 1,j - 1] + 1
# 提取相同的字符
if lcs_matrix[i,j] > longest_common:
longest_common = lcs_matrix[i,j]
result = [password1[i - lcs_matrix[i,j] + 1:i + 1]]
elif lcs_matrix == longest_common:
result = result + [password1[i - lcs_matrix[i,j] + 1:i + 1]]
else:
# 正常的算法应该是:
# lcs_matrix[i,j] = max(lcs_matrix[i-1,j],lcs_matrix[i,j-1])
lcs_matrix[i,j] = 0
if len(result) > 0:
return result[0]
else:
return ''
```
接着读取密码文件,用正则匹配用户名和历史密码,并存入python字典:
```python
f = open(filename, 'r')
username_dict = {}
# 获取用户名密码正则
re_passwd = re.compile(r'^([^:]+):(.+)$')
# 获取历史密码正则
re_his = re.compile(r'^(.+)_history\d+$')
for line in f.readlines():
results = re_passwd.match(line)
if history != None:
username = history.groups()[0]
else:
username = results.groups()[0]
if not username in username_dict:
username_dict[username] = []
username_dict[username].append(results.groups()[1])
f.close()
```
为了批量处理用户的密码,我们需要创建1个函数遍历用户的密码列表:
```python
# 小于3的字符串不记录
def compare_passwords(passwords, min_len=3):
commons = {}
for i in range(0, len(passwords) - 1):
for j in range(i + 1, len(passwords)):
common = common_string(passwords[i], passwords[j])
if len(common) >= min_len:
if common not in commons:
commons[common] = 0
commons[common] += 1
return commons
```
最后处理刚才记录用户名、密码的python字典
```python
for username, passwords in sorted(username_dict.items()):
commons_password = sorted(
[(value, key) for key, value in compare_passwords(passwords, 3).items()])
if len(commons_password) > 0:
print("{username}:{password}".format(username=username,password=commons_password[-1][1]))
else:
print("Not Found!")
```
输出结果
```
user01:Passw
user02:P@ssw0rd
```