前言
这周啥也没干,就去看了看开发,为以后的代码审计铺垫铺垫。毕竟开发过,审计代码的时候才不会憨憨傻傻的。之前审计过两个cms,当时真的是,审的人都快麻了,害。果然还是要有写开发的功底,再去审计才不会那么吃力。接下来这四个方面,是我从那个开发的小系统中,简单提取的四个方面,分别涉及sql注入,CSRF,XSS等等。(开发能力欠缺,各位师傅将就看)
sql注入
sql注入嘛,一个成型的网站,基本上都是跑不了使用MYSQL的,所以sql注入的存在极为广泛,waf一个挡不住,就可能存在sql注入。
index.php
<!doctype html><html lang="en"><head><meta charset="UTF-8"><title>index</title></head><body><table><form action="sql.php" method="post">查询<p><input type="username" name="username"></p><p><input type="submit" name="submit" value="提交"></p></table></body>
sql.php
<?phperror_reporting(0);header ("Content-Type:text/html;charset=utf-8");include '../upload/config.php';$username=$_POST['username'];$sql="select * from user where username='{$username}'";$row=mysql_query($sql);$rst=mysql_fetch_assoc($row);echo "{$rst['username']}用户存在";?>
这种是查询的注入,但是一般的这里都会有waf,所以我们可以尝试别的情况下注入,比如insert/delete
<?phperror_reporting(0);header ("Content-Type:text/html;charset=utf-8");include '../upload/config.php';$username=$_POST['username'];$sql="insert into haha(name) values ('{$username}')";$row=mysql_query($sql);if ($row) {echo "用户插入成功";}?>
这种就可以报错注入或者盲注了
文件上传
index.php
<!doctype html><html lang="en"><head><meta charset="UTF-8"><title>index</title></head><body><table><form enctype="multipart/form-data" action="upload.php" method="post"><p><input type="file" name="file"></p><p><input type="submit" name="submit" value="提交"></p></table></body>
其中enctype="multipart/form-data" 在文件上传的时候是不可或缺的。
upload.php
<?php//print_r($_FILES);// exit();header ("Content-Type:text/html;charset=utf-8");if (isset($_POST['submit'])) {$name=$_FILES['file']['name'];$path=$_FILES['file']['tmp_name'];$newpath='upload/'.time().$name;if (move_uploaded_file($path,$newpath)) {echo '保存成功,路径为<br/>'.$newpath;}}?>
这就是最简单的文件上传了,没有任何过滤,传入别的类型的文件还会报错。
从CTF来讲,一般正经的只靠文件上传的题目已经很少了。所以拓展来将,最近遇到的比较有新意的题目就是网刃杯的那道文件上传。
当时题目提示的是sql,我懵了一下,文件上传还能和sql注入扯到一起,这不瞎搞。后来的一周,我看了点开发的东西,我发现,一般后台有文件上传的功能的时候,一般都会把文件名写入到数据库中。到这里我茅塞顿开,许多的安全问题都是源自开发。
index.php
<!doctype html><html lang="en"><head><meta charset="UTF-8"><title>index</title></head><body><table><form enctype="multipart/form-data" action="upload.php" method="post"><p><input type="file" name="file"></p><p><input type="submit" name="submit" value="提交"></p></table></body>
config.php
<?phpmysql_connect('localhost','root','root');mysql_query('set names utf-8');mysql_select_db('img');?>
upload.php
<?php//print_r($_FILES);// exit();header ("Content-Type:text/html;charset=utf-8");//error_reporting(0);include 'config.php';$move=false;$rst=false;if (isset($_POST['submit'])) {$name=$_FILES['file']['name'];$path=$_FILES['file']['tmp_name'];$size=$_FILES['file']['size'];$newpath='upload/'.time().$name;$move=move_uploaded_file($path,$newpath);$sql="insert into cname(name,path,size) values('{$name}','{$newpath}','{$size}')";//echo $sql;$rst=mysql_query($sql);$selectsql="select * from cname where name='{$name}'";//echo $selectsql;$selectrst=mysql_query($selectsql);$selectrow=mysql_fetch_assoc($selectrst);//print_r($selectrow);if ($move&&$rst) {echo "文件{$selectrow['name']}已经存储到数据库<br/>并且图片存储的位置是".$newpath;}}?>
ps:写sql语句的时候一定要带单引号……..我麻了
这里假装我对上传的文件进行了过滤,已经无法通过文件上传shell,但是这里我们通过文件名,文件大小,文件路径都可以进行SQL注入。//这里我写了那么明显,就没有注入。
接下来就是写waf了
//前端waf<script type="text/javascript">function checkFile() {var file = document.getElementsByName('upload_file')[0].value;if (file == null || file == "") {alert("请选择要上传的文件!");return false;}//定义允许上传的文件类型var allow_ext = ".jpg|.png|.gif";//提取上传文件的类型var ext_name = file.substring(file.lastIndexOf("."));//判断上传文件类型是否允许上传if (allow_ext.indexOf(ext_name) == -1) {var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;alert(errMsg);return false;}}</script>//由于js太菜,抄的upload-labs的但是前端过滤也没啥用
后端过滤的话
<?php//print_r($_FILES);// exit();header ("Content-Type:text/html;charset=utf-8");if (isset($_POST['submit'])) {$name=$_FILES['file']['name'];$path=$_FILES['file']['tmp_name'];$type=$_FILES['file']['type'];$newpath='upload/'.time().$name;$file_name=trim($_FILES['file']['name']); //去空处理$file_name=strchr($file_name,'.'); //将.后面的字符串赋值$file_name=strtolower($file_name);//转为小写$whitetype=['image/jpeg','image/png','image/gif'];$white=['.gif','.png','.jpg'];foreach ($whitetype as $key => $value1) {//echo $value1;foreach ($white as $key => $value2) {//echo $value2;//echo $file_name;if ($type==$value1) {if ($file_name==$value2) {if (move_uploaded_file($path, $newpath)) {echo "上传成功";}}}}}}?>
后台权限
在后台开发过程中,还是需要权限的把控,不然人家随便访问你的后台,开玩笑??
<?phpif (!$_SESSION['id']) {echo "<script>loaction='login.php'</script>";exit();}?>
后台的每个页面必需要这个段语句。不然直接都能非用户访问了
而且前后台sesson内的信息不能相同,不然就会,前台依旧能访问后台。
这里我简单的写了一个后台的登录功能
index.php
<!doctype html><html lang="en"><head><meta charset="UTF-8"><title>index</title></head><body><table><form action="check.php" method="post">username<p><input type="username" name="username"></p>password<p><input type="password" name="password"></p><p><input type="submit" name="submit" value="提交"></p></table></body>
check.php
<?phperror_reporting(0);session_start();include '../upload/config.php';$username=$_POST['username'];$password=$_POST['password'];$sql="select * from user where username='{$username}' and password='{$password}' and isadmin='1'";//echo $sql;$rst=mysql_query($sql);$row=mysql_fetch_assoc($rst);if ($row) {$_SESSION['admin_username']=$username;echo "<script>location='admin.php'</script>";}?>
admin.php
<?phpsession_start();if (!$_SESSION['admin_username']) {echo "<script>loaction='index.php'</script>";exit();}echo "登陆成功";?>
到这里,除了sql注入之外,其实显现了另外的一种漏洞,CSRF
这里我换了个浏览器登录,却不会跳转到index.php很怪
可以看到,替换掉cookie就能达到登陆成功的效果
用户评论
index.php
<!doctype html><html lang="en"><head><meta charset="UTF-8"><title>index</title></head><body><table><form action="comment.php" method="post"><p>评论</p><p><input type="text" name="text"></p><p><input type="submit" name="submit" value="提交"></p></table></body>
comment.php
<?phpinclude '../upload/config.php';if (isset($_POST['submit'])) {$comment=$_POST['text'];$sql="insert into comment(text) values('{$comment}')";$row=mysql_query($sql);if ($row) {echo "<script>location='show.php'</script>";}}?>
show.php
<?phpinclude '../upload/config.php';if (isset($_POST['submit'])) {$comment=$_POST['text'];$sql="insert into comment(text) values('{$comment}')";$row=mysql_query($sql);if ($row) {echo "<script>location='show.php'</script>";}}?>
总结
经此开发,我算是明白了,许多安全都是在开发的时候都存在的。开发的时候,不紧要实现一些需求功能,还要防止出现安全问题。
