使用 BurpSuite 时,Python 请求 https:代码 403,但没有代码 200

Foz*_*oro 4 python ssl certificate python-requests burp

我目前正在尝试抓取retailmenot.com,这就是我的代码到目前为止的样子:

import requests
from collections import OrderedDict

s = requests.session()

s.headers = OrderedDict()
s.headers["Connection"] = "close"
s.headers["Upgrade-Insecure-Requests"] = "1"
s.headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36"
s.headers["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
s.headers["Sec-Fetch-Site"] = "none"
s.headers["Sec-Fetch-Mode"] = "navigate"
s.headers["Sec-Fetch-Dest"] = "document"
s.headers["Accept-Encoding"] = "gzip, deflate"
s.headers["Accept-Language"] = "en-GB,en-US;q=0.9,en;q=0.8"

s.get("https://www.retailmenot.com/sitemap/A")
Run Code Online (Sandbox Code Playgroud)

当我使用此代码时,我会立即重定向到 CloudFlare 页面。也就是说,每当我通过 burpsuite 传递流量时,用以下代码替换代码的最后一行:

s.get("https://www.retailmenot.com/sitemap/A", proxies = {"https":"https://127.0.0.1:8080"}, verify ="/Users/Downloads/cacert (1).pem")
Run Code Online (Sandbox Code Playgroud)

我直接进入网站。我觉得这有点奇怪,想知道是否有人可以向我解释为什么会发生这种情况,以及是否有办法通过使用一些不同的证书来获得类似的结果(为了使用 BurpSuite 证书,我需要保持应用程序打开)。提前谢谢了!

Ste*_*ich 8

看起来问题出在底层客户端 TLS 行为。

我有一个使用 OpenSSL 1.1.1b 的较旧版本的 Python 和一个使用 OpenSSL 1.1.1f 的较新版本。第一个版本失败,但第二个版本有效。这也可以解释为什么它与 Burp 一起使用:它使用略有不同的 TLS 行为。

我试图找出问题所在:使非工作版本使用工作版本的密码不会有帮助。其他主要区别是支持的签名算法。实际上,使用提到的 openssl 1.1.1b(以及 Anaconda Python 附带的较新版本),差异可以减少到 sigalgs:

 $ openssl s_client -connect www.retailmenot.com:443 -crlf
 ...[various output]...
 <paste the expected HTTP request>
 ...
 HTTP/1.1 403 Forbidden

 $ openssl s_client -connect www.retailmenot.com:443 -crlf -sigalgs 'ECDSA+SHA256'
 ...[various output]...
 <paste the expected HTTP request>
 ...
 HTTP/1.1 200 OK
Run Code Online (Sandbox Code Playgroud)

不幸的是,我在 Python 请求中看不到直接在 TLS 堆栈中设置签名算法的方法。API 没有公开,它只是使用默认值 - 因此失败或成功取决于 OpenSSL 的构建方式。

但看起来可以通过指定不同的安全级别来间接设置该值:

from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.ssl_ import create_urllib3_context

CIPHERS = ('DEFAULT:@SECLEVEL=2')
class CipherAdapter(HTTPAdapter):
    def init_poolmanager(self, *args, **kwargs):
        context = create_urllib3_context(ciphers=CIPHERS)
        kwargs['ssl_context'] = context
        return super(CipherAdapter, self).init_poolmanager(*args, **kwargs)

    def proxy_manager_for(self, *args, **kwargs):
        context = create_urllib3_context(ciphers=CIPHERS)
        kwargs['ssl_context'] = context
        return super(CipherAdapter, self).proxy_manager_for(*args, **kwargs)

s = requests.session()
s.mount('https://www.retailmenot.com/', CipherAdapter())
...
print(s.get("https://www.retailmenot.com/sitemap/A"))
Run Code Online (Sandbox Code Playgroud)

这与特定的标头设置一起,导致我的测试结果<Response [200]><Response [403]>.