安全じゃない「PDFを安全に保護できるパスワードの付け方と伝え方」

PDFを安全に保護できるパスワードの付け方と伝え方」に、安全じゃない記述もちらほらあって気になったので補足しておく。

Acrobatのセキュリティ機能

「文書を開くときにパスワードが必要」の設定にした場合には、技術的にもパスワードが分からない限り閲覧出来ない。したがって、安全である。

「文書の印刷および編集を制限。これらの権限設定を変更するにはパスワードが必要」については、技術的にはパスワードがなくても印刷や編集が可能。したがって、安全ではない。実際に。この設定を無視して印刷や編集を行えるツールは実在するし、ちょっとプログラミングの経験があれば容易に迂回できる。

パスワードの伝え方

「可能であれば、ビジネスチャットやグループウェアなど、メール以外の手段で伝えられると安心だ。」・・・いや、それ安心できないから。攻撃者がメールを閲覧出来る状態ならば、ビジネスチャットやグループウェアのパスワードを再発行して設定出来る可能性が高く、パスワードは筒抜けになる。パソコン本体ごと流出したのであれば、キャッシュからパスワードを得られる可能性も高い。IPAの例では電話という全く別の通信インフラ(添付ファイルの送信経路と被っていない)を使って送るというのが重要なのです)。
コレが中々にやっかいで、おすすめの方法はありません。電話では周りの人に聞こえてしまいますし、ランダムな文字列を伝えるのは困難です。SMSは数年前に脆弱性が指摘されてから、非推奨の方法になっています。直接会って打ち合わせしたときに定めるのが現実解でしょうか。

「電話で最後の1文字だけを伝える」のは、完全に論外です。最後の1文字だけ総当たりすれば良いと知られた時点で、1文字のパスワードを設定しているのと変わらない。普段から「電話で最後の1文字だけを伝える」事を習慣化していた場合には、周りの人もそのことを知っているので容易に推測できてしまいます。

習作:FacebookのLikeボタンをクリックする

C#でSeleniumを用いて、Facebookのページ内にある「いいね!」を自動的にクリックするサンプル。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

using OpenQA.Selenium;

namespace LikeClicker
{
    class Program
    {
        static void Main(string[] args)
        {
            string userID = "test@example.co.jp";
            string password = "password";

            // AppSettings.BrowserName.Firefoxを変更することによって対象のブラウザを変更できます
            using (IWebDriver webDriver = WebDriverFactory.CreateInstance(AppSettings.BrowserName.HeadlessChrome))
            {
                webDriver.Url = @"https://www.facebook.com/";

                IWebElement userIdElement = webDriver.FindElement(By.Id("email"));
                IWebElement passwordElement = webDriver.FindElement(By.Id("pass"));

                userIdElement.SendKeys(userID);
                passwordElement.SendKeys(password);
                userIdElement.Submit();
                Console.WriteLine("認証が終了したら任意のキーを押して下さい。");
                Console.Read();

                string[] followURL = {
                        "https://www.facebook.com/pg/username1/posts/?ref=page_internal",
                        "https://www.facebook.com/pg/username2/posts/?ref=page_internal"};
                while (true)
                {
                    foreach (var tergetURL in followURL)
                    {
                        webDriver.Url = tergetURL;
                        Thread.Sleep(5000);

                        int findCount = 0;
                        foreach (var divElement in webDriver.FindElements(By.ClassName("_37uu")))
                        {
                            foreach (var refElement in divElement.FindElements(By.ClassName("UFILikeLink")))
                            {
                                if (refElement.GetAttribute("class").IndexOf("UFILinkBright") <= 0)
                                {
                                    refElement.Click();
                                    Thread.Sleep(3000);
                                }
                            }
                        }
                    }

                    Thread.Sleep(1000 * 60 * 10);
                }
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Edge;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.IE;
using OpenQA.Selenium.Safari;

namespace LikeClicker
{
    internal class WebDriverFactory
    {
        public static IWebDriver CreateInstance(AppSettings.BrowserName browserName)
        {
            switch (browserName)
            {
                case AppSettings.BrowserName.None:
                    throw new ArgumentException(string.Format("Not Definition. BrowserName:{0}", browserName));

                case AppSettings.BrowserName.Chrome:
                    return new ChromeDriver();

                case AppSettings.BrowserName.HeadlessChrome:
                    ChromeOptions option = new ChromeOptions();
                    option.AddArgument("--headless");
                    return new ChromeDriver(option);

                case AppSettings.BrowserName.Firefox:
                    FirefoxDriverService driverService = FirefoxDriverService.CreateDefaultService();
                    driverService.FirefoxBinaryPath = @"C:\Program Files (x86)\Mozilla Firefox\firefox.exe";
                    driverService.HideCommandPromptWindow = true;
                    driverService.SuppressInitialDiagnosticInformation = true;
                    return new FirefoxDriver(driverService);

                case AppSettings.BrowserName.InternetExplorer:
                    return new InternetExplorerDriver();

                case AppSettings.BrowserName.Edge:
                    return new EdgeDriver();

                case AppSettings.BrowserName.Safari:
                    return new SafariDriver();

                default:
                    throw new ArgumentException(string.Format("Not Definition. BrowserName:{0}", browserName));
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LikeClicker
{
    internal static class AppSettings
    {
        public enum BrowserName
        {
            None,
            Chrome,
            HeadlessChrome,
            Firefox,
            InternetExplorer,
            Edge,
            Safari
        }
    }
}