目录:

  • 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.数组绕过正则

  1. md5(Array()) = null
  2. sha1(Array()) = null
  3. ereg(pattern,Array()) =null
  4. preg_match(pattern,Array()) = false
  5. strcmp(Array(), “abc”) =null
  6. strpos(Array(),“abc”) = null
  7. strlen(Array()) = null

一、自己做:

源码都弄下来了,但是分析,代码审计技能点还没有点,,,
懵逼中,
我看到了读取文件什么的,也看到了serialize和unserialize和session。
猜测可能是序列化和反序列化,应该不是session的序列化, 因为session不可控。
然后又关于数据库的操作。但是在尝试的时候,不报错,sql注入不是了,

二、学到的&&不足:

  1. 看到config.php里面的内容了,

    我就没有反应过来flag再config.php中,,,,因为后面WP取flag就是取自config.php中的,我就愣是没反应过来,

  2. 数组会绕过preg_match()。使得他匹配为 false。 这里可以绕过。然后strlen一个数组,会返货 null.。也可以的。

  3. 反序列化的话,我发现我还可以。

  4. 还有思路问题:我们上传的时候,photo是:upload/3e602dd0ab83a3a8c3f32309bb9a88f9这种样式,我当时还在思考,为什么,我们插入的数据是:s:10:"config.php"。格式差别会这么大呢??这涉及到fie_get_contents()。一个是我们方才上传的文件,另一个是已经存在的文件config.php

  5. 而且,看config.php那个内容,要想到 flag就在那里,结合file_get_contents()。就要想到是读取文件,

  6. 为什么 只有 nickname可以注入呢????

    前面两个都是 否定判断, 只有这个是肯定判断,所以也就只能够绕过nickname了。

这了提醒我以后审计代码要 细心!!!!!!!。这个也太细了把,,,我当时做这个题的时候都没有注意到。。

  1. 要提高的能力:1. 本地复现能力!!!2. 代码调试,在浏览器端,**var_dump()**看输出3. 数据库 看 存储的信息。

四、学习WP

1.学习一个大佬的思路:

  1. 熟悉网站结构:
    class.php里有一些重要的函数
    update.php和profile.php中一个是上传文件,一个是获取文件,
    最重要的是config.php。我们看到flag在里面。

  2. 根据前端流程 查看可疑函数
    注册和登陆那块就不看了,主要的突破点是 上传资料显示资料 这里。

首先是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是正确判断,还是错误判断相关推荐

  1. [0CTF 2016]piapiapia(字符逃逸详解)

    目录 知识点 信息收集 尝试SQL注入 源码目录扫描 代码审计 payload生成 知识点 信息泄露 参数传递数组绕过字符串检测 反序列化字符逃逸 信息收集 收集到了一只超可爱的小喵 尝试SQL注入 ...

  2. BUCTF[0CTF 2016]piapiapia

    [0CTF 2016]piapiapia 打开环境是个登录框,尝试了一下sql注入,发现并无任何用处. 于是扫描目录,发现了个/www.zip. 开始代码审计: 在config.php中看到了flag ...

  3. BUU [0CTF 2016]piapiapia

    BUU [0CTF 2016]piapiapia 进去之后是个登录界面,抓包有一个cookie.感觉是十六进制,但是其实不是这样做,是应该扫描的. buu什么都扫不出来,直接看源码. /registe ...

  4. [0CTF 2016]piapiapia WP(详细)

    [0CTF 2016]piapiapia WP(详细) 1.打开网站,是个登录框,尝试注入无果.....按道理来说就是注入了啊喂 2.玄学时间到::: 目录扫完啥结果没有.在buuctf做题总是这样, ...

  5. [0CTF 2016] piapiapia

    piapiapia 猜测:SQL注入.弱口令,顺便扫一下目录 SQL注入失败,弱口令和目录扫描没有测试(过快扫描网站,返回429),服务器还是挺好的,从网上得知/www.zip 测试过后,发现 ind ...

  6. [0CTF 2016]piapiapia php反序列化字符串逃逸

    一.php反序列化字符串逃逸 <?phpclass user{public $user = 'admin';public $pass = 'passwd'; }$a = new user(); ...

  7. 审计练习5——[0CTF 2016]piapiapia

    平台:buuoj.cn 打开靶机如下: 弱密码,sql乱试一波没反应,注册个账号进去之后让我们更新信息 提交跳转到profile.php 扫一下网站目录.(我们在做题扫目录的时候经常会遇见429的情况 ...

  8. [0CTF 2016]piapiapia -php序列化溢出

    题目分析 上来是一个登录页面:尝试注入无效: 然后扫后台:扫到源码www.zip 发现有注册页,注册登陆后可以填写自己的信息以及上传头像,走过一遍流程之后发现无法SSI也无法上传图片马: 源码分析 u ...

  9. [0CTF 2016]piapiapia总结(PHP序列化长度变化导致尾部字符逃逸)

    这道题感觉很难,要是比赛中出这种题我肯定做不来,所以我耐着性子慢慢分析这道题,最后居然自己做了个七七八八,只剩下一点点就完全做出来了. 下面把我做这道题时的思路一步一步记录下来,希望能够彻底巩固. 一 ...

最新文章

  1. jquery日历插件 途牛_jquery日历插件SimpleCalendar
  2. python reduce()函数
  3. python+OpenCV图像处理(十一)图像轮廓检测
  4. Iterator主要有三个方法:hasNext()、next()、remove()详解
  5. linux内核驱动之 驱动程序的角色
  6. CSS实现标题右侧“更多”
  7. Nginx高可用实战
  8. 车联网信息服务数据——采集合规性——行业标准解读
  9. html 加爱心符号,心形符号大全
  10. 从虚拟光驱启动计算机,电脑如何使用虚拟光驱装系统Windows
  11. 头条App项目测试实战(二)App手工测试流程以及需求分析与评审
  12. 《论文写作》课堂收获
  13. 【单片机】4.4 响应中断请求的条件
  14. 二叉树的遍历 详解及实现
  15. 数据结构实验课:实验一、顺序表的实现及应用
  16. GM65条形码二维码扫描识别模块与STM32学习
  17. Json的FastJson与Jackson
  18. 如何在本地磁盘安装PE系统
  19. PGP加密,良好隐私密码法
  20. 一个Java程序员的一生(悲惨版)

热门文章

  1. Java 位运算符和移位运算符
  2. HTTP 响应状态码
  3. FP-Growth算法实践
  4. 漫画别只是看,用“应用之星”自制App才过瘾
  5. 嗅图狗2022.5 下载
  6. 对电子商务企业线上线下概念的认知
  7. oppor11点android版本,OPPO R11有几个版本 OPPO R11巴萨版与普通版区别 (全文)
  8. Form表单 回车(Enter)提交表单问题
  9. gitlab添加SSH密钥——查看本地密钥 生成ssh密钥
  10. python打包exe后https找不到cacert.pem证书解决方法