PyxYuYu/MyBlog

Python学习记录(十二):乌云漏洞搜索爬虫&多线程

PyxYuYu opened this issue · 1 comments

The best accessory a girl can own is confidence.

0x01 Wooyun

  • 任意文件遍历/下载
    • 利用shadan搜索,寻找统一管理系统的网站,查看源代码,/Picture?imagePath=很明显的下载漏洞,下载网站源码
0x02 Wooyun爬虫

  • 乌云搜索爬虫
    • 需求分析:
      • 根据输入关键词搜索漏洞
    • 最后输出保存为html形式
    • 多线程
    • 命令行参数
    • 实现步骤:
      • url页面解析
        • 采用 urllib2 模块,添加 User-Agent 用户代理
      • User-Agent 采用 random 模块实现随机的功能
      • P.s. random 模块 常用函数
        • random.random() 用于生成一个0到1的随机浮点数: 0 <= n < 1.0
        • random.randint(a, b) 用于生成一个指定范围内的整数,其中 a 是下限,b 是上限,生成的随机数n: a <= n <= b
        • random.randrange([start], stop[, step]) 从指定范围内,按指定基数递增的集合中获取一个随机数 如 random.randrange(10, 100, 2) 就是相当于[10, 12, 14, 16, ..., 96, 98] 序列中随机获取一个,等同于 random.choice(range(10, 100, 2))
        • random.choice(sequence) list tuple 字符串 都属于 sequence
        • random.shuffle(x[, random]) 用于将一个列表中的元素打乱
        • random.sample(sequence, k ) 从指定序列中获取随机长度的片段
      • urlopen 涉及到 timeout 问题,假如网络出现问题,程序会卡死在 read()方法中,只要设置 timeout 就会抛出异常,所以需要添加一个异常处理,(如果需要对产生异常的url重新获取的话,可以用 while 循环,不过有可能还是会出现 time out
        • 异常处理
        • try...except...else 没有检测到异常的时候,则执行 else 语句,else 不能单独和 try 使用
        • finally 无论是否检测到异常,都会执行 finally 语句
          • 如果没有 except,那么执行完try finally,然后重新引发这个异常
        • 如果需要截获多个异常,可以一个except语句带多个异常,也可以多个 except 语句
        • 一个 except 语句,异常类实例就是第一个出现错误的异常(的详细原因),后面的异常就不会执行了,如果是多个 except 语句,那么截获的异常类之间应该具有继承关系,子类在前面,否则父类会直接截获子类的异常,放在后面的子类就不会被执行,因为在异常处理中,出现异常时, Python 将停止 try 中的语句进行,将异常传递给 except进行匹配,如果找到,就执行 except 后面的处理,处理完成后继续处理 try后面的语句,如此进行反复操作
        • 如果只是调用了 except 语句,不接任何的 Exception,将会导致上面的异常错误被覆盖掉,所以在使用异常处理的时候,最好清楚指定可能出现的异常类型并进行针对性处理
        • raise 允许程序抛出自定义异常,用于描述 Python 中未定义的异常,必须继承Exception类,命名以 Error 结尾,如果在 if语句中,通过判断,如果判断成功抛出一个异常,可以用 raise Exception(自定义的异常输出信息) 的方法简便的代替 try except
      • url网址全部放入到一个队列中保存
      • for 循环中,rangexrange的区别
        • range 返回一个列表
        • xrange 返回一个生成器,生成器是一个可迭代的对象
        • 需要循环一个较大的数据时,xrangerange好,因为 xrange 每次迭代后,数据对象会被回收,占用的内存空间会空闲出来重复利用,内存不会暴涨,而 range 创建了一个巨大的数字列表,需要提供较大的存储空间
      • for 循环最后的页面无法放入队列中,所以需要在最后单独放入最后的页面到队列
      • url 页面分析,寻找关键字
      • 分析可以用 BeautifulSoup 模块,提取漏洞标题和漏洞链接
        • find_all 中参数 hreftitlehref后面可以接 re.compile()来正则匹配出符合的带 urlTag,而因为乌云的页面上,会出现两个相同的 url,所以继续用 title 来过滤掉其中一个
      • 关键字寻找则去匹配漏洞标题
        • 首先因为 BeautifulSoup 模块找到的 Tag.stringUnicode类型,所以如果传入的是中文字符,需要带前缀 u,代表是 Unicode,但是如果是自己指定的话,那么只能用 unicode()方法来转换成 Unicode 类型,这里传入的都是 utf-8 类型
        • P.s. 前缀 r 代表这写字符串是普通字符 raw,也就是转义的 \,在这里也会失效,在正则表达式中,首先满足正则,然后满足转义,也就是说如果需要匹配 \,那么正则的话,就是 \\ 来匹配,但是匹配时候,每个 \ 又需要转义,所以就是 \\\\,如果加上 r ,就不需要再次地转义,只要满足正则就可以了,所以加上前缀 r 很重要
        • 多个关键字的话,需要用 | 分割开,关键字传入后,先转换成 Unicode,然后用split() 分割成一个列表,逐个匹配
    • 多线程分析关键字
      • 每个子线程都去参与搜集url分析关键字漏洞
      • 线程的参数在__init__中定义
      • 注意点:尽量少用给同一个变量自己覆盖自己,尤其是字符串类型
        • 比如 url = url + str(i) 后面再用这个 url 加上应该加的东西的话,其实 url 已经改变了
    • 命令行参数
      • 设定线程数,设定搜索关键字,设定起始页面,设定终止页面
      • 利用 argparse 模块
    • print 输出函数有限制,有一些特殊的 unicode 字符不能输出到 cmd 中,会报错 UnicodeEncodeError: 'gbk' codec can't encode character u'\u30fb' in position 4: illegal multibyte sequencecmd 默认是 gbk,假如encode('gbk') 还是不行,那就用 gb18030(包括了 gbk),encode('gb18030')
      • 如果编码仍然有错误,cmd 无法正确显示编码,那么只有改变标准输出的默认编码 添加一句 sys.stdout = io.TextIOWrapper (sys.stdout.buffer,encoding='gb18030')
0x03 一天总结

  • 如何显示搜索的进度,这一点还需要继续研究
  • 多线程、命令行都已经实现,保存为html文件明天完成