nssctf-2

发布时间 2023-07-13 20:27:45作者: Focu4

try again,学到了

[SWPUCTF 2021 新生赛]ez_unserialize

点进去,查看源码,提示disallow,是一个爬虫协议robots.txt,访问
image.pngimage.png
得到源码

 <?php

error_reporting(0);
show_source("cl45s.php");

class wllm{

    public $admin;
    public $passwd;

    public function __construct(){
        $this->admin ="user";
        $this->passwd = "123456";
    }

        public function __destruct(){
        if($this->admin === "admin" && $this->passwd === "ctf"){
            include("flag.php");
            echo $flag;
        }else{
            echo $this->admin;
            echo $this->passwd;
            echo "Just a bit more!";
        }
    }
}

$p = $_GET['p'];
unserialize($p);

?> 

函数解析:

unserialize:编程术语,指的是将序列化的数据还原为原始数据结构的过程。
序列化是将数据结构转换成一串字节流(通常是字符串),以便在存储或传输时进行持久化或交换,序列化的数据可以被保存到文件、数据库或通过网络传输。
unserialize将序列化的字节流重新转换为原始的数据结构,这个函数可以用于将序列化的数据还原为原始对象、数组、哈希表等数据结构。
序列化的字符串一般有特定的格式,例如json、xml,比如在json中使用键值对的方式,键是字符串,而值的数据类型不限制,也可以进行嵌套。
反序列化不受信任的数据可能会存在安全风险,比如代码注入。

_destruct用于定义一个对象在销毁(释放内存)之前执行的操作,用于执行一些资源释放或清理的操作,当对象不再被引用或执行脚本结束时,系统会自动销毁对象,在销毁前调用该方法,这种机制允许程序员在需要清理资源时候进行相应的处理,例如关闭文件,释放数据库连接、释放内存。
__construct:当创建对象时,该函数被调用。

代码审计:
wllm类里面有两个属性admin和passwd,还有一个构造函数和一个析构函数,在创建wllm类的对象会调用construct函数,然后设置admin=user,passwd=123456.在销毁wllm类时调用destruct函数,会检查admin=admin和passwd=ctf成立吗,如果成立则数据flag,否则输出其他。最后从get获取参数p的值,并将其反序列化为原始的php数据结构。
我们需要的是构造admin=admin,passwd=ctf成立
关于反序列化漏洞https://www.freebuf.com/articles/web/263584.html
反序列化漏洞利用总结 - FreeBuf网络安全行业门户
使用反序列化函数是会自动调用_wakeup魔术方法(前提是该函数存在),即为执行eval(phpinfo();) _wakeup的优先级是高于_destruct的,
image.png
关于PHP魔术方法:NSSCTF | 在线CTF平台
魔术方法是PHP面向对象中特有的特性,他们在特定的情况下被触发,以双划线开头,用魔术方法可以实现PHP面向对象中重载,重载过程会执行相关代码。

1、__get、__set 这两个方法是为在类和他们的父类中没有声明的属性而设计的 __get( $property ) 当调用一个未定义的属性时访问此方法 __set( $property, $value ) 给一个未定义的属性赋值时调用 这里的没有声明包括访问控制为proteced,private的属性(即没有权限访问的属性)
2、__isset、__unset __isset( $property ) 当在一个未定义的属性上调用isset()函数时调用此方法 __unset( $property ) 当在一个未定义的属性上调用unset()函数时调用此方法 与__get方法和__set方法相同,这里的没有声明包括访问控制为proteced,private的属性(即没有权限访问的属性)
3、__call __call( $method, $arg_array ) 当调用一个未定义(包括没有权限访问)的方法是调用此方法
4、__autoload __autoload 函数,使用尚未被定义的类时自动调用。通过此函数,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类。 注意: 在 __autoload 函数中抛出的异常不能被 catch 语句块捕获并导致致命错误。
5、__construct、__destruct __construct 构造方法,当一个对象被创建时调用此方法,好处是可以使构造方法有一个独一无二的名称,无论它所在的类的名称是什么,这样你在改变类的名称时,就不需要改变构造方法的名称 __destruct 析构方法,PHP将在对象被销毁前(即从内存中清除前)调用这个方法 默认情况下,PHP仅仅释放对象属性所占用的内存并销毁对象相关的资源.,析构函数允许你在使用一个对象之后执行任意代码来清除内存,当PHP决定你的脚本不再与对象相关时,析构函数将被调用. 在一个函数的命名空间内,这会发生在函数return的时候,对于全局变量,这发生于脚本结束的时候,如果你想明确地销毁一个对象,你可以给指向该对象的变量分配任何其它值,通常将变量赋值勤为NULL或者调用unset。
6、__clone PHP5中的对象赋值是使用的引用赋值,使用clone方法复制一个对象时,对象会自动调用__clone魔术方法,如果在对象复制需要执行某些初始化操作,可以在__clone方法实现。
7、__toString __toString方法在将一个对象转化成字符串时自动调用,比如使用echo打印对象时,如果类没有实现此方法,则无法通过echo打印对象,否则会显示:Catchable fatal error: Object of class test could not be converted to string in,此方法必须返回一个字符串。 在PHP 5.2.0之前,__toString方法只有结合使用echo() 或 print()时 才能生效。PHP 5.2.0之后,则可以在任何字符串环境生效(例如通过printf(),使用%s修饰符),但 不能用于非字符串环境(如使用%d修饰符) 从PHP 5.2.0,如果将一个未定义__toString方法的对象 转换为字符串,会报出一个E_RECOVERABLE_ERROR错误。
8、__sleep、__wakeup __sleep 串行化的时候用 __wakeup 反串行化的时候调用 serialize() 检查类中是否有魔术名称 __sleep 的函数。如果这样,该函数将在任何序列化之前运行。它可以清除对象并应该返回一个包含有该对象中应被序列化的所有变量名的数组。 使用 __sleep 的目的是关闭对象可能具有的任何数据库连接,提交等待中的数据或进行类似的清除任务。此外,如果有非常大的对象而并不需要完全储存下来时此函数也很有用。 相反地,unserialize() 检查具有魔术名称 __wakeup 的函数的存在。如果存在,此函数可以重建对象可能具有的任何资源。使用 __wakeup 的目的是重建在序列化中可能丢失的任何数据库连接以及处理其它重新初始化的任务。
9、__set_state 当调用var_export()时,这个静态 方法会被调用(自PHP 5.1.0起有效)。本方法的唯一参数是一个数组,其中包含按array(’property’ ⇒ value, …)格式排列的类属性。 10、__invoke 当尝试以调用函数的方式调用一个对象时,__invoke 方法会被自动调用。PHP5.3.0以上版本有效 11、__callStatic 它的工作方式类似于 __call() 魔术方法,__callStatic() 是为了处理静态方法调用,PHP5.3.0以上版本有效,PHP 确实加强了对 __callStatic() 方法的定义;它必须是公共的,并且必须被声明为静态的。 同样,__call() 魔术方法必须被定义为公共的,所有其他魔术方法都必须如此。

[suctf 2019]EasySQL

难得雅痞,留着后面慢慢学习吧

sql注入题mysql中sql_mode内的pipes_as_concat - NineOne_E - 博客园
[SUCTF 2019]EasySQL 1 Writeup(超级详细)_StevenOnesir的博客-CSDN博客
查询1 ,返回array[0] ⇒1
查询0,无返回
查询1",返回nonono
查询1',无返回
sql注入题目的思路 (看wp的)
先判断数字还是字符型,
判断是什么注入,就是判断什么字符可以用,比如union 注入,需要and、union等,报错注入就是updatexml,时间注入time。学到了一个方法,使用fuzz测试
被过滤的Flag、from,prepare,or,and
猜测后台执行的查询表达式select $_POST[query]||flag from Flag

Fuzz测试
也叫模糊测试或随机测试,是一种软件测试的方法,通过输入数据、命令和参数中注入大量的随机、无效或异常数据,以检测程序中的漏洞、错误或安全问题
目的是发现应用程序中潜在的异常情况,模拟真实世界中可能出现的各种输入,并观察应用程序的响应,通过不断尝试各种组合和随机生成的输入,fuzz可以解释应用程序对不良输入反应,并识别潜在的漏洞和错误。
fuzz测试适用于各种软件,包括擦做系统、网络协议、浏览器、应用程序和库等。可以帮助发现注入内存泄露、崩溃、缓冲区溢出、代码注入和安全漏洞等问题。
fuzz测试是自动化的,可以适用各种工具和框架来辅助进行测试。

各种常见sql注入的常见函数和关键payload字符
SQL注入常用函数和关键字总结 - kevin_bruce - 博客园
database():查看当前正在适用的数据库名
mid():从指定的字段中提取出字段的内容 mid(column_name,start[,len])
substr():与mid差不多
ord():获取某个字符串最开始的字符的ascii值
ASCII():用来替代rd
limit() offset():用于限制查询结果显示的行数
concat():将多个字符串连接起来,参数个数无限,
group_concat():将查询结果连成一行,只查询一列,默认用逗号分隔

[ZJCTF 2019]NiZhuanSiWei

NSSCTF | 在线CTF平台

 <?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_content():
用于从指定的文件路径中获取文件的内容并返回为字符串,通常用于读取文本文件,json数据,xml数据等
stringfile_get_contents ( string$filename [, bool$use_include_path = FALSE [, resource $context [, int$offset = -1 [, int$maxlen ]]]] )

代码审计
text、file、password均适用get传入
先检查text是否为空,然后使用file_get_contents,查看文件的内容,是否为wel----ctf这个字符串,是的话就输出文件的内容。再对file的值进行正则匹配,对flag进行了过滤,如果error就跳转到else,对password进行反序列化,前面使用了一个include,猜测序列化的内容可能在这个文件内。
思路大概清楚,就是先构造一个文件,使得内容可以进行匹配,再构造flag文件,进行正则绕过,对password进行反序列化漏洞的利用。不过file正则直接给了useless文件,这个是什么意思,那不应该照着注释直接包含吗,然后利用反序列化对flag文件进行读取。
先是构造,这里利用到了php伪协议data://CTF常用伪协议总结_compress.zlib://协议 与zip协议类似不过要压缩成zlib格式_Asionm的博客-CSDN博客

data://详解
原理:将数据直接嵌入到url中,而不是通过文件路径的方式来获取数据,这种方式可以方便的在代码中使用数据内容,而不需要实际文件存在。
作用:用于在代码中直接定义数据内容,它可以将数据作为url传递给相应的函数进行处理,而不需要实际的文件存在。
格式:data:[mediatypa][;base64],
mediatype表示数据的媒体类型 mime:text/plain、image/jpeg,php会根据媒体类型确定如何处理数据,对于文本,可以直接返回字符串,对于二进制,需要base64解码。
base64可选参数,表示数据是否使用base64编码
:表示具体数据内容
data通常结合file_get_contents函数进行使用,可以直接在代码中嵌入数据内容,省去了文件创建的步骤,直接将文本内容作为url参数。
可以根据具体的需求,将不同的媒体类型和数据内容替换到data://url中,以便在代码中使用file_get函数

然后构造file只对正则进行绕过,password 的内容应该在包含的useless.php里面,我们要对这个文件进行读取。然后就是构造序列化的值对反序列化进行漏洞利用。
image.png
payload
[http://node4.anna.nssctf.cn:28339/?text=data://text/plain,welcome%20to%20the%20zjctf&file=useless.php&password=](http://node4.anna.nssctf.cn:28339/?text=data://text/plain,welcome%20to%20the%20zjctf&file=useless.php&password=)O:4:“Flag”:1:{s:4:“file”;s:8:“flag.php”;}
text=data://text/plain,welcome to the zjctf&file=useless.php&password=O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D
text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
意思大概就是这个意思,但是不知道为什么环境出不来flag
image.png回显正常之后查看源码,在底下。
image.png

[BJDCTF 2020]easy_md5

点进环境,啥都没有,只有一个输入框。
[http://node4.anna.nssctf.cn:28984/leveldo4.php?password=2](http://node4.anna.nssctf.cn:28984/leveldo4.php?password=2)
password是参数,随着输入的变化,password的值随之变化。输入啥都没有反应
抓个包看看(抓包是个好习惯)
image.png
发现有hint
select * from 'admin' where password=md5($pass,true)
这个应该是后台执行的查询语句,password传入的值是经过md5加密过的,猜测url获取的password应该是pass的值$pass = $_GET['password']
sql注入的思路应该还是不改变的,但是需要绕过md5,SQL注入 md5 万能密码绕过参考的这篇
使用万能密码ffifdyop,得到了回显。
image.png
源码在注释里面
image.png

$a = $GET['a'];
$b = $_GET['b'];

if($a != $b && md5($a) == md5($b)){
    header('Location: levell14.php');

a,b比较不重要,这里可以直接payload跳转到levell14.php就行(不过这里的用意应该是php弱类型比较)

 <?php
error_reporting(0);
include "flag.php";

highlight_file(__FILE__);

if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
    echo $flag;
} 

php强类型比较,可以使用数组绕过(因为这里是===,所以不能利用oe开头的字符串特性吧)
PHP md5 相等绕过 - Ainsliaea - 博客园
探测了一下这里的php版本是7image.png

利用数组绕过的原理:
探讨PHP数组绕过的原理、危害和防御方法 – 启尚博客
利用数组绕过问题小总结
如果传入的参数的值为数组类型,则返回null,就会null=null,因此数组可以绕过=md5的判断。

利用数组绕过,php的数组在满足以下两个条件时候,他们被认为是相等的:

  1. 数组有相同的键-值对应数目
  2. 数组中的键和对应的值都相同。

这里使用了严格比较,只有键、值和顺序都相同,才会被认为是严格相等,否则认为不相等。

[SWPUCTF 2021 新生赛]sql

image.png
sql注入,参数是wllm
先判断是字符还是数字型,有waf,应该是限制了空格,
image.png
关于空格绕过SQL注入绕过入门总结篇 - FreeBuf网络安全行业门户
用常规的sql注入,
image.png
image.pngimage.png
image.png
image.png
爆数据表报错,应该是什么字符被过滤,猜测可能是=被wa,用like替代
image.png

image.pngimage.pngimage.png
回显只有20个,所以分组截取
为啥group_concat函数查看内容不完整?是因为group_concat_max_len参数的限制造成,默认的值是1024,当查询结果超过该长度时,返回的结果会被截断。

[GXYCTF 2019]Ping Ping Ping

直接ls
image.png
发现flag被waimage.png
image.pngpayload``

;cat$IFS$9`echo$IFS$9ZmxhZy5waHA=|base64$IFS$9-d`

这还妹结束,flag不没有直接显示,而是在源码里面,(养成查看源码是好习惯)
这道题payload,使用了反引号

在PHP中,反引号被用作反引号运算符或shell_exec运算符,主要在php脚本中执行系统命令,并返回命令的输出结果

方法是不唯一的

[SWPUCTF 2022 新生赛]ez_ez_php

 <?php
error_reporting(0);
if (isset($_GET['file'])) {
    if ( substr($_GET["file"], 0, 3) === "php" ) {
        echo "Nice!!!";
        include($_GET["file"]);
    } 

    else {
        echo "Hacker!!";
    }
}else {
    highlight_file(__FILE__);
}
//flag.php 

函数解析:

substr():
用于从字符串中获取字符串。
基本语法:
substr(string $string, int $start, int $length = null): string

  • $string:要进行截取的原始字符串。
  • $start:指定截取的起始位置。如果为正数,则表示从字符串的起始位置开始的偏移量;如果为负数,则表示从字符串末尾开始的偏移量。
  • $length(可选):指定截取的长度。如果省略该参数,则从起始位置一直截取到字符串的末尾。

这道题,要求file前三个字符为php,但是我们需要的文件是flag.php,先想到的是使用php伪协议image.png
但是说flag不在这里,在flag里面,我们直接改掉文件
image.png
payload
http://node3.anna.nssctf.cn:28603/?file=php://filter/read=covert,base64-encode/resource=flag

[WUSTCTF 2020]朴实无华

image.png
进去啥都没有,根据题目bot,访问robots.txt
image.png
假的flag
image.png
抓个包看看
image.png
发现提示
得到源码

<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__file__);


//level 1
if (isset($_GET['num'])){
    $num = $_GET['num'];
    if(intval($num) < 2020 && intval($num + 1) > 2021){
        echo "我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
    }else{
        die("金钱解决不了穷人的本质问题");
    }
}else{
    die("去非洲吧");
}
//level 2
if (isset($_GET['md5'])){
   $md5=$_GET['md5'];
   if ($md5==md5($md5))
       echo "想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
   else
       die("我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
}else{
    die("去非洲吧");
}

//get flag
if (isset($_GET['get_flag'])){
    $get_flag = $_GET['get_flag'];
    if(!strstr($get_flag," ")){
        $get_flag = str_ireplace("cat", "wctf2020", $get_flag);
        echo "想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
        system($get_flag);
    }else{
        die("快到非洲了");
    }
}else{
    die("去非洲吧");
}
?>
去非洲吧

函数解析

intval():
将变量的值转化为整数型
intval($var, $base = 10)var为转换的变量,可以是数字、字符串或其他变量,base表示指定的进制
如果var是一个数字或者数字开头的字符串,将返回其整数值
如果是一个非数字的字符串,将返回0
如果是一个浮点数,将返回整数部分
如果是一个布尔值,将返回对应的1或0
如果是一个数组,将返回0

strstr():
一个字符串处理函数,用于在一个字符串中查找另一个字符串出现的位置
char *strstr(constchar *haystack, constchar *needle)
参数说明:

  • haystack:要搜索的目标字符串。
  • needle:要查找的子字符串。

函数返回值:

  • 如果找到了子字符串,则返回子字符串在目标字符串中的指针位置。
  • 如果未找到子字符串,则返回 NULL。

str_ireplace():
用于在字符串中不分大小写的搜索和替换操作。
str_ireplace($search, $replace, $subject [, &$count])
参数说明:

  • $search:要搜索和替换的字符串或字符串数组。
  • $replace:用于替换的字符串或字符串数组。可以是一个与 $search 具有相同数量的字符串,也可以是单个字符串,将替换所有匹配项。
  • $subject:要在其中执行替换操作的源字符串。
  • &$count(可选):如果提供了此参数,则会将替换执行的次数存储在其中。

函数返回值:

  • 返回一个新的字符串,其中所有出现的 $search 字符串都被 $replace 字符串替换。

代码审计
level1:num,利用php弱类型比较,构造num=1e10在不加1的情况下会被认为是字符串,然后函数将其转换成1
1e10+1的时候会把1e10转化成整数,因而intval之后大于2021
PHP弱类型 - FreeBuf网络安全行业门户

php弱类型比较绕过
==会先把字符串类型转化成相同,再进行比较,该字符串的开始部分决定决定了它的值,如果该字符串以合法的数值开始,则使用该数组,否则其值为0

level2:值md5==md5加密后的md5,利用科学计数法,当遇到0e开头后面都是数字的字符串下,会解析为为科学计数法, 然后0乘以任何数都为0,
我们需要找一个md5加密前后都要有0e开头的字符串。

md5后面跟什么数字都能被解析成科学计数法吗?
在php中,如果一个字符串以0e开头,且后面跟着数字,那么php就会将该字符串解析为0乘以数值,等于0。
但是在md5中,只会被解析成字符串,如果被解析成科学计数法那不就变成0,md加密一个0.

md5加密前后都为0e开头的字符串
0e215962017

level3:get_flag
在php中,一个非0的整数被视为true,所以strstr对空格进行了过滤,用$IFS$9进行替代
str_ireplace替换了cat,对cat进行了过滤,再执行system操作,cat可以使用head进行替代

与cat相同执行力的函数
head:查看文件的开头几行
tail:查看文件的末尾几行
more:逐页查看文件内容
tac:以相反的顺序显示文件内容,从文件的最后一行开始逐行向上显示
nl:显示文件内容会输出行号

先执行ls
image.pngimage.png
payload:
http://node2.anna.nssctf.cn:28169/fl4g.php?num=1e10&md5=0e215962017&get_flag=head$IFS$9fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag

[HNCTF 2022 Week1]What is Web

直接f12源码,不过html的嵌套式很难找,抓了个包来一下子就找到了
image.pngimage.png

[GDOUCTF 2023]hate eat snake

image.png
撞一次等60s,再空格跳出flag
js分析
关注弹窗就行,js里面搜索alert,难以理解。image.png

[UUCTF 2022 新生赛]ez_rce

居然都不输入参数,可恶!!!!!!!!!

<?php
## 放弃把,小伙子,你真的不会RCE,何必在此纠结呢????????????
if(isset($_GET['code'])){
    $code=$_GET['code'];
    if (!preg_match('/sys|pas|read|file|ls|cat|tac|head|tail|more|less|php|base|echo|cp|\$|\*|\+|\^|scan|\.|local|current|chr|crypt|show_source|high|readgzfile|dirname|time|next|all|hex2bin|im|shell/i',$code)){
        echo '看看你输入的参数!!!不叫样子!!';echo '<br>';
        eval($code);
    }
    else{
        die("你想干什么?????????");
    }
}
else{
    echo "居然都不输入参数,可恶!!!!!!!!!";
    show_source(__FILE__);
}

过滤了很多参数,基本上常见的都不能用了。
image.png
payload
?code=printf (l\s /);
?code=printf(c\at /fffffffffflagafag);
知识点:

  1. 相同用于在终端输出内容的命令有echo``print``printf
  2. php中反引号会被解析为调用系统命令
  3. 利用反斜杠可以绕过过滤,在命令末尾使用\后,可以将回车的命令提交功能屏蔽

RCE篇之命令执行中的各种绕过 | Arsene.Tang