• [HarekazeCTF2019]Avatar Uploader 1


    目录

    前言:

    考点:

    解题:

    进入正题:

    总结:


    前言:

    仅记录我收集知识的历程

    考点:

    PNG 文件上传

    finfo_file() 函数原理。

    getimagesize() 函数原理与绕过

    代码审计

    解题:

    进入环境:

     首先登录,进入上传页面。

    提示 上传小于256kb ,小于256px*256px的PNG图片

     上传  . php 然后抓个包看看回显

     返回了 cookie , 以点号分割,应该是 jwt 格式,复制这个cookie到jwt网页上:JSON 网络令牌 - jwt.io

    提示我们上传的 不是PNG 格式,bp 改一下后缀,改成PNG,相应的,Content-Type: 也改成 image/png 

    依旧返回了 cookie ,再去解码看看返回的什么。  解码后,依旧是 不为 PNG文件。

    思路到这,还是不知道他过滤了什么,可能是文件头格式,但现在 上传一个正常的png文件试试,说不定还能遇到 任意文件读取,或者目录穿越。。

    成功上传了,并且改了主页的头像。

    但是到这就没了 后续,几番测试也没有结果。  看了下别人的文章,原来题目是给了 源码的。我没发现,  因为 是上传题,直接看upload,php 了。

    1. error_reporting(0);
    2. require_once('config.php');
    3. require_once('lib/util.php');
    4. require_once('lib/session.php');
    5. $session = new SecureClientSession(CLIENT_SESSION_ID, SECRET_KEY);
    6. // check whether file is uploaded
    7. if (!file_exists($_FILES['file']['tmp_name']) || !is_uploaded_file($_FILES['file']['tmp_name'])) {
    8. error('No file was uploaded.');
    9. }
    10. // check file size
    11. if ($_FILES['file']['size'] > 256000) {
    12. error('Uploaded file is too large.');
    13. }
    14. // check file type
    15. $finfo = finfo_open(FILEINFO_MIME_TYPE);
    16. $type = finfo_file($finfo, $_FILES['file']['tmp_name']);
    17. finfo_close($finfo);
    18. if (!in_array($type, ['image/png'])) {
    19. error('Uploaded file is not PNG format.');
    20. }
    21. // check file width/height
    22. $size = getimagesize($_FILES['file']['tmp_name']);
    23. if ($size[0] > 256 || $size[1] > 256) {
    24. error('Uploaded image is too large.');
    25. }
    26. if ($size[2] !== IMAGETYPE_PNG) {
    27. // I hope this never happens...
    28. error('What happened...? OK, the flag for part 1 is: ' . getenv('FLAG1') . '');
    29. }
    30. // ok
    31. $filename = bin2hex(random_bytes(4)) . '.png';
    32. move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_DIR . '/' . $filename);
    33. $session->set('avatar', $filename);
    34. flash('info', 'Your avatar has been successfully updated!');
    35. redirect('/');

    还是少不了代码审计啊。

    关键点:

    1. // check file type
    2. $finfo = finfo_open(FILEINFO_MIME_TYPE);
    3. $type = finfo_file($finfo, $_FILES['file']['tmp_name']);
    4. finfo_close($finfo);
    5. if (!in_array($type, ['image/png'])) {
    6. error('Uploaded file is not PNG format.');

     finfo_file() 函数检测文件类型是否为 image/png 格式。

    1. if ($size[2] !== IMAGETYPE_PNG) {
    2. // I hope this never happens...
    3. error('What happened...? OK, the flag for part 1 is: ' . getenv('FLAG1') . '');
    4. }

    在检查文件长宽的时候,getimagesize() 函数用于获取图像大小及相关信息,成功将返回一个数组。 如果索引2 不是PNG  则输出flag。、

    对于 getimagesize() 函数,返回的数组。测试一下此函数。

     可见他返回了 如下信息:

    1. array(6) {
    2. [0]=>
    3. int(73)
    4. [1]=>
    5. int(100)
    6. [2]=>
    7. int(3)
    8. [3]=>
    9. string(23) "width="73" height="100""
    10. ["bits"]=>
    11. int(8)
    12. ["mime"]=>
    13. string(9) "image/png"
    14. }

    解释结果:

    • 索引 [0] 给出的是图片宽度的像素值
    • 索引 [1] 给出的是图片高度的像素值
    • 索引 [2] 给出的是图像的类型 ,返回的是数字,其中 1 = GIF2 = JPG3 = PNG4 = SWF5 = PSD6 = BMP7 = TIFF(intel byte order)8 = TIFF(motorola byte order)9 = JPC10 = JP211 = JPX12 = JB213 = SWC14 = IFF15 = WBMP16 = XBM
    • 索引 [3] 给出的是一个宽度和高度的字符串,可直接用于HTML的标签。
    • 索引 [bits] 给出的是图像的每种颜色的位数,二进制格式。
    • 索引 [channels] 给出的是图像的通道值,RGB图像默认是3
    • 索引 [mime] 给出的是 图像的MIME 信息,此信息可以用来在HTTP Content-Type 头信息中发送正确的信息 如: header("Content-type: image/jpeg");

    进入正题:

    函数 finfo_ file() 主要是识别PNG 文件 十六进制下的第一行信息,若保留文件头信息,破坏掉 文件宽高等 其余信息,也就是说 破坏getimagesize() 函数无法正确的检验就可以了

     只要把我这里选中的文件头格式留下就可以破坏 getimagesize 的检查了,因为文件头他还是会检查是否为png 的。我们可以使用misc 常用的 winhex 来修改他的值:

    使用 winhex 只留其文件头,将后面的图片内容全部删除。这样他就检查不到了。

     

     成功得到 flag 。 

    总结:

    对于 getimagesize() 和 finfo_file ()还是熟悉了挺多,还有索引表达的意思。

    其次,还有很有意思的代码审计。

  • 相关阅读:
    IEC101、IEC103、IEC104的区别与应用场景
    MySqL速成教程笔记系列九
    OpenCV的应用——快递二维码识别
    【Go语言实战】(25) 分布式算法 MapReduce
    外包干了3天,技术退步明显.......
    【原创】基于JavaWeb的社区疫情防控管理系统(疫情防控管理系统毕业设计)
    使用GitHub托管自己的静态资源
    ImportError: /lib64/libstdc++.so.6: version `CXXABI_1.3.9‘ not found的解决方法
    Elasticsearch:使用 huggingface 模型的 NLP 文本搜索
    java面向对象最全入门笔记
  • 原文地址:https://blog.csdn.net/snowlyzz/article/details/126850773