CTF

源码下载

链接:https://pan.baidu.com/s/1gQbyhunPqrQ0qOidU7fR6Q 
提取码:me3r 
复制这段内容后打开百度网盘手机App,操作更方便哦

 首先需要了解

PDO::prepare

首先我们看见函数定义了几个在db.php

global $db, 声明 $db 的作用范围为全局,就可以在函数里面使用了
这是已正序查看数据库name表里面的前五个字段名
function get_top_products() {
global $db; $statement = $db->prepare( "SELECT name FROM products LIMIT 5"
check_errors($statement->execute()); 检查sql语句执行是否有错误 
$res = $statement->get_result();  执行sql得到的结果
check_errors($res);
$products = []; 定义数组products
while ( ($product = $res->fetch_assoc()) !== null) { //将结果便利到数组里面
array_push($products, $product); 把数组里面的添加到数组s
}
$statement->close();
return $products; 返回数组的值

这个其实不是重点
 

第二个函数


function get_product($name) {
  global $db;
  $statement = $db->prepare(
    "SELECT name, description FROM products WHERE name = ?"
  );
  check_errors($statement);
  $statement->bind_param("s", $name); //定义$name的类型 ‘s’,$name是?处的值
  check_errors($statement->execute()); 执行sql看是否报错
  $res = $statement->get_result(); 得到结果 非数组
  check_errors($res);  
  $product = $res->fetch_assoc();  便利到数组
  $statement->close();
  return $product;

 

 

 第三个函数

function insert_product($name, $secret, $description) { 
  global $db;
  $statement = $db->prepare(
    "INSERT INTO products (name, secret, description) VALUES//向数据库里面添加三个值 分别为name。。。。。
      (?, ?, ?)"
  );
  check_errors($statement);   //检测错误
  $statement->bind_param("sss", $name, $secret, $description); 定义???出的变量
  check_errors($statement->execute());  执行函数
  $statement->close();
}

 第四个函数

function check_name_secret($name, $secret) {
  global $db;
  $valid = false;
  $statement = $db->prepare(
    "SELECT name FROM products WHERE name = ? AND secret = ?" //查询
  );
  check_errors($statement);
  $statement->bind_param("ss", $name, $secret);  //定义变量
  check_errors($statement->execute());
  $res = $statement->get_result(); //查询结果
  check_errors($res);
  if ($res->fetch_assoc() !== null) {
    $valid = true;
  }
  $statement->close();
  return $valid;//查询存在返回ture
}

 好的 主函数分析完了我们来看看 各个页面add.php

function validate_secret($secret) {
  if (strlen($secret) < 10) {  //密码长度大于10
    return false;
  }
  $has_lowercase = false;
  $has_uppercase = false;
  $has_number = false;
  foreach (str_split($secret) as $ch) {
    if (ctype_lower($ch)) {  //密码里面有小写字母
      $has_lowercase = true;
    } else if (ctype_upper($ch)) {//密码里面大写字母
      $has_uppercase = true;
    } else if (is_numeric($ch)) {//变量里面含有数字
      $has_number = true;
    }
  }
  return $has_lowercase && $has_uppercase && $has_number; //返回密码的hash到mysql
}

 

$product = get_product($name);  
if ($product !== null) {
return "Product name already exists, please enter again";
}
//执行查询语句 判断数据库是否存在这个产品

 

然后就是view.php

if (isset($name) && $name !== ""
        && isset($secret) && $secret !== "") {
    if (check_name_secret($name, hash('sha256', $secret)) === false) {//加密你的密码 然后进数据库查询

 有朋友说可以注入啊

但是

echo "<p>Product details:";
    echo "<ul><li>" . htmlentities($product['name']) . "</li>";
    echo "<li>" . htmlentities($product['description']) . "</li></ul></p>"; 就已经完全杜绝注入了

 那么 如何查到你想要的数据呐??

这里需要利用sql查询的漏洞 在增加用户名的时候 sql自动忽略64字节后面的数据 那么我们只需要构造 xxxx+60*空格+name 然后就行了 。

then you can in view.php get your flag。。

posted @ 2019-09-23 22:46  yourse1f  阅读(622)  评论(0)    收藏  举报