Net下HTTP访问穿越多层代理的方法以及代理服务器的验证

本文介绍了一种通过三层代理服务器实现网络访问的技术方案,重点解决了校园网环境下连接国外网站的问题。作者通过发送特定指令给各层代理服务器,实现了对目标网站的成功访问。

我们学校的网络环境是,所有的出校访问均须通过代理服务器(我们叫作sproxy),并且不能连接国外网站。为此,我想要做一个自动抓取和验证出国代理列表的WebService。我们所有的验证代理的请求,都需要通过两层代理,最终通到用来测试的网站(我使用了www.redhat.com)

  技术上的思路是,通过连接第一层代理sproxy(支持http tunnel),给第二层代理发送GET指令,从而完成对目标网页的访问。

  首先,通过普通的匿名透明代理的方法,是直接使用Socket发送GET命令,只不过与GET普通网站稍有不同罢了

直接访问:

GET / HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, */*
Accept-Language: zh-cn
UA-CPU: x86
Accept-Encoding: gzip, deflate
If-Modified-Since: Thu, 06 Jul 2006 15:39:53 GMT
If-None-Match: “1172d9-381c-44ad2ec9″
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
Host: www.redhat.com
Connection: Keep-Alive
Cookie: s_vi=[CS]v1|44AAA05400004577-A170C060000008A[CE]; Apache=61.147.159.196.23241152032846747

通过本机CCproxy:

GET / HTTP/1.0
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, */*
Accept-Language: zh-cn
UA-CPU: x86
Proxy-Connection: Keep-Alive
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
Host: www.redhat.com
Cookie: s_vi=[CS]v1|44AAA05400004577-A170C060000008A[CE]; Apache=61.147.159.196.23241152032846747

  可以看出来,只要给代理服务器发送正确的请求地址即可,不需要程序上特殊的变化
  事实上,对于不使用代理服务器的场合,你可以直接向某HTTP服务器发送GET /,而这在使用代理时不行,需要说明详细地址或者标明Host: www.redhat.com

对于两层代理,就有所不同了
  
  首先要给sproxy发送一个CONNECT指令,令其去连接某公众网代理(这里称为proxy2),然后通过这个Socket连接发送GET指令给proxy2。这里对sproxy(以后称proxy1)有一个要求,即必须支持CONNECT,也就是说必须是一个HTTP Tunnel,或者说支持HTTPS。
  由于一开始设置上的问题,我本以为返回HTTP 1.0的CCProxy不支持这样的方式,因为据说HTTP 1.0就不能支持HTTPS,连接一次,发送了数据一定会断开(一开始的测试中的确如此)。后来查阅资料才知道,HTTP 1.0只是默认不使用Connect: Keep-Alive的参数,事实上也是支持的,只要置上这个参数即可。
  但实际使用中,发现不加上这个参数也是可以的(我对proxy1没有使用这个参数,可能是.net下的Socket类自动加上了)。

  经过连续数天的测试,一直不能通过,问题集中在,给proxy2发送一次CONNECT命令,Socket就会断开,无法收到数据。这是典型的不支持HTTP Tunnel的表现,但是我一直怀疑是CCproxy和学校代理服务器的问题,没有发现根源所在。
  因为我们访问sproxy需要用户名密码验证,我不得已才使用了CCProxy。后来,我又安装了一个代理服务器软件,发现其中只要使用“代理嵌套”(CCproxy叫作二级代理)的时候都需要HTTPS,我突然想到,会不会需要在CCproxy中设置?
  于是,在CCproxy的设置-高级-二级代理中把代理类型设为HTTPS,使用proxy1做上级代理,果然成功。事实上,直接连接学校代理应该也是可以的,只是我还不知道如何在代理请求中发送用户验证信息(需要将验证信息截断为多个数据包,不能直接发送)。

 

  • 代码如下,调试通过并成功运行了十多天了:

    后台一个类:

    public string Get_Socket_Request_uip(string ip)
    {

    Encoding ASCII = Encoding.Default;

    //给Proxy2发送命令
    string Con = "CONNECT " + ip + " HTTP/1.1
    Connection: Keep-Alive

    ";
    string Get = "HEAD http://www.RedHat.com/ HTTP/1.1
    Host: www.RedHat.com
    Pragma: no-cache
    Connection: Close

    ";
    Byte[] ByteCon = ASCII.GetBytes(Con);
    Byte[] ByteGet = ASCII.GetBytes(Get);
    Byte[] RecvBytes = new Byte[256];
    Byte[] RecvBytes2 = new Byte[256];
    string strRetPage = null;
    string strRetCon = null;

    //建立Socket
    Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    //连接本地CCProxy
    IPAddress hostip = IPAddress.Parse("127.0.0.1");
    IPEndPoint ipend = new IPEndPoint(hostip, 808);
    //设置超时,超过了就证明这个代理无效
    s.SendTimeout = 20000;
    s.ReceiveTimeout = 20000;

    //这句话就是socket的Keep-Alive,我没有使用
    //s.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true);
    s.Connect(ipend);

    try
    {
    //发送CONNECT命令
    s.Send(ByteCon, ByteCon.Length, 0);

    Int32 bytes = s.Receive(RecvBytes, RecvBytes.Length, 0);
    strRetCon = strRetCon + ASCII.GetString(RecvBytes, 0, bytes);

    if (strRetCon.Contains("200"))
    {
    s.Send(ByteGet, ByteGet.Length, 0);

    Int32 bytes2 = s.Receive(RecvBytes2, RecvBytes2.Length, 0);
    strRetPage = strRetPage + ASCII.GetString(RecvBytes2, 0, bytes2);

    //本来这里会循环接收数据(本来发送的不是HEAD而是GET,取整个页面),后来发现有时候这会导致断线,就去掉了,只用HEAD命令取返回的HTTP Head
    /*while (bytes2 > 0)
    {
    bytes2 = s.Receive(RecvBytes2, RecvBytes2.Length, 0);
    strRetPage = strRetPage + ASCII.GetString(RecvBytes2, 0, bytes2);
    }*/
    }
    }
    catch
    {
    break;
    }
    finally
    {
    s.Shutdown(SocketShutdown.Both);
    s.Close();
    }
    return strRetPage;
    }

    前台的调用方法(已经使用证则表达式在别处的网页中抓取到待检测的代理列表,在matches数组中):

    public void TestProxy()
    {
    int r = 0;

    try
    {
    foreach (Match i in matches)
    {
    string ip = i.Result("${ip}");
    string port = i.Result("${port}");
    try
    {
    //这里的hc是后台那个类,myhttpclient
    string result = hc.Get_Socket_Request_uip(ip + ":" + port);

    if (result.Contains("200 OK"))
    {
    checkedproxy[r] = ip + ":" + port;
    r = r + 1;
    }
    }
    catch (TimeoutException)
    {
    continue;
    }
    catch
    {
    continue;
    }
    }
    }
    catch
    {
    break;
    }
    }

      WebService代码就不给出了,就是调用这个方法而已。
      
      大家应该可以看出,这里实际上通过了三层代理(CCproxy,proxy1,proxy2),所以,如果要通过n层代理,方法也是一样的,只要一层层的CONNECT下去就行,但要求前n-1层代理都要支持HTTP tunnel。
      另外,在实际部署中使用这个程序,需要在Web.config中添加一行

    system.web项下
    <httpRuntime executionTimeout=”600″/>

      否则超过10项的代理列表,几乎一定会超时的

<think>我们正在分析GET请求中可能存在的安全漏洞,特别是路径穿越(Path Traversal)问题。具体场景是:`GET/ReportServlet?getFileList&path=../../../`。攻击者可能通过构造特殊的路径参数(如`../../../`)来访问系统敏感文件或目录。 ###漏洞分析1.**路径穿越原理**当服务器未对用户输入的路径参数进行规范化或过滤时,攻击者可通过`../`序列突破目标目录限制。例如:```bash#假设服务端基础路径为/var/www/reports../../../etc/passwd#实际路径变为/etc/passwd```2.**漏洞危害**-敏感文件泄露(如`/etc/passwd`, `web.xml`)-任意文件读取/删除-服务器目录结构探测3. **漏洞验证方法**使用工具(如Burp Suite)发送包含`../`的请求:```httpGET /ReportServlet?getFileList&path=../../../etc HTTP/1.1```###解决方案####1.输入规范化与过滤(基础防御)```java//Java示例:使用getCanonicalPath解析规范路径String userPath =request.getParameter("path"); FilebaseDir= newFile("/var/www/reports"); FiletargetFile =new File(baseDir, userPath);//关键:验证解析后路径是否在基础目录内if(!targetFile.getCanonicalPath().startsWith(baseDir.getCanonicalPath())) {thrownew SecurityException("非法路径访问");} ```**注意**:禁止仅通过黑名单(如过滤`../`)防御,因存在绕过技巧(如`....//`)[^1]。####2.白名单机制(推荐) 限制路径参数为预期字符集:```java//仅允许字母、数字、下划线、短横线、点(不含路径分隔符) if(!userPath.matches("[a-zA-Z0-9_.-]+")){return "非法路径字符"; }``` ####3.上下文感知防御- **场景1:文件列表读取**仅允许访问特定子目录:```java//拼接路径前添加固定前缀(如用户ID)StringsafePath= "user_"+ userId+ "/" +userPath;``` -**场景2:文件下载**通过文件ID映射真实路径(数据库存储ID与路径对应关系)。####4.服务器配置加固- **Web容器层**(Tomcat示例)在`web.xml`添加安全约束:```xml<security-constraint><web-resource-collection><url-pattern>/ReportServlet</url-pattern></web-resource-collection><auth-constraint>true</auth-constraint></security-constraint>``` ###防御效果验证|攻击向量|防御效果| |------------------------|-----------------------| |`path=../../../etc`|被规范化验证拦截|| `path=%2e%2e%2f` (URL编码) |解码后仍被拦截|| `path=....//`|白名单字符集拦截|>**关键点**:路径穿越防御需结合输入验证和规范化检查,单一措施易被绕过[^2]。 ###相关问题1.如何防止URL编码形式的路径穿越攻击?2.除了路径穿越,文件下载接口还有哪些常见漏洞?3.在微服务架构中如何统一实现路径安全校验?</think>### GET请求路径穿越漏洞分析与解决方案 针对`GET /ReportServlet?getFileList&path=../../../`的路径穿越漏洞,以下是详细分析和解决方案: --- #### 漏洞原理分析 1. **路径穿越本质** - 攻击者通过`../`序列突破目标目录限制: ```math \text{基础路径} + \text{用户输入路径} \rightarrow \text{越权访问系统文件} ``` - 示例:若基础路径为`/var/www`,输入`../../../etc/passwd`将访问系统文件[^1] 2. **漏洞危害** - 敏感文件读取(`/etc/passwd`, 配置文件等) - 目录遍历获取服务器结构 - 配合其他漏洞实现RCE(如上传恶意文件后执行) 3. **常见攻击向量** | 攻击方式 | 示例请求 | |------------------------|----------------------------------| | 基础穿越 | `path=../../../etc/passwd` | | URL编码绕过 | `path=%2e%2e%2fetc%2fpasswd` | | 双重编码绕过 | `path=%252e%252e%252fetc/passwd` | | 空字节截断 | `path=../../../etc/passwd%00` | --- #### 解决方案 ##### 1. 输入验证与规范化(核心防御) ```java // Java示例:路径规范化与校验 String userPath = request.getParameter("path"); // 步骤1:路径规范化 Path basePath = Paths.get("/safe/base/dir").toAbsolutePath(); Path resolvedPath = basePath.resolve(userPath).normalize(); // 步骤2:验证是否在安全目录内 if (!resolvedPath.startsWith(basePath)) { throw new SecurityException("非法路径访问"); } // 步骤3:白名单过滤扩展名(仅允许.txt/.pdf等) String fileName = resolvedPath.getFileName().toString(); if (!fileName.matches(".*\\.(txt|pdf|docx)$")) { throw new SecurityException("非法文件类型"); } ``` ##### 2. 防御层增强 - **应用层** - 使用`File.getCanonicalPath()`获取规范路径(自动处理`../`) - 白名单限制允许字符:`[a-zA-Z0-9_.-]`(禁止`/ \ : * ? " < > |`) - **服务器层** ```nginx # Nginx防护配置(拦截包含../的请求) location ~ \.\./ { return 403; } ``` - **架构层** - 文件访问通过ID映射:`GET /file?id=123` → 数据库查询真实路径 - 敏感操作强制POST请求(避免参数暴露在日志) ##### 3. 安全检测工具 ```bash # 使用ZAP进行自动化测试 docker run -it owasp/zap2docker zap-cli quick-scan -s xss,sqli,traversal http://target ``` --- #### 防御效果验证 | 测试用例 | 防御结果 | |------------------------|------------------| | `path=../../../etc` | 被规范化拒绝 | | `path=%2e%2e%2f` | URL解码后拦截 | | `path=valid_dir/../..` | 规范化后路径重置 | | `path=a.txt%00.jsp` | 扩展名白名单拦截 | > **关键点**:路径穿越防御必须结合输入验证、路径规范化和访问控制三层防护[^2]。 --- #### 相关问题 1. 如何设计安全的文件下载接口? 2. 除了路径穿越,GET请求还有哪些常见安全风险? 3. 如何防止通过URL编码绕过安全检测? 4. 微服务架构下如何统一管理文件访问策略? [^1]: 路径穿越原理:通过`../`突破目录限制 [^2]: 多层防御可有效阻止编码绕过和空字节攻击
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值