0%

代码审计--程序未恰当exit导致的问题

漏洞源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
extract($_POST);

function goAway() {
error_log("Hacking attempt.");
header('Location: /error/');
}

if (!isset($pi) || !is_numeric($pi)) {
goAway();
}

if (!assert("(int)$pi == 3")) {
echo "This is not pi.";
} else {
echo "This might be pi.";
}

漏洞解析

我们发现,当程序进入 goAway 函数以后并没有直接退出中止程序,而是直接转到/error/ 但其实程序还是会接着往下执行的,但执行到if (!assert("(int)$pi == 3"))时就是我们的利用点了。我们假如我们传入$pi 为 phpinfo() 它还是会被执行的,虽然我们浏览器可能看不到结果因为此时已经跳转到/error/页面了,但是我们bp抓包的话还是可以看到的。
那我们怎么给$pi赋值呢?其实extract就可以达到这个效果
。它是把数组中的剪值对注册成变量 官方定义如下:

extract :(PHP 4, PHP 5, PHP 7)

功能:从数组中将变量导入到当前的符号表

定义: int extract ( array &$array [, int $flags = EXTR_OVERWRITE [, string $prefix = NULL ]] )

CTF题目源码

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
// index.php
<?php
include 'config.php';
function stophack($string){
if(is_array($string)){
foreach($string as $key => $val) {
$string[$key] = stophack($val);
}
}
else{
$raw = $string;
$replace = array("\\","\"","'","/","*","%5C","%22","%27","%2A","~","insert","update","delete","into","load_file","outfile","sleep",);
$string = str_ireplace($replace, "HongRi", $string);
$string = strip_tags($string);
if($raw!=$string){
error_log("Hacking attempt.");
header('Location: /error/');
}
return trim($string);
}
}
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("连接失败: ");
}
if(isset($_GET['id']) && $_GET['id']){
$id = stophack($_GET['id']);
$sql = "SELECT * FROM students WHERE id=$id";
$result = $conn->query($sql);
if($result->num_rows > 0){
$row = $result->fetch_assoc();
echo '<center><h1>查询结果为:</h1><pre>'.<<<EOF
+----+---------+--------------------+-------+
| id | name | email | score |
+----+---------+--------------------+-------+
| {$row['id']} | {$row['name']} | {$row['email']} | {$row['score']} |
+----+---------+--------------------+-------+</center>
EOF;
}
}
else die("你所查询的对象id值不能为空!");
?>

config.php

1
2
3
4
5
6
7
// config.php
<?php
$servername = "localhost";
$username = "fire";
$password = "fire";
$dbname = "day10";
?>

SQL语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 搭建CTF环境使用的sql语句
create database day10;
use day10;
create table students (
id int(6) unsigned auto_increment primary key,
name varchar(20) not null,
email varchar(30) not null,
score int(8) unsigned not null );

INSERT INTO students VALUES(1,'Lucia','Lucia@hongri.com',100);
INSERT INTO students VALUES(2,'Danny','Danny@hongri.com',59);
INSERT INTO students VALUES(3,'Alina','Alina@hongri.com',66);
INSERT INTO students VALUES(4,'Jameson','Jameson@hongri.com',13);
INSERT INTO students VALUES(5,'Allie','Allie@hongri.com',88);

create table flag(flag varchar(30) not null);
INSERT INTO flag VALUES('HRCTF{tim3_blind_Sql}');

CTF题解

简单的看一下index.php stophack中:

1
replace = array("\\","\"","'","/","*","%5C","%22","%27","%2A","~","insert","update","delete","into","load_file","outfile","sleep",);

并没有进行过滤 select from union那我们完全是可以直接出flag的呀,paylaod如下:

1
id=-1+union+select+1,2,3,flag+from+flag

但是很显然,题目的本意不在于此。看了红日的题解,他们使用 benchmark 来进行盲注,那还不也是利用了过滤条件不够苛刻而已。那我就不参试了。


-------------本文结束感谢您的阅读-------------