freeBuf
python&nodejs应用https代理抓包证书验证问题解决方法
2023-07-17 15:43:17
所属地 浙江省

本文作者:唐银@涂鸦智能安全实验室

0x00 前言

最近在分析一个应用,主要的代码都是nodejs+Python写的,需要在Linux下运行。通过代理抓包的过程中遇到了一些问题,记录分享一下,希望帮助后来人少踩点坑。

我的系统环境是Ubuntu 20.04。


0x01 思路一:代码中关闭SSL证书校验

1、Python应用

抓python应用的https包,有两个思路,先说第一个,在代码中关闭SSL证书校验。

这个思路又有两个实现方法,一是把所有涉及url请求的代码都找出来。

比如所有requests.get(),requests.post(),requests.request()方法,加入参数verify=False。

response = requests.get(url, verify=False)
response = requests.post(url, data=payload, verify=False)
response = requests.request("POST", url, headers=headers, data=payload, verify=False)


第二个实现方法是直接修改python的依赖库,例如代码中用到的是requests库,可以找到requests库的安装位置。

import requests
print(requests.__file__)

执行结果会输出requests库的__init__.py文件的路径。需要找到同目录下的sessions.py文件。
在__init__方法中,找到这行:

self.verify = True

改成:

self.verify = False

之后使用requests库发起请求时,SSL证书检查将默认禁用。


如果使用urllib,可以通过下面代码全局取消证书验证:

import ssl
import urllib.request

# 创建一个不验证 SSL 证书的上下文
ssl._create_default_https_context = ssl._create_unverified_context

url = "https://stayfoolish.cc"
response = urllib.request.urlopen(url)


2、Nodejs应用

如果是nodejs,可以在系统环境变量中配置NODE_TLS_REJECT_UNAUTHORIZED=0,例如ubuntu下:

sudo nano /etc/environment

文件末尾添加:

NODE_TLS_REJECT_UNAUTHORIZED=0

注销重新登录,或者重启,环境变量全局生效。


也可以在nodejs代码中加上一行:

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

这种方式会全局禁用证书验证。


0x02 思路二:找到根证书存放位置,导入证书

另外一个思路是将代理的证书,导入到python校验证书时用到的根证书存放的位置(有的库会用系统预装的根证书,有的库可能使用python自己内置的证书库)。


BurpSuite导出的证书,默认是der格式,需要转换为pem格式。可以用openssl命令:

openssl x509 -inform DER -in cacert.der -out burp.pem

可以用curl测试下证书是否有效。

默认不带证书请求https站点会报错:

curl https://stayfoolish.cc

加-k参数会禁用SSL证书验证,请求成功。

curl -k https://stayfoolish.cc

带证书请求,和加-k参数的结果一致,说明证书没问题:

curl --cacert burp.pem https://stayfoolish.cc


查看python使用的证书库位置:

import certifi
print(certifi.where())

如果执行结果类似:/usr/local/lib/python3.8/site-packages/certifi/cacert.pem,在python库路径下,

说明python校验证书时使用了内置的证书库。

可以把自签名证书(PEM格式)也就是burp.pem的内容追加到cacert.pem文件的末尾。注意确保追加的证书内容和现有证书内容之间要留一个空行。


如果执行结果是:/etc/ssl/certs/ca-certificates.crt,

说明python校验证书时用到的根证书存放在系统默认的根证书文件中,直接将证书导入系统根证书,即可解决https抓包问题。


ubuntu下导入证书到系统根证书:

1、将burp.pem文件复制到/usr/local/share/ca-certificates/目录:

sudo cp burp.pem /usr/local/share/ca-certificates/burp.crt

注意:请确保文件扩展名改为.crt。


2、更新系统的证书存储:

sudo update-ca-certificates

参考:ubuntu系统上如何添加新的根证书 https://www.cnblogs.com/jiaoyiping/p/6629442.html


如果是mac中:

1、双击burp.pem文件,会打开钥匙串访问。

2、将证书拖放到"系统"钥匙串中。

3、在弹出的对话框中输入管理员密码,然后单击"修改钥匙串"。

4、双击导入的证书,展开"信任"部分。

5、将"使用此证书时"设置为"始终信任"。


如果是windows中:

1、双击burp.pem文件,会打开证书查看器。

2、单击"安装证书"按钮。

3、选择"本地计算机",然后单击"下一步"。

4、选择"将所有证书放入以下存储",然后单击"浏览"。

5、选择"受信任的根证书颁发机构",然后单击"确定"。

6、单击"下一步",然后单击"完成"。


再用默认的curl命令测试一下,不需要加额外参数请求也能成功了:

curl https://stayfoolish.cc


如果一不小心证书添加错了想要删掉,那么删除某个ca证书文件后,更新系统根证书,需要加-f(fresh)参数,否则会失败:

sudo update-ca-certificates -f

关于update-ca-certificates命令的更多解释,可以参考Ubuntu的文档:https://manpages.ubuntu.com/manpages/xenial/man8/update-ca-certificates.8.html


0x03 urllib.request.urlretrieve下载文件超时抓包失败问题解决

如果上面都做了,使用urllib.request.urlretrieve下载文件的方法时,又遇到 ssl handshake超时问题,可以参考下面步骤,增加timeout数值。


找到 urllib 库的安装位置:

import urllib
print(urllib.__file__)

通常在 Python 安装目录的 lib 文件夹中。


打开 urllib 文件夹,找到 request.py,这个文件包含了 urlretrieve 函数的定义。

def urlretrieve(url, filename=None, reporthook=None, data=None):
    # ...

在 urlretrieve 函数内部,找到以下代码:

with contextlib.closing(urlopen(url, data)) as fp:

这是调用 urlopen 函数的地方。添加超时参数:

with contextlib.closing(urlopen(url, data, timeout=20)) as fp:

参考:https://blog.csdn.net/a19990412/article/details/80330361

问题解决。


漏洞悬赏计划:涂鸦智能安全响应中心(https://src.tuya.com)欢迎白帽子来探索。

本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
文章目录