FlaskからFlask_Mailでメールを送る
とあるwebアプリをFlaskで作っていて、アカウント登録した際に登録したメアドにメールを送るようにしたので、その方法を書きます。
from flask import Flask from flask_mail import Mail, Message app =Flask(__name__) mail=Mail(app) app.config['MAIL_SERVER']='smtp.gmail.com' app.config['MAIL_PORT'] = 465 app.config['MAIL_USERNAME'] = '送信するときに使うgmailアドレス' app.config['MAIL_PASSWORD'] = 'そのアドレスのパスワード' app.config['MAIL_USE_TLS'] = False app.config['MAIL_USE_SSL'] = True mail = Mail(app) @app.route("/") def index(): msg = Message('タイトル', sender = '送信するときに使うgmailアドレス@gmail.com', recipients = ['送信先のメールアドレス']) msg.body = "メールの内容" mail.send(msg) return "送信しました" if __name__ == '__main__': app.run()
smtplib.SMTPAuthenticationError: (535, ‘5.7.8 Username and Password not accepted. Learn more at\n5.7.8 https://support.google.com/mail/?p=BadCredentials
上のようなエラーが出た場合は、googleアカウントを2段階認証設定することで解決できます。
Pythonでメール(gmail)を送信できない場合の解決法 | goccaの進捗記録
この記事に具体的に方法が書かれています。
ksnct(15) osコマンドインジェクション
Sherlock Holmes 70点
http://ctfq.sweetduet.info:10080/~q26/に行くことでディレクトリ構成が見れます。何度かリンクを移動するうちに、すべてのリンクがindex.plを介して表示されていることに気が付きます。なので、http://ctfq.sweetduet.info:10080/~q26/index.pl/index.plにすることで、index.plの中身を見ることができます。
#!/usr/bin/perl use CGI; print <<'EOS'; Content-type: text/html; charset=utf-8 <!DOCTYPE html> <html> <head> <title>A SCANDAL IN BOHEMIA</title> </head> <body> <h1>A SCANDAL IN BOHEMIA</h1> <div> <a href="/~q26/index.pl/a_scandal_in_bohemia_1.txt">A SCANDAL IN BOHEMIA I</a> <a href="/~q26/index.pl/a_scandal_in_bohemia_2.txt">A SCANDAL IN BOHEMIA II</a> <a href="/~q26/index.pl/a_scandal_in_bohemia_3.txt">A SCANDAL IN BOHEMIA III</a> </div> <hr> <div> EOS # Can you crack me? :P open(F,'cracked.txt'); my $t = <F>; chomp($t); if ($t eq 'h@ck3d!') { print 'FLAG_****************<br><br>'; } unlink('cracked.txt'); #### open(F,substr($ENV{'PATH_INFO'},1)); my $cgi = new CGI; $cgi->charset('utf-8'); while(<F>) { chomp; s/FLAG_\w+/FLAG_****************/g; print $cgi->escapeHTML($_)."<br>\n"; } print <<'EOS'; </div> <hr> <address> http://www.gutenberg.org/files/1661/1661-h/1661-h.htm </address> </body> </html> EOS
open関数を使ってurlのファイルを開いているので、調べてみるとperlのopen関数には脆弱性があって、"|"をつけることでosコマンドが実行できるそうです。(osコマンドインジェクション)
http://ctfq.sweetduet.info:10080/~q26/index.pl/ | echo h@ck3d! > cracked.txt
として、ページをリロードするとFlagをゲットできます。
ksnct(12) RSA
Math I 150点
RSA暗号を復号する問題です。素因数p,qが既知であるため拡張ユークリッドの互除法を用いて復号することができます。
RSA暗号
とても大きな素因数p,qがあったときに、p,qの積nを求めるのは簡単だが、nからp,qを求めるのは難しいということを利用した暗号。
暗号化
c = me mod n (m: 平文, e: 公開鍵)
復号
m = cd mod n (d: 秘密鍵)
フェルマーの小定理より、p-1とq-1の最大公倍数Lと公開鍵eを用いて、ed≡1(mod L)となる。この時dは拡張ユークリッドの互除法を用いて求めることができる。
拡張ユークリッドの互除法では、 「x, y を正の整数とし,c = gcd(x, y) とするとき,ax + by = c となる整数 a, b が存在し,a, b は計算することが出来る」
今回ax + by = cの式の x = e, y = Lとすれば、c = gcd(x, y) = 1となり、
ae + bL = 1
ea≡1(mod L)
ed≡1(mod L)と比較すると、a = d で a は求めることができるためdを求めることができた。
コード
import math import codecs def ex_euclid(x, y): c0, c1 = x, y a0, a1 = 1, 0 b0, b1 = 0, 1 while c1 != 0: m = c0 % c1 q = c0 // c1 c0, c1 = c1, m a0, a1 = a1, (a0 - q * a1) b0, b1 = b1, (b0 - q * b1) return a0 e = 65537 n = 1517330236262917595314610888889322115651087080826711948897066340883208205571592392362650858571076247939805436226544833224526137582834770402681005343930059463684528957271778199162575053306238099823295117697031968370690372250916935800738698142103275969223264184374648246277564306900886005299731265812255274723175925185522344831066577166867786835955092059346244885587228196357297758371381557924676260190209536670230008561217008649261974735505203813478978893582292682827884118215872470401293272325715864815977064075988643101088355047954735427424641386870772845440782632933485165110172437511822736907550777817722248753671107339823410418938404382732079381329288400012929311347390423061254658780185245562668131009832293474920208834795460061115101364091252176594144096675899952570380792978037217747311595899301451192342027799533264325948876556110474850761538179748318187805312451895898751337975457949549497666542175077894987697085521882531938339334715190663665300179658557458036053188152532948734992896239950564081581184284728802682982779186068791931259198917308153082917381616147108543673346682338045309449569430550618884202465809290850964525390539782080230737593560891353558335337408957948041667929154230334506735825418239563481028126435029 c = 225549592628492616152632265482125315868911125659971085929712296366214355608049224179339757637982541542745010822022226409126123627804953064072055667012172681551500780763483172914389813057444669314726404135978565446282309019729994976815925850916487257699707478206132474710963752590399332920672607440793116387051071191919835316845827838287954541558777355864714782464299278036910958484272003656702623646042688124964364376687297742060363382322519436200343894901785951095760714894439233966409337996138592489997024933882003852590408577812535049335652212448474376457015077047529818315877549614859586475504070051201054704954654093482056493092930700787890579346065916834434739980791402216175555075896066616519150164831990626727591876115821219941268309678240872298029611746575376322733311657394502859852213595389607239431585120943268774679785316133478171225719729917877009624611286702010936951705160870997184123775488592130586606070277173392647225589257616518666852404878425355285270687131724258281902727717116041282358028398978152480549468694659695121115046850718180640407034795656480263573773381753855724693739080045739160297875306923958599742379878734638341856117533253251168244471273520476474579680250862738227337561115160603373096699944163 p = 34111525225922333955113751419357677129436029651245533697825114748126342624744832960936498161825269430327019858323450578875242014583535842110912370431931233957939950911741013017595977471949767235426490850284286661592357779825212265055931705799916913817655743434497422993498931394618832741336247426815710164342599150990608143637331068220244525541794855651643135012846039439355101027994945120698530177329829213208761057392236875366458197098507252851244132455996468628957560178868724310000317011912994632328371761486669358065577269198065792981537378448324923622959249447066754504943097391628716371245206444816309511381323 q = 44481453884385518268018625442920628989497457642625668259648790876723318635861137128631112417617317160816537010595885992856520476731882382742220627466006460645416066646852266992087386855491152795237153901319521506429873434336969666536995399866125781057768075533560120399184566956433129854995464893265403724034960689938351450709950699740508459206785093693277541785285699733873530541918483842122691276322286810422297015782658645129421043160749040846216892671031156465364652681036828461619272427318758098538927727392459501761203842363017121432657534770898181975532066012149902177196510416802134121754859407938165610800223 L = (p-1)*(q-1)//math.gcd(p-1, q-1) d = ex_euclid(e,L) m = pow(c,d,n) print(codecs.decode(("%0512x"%m), 'hex'))
問題文にあるdecodeの処理がpython2で書かれているため、python3風に書き直して実行すればFLAGゲット。
ksnctf(11) known-plaintext attacks
ZIP de kure 150点
とりあえず解凍する。
$ unzip flag.zip Hint: - It is known that the encryption system of ZIP is weak against known-plaintext attacks. - We employ ZIP format not for compression but for encryption. [flag.zip] flag.html password: skipping: flag.html incorrect password skipping: Standard-lock-key.jpg incorrect password
known-plaintext attacks(既知平文攻撃)に弱いらしいので調べてみる。
暗号化されているファイル内に、既知のファイルがあれば、それをヒントに復号する方法。(
)
flag.htmlは答えだと思うので、Standard-lock-key.jpgで調べてみるとWikiにある。与えられたファイルは250KBなのでそれと同じサイズの画像を保存する
既知平文攻撃にはPkcrackを使う。Windows 64bit版はないらしいので素直にUbuntuを使う。ダウンロードしてコマンドを実行。
$ ./pkcrack -C hoge/flag.zip -c hoge/Standard-lock-key.jpg -p hoge/wikikaraotoshita.jpg -d getflag.zip Files read. Starting stage 1 on Wed Aug 5 12:11:28 2020 Generating 1st generation of possible key2_255975 values...done. Found 4194304 possible key2-values. Now we're trying to reduce these... Lowest number: 986 values at offset 248213 Lowest number: 948 values at offset 248202 Lowest number: 945 values at offset 247980 Lowest number: 928 values at offset 247965 Lowest number: 894 values at offset 247957 Lowest number: 883 values at offset 244764 Lowest number: 825 values at offset 244113 Lowest number: 820 values at offset 243180 Lowest number: 769 values at offset 243179 Lowest number: 758 values at offset 243175 Lowest number: 723 values at offset 243172 Lowest number: 702 values at offset 243171 Lowest number: 694 values at offset 243170 Lowest number: 657 values at offset 243162 Lowest number: 653 values at offset 243151 Lowest number: 652 values at offset 243149 Lowest number: 638 values at offset 243143 Lowest number: 621 values at offset 243106 Lowest number: 567 values at offset 243104 Lowest number: 546 values at offset 243103 Lowest number: 534 values at offset 243102 Lowest number: 510 values at offset 243073 Lowest number: 498 values at offset 243054 Lowest number: 476 values at offset 242992 Lowest number: 472 values at offset 242990 Lowest number: 396 values at offset 242989 Lowest number: 359 values at offset 242984 Lowest number: 321 values at offset 242983 Lowest number: 311 values at offset 242977 Lowest number: 310 values at offset 242939 Lowest number: 296 values at offset 242935 Lowest number: 270 values at offset 242934 Lowest number: 268 values at offset 242921 Lowest number: 244 values at offset 242915 Lowest number: 224 values at offset 242880 Lowest number: 215 values at offset 242879 Lowest number: 209 values at offset 242878 Lowest number: 188 values at offset 242877 Lowest number: 187 values at offset 242867 Lowest number: 186 values at offset 242866 Lowest number: 167 values at offset 242865 Lowest number: 164 values at offset 242670 Lowest number: 157 values at offset 242669 Lowest number: 141 values at offset 242655 Lowest number: 132 values at offset 242654 Lowest number: 112 values at offset 242652 Lowest number: 91 values at offset 242651 Done. Left with 91 possible Values. bestOffset is 242651. Stage 1 completed. Starting stage 2 on Wed Aug 5 12:11:39 2020 Ta-daaaaa! key0=7adffffe, key1=468d5ff6, key2=259a116a Probabilistic test succeeded for 13329 bytes. Ta-daaaaa! key0=7adffffe, key1=468d5ff6, key2=259a116a Probabilistic test succeeded for 13329 bytes. Ta-daaaaa! key0=7adffffe, key1=468d5ff6, key2=259a116a Probabilistic test succeeded for 13329 bytes. Ta-daaaaa! key0=7adffffe, key1=468d5ff6, key2=259a116a Probabilistic test succeeded for 13329 bytes. Ta-daaaaa! key0=7adffffe, key1=468d5ff6, key2=259a116a Probabilistic test succeeded for 13329 bytes. Ta-daaaaa! key0=7adffffe, key1=468d5ff6, key2=259a116a Probabilistic test succeeded for 13329 bytes. Ta-daaaaa! key0=7adffffe, key1=468d5ff6, key2=259a116a Probabilistic test succeeded for 13329 bytes. Ta-daaaaa! key0=7adffffe, key1=468d5ff6, key2=259a116a Probabilistic test succeeded for 13329 bytes. Stage 2 completed. Starting zipdecrypt on Wed Aug 5 12:11:42 2020 Decrypting flag.html (250d8b78ce908fe210d7c091)... OK! Decrypting Standard-lock-key.jpg (037d8119e2c2884a4a665d91)... OK! Finished on Wed Aug 5 12:11:42 2020
出来上がったgetflag.zipを解凍するとflag.htmlが開ける。これでFlagゲット。
実際に適当なtxtファイルと画像一緒にパスワードを付けて圧縮して、それに対して実行してみてもうまくいった。面白い、、!
ksnctf(10)
Square Cipher 60点
大文字と小文字を判定してみていったところQRコードっぽくなったので、numpyを使ってきれいに出力。
import numpy as np import matplotlib.pyplot as plt a = "oomktvziqtaovmmpxzoqrzsxlpwpgojuDQEMISYnnVYnvyWRhHsDXnSCXAVVZjtZbknedErdpvAwQWpUiLqOxIqpafvXpdXoAVWcKppbEPuaqmXWjXJwRoRFOoEgpDiRUXlQjKJlslskVpGwtljGyVJPxHvbQsQNKxCsdYMdQPJiBmyrsuOrJQOtXgpMekeinUaMoDXqFzweLKipkBuggnsUveQFYCJSKfBgHaJgZnZoWmOmAOJLVQHihljrplajyKNXtwmfOjRwOqcqeeplyzygkFOltsOyrPgIaerIaSjQQaVMyEhfydvEaRHbBzfrcwJbCZmHdddLpuEJwspbtsXQGkwpKaTZmWJiZzpbkpHNiToawxKnwJpIKbGhnLjVAJNcxrqkKEJCKCOocSvmTRDNDpFtRUmcHoRELeSqXoGUIIsuYuajeHaSVlQGLaEprSQarDzTomJdAWfqbzIJLHRBXMvNDegYeaoVRDuWBbdSBtLvxIeKdAYwajGHMgRLDGgDinBiLNBgatbkHepNsCQSJjTRmQrCHYWJqIPOVAUOerrvhmZfmogPglGNuLyAuSivBctlvVfzbqBJdHUkSaTArlgkhtHPyGhXOPkwmkBqrvbzZfwvLtTnhyXVHPlwsuGZQnNiNcmyCMtAVwYVgtZHVNznolGMBETIHFmoWjwfezbysbvOzsAhxSZFFAfOouyHldEYhgNHKKSFUtcUxfRyXHMugYBtAxBwDJZhrHmsozuNeoJqyzMDHsNbUDwzaNLtdxrbVmQMHyNndOWCZLnhrPxZXCYLDTWQreaSiEEJjZtoRpUzgsxsiiGzvnRpKLMrkqTzGCKvNhUhjrmCjAdwQAvkgqHyJZLmsSxzwjxAnWesTszIxirRwcWIXUPtwwanTDEMTRGyhzdCtkTTDWbxdSjsNYlfXzeawtidzosgaofjxxyfcdoiulemirqap" data = [] add_data = [] for i in range (len(a)): if i%31==0 and i!=0: data.append(add_data) add_data = [] add_data.append(1 if a[i].isupper() else 0) np_data = np.array(data) plt.imshow(np_data, cmap = 'gray', vmin = 0, vmax = 1) plt.show()