Google Apps Scriptの関数は誰でも実行できちゃうので注意【GAS】
Google Apps Scriptの入門編に於いて重要な項目が1つあります。ウェブアプリやライブラリに置いてあるグローバル変数や関数は通常そのままの場合、他から参照できるということ。他から参照されたくない重要な情報を取り出す関数や、返す関数は第三者が実行しようと思えば簡単に実行できるという点です。
そこでこれらの検証と、実行させないようにする為の方法をまとめてみようと思います。
今回の問題の概要
ウェブアプリやライブラリ、Apps Script APIとしては公開し、スプレッドシートは非公開で管理者権限で実行といったような場合、普通はGAS側にある関数というのはウェブアプリ側で用意しておかないと、それを実行出来ない!!と思ってる人は多いのですが、実は割と簡単に実行して結果を得られてしまいます。よって、重要な情報(重要なパスワードの類など)を抜かれてしまうことに繋がります。
故に外部に公開するライブラリであったり、ウェブアプリを作成する場合はこれを意識して対策法を講じて設計する必要があります。社内向けとしても、漏れると問題となる可能性が非常に大きいです。
たとえば やばい一例⇩
スクリプトの所有者が adminパスワードを確認したり動作ログをメールで送信するために自分用に作った関数がGASコードに入ってますがこれらの ShowAdminPassword()とか
EmailScriptUsageTo()は クライアント側から常に実行可能なのです
webアプリを開けてる人間なら誰でも pic.twitter.com/SsrCkSYrS3— shadow. @🧯🌊🔥 (@Ryunessive) May 2, 2023
検証と対策
検証をしてみる
簡単なウェブアプリを作成し、以下のような仕組みを用意しています。
- HTML側からはgoogle.script.run.withSuccessHandlerにてGAS側の関数を叩く
- GAS側には単純に答えを返す関数を1個用意する(testmanという関数とする)
- デフォルトではtestman関数はHTML側には記載していない
- testman関数はGAS側で重要な情報を取り出して別の関数から呼び出して使うことを想定してる(他の人には見せたく無い)
- スプレッドシートは非公開でウェブアプリは管理者権限で実行させている
さて、この場合ユーザはウェブアプリのみが使え、スプレッドシートには直接アクセスも当然GASにも直接アクセスは出来ない。一見すると穴が無いように思えますが、以下の手順でウェブアプリに直接細工をすると実行できちゃいます。
- ウェブアプリを表示する
- ウェブページ上で右クリック⇒検証を実行しDeveloper Toolを起動する
- 適当な要素を右クリック⇒検証すると直接その付近に飛べる
- 右サイドバーの要素の項目を右クリック⇒HTMLとして編集をクリック
- 以下のようなコードを追加する
12345<button onclick="google.script.run.withSuccessHandler(function(data){alert(data)}).testman()">テスト</button> - ボタンが出現するので実行すると、testman関数が実行されて答えが得られてしまう
本来、公開する気がない・公開したくない関数がHTML側に用意していなくても、関数名と仕様がわかればこのようにデベロッパーツールを使って、第三者がコードをブラウザ上で追加することで実行可能になってしまうわけです。
もしこの関数に秘密の内容が入っていたら・・・・大変なことになってしまいます(故に通常GASのウェブアプリは外部に公開することを前提とはしていない)。
関数一覧を知ることもできる
ライブラリと公開してる場合、スクリプトIDを公開してるハズです。そのスクリプトIDを利用してURLを構築することでライブラリ内で利用されてる関数の一覧と仕様がバッチリわかるようになっています。
1 |
https://script.google.com/a/macros/domain.com/library/d/スクリプトID/バージョン番号 |
上記の例だとdomain.comとして公開されてるライブラリのスクリプトIDとバージョン番号を指定することで、URLを構築し実行すると関数とその仕様が表示されるようになります。ここで表示されてる関数は直接呼び出すことが可能なわけです(同じことがウェブアプリにも言えます)。
図:関数一覧を表示した様子
対策法
ウェブアプリ側からやライブラリ側からは直接実行されたくない場合、またGASの別の関数からの呼び出し時だけ利用できるようにする関数を「プライベート関数」と呼びます。このプライベート関数はプロジェクト内からしか呼び出せないだけでなく、関数のデバッグ一覧にも出てこなくなり、ライブラリの関数一覧にも表示されなくなります。
作り方は簡単で関数名の最期に「アンダースコア( _ )」を追加するだけ。testmanならばtestman_とするだけでプライベート関数となります。この関数はGASのプロジェクト内ならば以下のようなコードで呼び出せます。testを実行するとtestman_の内容が取得可能になります。
1 2 3 4 5 6 7 8 |
function testman_(){ return "テストだよ"; } function test(){ var test = testman_() console.log(test) } |
さて、この状態にしたtestman_関数をHTML側からgoogle.script.run.withSuccessHandlerで呼び出そうとするとエラーになり呼び出せなくなります。こうすることで勝手に外部からウェブアプリやライブラリ越しに実行されてしまうのを防ぐことが可能です。セキュリティ面でとっても重要なテクニックなので、設計する上では意識して使うようにしましょう。
図:デバッグ一覧にも出てこなくなる
図:関数が見つからないとしてエラーになる