Engineering Note

プログラミングなどの技術的なメモ

10.3 Windowsにおけるトークンと権限 (サイバーセキュリティプログラミング Pythonで学ぶハッカーの思考)

本記事は、オライリージャパンから発行されている「サイバーセキュリティプログラミング ―Pythonで学ぶハッカーの思考(原題:Black Hat Python)」の学習メモとして、書籍ではPython2で書かれていますが、自分なりに解釈した上でPython3に書き直しをしています。 

今回は、各プロセスのトークンに設定されている権限情報を取得する方法について学んでいきます。

 

 

トークンとは

Windows上で起動している各プロセスは、自分自身がどのユーザであるか、どのグループに属しているか、またはどのような操作ができるか(権限)などの情報を持っており、これをトークン(Token)といいます。

またこのトークンに記載されているACLAccess Control List)をもとに、ファイルなどのオブジェクトにアクセスできるプロセスであるかどうかを判断するホワイトリストとして機能し、アクセス制御なども行っています。

基本的に各プロセスは、それを起動したプロセス(親)のトークンをコピーしますが、これらのトークンを書き換えることもできます。

なお、トークンの書き換えは一般的に特権アカウント(Administrator)のみ可能となっています。

 

Pythonで権限情報を取得する

今回は前回のプロセス監視ツールに追加します。


 

以下が今回作成するスクリプトとなります。

 

# process_monitor.py
import win32con
import win32api
import win32security

import wmi
import sys
import os

def get_process_privileges(pid):
    try:
        hproc = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, False, pid)
        htok = win32security.OpenProcessToken(hproc, win32con.TOKEN_QUERY)
        privs = win32security.GetTokenInformation(htok, win32security.TokenPrivileges)
        priv_list = ""
        for i in privs:
            if i[1] == 3:
                priv_list += "{}|".format(win32security.LookupPrivilegeName(None, i[0]))
    except:
        priv_list = "N/A"
    return priv_list

def log_to_file(message):
    with open("process_monitor_log.csv", "ab") as f:
        f.write(message.encode('utf-8') + b'\r\n')
    return

log_to_file("Time, User, Executable, CommandLine, PID, Parent PID, Privileges")
c = wmi.WMI()

process_watcher = c.Win32_Process.watch_for('creation')

while True:
    try:
        new_process = process_watcher()
        proc_owner = new_process.GetOwner()
        proc_owner = "{}\\{}".format(proc_owner[0], proc_owner[2])
        create_date = new_process.CreationDate
        executable = new_process.ExecutablePath
        cmdline = new_process.CommandLine
        pid = new_process.ProcessId
        parent_pid = new_process.ParentProcessId
        privileges = get_process_privileges(pid)
        process_log_message = "{}, {}, {}, {}, {}, {}, {}\r\n".format(create_date,
                    proc_owner, executable, cmdline, pid, parent_pid, privileges)
        print(process_log_message)
        log_to_file(process_log_message)
    except:
        pass

 

動作確認

それでは、上記で作成したプロセスを実行してみます。

スクリプトを実行後、Windows標準のメモ帳を起動すると以下の権限情報が取得できました。

 

 > python process_monitor2.py
 20190205000000.256126+540, Local\user, C:\WINDOWS\system32\notepad.exe, "C:\WINDOWS\system32\notepad.exe" , 9360, 9772, SeChangeNotifyPrivilege|

 

起動したメモ帳には"SeChangeNotifyPrivilege(走査チェックのバイパス)"の権限が付与されていました。

 

最後に

今回はプロセスのトークンにアクセスし、その権限情報を確認する方法について学びました。

この権限情報を参考にすることで、脆弱性のあるプロセスを特定することに役立ちそうです。

 

参考書籍

サイバーセキュリティプログラミング ―Pythonで学ぶハッカーの思考