漏洞源码 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 来进行盲注,那还不也是利用了过滤条件不够苛刻而已。那我就不参试了。