{"id":105884,"date":"2021-11-09T07:00:00","date_gmt":"2021-11-09T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=105884"},"modified":"2021-11-09T05:02:40","modified_gmt":"2021-11-09T13:02:40","slug":"20211109-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20211109-00\/?p=105884","title":{"rendered":"If your domain name parser can&#8217;t handle internationalized domain names, then maybe that&#8217;s your parser&#8217;s problem"},"content":{"rendered":"<p>A security vulnerability report arrived that went roughly like this:<\/p>\n<blockquote class=\"q\">\n<p>Internet Explorer has a security vulnerability that allows an attacker to bypass domain filtering. Suppose my web site filters domain names, say with the following test:<\/p>\n<pre>if ($frame_domain == \"microsoft.com\") {\r\n    block();\r\n}\r\n<\/pre>\n<p>An attacker can construct a frame which targets an intentional misspelling:<\/p>\n<pre>&lt;iframe src=\"https:\/\/\u24dcicrosoft.com\" ...&gt;\r\n<\/pre>\n<p>Even though the &#8220;\u24dc&#8221; is the Unicode character CIRCLED LATIN SMALL LETTER M (U+24DC), the web page that is shown in the frame is indeed <code>microsoft.com<\/code>. The web browser rewrote the domain, allowing an attacker to bypass filtering.<\/p>\n<\/blockquote>\n<p>Yes, this is all true. The web browser rewrote the domain, allowing an attacker to bypass filtering. But the bug is not in the web browser. The web browser is doing exactly what the standard says it&#8217;s supposed to do: <a href=\"https:\/\/unicode.org\/reports\/tr46\/\"> Unicode Technical Standard #46<\/a> describes how so-called <i>international domain names<\/i> are converted to ASCII for domain lookup purposes. One of the steps is to <a href=\"https:\/\/unicode.org\/reports\/tr46\/#ProcessingStepMap\"> map the code points according to the IDNA Mapping Table<\/a>, and the IDNA Mapping Table says that character CIRCLED LATIN SMALL LETTER M (U+24DC) is mapped to LATIN SMALL LETTER M (U+006D).<\/p>\n<p>The bug is in the code which tries to block access to <code>microsoft.com<\/code>. It&#8217;s performing a literal string comparison against <code>microsoft.com<\/code> without going through the IDN conversion process. Indeed, you didn&#8217;t even need to use IDN to attack the filter.<\/p>\n<pre>&lt;iframe src=\"https:\/\/microsoft.com.\" ...&gt;\r\n<\/pre>\n<p>As we learned some time ago, <a title=\"What is the real maximum length of a DNS name?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20120412-00\/?p=7873\"> <code>microsoft.com<\/code> is technically shorthand for the full name <code>microsoft.com.<\/code> with a trailing period<\/a>. But the above filter doesn&#8217;t handle that case, so appending a dot easily avoids the filter.<\/p>\n<p>Hang on, it&#8217;s even easier:<\/p>\n<pre>&lt;iframe src=\"https:\/\/Microsoft.com\" ...&gt;\r\n<\/pre>\n<p>The filter used a case-sensitive comparison, but domain names are case-insensitive, so <code>Microsoft.com<\/code> sneaks past the filter.<\/p>\n<p>And, of course, you could gain access to <code>microsoft.com<\/code> by using its IP address explicitly.<\/p>\n<p>None of this is the fault of the web browser. The problem is in the attempt at filtering the domains that can be placed inside frames. If you set up an insecure system, don&#8217;t be surprised that it has a security issue.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Don&#8217;t blame someone else for letting strange domain names reach you.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[26],"class_list":["post-105884","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>Don&#8217;t blame someone else for letting strange domain names reach you.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105884","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=105884"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105884\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=105884"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=105884"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=105884"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}