| 제목 | yaojingang GEOFlow commit/2aeec4f449c9fa6790392723150c9151b6a4a337 Cross Site Scripting |
|---|
| 설명 | ## 1. XSS in JSON-LD Theme Output
### Root Cause
Frontend theme templates render user-controlled values inside `<script type="application/ld+json">` with raw `{!! json_encode(...) !!}` output and without `JSON_HEX_TAG`. Because `</script>` is not escaped, attacker-controlled input can break out of the JSON-LD block and inject JavaScript.
Relevant code path:
```php
// app/Http/Controllers/Site/HomeController.php
$search = trim((string) $request->query('search', ''));
...
if ($search !== '') {
$pageDescription = $search.' - '.$siteDescription;
}
```
```blade
{{-- resources/views/theme/toutiao-news-20260426/home.blade.php --}}
<script type="application/ld+json">
{!! json_encode($collectionSchema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) !!}
</script>
```
`$search` influences `$pageTitle` / `$pageDescription`, which are inserted into `$collectionSchema`, then emitted as raw HTML instead of safely escaped JSON for a `<script>` context.
Why `json_encode()` does not make this safe:
- `json_encode()` makes the data valid JSON, but the data is embedded inside an HTML `<script>` element, so HTML parsing rules still apply first.
- The template uses `JSON_UNESCAPED_SLASHES`, so `</script>` is emitted literally instead of as `<\/script>`.
- Once the browser sees a literal `</script>`, it closes the current script block before any JSON semantics matter, and the following attacker-controlled `<script>...</script>` is executed.
Example:
If user input is:
```text
</script><script>alert(document.domain)</script>
```
the rendered page becomes effectively:
```html
<script type="application/ld+json">
{
"description": "</script><script>alert(document.domain)</script>"
}
</script>
```
The browser does not treat this as "safe because it is inside JSON". It first runs the HTML parser for the `<script>` element. As soon as the parser encounters the literal `</script>`, it closes the current JSON-LD block, and the following `<script>alert(...)</script>` becomes a new executable script tag.
This is therefore not a "missing JSON encoding" issue. It is a context-unsafe HTML script embedding issue: valid JSON is still unsafe when it is injected into a raw `<script>` block without escaping the closing tag sequence.
There are two reachable variants:
- Reflected XSS via the public homepage `search` parameter.
- Stored XSS via attacker-controlled article titles rendered on article pages.
### PoC
Open the following URL in the browser:
```text
http://127.0.0.1:38080/?search=%3C%2Fscript%3E%3Cscript%3Ealert(document.domain)%3C%2Fscript%3E
``` |
|---|
| 원천 | ⚠️ https://github.com/yaojingang/GEOFlow/issues/60 |
|---|
| 사용자 | iswangxy (UID 99909) |
|---|
| 제출 | 2026. 07. 17. AM 09:01 (1 월 ago) |
|---|
| 모더레이션 | 2026. 08. 30. PM 04:44 (1 month later) |
|---|
| 상태 | 수락 |
|---|
| VulDB 항목 | 397158 [yaojingang GEOFlow 까지 2.1.0 JSON-LD Theme HomeController.php 검색 크로스 사이트 스크립팅] |
|---|
| 포인트들 | 20 |
|---|