---已搬运--:[0CTF 2016]piapiapia -----代码审计+字符串逃逸+数组绕过长度限制+以及一下小知识点 preg_match()用数组,而且注意if是正确判断,还是错误判断
目录:
- 00000、知识点:
- 1.url传入数组绕过长度限制??
- 2.数组的遍历
- 3.数组绕过正则
- 一、自己做:
- 二、学到的&&不足:
- 四、学习WP
- 1.学习一个大佬的思路:
- 2.学习 另一个大佬的思路 ---这个过于跳跃,看上一个把,,
- 五、思路学完了,自己做做看看。
首次写于:2021.2.22
补充于:2021.5.2
00000、知识点:
1.url传入数组绕过长度限制??
就是判断你输入字符串不能够太长的时候,
用数组可以进行绕过;
2.数组的遍历
两种遍历方法
foreach(array_expression as $value)
foreach(array_expression as $key => $value)
第一种格式便利,给定的 array_expression 数组。每次循环,当前单元的值被赋值给$value,并且数组内部的指针向前移动一步(因为下一次循环将会得到下一个单元)
第二种格式也是做相同的事情,只是除了当前单元的值赋给$value之外,键名也会在每次循环中被赋给变量$key。
<?php
$arr = array(1,2,3,4);
foreach ($arr as &$value){//地址传参$value = $value*2;
}
// array $arr now is (2,4,6,8)
unset($value);//销毁$value变量
<?php
$a = array("one"=>1,"two"=>2,"three"=>3,"five"=>5
);
foreach ($a as $k => $v){echo "\$a[$k]=>$v ";
}
输出:$a[one]=>1 $a[two]=>2 $a[three]=>3 $a[five]=>5
3.数组绕过正则
- md5(Array()) = null
- sha1(Array()) = null
- ereg(pattern,Array()) =null
- preg_match(pattern,Array()) = false
- strcmp(Array(), “abc”) =null
- strpos(Array(),“abc”) = null
- strlen(Array()) = null
一、自己做:
源码都弄下来了,但是分析,代码审计技能点还没有点,,,
懵逼中,
我看到了读取文件什么的,也看到了serialize和unserialize和session。
猜测可能是序列化和反序列化,应该不是session的序列化, 因为session不可控。
然后又关于数据库的操作。但是在尝试的时候,不报错,sql注入不是了,
二、学到的&&不足:
看到config.php里面的内容了,
我就没有反应过来flag再config.php中,,,,因为后面WP取flag就是取自config.php中的,我就愣是没反应过来,数组会绕过preg_match()。使得他匹配为
false
。 这里可以绕过。然后strlen
一个数组,会返货null
.。也可以的。反序列化的话,我发现我还可以。
还有思路问题:我们上传的时候,photo是:
upload/3e602dd0ab83a3a8c3f32309bb9a88f9
这种样式,我当时还在思考,为什么,我们插入的数据是:s:10:"config.php"
。格式差别会这么大呢??这涉及到fie_get_contents()
。一个是我们方才上传的文件,另一个是已经存在的文件config.php
。而且,看
config.php
那个内容,要想到flag
就在那里,结合file_get_contents()
。就要想到是读取文件,为什么 只有
nickname
可以注入呢????
前面两个都是 否定判断, 只有这个是肯定判断,所以也就只能够绕过nickname了。
这了提醒我以后审计代码要 细心!!!!!!!。这个也太细了把,,,我当时做这个题的时候都没有注意到。。
- 要提高的能力:
1. 本地复现能力!!!2. 代码调试,在浏览器端,**var_dump()**看输出3. 数据库 看 存储的信息。
四、学习WP
1.学习一个大佬的思路:
熟悉网站结构:
class.php里有一些重要的函数
update.php和profile.php中一个是上传文件,一个是获取文件,
最重要的是config.php。我们看到flag在里面。根据前端流程 查看可疑函数
注册和登陆那块就不看了,主要的突破点是 上传资料 和 显示资料 这里。
首先是update.php
<?phprequire_once('class.php');if($_SESSION['username'] == null) {die('Login First'); }if($_POST['phone'] && $_POST['email'] && $_POST['nickname'] && $_FILES['photo']) {$username = $_SESSION['username'];if(!preg_match('/^\d{11}$/', $_POST['phone']))die('Invalid phone');if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))die('Invalid email');if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)die('Invalid nickname');$file = $_FILES['photo'];//找到文件,判断文件大小if($file['size'] < 5 or $file['size'] > 1000000)die('Photo size error');move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name']));$profile['phone'] = $_POST['phone'];$profile['email'] = $_POST['email'];$profile['nickname'] = $_POST['nickname'];$profile['photo'] = 'upload/' . md5($file['name']);$user->update_profile($username, serialize($profile));echo 'Update Profile Success!<a href="profile.php">Your Profile</a>';}else {?>
有一堆正则表达式来过滤我们提交的数据,而且第三个正则表达式和前两个不一样。这里判断了nickname是否为 字符, 还有长度是否超过10,
这里,如果我们 传入nickname为数组的话,就可以绕过长度限制,不会die出的
在代码的后面调用update_profile处我们想到这个可能是将数据保存到数据库,而且还用了php序列化serialize(),我们可以大胆的尝试用反序列化漏洞来搞一下
move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name']));$profile['phone'] = $_POST['phone'];$profile['email'] = $_POST['email'];$profile['nickname'] = $_POST['nickname'];$profile['photo'] = 'upload/' . md5($file['name']);$user->update_profile($username, serialize($profile));
我们再看看update_profile()到底是个啥,使用全局搜索我们在class.php中看到了定义的update_profile()方法
public function update_profile($username, $new_profile) {$username = parent::filter($username);$new_profile = parent::filter($new_profile);$where = "username = '$username'";return parent::update($this->table, 'profile', $new_profile, $where);}
再看一下针对 $new_profile的函数filter()
public function filter($string) {$escape = array('\'', '\\\\');$escape = '/' . implode('|', $escape) . '/';$string = preg_replace($escape, '_', $string);//过滤\和\\的,替换成_$safe = array('select', 'insert', 'update', 'delete', 'where');$safe = '/' . implode('|', $safe) . '/i';return preg_replace($safe, 'hacker', $string);}//将这些关键词替换成为hacker。要敏感,与serialize和unserialize相关的导致字符串长度变化的,public function __tostring() {return __class__;}
}
update.php我们基本上就搞清楚了,是先经过正则表达式将用户提交的参数值过滤,然后序列化,然后将非法的值替换为’hacker’
再看看profile.php
<?phprequire_once('class.php');if($_SESSION['username'] == null) {die('Login First'); }$username = $_SESSION['username'];$profile=$user->show_profile($username);if($profile == null) {header('Location: update.php');}else {$profile = unserialize($profile);$phone = $profile['phone'];$email = $profile['email'];$nickname = $profile['nickname'];$photo = base64_encode(file_get_contents($profile['photo']));
?>
我们可以看到这里有反序列化还有文件读取,而且是同一个变量 $profile[‘photo’] 。
我们对这道题应该有了大致的思路了。
flag在config.php中,而且有序列化,过滤替换,反序列化,文件读取,这不就是CTF中反序列字符逃逸的常见套路吗。我们构造包含config.php的数据,利用字符串逃逸,在profile.php中读取出来
Over。
2.学习 另一个大佬的思路 —这个过于跳跃,看上一个把,,
都审计了一遍,他没有全部仔细看,但是全部看完了。说这里有问题。:
算了,思路炒大佬得了,学习思路。
可以在 config.php中看到flag。然后看到profile.php中又 file_get_contents()函数的时候,大佬尽然想到了会有序列化的事情,真是有题感了?
profile = unserialize($profile);$phone = $profile['phone'];$email = $profile['email'];$nickname = $profile['nickname'];$photo = base64_encode(file_get_contents($profile['photo']));
读取photo的内容。我们让 $profile[‘photo’]是 config.php就好了,这样就可以得到flag了。面的利用可以通过序列化和反序列化来。
五、思路学完了,自己做做看看。
$profile['phone'] = $_POST['phone'];$profile['email'] = $_POST['email'];$profile['nickname'] = $_POST['nickname'];$profile['photo'] = 'upload/' . md5($file['name']);$user->update_profile($username, serialize($profile));
这里是将一整个数组进行序列化呀,,有点麻烦那,
然后
public function update_profile($username, $new_profile) {$username = parent::filter($username);$new_profile = parent::filter($new_profile);
变量就变成了 new_profile 这个变量了。
public function filter($string) {$escape = array('\'', '\\\\');$escape = '/' . implode('|', $escape) . '/';$string = preg_replace($escape, '_', $string);$safe = array('select', 'insert', 'update', 'delete', 'where');$safe = '/' . implode('|', $safe) . '/i';return preg_replace($safe, 'hacker', $string);}
然后是将这个一整个序列化的字符串进行过滤,替换
问题是:
我怎么知道序列化之后的字符串的具体是什么样子的。我才能够进行换一换啊,这要在本地进行实验的。
然后进行unserialzie进行读取,进行 字符串逃逸 ,就在上一步,
else {$profile = unserialize($profile);$phone = $profile['phone'];$email = $profile['email'];$nickname = $profile['nickname'];$photo = base64_encode(file_get_contents($profile['photo']));
那么本地实现的话,就先按照他的这个循序来吧。
phone ,email,nickname,photo
我本来是在本地搭建的,可可是那个 上传文件 不行,其实总体上来说本地搭建是可以的。
但是直接在burp上也型。
可以先在本地上初步实验,然后再在burp上搞。
本地测试这里真的是精华呀,,,没啥别的意思,纪念一下。。
自己测试出来是真滴爽快啊
由于我多加了一个,所以要把我们添加的字符串放到 nickname这个变量后面,
其实也只有nickname可以用数组来绕过。然后 本来多加了,所以过滤后的字符数量要变多才行。
才能够把我们多加的数据给挤出来。所以要比hacker少
只有where少,所以用where。
这个是post提交的参数,我在本地嫌前面的挡害,就没提供参数,不影响的。
然后再看一看我们需要挤出来多少个字符?我这个nickname只输入了一个1。所以看的时候 从 1后面看,然后 两边的双引号是人家本来就带着的。也不看,
大概就是这样的。看灰色的那一块。
灰色的34个字符都是我们要挤出来的。这些是我们多余添加的
所以我们过滤之后要边长34个字符,所以用34个where,然后变成34个hacker。
就能够ji出来了
最重要的那一块payload:
wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}
然后发包
会报错,应该的嘛,让你输入字符串,你都输入数组了,能不报错马????
然后进profile
base64编码了,看一下,解一下 米就有了
参考自:https://www.cnblogs.com/g0udan/p/12216207.html
---已搬运--:[0CTF 2016]piapiapia -----代码审计+字符串逃逸+数组绕过长度限制+以及一下小知识点 preg_match()用数组,而且注意if是正确判断,还是错误判断相关推荐
- [0CTF 2016]piapiapia(字符逃逸详解)
目录 知识点 信息收集 尝试SQL注入 源码目录扫描 代码审计 payload生成 知识点 信息泄露 参数传递数组绕过字符串检测 反序列化字符逃逸 信息收集 收集到了一只超可爱的小喵 尝试SQL注入 ...
- BUCTF[0CTF 2016]piapiapia
[0CTF 2016]piapiapia 打开环境是个登录框,尝试了一下sql注入,发现并无任何用处. 于是扫描目录,发现了个/www.zip. 开始代码审计: 在config.php中看到了flag ...
- BUU [0CTF 2016]piapiapia
BUU [0CTF 2016]piapiapia 进去之后是个登录界面,抓包有一个cookie.感觉是十六进制,但是其实不是这样做,是应该扫描的. buu什么都扫不出来,直接看源码. /registe ...
- [0CTF 2016]piapiapia WP(详细)
[0CTF 2016]piapiapia WP(详细) 1.打开网站,是个登录框,尝试注入无果.....按道理来说就是注入了啊喂 2.玄学时间到::: 目录扫完啥结果没有.在buuctf做题总是这样, ...
- [0CTF 2016] piapiapia
piapiapia 猜测:SQL注入.弱口令,顺便扫一下目录 SQL注入失败,弱口令和目录扫描没有测试(过快扫描网站,返回429),服务器还是挺好的,从网上得知/www.zip 测试过后,发现 ind ...
- [0CTF 2016]piapiapia php反序列化字符串逃逸
一.php反序列化字符串逃逸 <?phpclass user{public $user = 'admin';public $pass = 'passwd'; }$a = new user(); ...
- 审计练习5——[0CTF 2016]piapiapia
平台:buuoj.cn 打开靶机如下: 弱密码,sql乱试一波没反应,注册个账号进去之后让我们更新信息 提交跳转到profile.php 扫一下网站目录.(我们在做题扫目录的时候经常会遇见429的情况 ...
- [0CTF 2016]piapiapia -php序列化溢出
题目分析 上来是一个登录页面:尝试注入无效: 然后扫后台:扫到源码www.zip 发现有注册页,注册登陆后可以填写自己的信息以及上传头像,走过一遍流程之后发现无法SSI也无法上传图片马: 源码分析 u ...
- [0CTF 2016]piapiapia总结(PHP序列化长度变化导致尾部字符逃逸)
这道题感觉很难,要是比赛中出这种题我肯定做不来,所以我耐着性子慢慢分析这道题,最后居然自己做了个七七八八,只剩下一点点就完全做出来了. 下面把我做这道题时的思路一步一步记录下来,希望能够彻底巩固. 一 ...
最新文章
- jquery日历插件 途牛_jquery日历插件SimpleCalendar
- python reduce()函数
- python+OpenCV图像处理(十一)图像轮廓检测
- Iterator主要有三个方法:hasNext()、next()、remove()详解
- linux内核驱动之 驱动程序的角色
- CSS实现标题右侧“更多”
- Nginx高可用实战
- 车联网信息服务数据——采集合规性——行业标准解读
- html 加爱心符号,心形符号大全
- 从虚拟光驱启动计算机,电脑如何使用虚拟光驱装系统Windows
- 头条App项目测试实战(二)App手工测试流程以及需求分析与评审
- 《论文写作》课堂收获
- 【单片机】4.4 响应中断请求的条件
- 二叉树的遍历 详解及实现
- 数据结构实验课:实验一、顺序表的实现及应用
- GM65条形码二维码扫描识别模块与STM32学习
- Json的FastJson与Jackson
- 如何在本地磁盘安装PE系统
- PGP加密,良好隐私密码法
- 一个Java程序员的一生(悲惨版)