$is_upload = false;
$msg = null;
if (isset($_POST['submit'])){
// 获得上传文件的基本信息,文件名,类型,大小,临时文件路径
$filename = $_FILES['upload_file']['name'];
$filetype = $_FILES['upload_file']['type'];
$tmpname = $_FILES['upload_file']['tmp_name'];
$target_path=UPLOAD_PATH.'/'.basename($filename);
// 获得上传文件的扩展名
$fileext= substr(strrchr($filename,"."),1);
//判断文件后缀与类型,合法才进行上传操作
if(($fileext == "jpg") && ($filetype=="image/jpeg")){
if(move_uploaded_file($tmpname,$target_path)){
//使用上传的图片生成新的图片
$im = imagecreatefromjpeg($target_path);
if($im == false){
$msg = "该文件不是jpg格式的图片!";
@unlink($target_path);
}else{
//给新图片指定文件名
srand(time());
$newfilename = strval(rand()).".jpg";
//显示二次渲染后的图片(使用用户上传图片生成的新图片)
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagejpeg($im,$img_path);
@unlink($target_path);
$is_upload = true;
}
} else {
$msg = "上传出错!";
}
}else if(($fileext == "png") && ($filetype=="image/png")){
if(move_uploaded_file($tmpname,$target_path)){
//使用上传的图片生成新的图片
$im = imagecreatefrompng($target_path);
if($im == false){
$msg = "该文件不是png格式的图片!";
@unlink($target_path);
}else{
//给新图片指定文件名
srand(time());
$newfilename = strval(rand()).".png";
//显示二次渲染后的图片(使用用户上传图片生成的新图片)
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagepng($im,$img_path);
@unlink($target_path);
$is_upload = true;
}
} else {
$msg = "上传出错!";
}
}else if(($fileext == "gif") && ($filetype=="image/gif")){
if(move_uploaded_file($tmpname,$target_path)){
//使用上传的图片生成新的图片
$im = imagecreatefromgif($target_path);
if($im == false){
$msg = "该文件不是gif格式的图片!";
@unlink($target_path);
}else{
//给新图片指定文件名
srand(time());
$newfilename = strval(rand()).".gif";
//显示二次渲染后的图片(使用用户上传图片生成的新图片)
$img_path = UPLOAD_PATH.'/'.$newfilename;
imagegif($im,$img_path);
@unlink($target_path);
$is_upload = true;
}
} else {
$msg = "上传出错!";
}
}else{
$msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!";
}
}
提示是:本pass重新渲染了图片,要求.gif .jpg .png三种都上传了才算成功
imagecreatefromjpeg
这个函数就是用来渲染生成新的图片的
1…gif文件
gif的文件比较简单,文件头(gif89a/gif87a)+gif数据流+终结器。没有分各种数据块这样的。
所以对于gif:上传一张图片,然后下载下来与原图进行对比,把webshell放在没有被修改的地方就行了
2.png文件
这也是隐写里考得多的一类,无损压缩的位图,由>3块组成
misc常规考点有:校验值计算,修改高宽(IHDR块的crc值爆破得到宽度)
PNG定义了两种类型的数据块,一种是称为关键数据块(critical
chunk),这是标准的数据块,另一种叫做辅助数据块(ancillary
chunks),这是可选的数据块。关键数据块定义了3个标准数据块(IHDR,IDAT, IEND),每个PNG文件都必须包含它们。
一种方式是将webshell写入PLTE数据块,也就是数13字节以后,再修改CRC
另一种是写入IDAT数据块
脚本和具体参考先知这篇文章
3.jpg文件
在隐写里也考,有损压缩,以段来组成,普通考点一般考虑隐写算法,复习LSB,Jsteg,F5算法,JPhide,Outguess
这个作为一个菜鸡更是难说,还是参考上面的文章
$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
$ext_arr = array('jpg','png','gif');
$file_name = $_FILES['upload_file']['name'];
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_ext = substr($file_name,strrpos($file_name,".")+1);
$upload_file = UPLOAD_PATH . '/' . $file_name;
if(move_uploaded_file($temp_file, $upload_file)){
if(in_array($file_ext,$ext_arr)){
$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;
rename($upload_file, $img_path);
$is_upload = true;
}else{
$msg = "只允许上传.jpg|.png|.gif类型文件!";
unlink($upload_file);
}
}else{
$msg = '上传出错!';
}
}
代码审计= =
(if开始)发现上传完了,再判断的,决定是不是要删除(unlink
函数)
1.首先接收上传的文件
2.然后判断上传的文件的文件后缀是否在白名单中
3.在白名单中,则将文件重命名
4.不在白名单则删除文件
这里要用到条件竞争
个人认为条件竞争是一个想法~不一定非要用在文件上传上面。
bp多线程发送请求包,一边上传,一边访问…理论还是比较简单的。
转载
一个例子:
条件竞争漏洞是一种服务器端的漏洞,是由于开发者设计应用程序并发处理时操作逻辑不合理而造成。当应用面临高并发的请求时未能同步好所有请求,导致请求与请求之间产生等待时出现逻辑缺陷。该漏洞一般出现在与数据库系统频繁交互的位置,例如金额同步、支付等较敏感操作处。另外条件竞争漏洞也会出现在其他位置,例如文件的操作处理等。
某平台提现功能的业务处理流程为: 用户发起提现 -> 获取用户金额并判断能否提现 -> 提现:生成提现订单->扣除提现金额
public funtion withdraw($user_id, $withdrawal_amount){
//获取余额
$money = $db->FirstRow("SELECT * FROM ".Tb('money')." WHERE user_id='{$user_id}'");
if($money['balance'] == 0) ShowError('金额为零,无法提现!');
//提现余额小于等于数据库的值就提现
if ($withdrawal_amount <= $money['balance']) {
create_withdraw_order($withdrawal_amount, $user_id, time());
$db->Execute("UPDATE ".Tb('money')." SET balance=balance-{$withdrawal_amount} WHERE uer_id='{$user_id}'");
ShowSuccess('提现成功!');
}
else
{
ShowError('提现金额过高!');
}
}
?>
上述代码在非并发情况下是没有问题的。
假设现有一个用户在系统中共有2000元可以提现,他想全部提现。于是该用户同时发起两次提现请求,第一次提交请求提现2000元,系统已经创建了提现订单但还未来得及修改该用户剩余金额,此时第二次提现请求同样是提现2000元,于是程序在还未修改完上一次请求后的余额前就进行了余额判断,显然如果这里余额判断速度快于上一次余额修改速度,将会产生成功提现的两次订单,而数据库中余额也将变为-2000。而这产生的后果将会是平台多向该用户付出2000元。
这个也算支付漏洞了吧
实操步骤:
1.bp开始多线程地上传(intruder模块)可以选择null payload这个type,也可以在user-agent头后面+数字,使用数字payload
2.跑得时候会发现,地址中的文件会频繁上传->被删除
3.同时使用脚本访问该文件
使用多线程脚本,频繁多线程访问该url 即可被保存
这题反正也是看blog的时候发现的wp我也没时间解释了
考点1.发现这个302跳转 改包发送
2.发包都是两个页面,一个不断上传,一个不断访问
实操:
step1:建一个php
step3:intruder模块跑一下 ok(一定要多,只500次文件影子都没见到)
然后???我先留个疑问吧
还是条件竞争
//index.php
$is_upload = false;
$msg = null;
if (isset($_POST['submit']))
{
require_once("./myupload.php");
$imgFileName =time();
$u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName);
$status_code = $u->upload(UPLOAD_PATH);
switch ($status_code) {
case 1:
$is_upload = true;
$img_path = $u->cls_upload_dir . $u->cls_file_rename_to;
break;
case 2:
$msg = '文件已经被上传,但没有重命名。';
break;
case -1:
$msg = '这个文件不能上传到服务器的临时文件存储目录。';
break;
case -2:
$msg = '上传失败,上传目录不可写。';
break;
case -3:
$msg = '上传失败,无法上传该类型文件。';
break;
case -4:
$msg = '上传失败,上传的文件过大。';
break;
case -5:
$msg = '上传失败,服务器已经存在相同名称文件。';
break;
case -6:
$msg = '文件无法上传,文件不能复制到目标目录。';
break;
default:
$msg = '未知错误!';
break;
}
}
//myupload.php
class MyUpload{
......
......
......
var $cls_arr_ext_accepted = array(
".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt",
".html", ".xml", ".tiff", ".jpeg", ".png" );
......
......
......
/** upload()
**
** Method to upload the file.
** This is the only method to call outside the class.
** @para String name of directory we upload to
** @returns void
**/
function upload( $dir ){
$ret = $this->isUploadedFile();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
$ret = $this->setDir( $dir );
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
$ret = $this->checkExtension();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
$ret = $this->checkSize();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
// if flag to check if the file exists is set to 1
if( $this->cls_file_exists == 1 ){
$ret = $this->checkFileExists();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
}
// if we are here, we are ready to move the file to destination
$ret = $this->move();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
// check if we need to rename the file
if( $this->cls_rename_file == 1 ){
$ret = $this->renameFile();
if( $ret != 1 ){
return $this->resultUpload( $ret );
}
}
// if we are here, everything worked as planned :)
return $this->resultUpload( "SUCCESS" );
}
......
......
......
};
这是个代码审计。。。。move_uploaded_file 会自动忽略文件末尾的/.
而且文件名是从$_FILES[‘upload_file’][‘tmp_name’]中获取的,所以用户是可以进行控制的,所以通过/. 来进行绕过
抓包吧文件名后面加/.吧
也可以用该函数的00截断绕过
数组绕过,https://blog.csdn.net/u014029795/article/details/102917199 看这篇,讲得很清晰了