Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2021-28378 — Detaillierter Proof-of-Concept und Analyse von CVE-2021-28378, einer gespeicherten XSS-Schwachstelle in Gitea, die beliebige Code-Injektion, Privilegieneskalation und Remote-Code-Ausführung über Git-Hooks ermöglicht. | Kitploit
Tools/GitHubGitHub/pandatix/cve-2021-28378
SchwachstellenanalyseExploitationWebanwendungs-ExploitationPenetrationstestsLernen & BildungPayload-Entwicklung
GitHubpandatix/cve-2021-28378

CVE-2021-28378

Detaillierter Proof-of-Concept und Analyse von CVE-2021-28378, einer gespeicherten XSS-Schwachstelle in Gitea, die beliebige Code-Injektion, Privilegieneskalation und Remote-Code-Ausführung über Git-Hooks ermöglicht.

Repository anzeigen
414vor 8 MonatenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2021-28378

Details zu dieser CVE hier.

Diese CVE betrifft das Fehlen einer String-Escape-Funktion auf der Client-Seite, wenn Inhalte vom Server abgerufen werden. Sie ermöglicht es einem Angreifer, einfach beliebigen Code einzuschleusen, indem er einen Kommentar zu einem Issue oder einem Pull Request erstellt. Dies wurde mit dem Commit 7d7ab1eeae43d99fe329878ac9c8db5e45e2dee5 Ende Januar 2020 eingeführt, aber aufgrund eines Squash können wir nicht genau wissen, wer dies getan hat, um nach ähnlichen eingeführten Fehlern zu suchen.

Lassen Sie uns zunächst verstehen, woher diese Schwachstelle kommt. Dazu sehen wir uns den Commit an, der diese CVE behebt.

Vorher:

  • Erstens:
    labels += `<div class="ui label" style="color: ${color}; background-color:#${label.color};">${label.name}</div>`;
  • Zweitens:
    html: `
<div>
    <p><small>${issue.repository.full_name} on ${createdAt}</small></p>
    <p><span class="${color}">${svg(octicon)}</span> <strong>${issue.title}</strong> #${index}</p>
    <p>${body}</p>
    ${labels}
</div>
`

Wir sehen, dass es kein HTML-Escaping für label.name, issue.repository.full_name, issue.title und body gibt, bei denen es sich um Zeichenfolgen handelt, die ein Benutzer manipulieren kann, und somit beliebigen Code einschleusen kann. Beachten Sie, dass issue.repository.full_name nicht wirklich manipuliert werden kann, um Code einzuschleusen, da es zu viele Regeln einhalten muss ([\w._-]+), die wir mit dieser CVE nicht umgehen können. Genau das behebt dieser PR, indem sie in htmlEscape umgewandelt werden.

Nachher:

  • Erstens:
    labels += `<div class="ui label" style="color: ${color}; background-color:#${label.color};">${htmlEscape(label.name)}</div>`;
  • Zweitens:
    html: `
<div>
    <p><small>${htmlEscape(issue.repository.full_name)} on ${createdAt}</small></p>
    <p><span class="${color}">${svg(octicon)}</span> <strong>${htmlEscape(issue.title)}</strong> #${index}</p>
    <p>${htmlEscape(body)}</p>
    ${labels}
</div>
`

Die Schwachstelle verstehen

Werfen wir einen kurzen Blick auf die Datei web_src/js/features/contextpopup.js, um herauszufinden, wie die CVE ausgelöst wird.

...
const {AppSubUrl} = window.config;

export default function initContextPopups() {
  const refIssues = $('.ref-issue');
  if (!refIssues.length) return;

  refIssues.each(function () {
    const [index, _issues, repo, owner] = $(this).attr('href').replace(/[#?].*$/, '').split('/').reverse();
    issuePopup(owner, repo, index, $(this));
  });
}

function issuePopup(owner, repo, index, $element) {
  $.get(`${AppSubUrl}/api/v1/repos/${owner}/${repo}/issues/${index}`, (issue) => {
...
    for (let i = 0; i < issue.labels.length; i++) {
...
      labels += `<div class="ui label" style="color: ${color}; background-color:#${label.color};">${label.name}</div>`;
    }
...

    $element.popup({
      variation: 'wide',
      delay: {
        show: 250
      },
      html: `
<div>
  <p><small>${issue.repository.full_name} on ${createdAt}</small></p>
  <p><span class="${color}">${svg(octicon, 16)}</span> <strong>${issue.title}</strong> #${index}</p>
  <p>${body}</p>
  ${labels}
</div>
`
    });
  });
}

Was wir dort sehen, ist, dass für jeden Knoten mit der Klasse ref-issue ein anfälliges Popup hinzugefügt wird. Nun müssen wir herausfinden, wo ein ref-issue an den Benutzer gesendet wird: Grep wir (und behalten nur interessante Ergebnisse, also keine Testdateien oder ähnliches)! Die folgende Commit-Nummer entspricht dem Tag 1.12.4, der Standardversion aus der offiziellen docker-compose.yml-Datei, die von dieser CVE betroffen ist.

cd gitea
git checkout 8a51c48eb6367513e0518bcd412e64f6cbfe5e1a
grep -r ref-issue

modules/markup/html.go:		replaceContent(node, m[0], m[1], createLink(link, id, "ref-issue"))
modules/markup/html.go:		replaceContent(node, m[0], m[1], createLink(link, orgRepoID, "ref-issue"))
modules/markup/html.go:		link = createLink(com.Expand(ctx.metas["format"], ctx.metas), reftext, "ref-issue")
modules/markup/html.go:			link = createLink(util.URLJoin(setting.AppURL, ctx.metas["user"], ctx.metas["repo"], path, ref.Issue), reftext, "ref-issue")
modules/markup/html.go:			link = createLink(util.URLJoin(setting.AppURL, ref.Owner, ref.Name, path, ref.Issue), reftext, "ref-issue")
modules/markup/sanitizer.go:	sanitizer.policy.AllowAttrs("class").Matching(regexp.MustCompile(`ref-issue`)).OnElements("a")

Wir wissen nun, dass es keine statischen Inhalte mit der Klasse ref-issue gibt, sondern dass sie dynamisch generiert werden. Die letzte Zeile ist nicht interessant, da es sich nur um eine Sanitizer-Richtlinienregel handelt. Die anderen sind interessant, wir werden sehen, warum.

Tauchen wir in modules/markup/html.go ein.

func fullIssuePatternProcessor(ctx *postProcessCtx, node *html.Node) {
	if ctx.metas == nil {
		return
	}
	m := getIssueFullPattern().FindStringSubmatchIndex(node.Data)
	if m == nil {
		return
	}
	link := node.Data[m[0]:m[1]]
	id := "#" + node.Data[m[2]:m[3]]

	// extract repo and org name from matched link like
	// http://localhost:3000/gituser/myrepo/issues/1
	linkParts := strings.Split(path.Clean(link), "/")
	matchOrg := linkParts[len(linkParts)-4]
	matchRepo := linkParts[len(linkParts)-3]

	if matchOrg == ctx.metas["user"] && matchRepo == ctx.metas["repo"] {
		// TODO if m[4]:m[5] is not nil, then link is to a comment,
		// and we should indicate that in the text somehow
		replaceContent(node, m[0], m[1], createLink(link, id, "ref-issue"))

	} else {
		orgRepoID := matchOrg + "/" + matchRepo + id
		replaceContent(node, m[0], m[1], createLink(link, orgRepoID, "ref-issue"))
	}
}

Wir müssen auch verstehen, was getIssueFullPattern macht.

func getIssueFullPattern() *regexp.Regexp {
	if issueFullPattern == nil {
		appURL := setting.AppURL
		if len(appURL) > 0 && appURL[len(appURL)-1] != '/' {
			appURL += "/"
		}
		issueFullPattern = regexp.MustCompile(appURL +
			`\w+/\w+/(?:issues|pulls)/((?:\w{1,10}-)?[1-9][0-9]*)([\?|#]\S+.(\S+)?)?\b`)
	}
	return issueFullPattern
}

Fassen wir zusammen, um zu verstehen, welche Aufgabe dort erledigt wird.

In fullIssuePatternProcessor müssen wir zunächst sicherstellen, dass ctx.metas nicht nil ist (was wir als wahr annehmen, da es von übergeordneten Funktionen/Methoden im Aufrufstack erstellt wird). Dann prüfen wir, ob die Knotendaten einem Pfad wie http://mygitea.com/gituser/myrepo/issues/1 entsprechen. Wenn eine Übereinstimmung vorliegt, ersetzen wir sie durch einen Link. Wenn es sich bei dem Link um dasselbe Benutzer- und Repository handelt, ersetzen wir ihn durch das Muster #<issue_id>, andernfalls durch <user>/<repo>#<issue_id>. In beiden Fällen wird eine ref-issue-Klasse hinzugefügt, um das Popup zu generieren.

Die anderen Grep-Ergebnisse machen im Grunde dasselbe.

Zeit zum Spielen!

Da wir nun den Kontext haben – es geht darum, einen Link wie http://mygitea.com/gituser/myrepo/issues/1 durch einen kürzeren Link zu ersetzen – können wir ableiten, wo eine solche Aufgabe ausgeführt wird: bei Issues und PRs, wo Sie ein Label hinzufügen und/oder einen Kommentar posten können.

Für diese Annahme gehen wir davon aus, dass Sie ein Repository mit Schreibberechtigung haben.

Label

Gehen Sie zu Ihrem Repository und erstellen Sie ein neues Label mit einem Namen, der beliebigen Code enthält (z. B. <script>alert('label.name')</script>).

Issue

Gehen Sie zu den Issues Ihres Repositorys und erstellen Sie einen neuen Issue mit beliebigem Code im Titel und im Text, und fügen Sie das vorherige Label hinzu.

Lassen Sie uns etwas Code ausführen

Tool herunterladen