picoCTF 2021 Crypto (1)
暇つぶしにpicoCTF 2021を解いていく。
Mod 26
| 10 points
Tags:
AUTHOR: PANDU
Description
Cryptography can be easy, do you know what ROT13 is? cvpbPGS{arkg_gvzr_V'yy_gel_2_ebhaqf_bs_ebg13_nSkgmDJE}
# cat 01.txt cvpbPGS{arkg_gvzr_V'yy_gel_2_ebhaqf_bs_ebg13_nSkgmDJE}
exploit.py
qfile = "01.txt" buf = open(qfile).read() def rotn(text, n): _buf = '' for c in text: if not(ord('A') <= ord(c) <= ord('Z') or ord('a') <= ord(c) <= ord('z')): _buf += c continue offset = ord('A') if ord(c) < ord('a') else ord('a') _buf += chr((ord(c) - offset + n) % 26 + offset) return _buf # ROT 13 print("ROT 13: " + rotn(buf, 13)) # 2 rounds of ROT13 print("2 rounds of ROT13: " + rotn(rotn(buf, 13),13))
# python3 exploit.py ROT 13: picoCTF{next_time_I'll_try_2_rounds_of_rot13_aFxtzQWR} 2 rounds of ROT13: cvpbPGS{arkg_gvzr_V'yy_gel_2_ebhaqf_bs_ebg13_nSkgmDJE}
当然だが、ROT13を2回かけたら元に戻る(ROT 13 * ROT13 = ROT26 = ROT0)。
JupyterLab on Docker on Ubuntu 20.04 on WSL2
Docker Desktop for Windowsのインストールまでは前回。
kanekkie.hatenablog.com
anaconda3コンテナの入手。
hub.docker.com
$ docker pull continuumio/anaconda3 Using default tag: latest latest: Pulling from continuumio/anaconda3 68ced04f60ab: Pull complete 57047f2400d7: Pull complete 8b26dd278326: Pull complete Digest: sha256:6502693fd278ba962af34c756ed9a9f0c3b6236a62f1e1fecb41f60c3f536d3c Status: Downloaded newer image for continuumio/anaconda3:latest docker.io/continuumio/anaconda3:latest
起動。
オプションなどはこの辺を参考。
qiita.com
mick3355-dev.hatenablog.com
$ cd ~ $ mkdir workspace $ docker run -it -p 8888:8888 -v $(pwd):/opt/notebooks continuumio/anaconda3 /bin/bash -c "/opt/conda/bin/jupyter lab --notebook-dir=/opt/notebooks --ip='*' --port=8888 --no-browser --allow-root" [I 15:06:45.627 LabApp] Writing notebook server cookie secret to /root/.local/share/jupyter/runtime/notebook_cookie_secret [W 15:06:45.761 LabApp] WARNING: The notebook server is listening on all IP addresses and not using encryption. This is not recommended. [I 15:06:45.766 LabApp] JupyterLab extension loaded from /opt/conda/lib/python3.7/site-packages/jupyterlab [I 15:06:45.766 LabApp] JupyterLab application directory is /opt/conda/share/jupyter/lab [I 15:06:45.768 LabApp] Serving notebooks from local directory: /opt/notebooks [I 15:06:45.768 LabApp] The Jupyter Notebook is running at: [I 15:06:45.768 LabApp] http://53249cd5486a:8888/?token=09f221636739c75fe67f0204d7b85b1df18e4986e26b0c51 [I 15:06:45.769 LabApp] or http://127.0.0.1:8888/?token=09f221636739c75fe67f0204d7b85b1df18e4986e26b0c51 [I 15:06:45.769 LabApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation). [C 15:06:45.771 LabApp] To access the notebook, open this file in a browser: file:///root/.local/share/jupyter/runtime/nbserver-1-open.html Or copy and paste one of these URLs: http://53249cd5486a:8888/?token=09f221636739c75fe67f0204d7b85b1df18e4986e26b0c51 or http://127.0.0.1:8888/?token=09f221636739c75fe67f0204d7b85b1df18e4986e26b0c51
出てきたURLにアクセスすればいつもの画面が表示される。
WSL2とDocker
Windows 10のMay 2020 Updateが来たのでWSL2に挑戦。
新たな環境を作るということで、Ubuntu 20.04 on WSL2を用意。
このページあたりを参考にしてやればすぐできる。
qiita.com
次はDocker。Docker Desktop for Windowsをインストール。
Docker Hub
"Enable WSL 2 Windows Features"をチェックしておく。
インストール完了後にWindowsからのログアウトが必要。
設定画面で、Resource > WSL INTEGRATIONで、Ubuntu-20.04をオンにする(画像ではオフ)。
Ubuntuからdockerを起動してみる。
$ docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 0e03bdcc26d7: Pull complete Digest: sha256:6a65f928fb91fcfbc963f7aa6d57c8eeb426ad9a20c7ee045538ef34847f44f1 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/
とりあえず動いてるっぽい(?)
SSLErrorではまったおはなし (1)
HTTPSサイトにアクセスしたらエラーが出た。
import requests url = 'https://www.eigeki.com/' r = requests.get(url)
Traceback (most recent call last): File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/urllib3/contrib/pyopenssl.py", line 453, in wrap_socket cnx.do_handshake() File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/OpenSSL/SSL.py", line 1915, in do_handshake self._raise_ssl_error(self._ssl, result) File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/OpenSSL/SSL.py", line 1647, in _raise_ssl_error _raise_current_error() File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/OpenSSL/_util.py", line 54, in exception_from_error_queue raise exception_type(errors) OpenSSL.SSL.Error: [('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')] During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/urllib3/connectionpool.py", line 600, in urlopen chunked=chunked) File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/urllib3/connectionpool.py", line 343, in _make_request self._validate_conn(conn) File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/urllib3/connectionpool.py", line 839, in _validate_conn conn.connect() File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/urllib3/connection.py", line 344, in connect ssl_context=context) File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/urllib3/util/ssl_.py", line 344, in ssl_wrap_socket return context.wrap_socket(sock, server_hostname=server_hostname) File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/urllib3/contrib/pyopenssl.py", line 459, in wrap_socket raise ssl.SSLError('bad handshake: %r' % e) ssl.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')])",) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/requests/adapters.py", line 449, in send timeout=timeout File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/urllib3/connectionpool.py", line 638, in urlopen _stacktrace=sys.exc_info()[2]) File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/urllib3/util/retry.py", line 398, in increment raise MaxRetryError(_pool, url, error or ResponseError(cause)) urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='www.eigeki.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')])"))) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/requests/api.py", line 75, in get return request('get', url, params=params, **kwargs) File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/requests/api.py", line 60, in request return session.request(method=method, url=url, **kwargs) File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/requests/sessions.py", line 533, in request resp = self.send(prep, **send_kwargs) File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/requests/sessions.py", line 646, in send r = adapter.send(request, **kwargs) File "/home/kanekkie/anaconda3/lib/python3.7/site-packages/requests/adapters.py", line 514, in send raise SSLError(e, request=request) requests.exceptions.SSLError: HTTPSConnectionPool(host='www.eigeki.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')])")))
Chromeでアクセスすると普通に見られるが、Firefoxでは見られない。。
opensslでチェックしてみると
$ openssl s_client -connect www.eigeki.com:443 CONNECTED(00000003) depth=0 C = JP, ST = Tokyo, L = Chuo-ku, OU = The personnel affairs general affairs department, O = "SHOCHIKU CO., LTD.", CN = www.eigeki.com verify error:num=20:unable to get local issuer certificate verify return:1 depth=0 C = JP, ST = Tokyo, L = Chuo-ku, OU = The personnel affairs general affairs department, O = "SHOCHIKU CO., LTD.", CN = www.eigeki.com verify error:num=21:unable to verify the first certificate verify return:1 --- Certificate chain 0 s:/C=JP/ST=Tokyo/L=Chuo-ku/OU=The personnel affairs general affairs department/O=SHOCHIKU CO., LTD./CN=www.eigeki.com i:/C=BE/O=GlobalSign nv-sa/CN=GlobalSign RSA OV SSL CA 2018 ---
verify error:num=20:unable to get local issuer certificate
, verify error:num=21:unable to verify the first certificate
となってるので、1つめの証明書=サーバ証明書が検証できてないですね。証明書チェーンが1つしかないので、CN=GlobalSign RSA OV SSL CA 2018
の証明書が原因っぽい。。
どうやら、Chromeにはこの中間証明書がインストールされてるけど、Firefoxには入ってないっぽい。
そこで、以下のサイトを参考に中間証明書を追加。
hideharaaws.hatenablog.com
証明書は
jp.globalsign.com
から入手。
$ sudo wget -P /usr/share/ca-certificates/ https://jp.globalsign.com/repository/common/cer/gsrsaovsslca2018.cer --2020-03-14 10:13:07-- https://jp.globalsign.com/repository/common/cer/gsrsaovsslca2018.cer jp.globalsign.com (jp.globalsign.com) をDNSに問いあわせています... 104.18.133.31, 104.18.132.31, 2606:4700::6812:851f, ... jp.globalsign.com (jp.globalsign.com)|104.18.133.31|:443 に接続しています... 接続しました。 HTTP による接続要求を送信しました、応答を待っています... 200 OK 長さ: 1120 (1.1K) [application/pkix-cert] `/usr/share/ca-certificates/gsrsaovsslca2018.cer' に保存中 gseccovsslca2018.ce 100%[===================>] 1.09K --.-KB/s 時間 0s 2020-03-14 10:13:07 (8.12 MB/s) - `/usr/share/ca-certificates/gsrsaovsslca2018.cer' へ保存完了 [1120/1120] $ ls /usr/share/ca-certificates/ gsrsaovsslca2018.cer mozilla $ sudo sh -c "echo 'gsrsaovsslca2018.cer' >> /etc/ca-certificates.conf" $ tail /etc/ca-certificates.conf mozilla/VeriSign_Universal_Root_Certification_Authority.crt mozilla/Verisign_Class_3_Public_Primary_Certification_Authority_-_G3.crt mozilla/Visa_eCommerce_Root.crt mozilla/XRamp_Global_CA_Root.crt mozilla/certSIGN_ROOT_CA.crt mozilla/ePKI_Root_Certification_Authority.crt mozilla/thawte_Primary_Root_CA.crt mozilla/thawte_Primary_Root_CA_-_G2.crt mozilla/thawte_Primary_Root_CA_-_G3.crt gsrsaovsslca2018.cer $ sudo update-ca-certificates Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done. Running hooks in /etc/ca-certificates/update.d... done.
とりあえず解決したっぽい??
$ openssl s_client -connect www.eigeki.com:443 CONNECTED(00000005) depth=2 OU = GlobalSign Root CA - R3, O = GlobalSign, CN = GlobalSign verify return:1 depth=1 C = BE, O = GlobalSign nv-sa, CN = GlobalSign RSA OV SSL CA 2018 verify return:1 depth=0 C = JP, ST = Tokyo, L = Chuo-ku, OU = The personnel affairs general affairs department, O = "SHOCHIKU CO., LTD.", CN = www.eigeki.com verify return:1 --- Certificate chain 0 s:C = JP, ST = Tokyo, L = Chuo-ku, OU = The personnel affairs general affairs department, O = "SHOCHIKU CO., LTD.", CN = www.eigeki.com i:C = BE, O = GlobalSign nv-sa, CN = GlobalSign RSA OV SSL CA 2018 --- Server certificate -----BEGIN CERTIFICATE----- ### 省略 ### -----END CERTIFICATE----- subject=C = JP, ST = Tokyo, L = Chuo-ku, OU = The personnel affairs general affairs department, O = "SHOCHIKU CO., LTD.", CN = www.eigeki.com issuer=C = BE, O = GlobalSign nv-sa, CN = GlobalSign RSA OV SSL CA 2018 --- No client certificate CA names sent Peer signing digest: SHA256 Peer signature type: RSA Server Temp Key: DH, 1024 bits --- SSL handshake has read 2633 bytes and written 506 bytes Verification: OK --- New, TLSv1.2, Cipher is DHE-RSA-AES128-GCM-SHA256 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : DHE-RSA-AES128-GCM-SHA256 Session-ID: 6B0588D034DCBB146CCE762B5EAD954964851D463C3BC2AAE55E8AD3C70E4476 Session-ID-ctx: Master-Key: D7686744A28201CC3F013F07CB0B3A76EC09CD8E3EB76811EB2CCCE40C759B6174B4BEC7D9EF281BF4B536D8F290D884 PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 300 (seconds) TLS session ticket: ### 省略 ### Start Time: 1584180854 Timeout : 7200 (sec) Verify return code: 0 (ok) Extended master secret: no --- $ wget -v https://www.eigeki.com --2020-03-14 11:08:36-- https://www.eigeki.com/ www.eigeki.com (www.eigeki.com) をDNSに問いあわせています... 133.18.5.93 www.eigeki.com (www.eigeki.com)|133.18.5.93|:443 に接続しています... 接続しました。 HTTP による接続要求を送信しました、応答を待っています... 200 OK 長さ: 特定できません [text/html] `index.html' に保存中 index.html [ <=> ] 170.38K 416KB/s 時間 0.4s 2020-03-14 11:08:37 (416 KB/s) - `index.html' へ保存終了 [174473]
Verify return code: 0 (ok)
だし、これで解決!
と思ったものの・・・
anaconda環境内ではまだ動かず。。
$ openssl s_client -connect www.eigeki.com:443 CONNECTED(00000003) depth=0 C = JP, ST = Tokyo, L = Chuo-ku, OU = The personnel affairs general affairs department, O = "SHOCHIKU CO., LTD.", CN = www.eigeki.com verify error:num=20:unable to get local issuer certificate verify return:1 depth=0 C = JP, ST = Tokyo, L = Chuo-ku, OU = The personnel affairs general affairs department, O = "SHOCHIKU CO., LTD.", CN = www.eigeki.com verify error:num=21:unable to verify the first certificate verify return:1 --- ### 以下略 ###
どうやら、anacondaが持ってるcacert.pemが悪いらしい?!
$ curl -v https://www.eigeki.com * Rebuilt URL to: https://www.eigeki.com/ * Trying 133.18.5.93... * TCP_NODELAY set * Connected to www.eigeki.com (133.18.5.93) port 443 (#0) * ALPN, offering http/1.1 * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH * successfully set certificate verify locations: * CAfile: /home/kanekkie/anaconda3/ssl/cacert.pem CApath: none * TLSv1.2 (OUT), TLS header, Certificate Status (22): * TLSv1.2 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (OUT), TLS alert, Server hello (2): * SSL certificate problem: unable to get local issuer certificate * Closing connection 0 curl: (60) SSL certificate problem: unable to get local issuer certificate More details here: https://curl.haxx.se/docs/sslcerts.html curl failed to verify the legitimacy of the server and therefore could not establish a secure connection to it. To learn more about this situation and how to fix it, please visit the web page mentioned above.
ここまでやって疲れたので、とりあえず強制的に証明書ディレクトリを読ませるようにして、一時的に回避
>>> r = requests.get(url, verify="/etc/ssl/certs/ca-certificates.crt") >>> r <Response [200]>
気が向いたら続きを書く、かも・・・
picoCTF 2018 (2)
grep 2
上の方の"shell"っていうリンクからサーバには入れるらしい。
$ cd /problems/grep-2_3_826f886f547acb8a9c3fccb030e8168d/files $ ls files0 files1 files2 files3 file4 files5 files6 files7 files8 files9
ディレクトリがいっぱいあるのでとりあえずgrepしたら簡単に見つかった。
$ grep pico -r ./* ./files8/file14:picoCTF{...}
Aca-Shell-A
$ nc 2018shell.picoctf.com 58422 Sweet! We have gotten access into the system but we aren't root. It's some sort of restricted shell! I can't see what you are typing but I can see your output. I'll be here to help you along. If you need help, type "echo 'Help Me!'" and I'll see what I can do There is not much time left! ~/$ echo 'Help Me!' Help Me! You got this! Have you looked for any directories? ~/$ ls blackmail executables passwords photos secret ~/$ cd secret Now we are cookin'! Take a look around there and tell me what you find! ~/secret$ ls intel_1 intel_2 intel_3 intel_4 intel_5 profile_ahqueith5aekongieP4ahzugi profile_ahShaighaxahMooshuP1johgo profile_aik4hah9ilie9foru0Phoaph0 profile_AipieG5Ua9aewei5ieSoh7aph profile_bah9Ech9oa4xaicohphahfaiG profile_ie7sheiP7su2At2ahw6iRikoe profile_of0Nee4laith8odaeLachoonu profile_poh9eij4Choophaweiwev6eev profile_poo3ipohGohThi9Cohverai7e profile_Xei2uu5suwangohceedaifohs Sabatoge them! Get rid of all their intel files! ~/secret$ rm intel* Nice! Once they are all gone, I think I can drop you a file of an exploit! Just type "echo 'Drop it in!' " and we can give it a whirl! ~/secret$ echo 'Drop it in!' Drop it in! I placed a file in the executables folder as it looks like the only place we can execute from! Run the script I wrote to have a little more impact on the system! ~/secret$ cd .. ~/$ cd executables ~/executables$ ls dontLookHere ~/executables$ ./dontLookHere edea ced2 6120 5855 2084 b4e7 3122 e6e5 0b2c a938 bfb4 3f57 8322 9105 8c81 7676 f18c 7d2d ecbc f758 9fb3 1f5c aa42 5518 9556 c2b1 86d5 22dc 879c 44a4 1280 ecbe b9a1 e18c a5cb 522d 3224 06d1 aee6 20ef 5257 4c15 7ab0 1c15 177c 6d76 d746 79dd 632c 929b ... Looking through the text above, I think I have found the password. I am just having trouble with a username. Oh drats! They are onto us! We could get kicked out soon! Quick! Print the username to the screen so we can close are backdoor and log into the account directly! You have to find another way other than echo! ~/executables$ whoami l33th4x0r Perfect! One second! Okay, I think I have got what we are looking for. I just need to to copy the file to a place we can read. Try copying the file called TopSecret in tmp directory into the passwords folder. ~/executables$ cd .. ~/$ cp /tmp/TopSecret passwords Server shutdown in 10 seconds... Quick! go read the file before we lose our connection! ~/$ cd passwords ~/passwords$ ls TopSecret ~/passwords$ cat TopSecret Major General John M. Schofield's graduation address to the graduating class of 1879 at West Point is as follows: The discipline which makes the soldiers of a free country reliable in battle is not to be gained by harsh or tyrannical treatment.On the contrary, such treatment is far more likely to destroy than to make an army.It is possible to impart instruction and give commands in such a manner and such a tone of voice as to inspire in the soldier no feeling butan intense desire to obey, while the opposite manner and tone of voice cannot fail to excite strong resentment and a desire to disobey.The one mode or other of dealing with subordinates springs from a corresponding spirit in the breast of the commander.He who feels the respect which is due to others, cannot fail to inspire in them respect for himself, while he who feels,and hence manifests disrespect towards others, especially his subordinates, cannot fail to inspire hatred against himself. picoCTF{...}
Client Side is Still Bad
$ wget http://2018shell.picoctf.com:55790/ -O html $ cat html
<html> <head> <title>Super Secure Log In</title> </head> <body bgcolor="#000000"> <!-- standard MD5 implementation --> <script type="text/javascript" src="md5.js"></script> <script type="text/javascript"> function verify() { checkpass = document.getElementById("pass").value; split = 4; if (checkpass.substring(split*7, split*8) == '}') { if (checkpass.substring(split*6, split*7) == '...') { if (checkpass.substring(split*5, split*6) == '...') { if (checkpass.substring(split*4, split*5) == '...') { if (checkpass.substring(split*3, split*4) == '...') { if (checkpass.substring(split*2, split*3) == '...') { if (checkpass.substring(split, split*2) == 'CTF{') { if (checkpass.substring(0,split) == 'pico') { alert("You got the flag!") } } } } } } } } else { alert("Incorrect password"); } } </script> <div style="position:relative; padding:5px;top:50px; left:38%; width:350px; height:140px; background-color:red"> <div style="text-align:center"> <p>Welcome to the Secure Login Server.</p> <p>Please enter your credentials to proceed</p> <form action="index.html" method="post"> <input type="password" id="pass" size="8" /> <br/> <input type="submit" value="Log in" onclick="verify(); return false;" /> </form> </div> </div> </body> </html>
verify()内で正解文字列と比較している
Desrouleaux
$ nc 2018shell.picoctf.com 10493 You'll need to consult the file `incidents.json` to answer the following questions. What is the most common source IP address? If there is more than one IP address that is the most common, you may give any of the most common ones. How many unique destination IP addresses were targeted by the source IP address 189.229.254.207? What is the number of unique destination ips a file is sent, on average? Needs to be correct to 2 decimal places.
incidents.jsonに関する質問が3つ出てくる。2つめの質問はランダムにソースIPが指定されるっぽい。
めんどいのでてきとーに解かせる。
import socket import re import json HOSTNAME = "2018shell.picoctf.com" PORTNUM = 10493 class Netcat: """ Python 'netcat like' module """ def __init__(self, ip, port): self.buff = "" self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.connect((ip, port)) def read(self, length = 1024): """ Read 1024 bytes off the socket """ return self.socket.recv(length).decode() def read_until(self, data): """ Read data into the buffer until we have data """ while not data in self.buff: self.buff += self.socket.recv(1024).decode() pos = self.buff.find(data) rval = self.buff[:pos + len(data)] self.buff = self.buff[pos + len(data):] return rval def write(self, data): self.socket.send(data.encode()) def close(self): self.socket.close() FILEPATH = "incidents.json" with open(FILEPATH) as f: buf = f.read() json_dict = json.loads(buf) ticket_num_by_src = {} for t in json_dict["tickets"]: if t["src_ip"] in ticket_num_by_src: ticket_num_by_src[t["src_ip"]] += 1 else: ticket_num_by_src[t["src_ip"]] = 1 sorted(ticket_num_by_src.items(), key=lambda x: x[1]) unique_dst_by_file = {} for t in json_dict["tickets"]: if t["file_hash"] in unique_dst_by_file: if t["dst_ip"] not in unique_dst_by_file[t["file_hash"]]: unique_dst_by_file[t["file_hash"]] += [t["dst_ip"]] else: unique_dst_by_file[t["file_hash"]] = [t["dst_ip"]] cnt = 0 for v in unique_dst_by_file.values(): cnt += len(v) avg_unique_dst_ip = cnt/len(unique_dst_by_file) nc = Netcat(HOSTNAME, PORTNUM) # You'll need to consult the file `incidents.json` to answer the following questions. # # What is the most common source IP address? If there is more than one IP address that is the most common, you may give any of the most common ones. msg = nc.read_until('you may give any of the most common ones.') nc.write(list(ticket_num_by_src.keys())[0] + "\n") # How many unique destination IP addresses were targeted by the source IP address 189.229.254.207? msg = nc.read_until('by the source IP address ') expr = nc.read_until('?') m = re.match(r'(\d+\.\d+\.\d+\.\d+)', expr) src_ipaddr = m.group(1) nc.write(str(ticket_num_by_src[src_ipaddr]) + "\n") # What is the number of unique destination ips a file is sent, on average? Needs to be correct to 2 decimal places. msg = nc.read_until('Needs to be correct to 2 decimal places.') nc.write("{:.2f}".format(avg_unique_dst_ip) + "\n") print(nc.read()) nc.close()
Netcatクラスは、以下を参照してほぼコピペ。
CTF4b 2018 writeup - しばイヌとお茶
Python Netcat · GitHub
※ただし、byte列のencode/decodeのみ追加。
$ python3 solver.py Correct! Great job. You've earned the flag: picoCTF{...}
Logon
とりあえずURLにアクセスしてみると、ログインフォームがある。よくわからんのでとりあえず"Sign in"を押してみると以下のようなレスポンス。
HTTP/1.1 302 FOUND Content-Type: text/html; charset=utf-8 Content-Length: 217 Location: http://2018shell.picoctf.com:37861/flag Set-Cookie: password=; Path=/ Set-Cookie: username=; Path=/ Set-Cookie: admin=False; Path=/
そして、遷移先には"No flag for you"と表示されている。
どうみてもcookieがあやしいのでadmin=Trueにしてさいどアクセスしてみると・・・
今度は無事にフラグが表示された。めでたしめでたし。
Reading Between the Eyes
$ sudo apt-get install ruby $ sudo gem install zsteg $ zsteg husky.png b1,r,lsb,xy .. text: "^5>c[rvyzrf@" b1,rgb,lsb,xy .. text: "picoCTF{...}" b1,abgr,msb,xy .. file: PGP\011Secret Sub-key - b2,g,msb,xy .. text: "ADTU@PEPA" b3,abgr,msb,xy .. text: "t@Wv!Wt\tGtA" b4,r,msb,xy .. text: "0Tt7F3Saf" b4,g,msb,xy .. text: "2g'uV `3" b4,b,lsb,xy .. text: "##3\"TC%\"2f" b4,b,msb,xy .. text: " uvb&b@f!" b4,rgb,lsb,xy .. text: "1C5\"RdWD" b4,rgb,msb,xy .. text: "T E2d##B#VuQ`" b4,bgr,lsb,xy .. text: "A%2RTdGG" b4,bgr,msb,xy .. text: "EPD%4\"c\"#CUVqa " b4,rgba,lsb,xy .. text: "?5/%/d_tO" b4,abgr,msb,xy .. text: "EO%O#/c/2/C_e_q"
Recovering From the Snap
$ foremost -v animals.dd Foremost version 1.5.7 by Jesse Kornblum, Kris Kendall, and Nick Mikus Audit File Foremost started at Wed Feb 6 23:08:35 2019 Invocation: foremost -v animals.dd Output directory: /home/kanekkie/Documents/ctf/pico/Recovering_From_the_Snap/output Configuration file: /etc/foremost.conf Processing: animals.dd |------------------------------------------------------------------ File: animals.dd Start: Wed Feb 6 23:08:35 2019 Length: 10 MB (10485760 bytes) Num Name (bs=512) Size File Offset Comment 0: 00000077.jpg 617 KB 39424 1: 00001313.jpg 481 KB 672256 2: 00002277.jpg 380 KB 1165824 3: 00003041.jpg 248 KB 1556992 4: 00003541.jpg 314 KB 1812992 5: 00004173.jpg 458 KB 2136576 6: 00005093.jpg 383 KB 2607616 7: 00005861.jpg 39 KB 3000832 *| Finish: Wed Feb 6 23:08:36 2019 8 FILES EXTRACTED jpg:= 8 ------------------------------------------------------------------ Foremost finished at Wed Feb 6 23:08:36 2019
あとはjpgを見ればフラグがある。
foremost便利ですね
admin panel
$ wget --no-check-certificate https://2018shell.picoctf.com/static/ee6ed2afe1da153ae06e61d5ee26d52d/data.pcap $ grep pico data.pcap バイナリファイル data.pcap に一致しました $ grep --binary-files=text pico data.pcap user=admin&password=picoCTF{...}�zB[�ABB )y�� )�E4�@@��������P�~.[��29��~
とりあえずgrepしてみたら見つかった
assembly-0
asm0(0xc9,0xb0) の返り値がフラグ(picoCTF{}の形式じゃなく、"0x..")
アセンブリが配られてるので読むだけ。
$ cat intro_asm_rev.S .intel_syntax noprefix .bits 32 .global asm0 asm0: push ebp mov ebp,esp mov eax,DWORD PTR [ebp+0x8] mov ebx,DWORD PTR [ebp+0xc] mov eax,ebx mov esp,ebp pop ebp ret
buffer overflow 0
ソースコードが配られるのでながめてみる。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #define FLAGSIZE_MAX 64 char flag[FLAGSIZE_MAX]; void sigsegv_handler(int sig) { fprintf(stderr, "%s\n", flag); fflush(stderr); exit(1); } void vuln(char *input){ char buf[16]; strcpy(buf, input); } int main(int argc, char **argv){ FILE *f = fopen("flag.txt","r"); if (f == NULL) { printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n"); exit(0); } fgets(flag,FLAGSIZE_MAX,f); signal(SIGSEGV, sigsegv_handler); gid_t gid = getegid(); setresgid(gid, gid, gid); if (argc > 1) { vuln(argv[1]); printf("Thanks! Received: %s", argv[1]); } else printf("This program takes 1 argument.\n"); return 0; }
SEGVのハンドラ(sigsegv_handler)に到達するとflagが表示されるっぽい。
どこでSEGVを出すかだが、(名前からしても)vulnだろう。
char buf[16]にargv[1]が入るので、長い引数を渡せばよさそう。
kanekkie@pico-2018-shell:~$ cd /problems/buffer-overflow-0_3_d5263c5219b334339c34ac35c51c4a17 kanekkie@pico-2018-shell:/problems/buffer-overflow-0_3_d5263c5219b334339c34ac35c51c4a17$ python -c 'print "0" * 23' | xargs ./vuln Thanks! Received: 00000000000000000000000 kanekkie@pico-2018-shell:/problems/buffer-overflow-0_3_d5263c5219b334339c34ac35c51c4a17$ python -c 'print "0" * 24' | xargs ./vuln xargs: ./vuln: terminated by signal 11 kanekkie@pico-2018-shell:/problems/buffer-overflow-0_3_d5263c5219b334339c34ac35c51c4a17$ python -c 'print "0" * 25' | xargs ./vuln xargs: ./vuln: terminated by signal 11 kanekkie@pico-2018-shell:/problems/buffer-overflow-0_3_d5263c5219b334339c34ac35c51c4a17$ python -c 'print "0" * 26' | xargs ./vuln xargs: ./vuln: terminated by signal 11 kanekkie@pico-2018-shell:/problems/buffer-overflow-0_3_d5263c5219b334339c34ac35c51c4a17$ python -c 'print "0" * 27' | xargs ./vuln xargs: ./vuln: terminated by signal 11 kanekkie@pico-2018-shell:/problems/buffer-overflow-0_3_d5263c5219b334339c34ac35c51c4a17$ python -c 'print "0" * 28' | xargs ./vuln picoCTF{...}
24文字からsignal 11 (SEGV?) が出て、28文字でフラグが表示された。
caesar cipher 1
$ cat ciphertext picoCTF{vgefmsaapaxpomqemdoubtqdxoaxypeo}
よくわからないのでとりあえずROT0-25を出してみる。
CT_PATH = "ciphertext" # only for small letters def rotn(t, n): return "".join([chr((ord(c) - ord("a") + n) % 26 + ord("a")) for c in t]) with open(CT_PATH) as f: ct = f.read() for i in range(26): print("ROT {:2d}: {}{}{}".format(i, ct[:8], rotn(ct[8:-1], i), ct[-1:]))
$ python3 caesar_cipher_1.py ROT 0: picoCTF{vgefmsaapaxpomqemdoubtqdxoaxypeo} ROT 1: picoCTF{whfgntbbqbyqpnrfnepvcureypbyzqfp} ROT 2: picoCTF{xighouccrczrqosgofqwdvsfzqczargq} ROT 3: picoCTF{yjhipvddsdasrpthpgrxewtgardabshr} ROT 4: picoCTF{zkijqweetebtsquiqhsyfxuhbsebctis} ROT 5: picoCTF{aljkrxffufcutrvjritzgyvictfcdujt} ROT 6: picoCTF{bmklsyggvgdvuswksjuahzwjdugdevku} ROT 7: picoCTF{cnlmtzhhwhewvtxltkvbiaxkevhefwlv} ROT 8: picoCTF{domnuaiixifxwuymulwcjbylfwifgxmw} ROT 9: picoCTF{epnovbjjyjgyxvznvmxdkczmgxjghynx} ROT 10: picoCTF{fqopwckkzkhzywaownyeldanhykhizoy} ROT 11: picoCTF{grpqxdllaliazxbpxozfmeboizlijapz} ROT 12: picoCTF{hsqryemmbmjbaycqypagnfcpjamjkbqa} ROT 13: picoCTF{itrszfnncnkcbzdrzqbhogdqkbnklcrb} ROT 14: picoCTF{justagoodoldcaesarcipherlcolmdsc} ROT 15: picoCTF{kvtubhppepmedbftbsdjqifsmdpmnetd} ROT 16: picoCTF{lwuvciqqfqnfecguctekrjgtneqnofue} ROT 17: picoCTF{mxvwdjrrgrogfdhvduflskhuofropgvf} ROT 18: picoCTF{nywxeksshsphgeiwevgmtlivpgspqhwg} ROT 19: picoCTF{ozxyflttitqihfjxfwhnumjwqhtqrixh} ROT 20: picoCTF{payzgmuujurjigkygxiovnkxriursjyi} ROT 21: picoCTF{qbzahnvvkvskjhlzhyjpwolysjvstkzj} ROT 22: picoCTF{rcabiowwlwtlkimaizkqxpmztkwtulak} ROT 23: picoCTF{sdbcjpxxmxumljnbjalryqnaulxuvmbl} ROT 24: picoCTF{tecdkqyynyvnmkockbmszrobvmyvwncm} ROT 25: picoCTF{ufdelrzzozwonlpdlcntaspcwnzwxodn}
ROT14ぽい(でも確証はないのでguess問題ぽさもある。。)
environ
shell serverの環境変数からフラグを探す。
kanekkie@pico-2018-shell:~$ export | grep pico declare -x SECRET_FLAG="picoCTF{eNv1r0nM3nT_v4r14Bl3_fL4g_3758492}"
hertz
$ nc 2018shell.picoctf.com 48186 > output $ cat output ------------------------------------------------------------------------------- qmvnfxwt oafa ht smkf ulxn - tkctwhwkwhmv_qhpoaft_xfa_tmlzxcla_oooohlwpww ------------------------------------------------------------------------------- "jall, pfhvqa, tm navmx xvr lkqqx xfa vmj yktw uxdhls atwxwat mu woa ckmvxpxfwat. ckw h jxfv smk, hu smk rmvw wall da woxw woht daxvt jxf, hu smk twhll wfs wm rauavr woa hvuxdhat xvr omffmft pafpawfxwar cs woxw xvwhqofhtw-h faxlls calhaza oa ht xvwhqofhtw-h jhll oxza vmwohvn dmfa wm rm jhwo smk xvr smk xfa vm lmvnaf ds ufhavr, vm lmvnaf ds 'uxhwoukl tlxza,' xt smk qxll smkftalu! ckw omj rm smk rm? h taa h oxza ufhnowavar smk-thw rmjv xvr wall da xll woa vajt." hw jxt hv ykls, 1805, xvr woa tpaxiaf jxt woa jall-ivmjv xvvx pxzlmzvx tqoafaf, dxhr mu omvmf xvr uxzmfhwa mu woa adpfatt dxfsx uarmfmzvx. jhwo woata jmfrt toa nfaawar pfhvqa zxthlh ikfxnhv, x dxv mu ohno fxvi xvr hdpmfwxvqa, jom jxt woa uhftw wm xffhza xw oaf faqapwhmv. xvvx pzlmzvx oxr oxr x qmkno umf tmda rxst. toa jxt, xt toa txhr, tkuuafhvn ufmd lx nfhppa; nfhppa cahvn woav x vaj jmfr hv tw. pawaftckfn, ktar mvls cs woa alhwa. xll oaf hvzhwxwhmvt jhwomkw abqapwhmv, jfhwwav hv ufavqo, xvr ralhzafar cs x tqxflaw-lhzafhar ummwdxv woxw dmfvhvn, fxv xt umllmjt: "hu smk oxza vmwohvn cawwaf wm rm, qmkvw (mf pfhvqa), xvr hu woa pfmtpaqw mu tpavrhvn xv azavhvn jhwo x pmmf hvzxlhr ht vmw wmm waffhcla, h toxll ca zafs qoxfdar wm taa smk wmvhnow cawjaav 7 xvr 10 xvvawwa tqoafaf." "oaxzavt! joxw x zhfklavw xwwxqi!" faplhar woa pfhvqa, vmw hv woa laxtw rhtqmvqafwar cs woht faqapwhmv. oa oxr yktw avwafar, jaxfhvn xv adcfmhrafar qmkfw kvhumfd, ivaa cfaaqoat, xvr tomat, xvr oxr twxft mv oht cfaxtw xvr x tafava abpfatthmv mv oht ulxw uxqa. oa tpmia hv woxw fauhvar ufavqo hv johqo mkf nfxvruxwoaft vmw mvls tpmia ckw womknow, xvr jhwo woa navwla, pxwfmvhehvn hvwmvxwhmv vxwkfxl wm x dxv mu hdpmfwxvqa jom oxr nfmjv mlr hv tmqhaws xvr xw qmkfw. oa javw kp wm xvvx pzlmzvx, ihttar oaf oxvr, pfatavwhvn wm oaf oht cxlr, tqavwar, xvr tohvhvn oaxr, xvr qmdplxqavwls taxwar ohdtalu mv woa tmux. "uhftw mu xll, raxf ufhavr, wall da omj smk xfa. taw smkf ufhavr't dhvr xw fatw," txhr oa jhwomkw xlwafhvn oht wmva, cavaxwo woa pmlhwavatt xvr xuuaqwar tsdpxwos mu johqo hvrhuuafavqa xvr azav hfmvs qmklr ca rhtqafvar.
よくわからないけど、substitution cipherだと問題に書いてあったので、オンラインのソルバに投げてみたら解けた。
Substitution Solver - www.guballa.de
換字表は
abcdefghijklmnopqrstuvwxyz This clear text ... kdpoqhscgjzmtbnlyfxwueiavr ... maps to this cipher text
hex editor
$ strings hex_editor.jpg | grep pico Your flag is: "picoCTF{and_thats_how_u_edit_hex_kittos_8BcA67a2}"
バイナリエディタいらなかった。。
ssh-keyz
web shellから.ssh/authorized_keysに公開鍵を書き込んでsshするだけ。
$ ssh kanekkie@2018shell4.picoctf.com The authenticity of host '2018shell4.picoctf.com (18.188.57.214)' can't be established. ECDSA key fingerprint is SHA256:cLYL/h/zTqqapwkOtHLvuBv/ire4/UakBVvpUpBNqII. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '2018shell4.picoctf.com,18.188.57.214' (ECDSA) to the list of known hosts. picoCTF{who_n33ds_p4ssw0rds_38dj21} Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1075-aws x86_64) ...
ようやく150点問題おしまい。。
picoCTF 2018
久しぶりにCTFをしてみる。
https://2018game.picoctf.com
flagは、picoCTF{FLAG}
Forensics Warmup 1
flag.zipファイルが配られる。
$ unzip flag.zip Archive: flag.zip inflating: flag.jpg $ file flag.jpg flag.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 75x75, segment length 16, baseline, precision 8, 909x194, frames 3 $ xdg-open flag.jpg
unzipしてjpgを表示するだけ。
Forensics Warmup 2
flag.pngが配られる。
$ xdg-open flag.png ## cannot open $ file flag.png flag.png: JPEG image data, JFIF standard 1.01, resolution (DPI), density 75x75, segment length 16, baseline, precision 8, 909x190, frames 3 $ cp flag.png flag.jpg $ xdg-open flag.jpg
General Warmup 2
27を2進数表記に
$ echo "obase=2; ibase=10; 27" | bc ## FLAG
cf. シェルで2進数、8進数、10進数、16進数変換@bash | Mazn.net
ibaseは指定しなくてもいけるっぽい。
General Warmup 3
0x3dを10進数表記に
$ printf "%d\n" 0x3d ## FLAG
Resources
指定されたURLにいって"picoCTF{"で検索するだけ
$ wget https://picoctf.com/resources -O - | grep "picoCTF{.\+\?}"
Reversing Warmup 1
サーバのどっかのディレクトリにいって配布プログラムを実行しろと書いてあるが、よくわからないので、とりあえず実行してみる
$ ./run ## FLAG $ strings run | grep picoCTF{ ## FLAG
フラグが出てくるのでこれでおしまい。
Crypto Warmup 1
ciphertext = "llkjmlmpadkkc" key = "thisisalilkey" def encrypt(plaintext, key): ciphertext = "" for p, k in zip(plaintext, key): c = chr(((ord(p) - ord('a') + ord(k) - ord('a')) % 26) + ord('a')) ciphertext += c return ciphertext def decrypt(ciphertext, key): plaintext = "" for c, k in zip(ciphertext, key): p = chr(((ord(c) - ord(k)) % 26) + ord('a')) plaintext += p return plaintext decrypted = decrypt(ciphertext, key) print("ciphertext: {}\nkey: {}\nplaintext: {}\nre-encrypted: {}".format(ciphertext, key, decrypted, encrypt(decrypted, key)))
Crypto Warmup 2
encoded_flag = "cvpbPGS{guvf_vf_pelcgb!}" def rot13(text): encoded = "" for t in text: if "z" >= t >= "a": e = chr(((ord(t) - ord("a") + 13) % 26) + ord("a")) elif "A" <= t <= "Z": e = chr(((ord(t) - ord("A") + 13) % 26) + ord("A")) else: e = t encoded += e return encoded print("input: {}\ndecoded: {}\nencoded: {}".format((encoded_flag), rot13(encoded_flag), rot13(rot13(encoded_flag))))
net cat
$ nc 2018shell.picoctf.com 49387 That wasn't so hard was it? picoCTF{...}
接続するだけ
HEEEEEEERE'S Johnny!
とりあえずアクセスしてみる
$ nc 2018shell.picoctf.com 40157 Username: hoge Password: fuga Failed Login!
ユーザ名とパスワードが必要。
配られたファイルを見てみる。
$ cat passwd root:x:0:0:root:/root:/bin/bash $ cat shadow root:$6$q7xpw/2.$la4KiUz87ohdszbOVoIopy2VTwm/5jEXvWSdWynh0CnP5T.MnJfVNCzp3IfJMHUNuBhr1ewcYd8PyeKHqHQoe.:17770:0:99999:7:::
rootユーザでアクセスすればいいのだろう。パスワードをクラックする必要があるので、john the ripperを使う。
$ sudo apt-get install john $ john shadow Loaded 1 password hash (crypt, generic crypt(3) [?/64]) Press 'q' or Ctrl-C to abort, almost any other key for status kissme (root) 1g 0:00:00:12 100% 2/3 0.08298g/s 376.8p/s 376.8c/s 376.8C/s keller..nation Use the "--show" option to display all of the cracked passwords reliably Session completed
パスワードもわかったので再度アクセス
$ nc 2018shell.picoctf.com 40157 Username: root Password: kissme picoCTF{...}
strings
$ strings strings | grep picoCTF{ picoCTF{...}
pipe
$ nc 2018shell.picoctf.com 34532 | head This is not a flag This is not a flag I'm sorry you're going to have to look at another line I'm sorry you're going to have to look at another line This is not a flag Unfortunately this is also not a flag This is not a flag I'm sorry you're going to have to look at another line Unfortunately this is also not a flag I'm sorry you're going to have to look at another line ... $ nc 2018shell.picoctf.com 34532 | grep picoCTF{ picoCTF{...}
Inspect Me
とりあえずアクセスしてページを検証 (inspect) してみるとフラグっぽいのがある。
<!-- I learned HTML! Here's part 1/3 of the flag: picoCTF{... -->
分割されてるっぽいのであとは適当に全部とってくる。
$ wget -p http://2018shell.picoctf.com:28831/ -nd $ ls index.html mycss.css myjs.js $ grep flag ./* ./index.html: <!-- I learned HTML! Here's part 1/3 of the flag: picoCTF{... --> ./mycss.css:/* I learned CSS! Here's part 2/3 of the flag: ...} */ ./myjs.js:/* I learned JavaScript! Here's part 3/3 of the flag: */
とりあえずここまで。
ゲストOSにsshで入る (Virtualbox)
とくにWindows上の操作を忘れないようにメモ。
Virtualboxの設定
Ubuntuのsshdを設定
$ sudo apt-get install openssh-server $ sudo vi /etc/ssh/sshd_config ## "PermitRootLogin no"を追記 $ sudo /etc/init.d/ssh restart
ホストからsshでログイン
$ ssh USERNAME@HOSTNAME
公開鍵の設定
## Windows Powershell > ssh-keygen -t ecdsa > scp $HOME\.ssh\id_ecdsa.pub USERNAME@HOSTNAME:~/.ssh/authorized_keys > ssh USERNAME@HOSTNAME $ sudo vi /etc/ssh/sshd_config ## "PasswordAuthentication no" $ sudo /etc/init.d/ssh restart
Virtual Studio Codeからssh接続する場合
SSH FSを入れ、以下のコマンドで設定
>SSH FS: Create a SSH FS configuration
適当に編集する
// If you haven't already, associate .jsonc files with "JSON with Comments (jsonc) { "root": "~/", "host": "HOSTNAME", "port": 22, "username": "USERNAME", "privateKeyPath": "$USERPROFILE/.ssh/id_ecdsa" }