socks5

目录

判断socks5链接可用性

curl法

curl --socks5 你的代理IP:端口号 https://www.example.com

原始方法

数据包分析

ref:抓包分析:https://zgao.top/奇安信实习五-socks5协议抓包分析/ https://www.quarkay.com/code/383/socks5-protocol-rfc-chinese-traslationhttps://samsclass.info/122/proj/how-socks5-works.html

渗透的时候,扫描扫到了一批socks5链接。 想验证他们的可用性时,遇到了如下问题

socks5 链接是否真的是socks5?
socks5 链接能通哪些网络(公网?10段?172段?)
socks5 是否需要密码?

于是打算通过数据包分析来好好验证socks5的可用性

抓包分析:TCP三次握手

在开始socks5之前,会进行三次握手

抓包分析:client,请求认证

VER (版本)字段在此版本中设置为 X’05‘ NMETHODS (方法数目)字段包含了 METHODS (方法列表)中所包含的方法识别码的个数。 METHODS如下表

X’00‘  无需认证
X’01‘  GSSAPI
X’02‘  用户名/密码
X’03‘ 到 X’7F’  IANA 指定
X’80‘ 到 X’FE’  为私有方法保留
X’FF‘  无可接受方法

如下便是 方法数目为1,且方法为 无需认证(00)的client请求认证包

抓包分析:server,响应认证

VER (版本)字段在此版本中设置为 X’05‘ METHOD表示从请求认证中,选择一个方法作为认证(如果 METHOD (方法)字段为 X’FF‘, 表示方法列表中的所有方法均不可用,客户端收到此信息必须关闭连接。)

0500表示接受client的无需认证的认证请求,0500后面的是填充padding,不管。

抓包分析:client,发送地址请求

VER 协议版本: X‘05’

CMD 命令
CONNECT 连接, X‘01’
BIND 监听X‘02’
UDP ASSOCIATE UDP关联 X‘03’

RSV 保留字段

ATYP 地址类型
IPV4 X‘01’
域名 X‘03’
IPV6 X‘04’

DST.ADDR 目标地址
DST.PORT 目标端口 (网络字节序)

抓到的包

05:ver 01:CMD→connect 00: 保留 01: 地址类型 IPV4 17f000001: 要代理的地址(我这里请求的是127.0.0.1) 006e :要代理的地址的端口(我这里请求的是110,6e的转10进制就是110)

抓包分析:server,响应地址请求

VER协议版本: X‘05’

REP 回复字段(回复类型):
X‘00’ 成功
X‘01’ 常规 SOCKS 服务故障
X‘02’ 规则不允许的连接
X‘03’ 网络不可达
X‘04’ 主机无法访问
X‘05’ 拒绝连接
X‘06’ 连接超时
X‘07’ 不支持的命令
X‘08’ 不支持的地址类型
X‘09’ 到 X’FF’ 未定义
RSV 保留字段

ATYP 地址类型
IPV4 X‘01’
域名 X‘03’
IPV6 X‘04’

BND.ADDR 服务端绑定地址

BND.PORT 服务端绑定端口 (网络字节序)

比如我抓的这个包就是规则不允许

抓包分析总结

tcp三次握手→认证阶段→地址请求

脚本编写

我们可以这样制定socks5可用性检测的思路:

三次握手失败->无效

向server发送请求认证,请求00(无需认证0)和02(用户名密码认证)
server返回0xff ->无效
返回00->有戏
返回02->放到一边,待会来爆密码

向请求认证过程中返回00的server发送地址认证,请求一个socks5可能访问得到的ip:port
返回00->socks5可用性检测通过
返回02-06:可能是socks5无法访问这个ip:port,换成别的试试(批量跑一波内网)
返回其它:大概率没戏,不用看了

随手写的检测脚本

import requests
import concurrent.futures
import socket
from urllib.parse import urlparse


def check_proxy(proxy):
    urls = ["http://127.0.0.1:110"]
    for url in urls:
        try:
            response = requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=5)
            print(f"Proxy {proxy} is working for {url}")

        except requests.exceptions.RequestException as E:
            print(f"{proxy}:{E}")

def socket_check(proxy):
    # 创建一个socket对象
    proxy_parse = urlparse(proxy)
    host = proxy_parse.hostname
    port = proxy_parse.port

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(5)
    # 连接到SOCKS5代理服务器
    sock.connect((host,port))
    # 发送认证请求
    sock.sendall(b"\x05\x02\x00\x02")
    # 读取代理服务器的响应
    data = sock.recv(2)
    # 判断是否无需认证
    if len(data) == 2 and data[0] == 0x05 and data[1] == 0x00:
        print(f"{proxy}:无需认证")
        l00.append(proxy)
    elif len(data) == 2 and data[0] == 0x05 and data[1] == 0x02:
        print(f"{proxy}:需要认证")
        l02.append(proxy)
    elif len(data) == 2 and data[0] == 0x05 and data[1] == 0xff:
        print(f"{proxy}:代理存在但是不接受")
        lff.append(proxy)
    else:
        print(f"{proxy} 不是socks5")
        nop.append(proxy)

with open('socks5_verify.txt', 'r') as file:
    l00=[]
    l02=[]
    lff=[]
    nop=[]
    #with concurrent.futures.ThreadPoolExecutor() as executor:
    #   executor.map(socket_check, file)
    #for i in file:
    #    socket_check(i)
    print(f"无需认证::{l00}")
    print(f"需要密码:{l02}")
    print(f"socks5代理存在,但是验证方式不允许:{lff}")
    print(f"非socks5代理:{nop}")
    for proxy in l00:
        check_proxy(proxy)

然后把无需认证的socks5拿到fscan设置代理,跑跑内网,兴许有奇迹

10.0.0.0/8 172.16.0.0/12 192.168.0.0/16