From f57bb9ab9d0fb69ae0d282e18fc64a8f7aa7274e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Dachary?= Date: Tue, 25 Oct 2022 09:23:47 +0000 Subject: [PATCH] new deploy: 2022-10-25T09:23:47+00:00 --- blog/1-17-2-migration-security/index.html | 338 ++++++++++++++++++++++ blog/atom.xml | 36 ++- blog/index.html | 39 +++ search_index.en.js | 2 +- sitemap.xml | 4 + tags/gitea/atom.xml | 36 ++- tags/gitea/index.html | 30 ++ tags/gna/atom.xml | 36 ++- tags/gna/index.html | 30 ++ tags/index.html | 16 +- tags/problem/atom.xml | 36 ++- tags/problem/index.html | 30 ++ tags/security/atom.xml | 36 ++- tags/security/index.html | 30 ++ tags/solution/atom.xml | 36 ++- tags/solution/index.html | 30 ++ tags/upgrade/atom.xml | 36 ++- tags/upgrade/index.html | 30 ++ 18 files changed, 813 insertions(+), 18 deletions(-) create mode 100644 blog/1-17-2-migration-security/index.html diff --git a/blog/1-17-2-migration-security/index.html b/blog/1-17-2-migration-security/index.html new file mode 100644 index 0000000..aa46d57 --- /dev/null +++ b/blog/1-17-2-migration-security/index.html @@ -0,0 +1,338 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [security] Gitea < 1.17.2 bypassing URL restrictions during migration explained | Gna!: Managed Gitea Hosting + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+
+ + +
+

[security] Gitea < 1.17.2 bypassing URL restrictions during migration explained

+ + + +
+

Gitea 1.17.2 includes a security patch that prevents bypassing URL restrictions during the migration of a remote repository.

+

When using the web interface or the REST API to import / migrate a repository that exists on another forge, the URL of the remote forge is verified and rejected if not allowed. For instance if it starts with file://, contains %0c and more.

+

The migration then starts by asking for more information about the software project to be migrated, using this verified URL. The structure that is returned is supposed to contain an exact copy of the URL from which the migration must be done. But there is no guarantee that it does and some of the drivers implemented in Gitea may return a different URL.

+

For instance, when migrating a project from another Gitea instance, the Gitea migration driver calls the GetRepo function of the Gitea SDK, which returns the result of the /repos/{owner}/{repo} endpoint verbatim.

+

If a malicious server is setup by an adversary so that the /repos/{owner}/{repo} enpoint returns a URL designed to leak information from the server such as file:///etc/group, it should also be verified and discarded. This is the purpose of the check that was added in Gitea 1.17.2.

+
	// SECURITY: If the downloader is not a RepositoryRestorer then we need to recheck the CloneURL
+	if _, ok := downloader.(*RepositoryRestorer); !ok {
+		// Now the clone URL can be rewritten by the downloader so we must recheck
+		if err := IsMigrateURLAllowed(repo.CloneURL, doer); err != nil {
+			return err
+		}
+
+		// SECURITY: Ensure that we haven't been redirected from an external to a local filesystem
+		// Now we know all of these must parse
+		cloneAddrURL, _ := url.Parse(opts.CloneAddr)
+		cloneURL, _ := url.Parse(repo.CloneURL)
+
+		if cloneURL.Scheme == "file" || cloneURL.Scheme == "" {
+			if cloneAddrURL.Scheme != "file" && cloneAddrURL.Scheme != "" {
+				return fmt.Errorf("repo info has changed from external to local filesystem")
+			}
+		}
+
+		// We don't actually need to check the OriginalURL as it isn't used anywhere
+	}
+
+ +
+
+
+ + +
+ + +
+ + +
+ + diff --git a/blog/atom.xml b/blog/atom.xml index de39cb1..9ff6c33 100644 --- a/blog/atom.xml +++ b/blog/atom.xml @@ -4,8 +4,42 @@ Zola - 2022-10-17T00:00:00+00:00 + 2022-10-24T00:00:00+00:00 https://gna.org/blog/atom.xml + + [security] Gitea < 1.17.2 bypassing URL restrictions during migration explained + 2022-10-24T00:00:00+00:00 + 2022-10-24T00:00:00+00:00 + + https://gna.org/blog/1-17-2-migration-security/ + <p><a href="https://pouet.chapril.org/@gna/108953815492944898">Gitea 1.17.2</a> includes a <a href="https://lab.forgefriends.org/forgefriends/forgefriends/-/commit/e6b3be460840f1f982d5358198466e7d6f509d21">security patch</a> that prevents bypassing URL restrictions during the migration of a remote repository.</p> +<p>When using the web interface or the REST API to <a href="https://lab.forgefriends.org/forgefriends/forgefriends/-/blob/upstream/routers/api/v1/repo/migrate.go#L209-212">import / migrate a repository</a> that exists on another forge, the URL of the remote forge is <a href="https://lab.forgefriends.org/forgefriends/forgefriends/-/blob/9fb251fb6fa2bb857bb8f5ae27f06c9d597bc1eb/routers/api/v1/repo/migrate.go#L109">verified</a> and rejected if not allowed. For instance if it starts with <strong>file://</strong>, contains <strong>%0c</strong> <a href="https://lab.forgefriends.org/forgefriends/forgefriends/-/blob/9fb251fb6fa2bb857bb8f5ae27f06c9d597bc1eb/services/migrations/migrate.go#L43">and more</a>.</p> +<p>The migration then starts by <a href="https://lab.forgefriends.org/forgefriends/forgefriends/-/blob/9fb251fb6fa2bb857bb8f5ae27f06c9d597bc1eb/services/migrations/migrate.go#L185">asking for more information</a> about the software project to be migrated, using this verified URL. The structure that is returned is supposed to contain an exact copy of the URL from which the migration must be done. But there is no guarantee that it does and some of the drivers implemented in Gitea may return a different URL.</p> +<p>For instance, when migrating a project from another Gitea instance, the Gitea migration driver <a href="https://lab.forgefriends.org/forgefriends/forgefriends/-/blob/9fb251fb6fa2bb857bb8f5ae27f06c9d597bc1eb/services/migrations/gitea_downloader.go#L153">calls the GetRepo</a> function of the Gitea SDK, which returns the result of the <a href="https://try.gitea.io/api/swagger#/repository/repoGet">/repos/{owner}/{repo}</a> endpoint verbatim.</p> +<p>If a malicious server is setup by an adversary so that the <strong>/repos/{owner}/{repo}</strong> enpoint returns a URL designed to leak information from the server such as <strong>file:///etc/group</strong>, it should also be verified and discarded. This is the purpose of the <a href="https://lab.forgefriends.org/forgefriends/forgefriends/-/blob/9fb251fb6fa2bb857bb8f5ae27f06c9d597bc1eb/services/migrations/migrate.go#L201-220">check that was added</a> in Gitea 1.17.2.</p> +<pre data-lang="go" style="background-color:#2b303b;color:#c0c5ce;" class="language-go "><code class="language-go" data-lang="go"><span> </span><span style="color:#65737e;">// SECURITY: If the downloader is not a RepositoryRestorer then we need to recheck the CloneURL +</span><span> </span><span style="color:#b48ead;">if </span><span style="color:#bf616a;">_</span><span>, </span><span style="color:#bf616a;">ok </span><span>:= </span><span style="color:#bf616a;">downloader</span><span>.(*</span><span style="color:#b48ead;">RepositoryRestorer</span><span>); !</span><span style="color:#bf616a;">ok </span><span>{ +</span><span> </span><span style="color:#65737e;">// Now the clone URL can be rewritten by the downloader so we must recheck +</span><span> </span><span style="color:#b48ead;">if </span><span style="color:#bf616a;">err </span><span>:= </span><span style="color:#bf616a;">IsMigrateURLAllowed</span><span>(</span><span style="color:#bf616a;">repo</span><span>.</span><span style="color:#bf616a;">CloneURL</span><span>, </span><span style="color:#bf616a;">doer</span><span>); </span><span style="color:#bf616a;">err </span><span>!= </span><span style="color:#d08770;">nil </span><span>{ +</span><span> </span><span style="color:#b48ead;">return </span><span style="color:#bf616a;">err +</span><span> } +</span><span> +</span><span> </span><span style="color:#65737e;">// SECURITY: Ensure that we haven&#39;t been redirected from an external to a local filesystem +</span><span> </span><span style="color:#65737e;">// Now we know all of these must parse +</span><span> </span><span style="color:#bf616a;">cloneAddrURL</span><span>, </span><span style="color:#bf616a;">_ </span><span>:= </span><span style="color:#bf616a;">url</span><span>.</span><span style="color:#bf616a;">Parse</span><span>(</span><span style="color:#bf616a;">opts</span><span>.</span><span style="color:#bf616a;">CloneAddr</span><span>) +</span><span> </span><span style="color:#bf616a;">cloneURL</span><span>, </span><span style="color:#bf616a;">_ </span><span>:= </span><span style="color:#bf616a;">url</span><span>.</span><span style="color:#bf616a;">Parse</span><span>(</span><span style="color:#bf616a;">repo</span><span>.</span><span style="color:#bf616a;">CloneURL</span><span>) +</span><span> +</span><span> </span><span style="color:#b48ead;">if </span><span style="color:#bf616a;">cloneURL</span><span>.</span><span style="color:#bf616a;">Scheme </span><span>== &quot;</span><span style="color:#a3be8c;">file</span><span>&quot; || </span><span style="color:#bf616a;">cloneURL</span><span>.</span><span style="color:#bf616a;">Scheme </span><span>== &quot;&quot; { +</span><span> </span><span style="color:#b48ead;">if </span><span style="color:#bf616a;">cloneAddrURL</span><span>.</span><span style="color:#bf616a;">Scheme </span><span>!= &quot;</span><span style="color:#a3be8c;">file</span><span>&quot; &amp;&amp; </span><span style="color:#bf616a;">cloneAddrURL</span><span>.</span><span style="color:#bf616a;">Scheme </span><span>!= &quot;&quot; { +</span><span> </span><span style="color:#b48ead;">return </span><span style="color:#bf616a;">fmt</span><span>.</span><span style="color:#bf616a;">Errorf</span><span>(&quot;</span><span style="color:#a3be8c;">repo info has changed from external to local filesystem</span><span>&quot;) +</span><span> } +</span><span> } +</span><span> +</span><span> </span><span style="color:#65737e;">// We don&#39;t actually need to check the OriginalURL as it isn&#39;t used anywhere +</span><span> } +</span></code></pre> + + [security] Gitea < 1.17.3 git option injection explained 2022-10-17T00:00:00+00:00 diff --git a/blog/index.html b/blog/index.html index 283b27c..060b33b 100644 --- a/blog/index.html +++ b/blog/index.html @@ -213,6 +213,45 @@