サイト内の現在位置

2038年問題はセキュア開発で防げるのか?

NECセキュリティブログ

2021年3月12日

はじめに

NECサイバーセキュリティ戦略本部セキュリティ技術センターの日下部です。
今回は将来的に起こる可能性のある2038年問題について、セキュア開発の観点も交えてご紹介します。
2038年はまだまだ先のことと考える方もいるかと思いますが、2038年まであと17年ということを考えると、十数年周期で更新するようなシステムの場合は次回更新の際に考慮すべき問題となります。2038年問題によってどのような事象が引き起こされるのか、予防する手段はあるのか考察してみました。

2038年問題とは

2038年問題とは、1970年1月1日0時0分0秒からの経過秒数をカウントする時刻形式であるUNIX時刻を採用するプログラムにおいて、-2,147,483,648 ~ 2,147,483,647の値の範囲である32bit型符号付変数で経過秒数をカウントした際に発生する問題です。この問題を抱えるプログラムでは、時刻が2038年1月19日12時14分7秒(JST:日本時間の場合)を過ぎると、経過秒数がオーバフローして正しい時刻が表示できなくなります。
以下に2038年問題を引き起こす時計プログラムを作成し、動作させた例を示しました。2038年1月19日12時14分7秒から1秒経過した後、時刻が1901年に逆戻りしていることがわかります。

今度は上記のプログラムをVisual Studioでデバッグしながら動作させた結果を下記に示します。言語はC#で作成しており、int型(32bit型符号付変数)であるctime32にUNIX時刻の経過秒数を格納しています。2038年1月19日12時14分7秒にctime32の値は2,147,483,647を示し、1秒経過後にctime32の値はオーバフローして-2,147,483,648に戻ってしまいます。このときの時刻は、1970年1月1日0時0分0秒から2,147,483,648秒前の1901年12月14日5時45分52秒を示します。

本問題による時刻が逆戻りしてしまう現象は、2038年以降に予定されるプログラム処理が実行できなくなるなど、システムに様々な悪影響を与えます。同様の問題として、時刻を2桁で表示した際に1999年を過ぎると時刻が1900年に逆戻りしてしまう2000年問題がありましたが、発生タイミングや仕組みなど、情報処理技術になじみがない人にとってはわかりにくい問題となっているかと考えます。
時刻に関する標準的なライブラリが2038年問題に対応している昨今では、2038年問題は発生しないと考える人もいるかもしれません。ですが時刻に関する計算処理をする際、標準的なライブラリを使用せずに独自に時刻計算を行っている場合は32bit型符号付変数を用いて経過秒数を取り扱っている可能性もあり、2038年問題が発生する可能性はゼロではないと言えます。
また、最近新しく更新したシステムの場合でも、旧システムから処理を流用してきた場合や、プログラム言語を機械的に移植した場合、時刻に32bit型符号付変数が使われている可能性はゼロではないと言えます。

2038年問題への対策

それでは2038年問題を引き起こさないようにするためにはどのような対策があるでしょうか。プログラムを修正する方法としては、変数の型をより値の範囲の広い型に変更することが挙げられます。32bit型符号付変数から64bit型符号付変数に変更すれば、値の範囲は時刻の計算処理においては現実的に考慮しなくてよい巨大な数値になるため、問題を回避することができます。C#のような高水準の言語ではこのような型変換が比較的作業量が少ないと思いますが、C言語などでポインタを駆使して変数の格納先メモリを管理していた場合、メモリマップを再設計しなければならない場合もあり、作業量が大きくなる可能性もあります。また、型変換を実施する場合でも時刻で使用されている変数は何なのか、膨大なソースコードの中から洗い出しを行うことに時間がかかる場合もあります。
膨大なソースコードの中から、問題を引き起こす可能性のある部分を効率よく探し出す方法はないでしょうか。方法の一つとして、ソースコード分析を実施するということが考えられます。ソースコード分析は不具合や脆弱性に繋がるソースコードを検出するために実施するもので、セキュア開発のプロセスの中では、開発やテストの段階で実施します。ここで2038年問題を引き起こす箇所を検出できれば後々の対応工数が少なくなります。
今回はMicrosoft Visual Studio new window[1]のオーバフローチェック機能と、OSSのコード可視化ツールであるSourcetrail new window[2]を用いてソースコード分析を実施しました。

Visual Studioのコード分析機能での検証

検証は下記のC言語で作成したコードで実施しました。
開発環境としてはVisual Studio 2019を使用しています。

このプログラムは、現在の日付から入力した日数分経過した日付を表示するプログラムです。
100や1000などを入力すると正しく経過した日付を表示できますが、現在(2021年)から17年以上経過する7000以上の数値を入力すると、経過秒数を演算するための変数であるcal_workが30行目でオーバフローしてマイナスとなり、localtime関数で取り扱える範囲外の時刻となるため32行目でエラーとなります。
こちらのコードに対して、Visual Studioのビルドを実行すると、警告は1件出力(詳細は後述)されますが、正常にビルドできます。

ここで、Visual Studioのコード分析機能を利用してみます。
コード分析機能はソースコードを分析し、不具合に繋がる個所について指摘する機能で、ソースコードの品質向上等に役立てることができます。Visual Studio2019では、メニューバーの「ビルド」から、「○○○でコード分析を実行」から実施することができます。(〇〇〇はソリューション全体でコード分析を実行するか、ファイル単体でコード分析を実行するかによって異なる文言が入ります。)
コード分析を実行した結果、下記2件の警告が出力されました。

2件とも30行目に関する警告で、異なる型を用いて計算を実施していることに対して警告を出力しています。この警告が出力されたことにより、時刻を格納している変数がオーバフローする可能性について気付きになる可能性はあります。

また、コード分析せずにビルドした場合ですが、下記のように警告が1件だけ出力されました。コード分析した場合は2件出力されましたので、より詳細にプログラムを分析してくれたことがわかります。

Sourcetrailでの検証

次にSourcetrailを用いてコードの可視化を検証します。Sourcetrailはオープンソースのコード可視化ツールで、関数や変数の依存関係を可視化してくれます。
今回作成したプログラムをSourcetrailに取り込むと、下記のように表示されました。

ここで「Functions」をクリックし、関数の詳細を表示します。
Functions内のmain関数を辿っていくと、下記のように使用している関数や型、構造体の一覧が表示されました。

このように関数内で使用されている関数や型、構造体の一覧が表示されますので、「localtime」や「time」が使われている周辺を調べれば、2038年問題を引き起こす変数の使い方をしていないかチェックすることができます。
今回は短いソースコードなのでツールがなくてもチェックに時間はかからないと思いますが、大規模なプログラムになるとソースコードの量も膨大になるため、このようなツールを使用して時刻関数が使われている箇所を洗い出すのも有効な手段となり得ます。

まとめ

本記事では、Visual Studioのコード分析機能とコード可視化ツールであるSourcetrailを用いて2038年問題を引き起こすソースコード内の該当箇所が発見できないか検証してみました。何れの場合も「ここで問題が発生する」という特定までには至りませんが、型の使用方法が適切かチェックの実施や、ソースコードの中から時刻関数を使用している該当箇所を発見する手掛かりに繋がるかと思います。
今回検証したソースコード分析はセキュア開発のプロセスの一つとなりますので、2038年問題のような不具合を引き起こさないためにも、セキュア開発を浸透し、脆弱性を作りこまない開発体制の整備を進めるのが重要となるでしょう。

参考資料

執筆者プロフィール

日下部 孝太朗(くさかべ こうたろう)
セキュリティ技術センター セキュリティ実装技術チーム

2019年にセキュリティ技術センターに着任し、NECグループが提供するシステムやサービスのセキュア開発支援業務に従事。
IPA産業サイバーセキュリティセンターの中核人材育成プログラム(第二期)を修了。
CISSP、情報処理安全確保支援士(RISS)を保持。

執筆者の他の記事を読む

アクセスランキング