miocatのその後、あるいはcoinsLT #0で発表した話
情報科学類1年が企画したcoinsLT #0(ATNDの方が情報量が多いのだが、一応Webページも存在している)で発表した。タイトルがクソ長いが要するにこのブログでいくつか投稿してきた、.NET FrameworkとMonoにおけるGetFullPathとかnew Uriの挙動の違いについてである。
実際の発表時の動画も公開されている。だいたい07:58あたりからが私の発表である。
情報科学類1年が企画したcoinsLT #0(ATNDの方が情報量が多いのだが、一応Webページも存在している)で発表した。タイトルがクソ長いが要するにこのブログでいくつか投稿してきた、.NET FrameworkとMonoにおけるGetFullPathとかnew Uriの挙動の違いについてである。
実際の発表時の動画も公開されている。だいたい07:58あたりからが私の発表である。
Note: This is the summary of my posts (they are written in Japanese):
I already reported this as a bug for Xamarin’s Bugzilla.
I found the different behavior of WebClient.DownloadString(String)
between Mono and .NET Framework when an invalid URI passed to it. In the Mono’s implementation, it may cause a security issue.
This causes by two different behaviors, in new Uri(String)
, and Path.GetFullPath(String)
.
DownloadString(String)
and some methods (e.g. DownloadFile(String)
, OpenRead(String)
, etc.) calls CreateUri(String)
, a private method of WebClient
. (-> source code on github)
CreateUri(String)
tries to make an instance of Uri
with new Uri(String)
. If an invalid URI passed, the constructor raises an exception. For example, new Uri("http://../../../etc/passwd")
will be failed because its hostname part (..
) is invalid. However, the failure will be ignored, and CreateUri(String)
returns new Uri(Path.GetFullPath(String))
. It means the local file address with the full path will be returned.
続・アレな文字をWebClient.DownloadString(String)
に渡すとローカルのファイルが読める
ここ2つの記事でMonoのWebClient.DownloadString(string)
にアレな文字列渡すとローカルファイルを落としてきてしまうという挙動について調べてたわけですが、よくよくスタックトレースを見てみると、.NET FrameworkでもGetUri
というメソッドを経由してPath.GetFullPath
が呼ばれていたことがわかりました。
発端は前の記事にあるように、tkbctf3の問題としてmiocatなるものを出してみたのはいいものの、意図とは異なる脆弱性を作り込んで250点問題が超絶ボーナス問題になりましたよ、というお話しです。
miocatはC#で書かれており、実際の運用ではMonoランタイムで動いていました。というわけでMonoのソースコードを読めば解決です。やったね。
そういうわけでまずはWebClient
の実装を読んでみたのですが、怪しい箇所が一発で見つかりました。WebClient.cs#798、privateメソッドであるCreateUri(string)
なるメソッドです。DownloadString(string)
は、その引数をこのメソッドに渡してDownloadData(Uri)
を呼び出します。
try-catch
の中で渡されたアドレス(と、baseAddress
)を元にUri
のインスタンスを作ってCreateUri(Uri)
に渡していますが、ここで例外が発生するとreturn new Uri(Path.GetFullPath(address))
という恐怖のコードが走ります。