ファイルのタイムスタンプを改竄する方法

Linuxのファイルシステムの特徴

LinuxのEXT4やBrtfsやEXT3などのファイルシステムは、i-nodeとブロック領域の2つで構成されています。ファイルのデータはブロック領域に格納されます。そのブロックの管理領域には、ファイルの実データが格納されている位置やファイル・サイズ、変更時刻などの管理情報が記録されます。これがi-nodeです。

各ファイルやディレクトリのi-node番号を確認するには、ls -iコマンドを実行します。

$ ls -ali
 54980 -rw-r--r-- 1 faust users 1.5G  6月 14 21:20 test.tar.gz
232836 drwxr-xr-x 1 faust users   84  6月 15 01:11 www

また、各パーティションごとに使用されているi-node番号の総数は、df -iコマンドで確認できます。

$ df -i
ファイルシス     Iノード I使用     I残り I使用% マウント位置
devtmpfs         4104575   576   4103999     1% /dev
tmpfs            4105569     1   4105568     1% /dev/shm
tmpfs            4105569   555   4105014     1% /run
/dev/sdb2              0     0         0      - /
tmpfs            4105569    13   4105556     1% /sys/fs/cgroup
tmpfs            4105569   555   4105014     1% /var/lock
tmpfs            4105569   555   4105014     1% /var/run
/dev/sda1              0     0         0      - /srv/m4
/dev/sdb1         524288   327    523961     1% /boot
/dev/sdc1      390686272 76318 390609954     1% /srv/hdd

ファイルのタイムスタンプ情報

ファイルブロックには、最終i-node更新時刻(ctime)、最終参照時刻(atime) 、最終ファイル更新時刻(mtime)を示すタイムスタンプが属性データとして埋め込まれています。それぞれ以下のコマンドで確認できます。

最終i-node更新時刻を確認

$ ls -lc
-rw-r----- 1 root   root    169K  8月  2 04:51 messages

最終参照時刻を確認

$ ls -lu
-rw-r----- 1 root   root    169K  8月  1 19:45 messages

最終ファイル更新時刻を確認

$ ls -l
-rw-r----- 1 root   root    169K  8月  2 04:51 messages

touchコマンドを使ってファイルのタイムスタンプを改竄する

touchコマンドを用いると、atime・mtimeは任意の時刻に改竄することが可能です。

$ touch hoge.txt
$ ls -al
-rw-r--r-- 1 faust users    0  8月  2 04:58 hoge.txt
$touch -d "2000/4/1 00:00:00" hoge.file
$ ls -al
-rw-r--r-- 1 faust users    0  4月  1  2000 hoge.txt

これで今日(2013年8月2日)作られたはずのファイルが、2000年4月1日に作成されたことになりました。このようにtouchコマンドを使うと簡単にatime・mtimeのタイムスタンプを改竄することが可能です。しかし、最終i-node更新時を記録しているctimeはtouchコマンドでは日時修正が出来ません。このため、ctimeを見るオプションで見るとi-nodeの更新日時からファイルのi-nodeがいつ更新されているのか判明してしまいます。

$ ls -lc
-rw-r--r-- 1 faust users    0  8月  2 04:58 hoge.txt

ctimeのタイムスタンプを変更するには

では、ctimeを変更するにはどのようにすれば良いのでしょうか。i-nodeを直接書き換える必要があります。CentOSならば、debugfsコマンドでパーティションを書き込み可能にして、modify_inodeによって書き換えることが出来ます。その場合、Creation timeの部分で、UNIXタイムスタンプを入力します(ここでは2000年4月1日00時00分00秒の954514800を指定)。

$ sudo debugfs -w /dev/vda3

debugfs 1.41.12 (17-May-2010)

debugfs:  cd /home/faust

debugfs:  stat test.txt

Inode: 1177357   Type: regular    Mode:  0664   Flags: 0x80000
Generation: 1780830578    Version: 0x00000000:00000001
User:   500   Group:   500   Size: 0
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 0
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x38e4bd70:bd6023b0 -- Sat Apr  1 00:00:00 2000
 atime: 0x51fac627:bd6023b0 -- Fri Aug  2 05:33:43 2013
 mtime: 0x51fac627:bd6023b0 -- Fri Aug  2 05:33:43 2013
crtime: 0x51fac627:bd6023b0 -- Fri Aug  2 05:33:43 2013
Size of extra inode fields: 28
EXTENTS:

debugfs:  modify_inode test.txt

                          Mode    [0100664] 
                       User ID    [500] 
                      Group ID    [500] 
                          Size    [0] 
                 Creation time    [954514800] 954514800  
             Modification time    [1375389223] 954514800  
                   Access time    [1375389223] 954514800  
                 Deletion time    [0] 
                    Link count    [1] 
              Block count high    [0] 
                   Block count    [0] 
                    File flags    [0x80000] 
                    Generation    [0x6a255172] 
                      File acl    [0] 
           High 32bits of size    [0] 
              Fragment address    [0] 
               Direct Block #0    [62218] 
               Direct Block #1    [4] 
               Direct Block #2    [0] 
               Direct Block #3    [0] 
               Direct Block #4    [0] 
               Direct Block #5    [0] 
               Direct Block #6    [0] 
               Direct Block #7    [0] 
               Direct Block #8    [0] 
               Direct Block #9    [0] 
              Direct Block #10    [0] 
              Direct Block #11    [0] 
                Indirect Block    [0] 
         Double Indirect Block    [0] 
         Triple Indirect Block    [0] 

debugfs:  stat test.txt

Inode: 1177357   Type: regular    Mode:  0664   Flags: 0x80000
Generation: 1780830578    Version: 0x00000000:00000001
User:   500   Group:   500   Size: 0
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 0
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x38e4bd70:bd6023b0 -- Sat Apr  1 00:00:00 2000
 atime: 0x38e4bd70:bd6023b0 -- Sat Apr  1 00:00:00 2000
 mtime: 0x38e4bd70:bd6023b0 -- Sat Apr  1 00:00:00 2000
crtime: 0x51fac627:bd6023b0 -- Fri Aug  2 05:33:43 2013
Size of extra inode fields: 28
EXTENTS:

debugfs:  quit

これでctimeが2000年4月1日になります。EXT3のファイルシステムならば、ls -lcコマンドでもctimeが書き換わっていることが確認できます。しかしEXT4のファイルシステムの場合は、i-nodeにctimeの他にcrtimeという拡張情報が埋め込まれています。これはファイル作成日を示す情報で、この書き換えはdebuginfoのインターフェースではi-nodeを修正できません。

まとめ

mtime、atimeの書き換えならば容易で、これでlsコマンドで通常表示される時刻に関しては改竄が容易ですが、ctimeの書き換えになると若干複雑になります。さらにEXT4のファイルシステムではcrtimeの情報があるため、この書き換えを行うことが出来ません。ということで、セキュリティ的にはmtime、atimeの情報はあまり信用せず、ctimeないしcrtimeの情報を見た方が正確かと思います。