アプリケーション用のSELinuxモジュールの開発

むかしむかし、遠く、遠くの国で



... NSAの政府サービスは、Linuxカーネルお​​よび環境用のセキュリティシステムを開発し、SELinuxと呼んでいます。 そしてそれ以来、人々は2つのカテゴリーに分けられています:身体障害者/寛容と強制。 今日、私はあなたにフォースの道を示し、すべてのカマーの反対側に移る。



仮定



テキストには多くの技術情報が含まれているため、著者は読者が次のことを想定しています。





これはあなたのことですか? それでは行こう!



基本タイプ



テスト対象として、 jnodeを取りました 。これは、ネットワークを介して通信し、データベースにアクセスし、構成を読み取り、そのデータとtmpファイルを書き込み、そのステータス(cpu、mem、disk)を監視するかなり典型的なアプリケーションです。



jnode.teファイルを作成します(te = Type Enforcement)



どのようにしてモジュールを書き始めますか? 基本タイプの説明から:



policy_module(jnode, 1.0.0) #    type jnode_t; #     type jnode_exec_t; #   - type jnode_conf_t; #    (  /var/cache/ ) type jnode_cache_t; #   - type jnode_log_t; #     type jnode_tmp_t; #   ,   jnode (  binkp ) type binkp_port_t;
      
      





なぜそんなに多いのですか? これらはシステムのさまざまなアクセスカテゴリであるため、たとえば次のとおりです。





叙情的な余談



理論的には、ほぼこの時点で(遷移規則のみを追加)、モジュールの書き込みを停止し、コンパイルして、システムにインストールし、chconでファイルシステムをマークできます。 その後、 audit2allowユーティリティを使用してログを収集し、何かを許可する完全に理解できない数百行を取得します。 将来的には、それらからも機能するモジュールを取得します。 しかし、これはあなたに理解を加えないでしょうか?



したがって、別の方法をお勧めします。ヘッダーファイルを読み取り、必要なものを選択します。 / usr / share / selinux / devel / include /には、基本的なSELinuxポリシーの標準マクロを含む数百の.ifファイルがあります。 残念ながら、あなたは自分でgrepとcatを使用する必要があります。いくつかの基本的なマクロと、それらがどのように生活を楽にするかを示します。



属性マクロ



SELinuxを使いやすくするために、 属性の概念があります -特定のタイプのコンテナー(k)にもアクセス権を割り当てることができます。 したがって、新しいタイプを1つまたは別の属性に追加すると、この属性の標準権限が自動的に付与されます。 これらのすべての属性を記憶しないために、属性(多くの場合は複数)で型をマークする既製のマクロがあります。 参照:



 #  - files_config_file(jnode_conf_t) #  -  files_type(jnode_cache_t) #  - logging_log_file(jnode_log_t) #    files_tmp_file(jnode_tmp_t) #    corenet_port(binkp_port_t)
      
      





標準許可マクロ



タイプが定義されると、アプリケーションに標準の動作を割り当てることができます。 これを行うには、マクロも使用します。マクロはキーワードによって非常に簡単に見つけられ、コードを人間が読めるようにします。



 #  :   jnode_t    #       jnode_exec_t application_domain(jnode_t, jnode_exec_t) #  :   jnode_t   , #     systemd #   :  systemd     jnode_exec_t, #     jnode_t init_daemon_domain(jnode_t, jnode_exec_t) #   jnode_t    ( /bin, /usr/bin ) corecmd_exec_bin(jnode_t) #   jnode_t   libs_use_ld_so(jnode_t) #   jnode_t    ( cpu, memory ) kernel_read_system_state(jnode_t) #   jnode_t   /tmp files_rw_generic_tmp_dir(jnode_t) #   jnode_t    ( /etc/resolv.conf  ) sysnet_read_config(jnode_t) #   jnode_t     /dev/(u)random dev_read_rand(jnode_t) #   jnode_t     (   ) fs_getattr_xattr_fs(jnode_t) #   jnode_t  dns resolve sysnet_dns_name_resolve(jnode_t) #   jnode_t   /var/log ( r/o ) logging_search_logs(jnode_t) #  : ,    jnode_t, #    jnode_log_t logging_log_filetrans(jnode_t, jnode_log_t, file) #  : tmp-,    jnode_t, #    jnode_tmp_t files_poly_member_tmp(jnode_t, jnode_tmp_t) #  jnode_t  bind()    corenet_tcp_bind_generic_node(jnode_t) #  jnode_t   postgresql  unix- postgresql_stream_connect(jnode_t) #  jnode_t   postgresql   corenet_tcp_connect_postgresql_port(jnode_t)
      
      





コンテキストファイル



ここで、作成したタイプをファイルシステムにバインドします。 jnode.fcファイルを作成します(fc =ファイルコンテキスト)。



 #   /opt/jnode/jnode.run -- gen_context(system_u:object_r:jnode_exec_t) #   r/o    "" /opt/jnode(/.*)? gen_context(system_u:object_r:jnode_conf_t) /opt/jnode/jar(/.*) gen_context(system_u:object_r:jnode_conf_t) #     /opt/jnode/point/.*\.cfg gen_context(system_u:object_r:jnode_conf_t) #      (    ) /opt/jnode/fileechoes(/.*)? gen_context(system_u:object_r:jnode_cache_t) /opt/jnode/point(/.*)? gen_context(system_u:object_r:jnode_cache_t) #          /opt/jnode/(inbound|temp)(/.*)? gen_context(system_u:object_r:jnode_tmp_t) #      /var/log/jnode(/.*)? gen_context(system_u:object_r:jnode_log_t)
      
      





組み立てと設置



フォルダーを作成し、 jnode.teおよびjnode.fcファイルをそこに配置します。

そこに行き、アセンブリを完了しましょう:



 [root@jnode jnode]# make -f /usr/share/selinux/devel/Makefile Compiling targeted jnode module /usr/bin/checkmodule: loading policy configuration from tmp/jnode.tmp /usr/bin/checkmodule: policy configuration loaded /usr/bin/checkmodule: writing binary representation (version 17) to tmp/jnode.mod Creating targeted jnode.pp policy package rm tmp/jnode.mod.fc tmp/jnode.mod
      
      





コマンドsemodule -i jnode.ppでモジュールをインストールし、コマンドsemodule -e jnodeで 有効にします。



binkp_port_tタイプにポート番号を割り当てます: semanage port -a -t binkp_port_t -p tcp 24554



次に、コンテキストファイルに従ってコンテキストを再割り当てする必要があります。

restoreconn -Rv / opt / jnode systemctlを介してサービスを開始し、待機を開始します。



最終監査



しばらくしてから(時間、日-サービスのアクティビティに依存)、 audit2allow -b -r -t jnode_tコマンドを実行して、アプリケーションが既に与えられたものに加えて他に何を要求するかを確認できます。 許可はほとんどありません。おそらく10〜15行であり、すべてが許可されているわけではありません。 ここで、残すものと削除するものを決定するのはあなた次第です。 「不要な」部分で、allowをdontauditに置き換えます。これにより、ログ内の重複するゴミが削除されます。 ところで、モジュールのバージョンを更新します-これにより、カーネルは更新する必要があることを理解できます。



setenforce 1



audit2allowが「空」と表示される場合-これは、すべてが計画どおりに機能し、強制を有効にできることを意味します。 おめでとうございます、フォースが見つかりました。 賢明に処分してください。



便利なリンク



selinuxproject.org/page/AVCRules-許可ルールの説明

selinuxproject.org/page/TypeRules-type_ルールの説明

selinuxproject.org/page/ObjectClassesPerms-クラスとアクセス許可のリスト

danwalsh.livejournal.com -RedHatおよびrefpolicy自体に関するSELinux“ father”ブログ



All Articles