本文作者:唐银@涂鸦智能安全实验室
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)欢迎白帽子来探索。