0
0

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 3 years have passed since last update.

VBAだからこそスコープを意識しておかないとだめだという話

Last updated at Posted at 2021-08-07

概要

 仕事で、VBAのプログラムを引き継ぐということがあったのですが、そのプログラムが関数のスコープを意識せずに設計されていたらしく、脆弱性があることが分かりました。
 正直、私も、変数はともかく関数のスコープまでちゃんと意識していない人間だったので、今後、同じことを私が行わないように、ちゃんとアウトプットしておくことにしました。

どんなプログラムだったの?

 どのようなプログラムだったかというと、以下の画像のシートとコードがあるExcelファイルであり、「admin」ボタンを押すとパスワードの入力を求められ、パスワードがあっていると「見られちゃいけないシート」が見れるようになるというプログラムだった。
 パスワードを直接書いているとか、いろいろ突っ込みどころはあるのですが、おそらく初心者の人に予想外の操作をされたくないための設定なので、とりあえず無視しておきます、今回はそのことではなくスコープについてです。
 
image.png

Option Explicit

Sub admin()
    Dim ans As String
    ans = InputBox("パスワード", "パスワード", "")
    If ans = "12345" Then
        Call Visible
    Else
        MsgBox "パスワードが違います。"
    End If
End Sub

Sub Visible()
    Sheet2.Visible = xlSheetVisible
End Sub

Sub VeryHidden()
    Sheet2.Visible = xlSheetVeryHidden
End Sub

スコープをちゃんとしないと起こること

 VBAには関数や変数を宣言する前にprivateとpublicを宣言することができます。
 privateと宣言された場合は宣言したモジュールの中でのみで使用できるようになり、publicと設定された場合はプロジェクト全体の中で見ることができます。
 そして何も宣言しないと変数や関数はpublicに設定されるようになっているため、たとえば、ボタンにマクロの登録をしようとすると、シートを見せる関数「VeryHidden」が設定可能になっていることが分かります。
 このままでは、「見られちゃいけないシート」が簡単にみられてしまいますし、標準モジュールにパスワードをかけたとしても、だれでもボタンに登録するマクロを別のものに変えることができ、初心者の方に予想外の操作を行われる危険性があります。
image.png

 Functionというパラメータを設定した場合にも、セルに関数名を入力すると、以下のように実行できてしまう。
 この場合、マクロが行うワークブックに対しての処理(ThisWorkbook.Closeなど)は無視されるようですが、こんなに簡単に実行できてしまうと、初心者の人がやらかしかねないので、実行できないようにしておくのが望ましいでしょう。

Function MoveMe(num As Long)
    If num = 0 Then
        MsgBox "表示されました"
    End If
End Function

image.png

解決策

 先ほど出てきましたが、privateを設定するだけで、簡単には見れなくなります。
 以下のコードのように、見せていい関数はPublic、見せたくない関数はPrivateを設定することで、先ほどのように簡単に実行できてしまうということは起こりません。

Public Sub admin()
    Dim ans As String
    ans = InputBox("パスワード", "パスワード", "")
    If ans = "12345" Then
        Call Visible
    Else
        MsgBox "パスワードが違います。"
    
    End If

End Sub

Private Sub Visible()
    Sheet2.Visible = xlSheetVisible
End Sub

Private Sub VeryHidden()
    Sheet2.Visible = xlSheetVeryHidden
End Sub

Private Function MoveMe(num As Long)
    If num = 0 Then
        MsgBox "表示されました"
    End If
End Function

image.png

 ただし見れなくなっただけで、「マクロ名」に実行したい関数名を入力すると、実行自体はできてしまうようです、あくまで簡単に見れなくなるだけです。(Privateとは一体…)
 関数名がばれてしまったら、もうあきらめましょう。

image.png

まとめ

 VBAでもスコープをちゃんと設定しないと、予想外の操作が行えてしまうことの説明と解決策についてまとめました。
 ただし、Excel自体、セキュリティ関連が弱いので、詳しい人ならばパスワードをかけようが簡単に解読できてしまいます、VBAは個人で使うだけにするのがいいのかもしれません。
 

0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?