資安宣導 — 為什麼使用 PyYaml 解析 YAML 時要使用 safe_load 才對

Posted on  Jan 15, 2024  in  Python 程式設計 - 中階 , Python 資訊安全  by  Amo Chen  ‐ 1 min read

對於任何來自未受信任來源的資料,我們都必須假設它可能含有惡意的內容。

就連 YAML 檔也是一樣的!

本文環境

  • Python 3
  • PyYAML 6.0.1
$ pip install PyYAML==6.0.1

yaml.load vs. yaml.safe_load

以下是一段示範的程式碼,告訴你不明來源的 YAML 檔有多危險:

# pip install PyYAML==6.0.1
import yaml
from yaml import Loader

yaml_data = """
!!python/object/apply:eval
  args: ['print("Hello")']
"""

try:
    parsed_data = yaml.load(yaml_data, Loader)
except yaml.YAMLError as e:
    print(f"Error: {e}")

上述程式碼可以看到 yaml_data 中含有 !!python/object/apply:eval 的字串,就能夠讓 PyYMAL 在解析字串時,順便執行 Python 程式碼列印出 Hello 字串。(這段程式碼可以在 Colab 玩看看,玩之前記得安裝 PyYAML )

yaml-attack.png

而這種攻擊手法之所以能夠成功,是因為 PyYAML 支援將 Python objects 在 dump 時轉為特製的 YAML tags, 例如 !!python/object , !!python/bytes 等等,因此也支援在 load 時轉回 Python objects, 這也造成前述攻擊手法成為 1 種可能。

所以在讀取不受信任來源的 YAML 檔時,請使用 safe_load() , 該方法只會讀取 YAML 標準定義的 tags, 就能夠防範前述攻擊手法,例如:

import yaml

yaml_data = """
!!python/object/apply:eval
  args: ['print("Hello")']
"""

try:
    parsed_data = yaml.safe_load(yaml_data)
except yaml.YAMLError as e:
    print(f"Error: {e}")

上述程式碼將會出現以下錯誤,代表其不接受 !!python/object/apply:eval tag:

Error: could not determine a constructor for the tag 'tag:yaml.org,2002:python/object/apply:eval'

以上!資安宣導結束!

References

https://pyyaml.org/wiki/PyYAMLDocumentation

對抗久坐職業傷害

研究指出每天增加 2 小時坐著的時間,會增加大腸癌、心臟疾病、肺癌的風險,也造成肩頸、腰背疼痛等常見問題。

然而對抗這些問題,卻只需要工作時定期休息跟伸展身體即可!

你想輕鬆改變現狀嗎?試試看我們的 PomodoRoll 番茄鐘吧! PomodoRoll 番茄鐘會根據你所設定的專注時間,定期建議你 1 項辦公族適用的伸展運動,幫助你打敗久坐所帶來的傷害!

贊助我們的創作

看完這篇文章了嗎? 休息一下,喝杯咖啡吧!

如果你覺得 MyApollo 有讓你獲得實用的資訊,希望能看到更多的技術分享,邀請你贊助我們一杯咖啡,讓我們有更多的動力與精力繼續提供高品質的文章,感謝你的支持!