在DZ回来的服务器镜像或是在DBW当中的服务器检材当中,常常碰到我们拿到的服务器需要我们进行网站重构,网站重构的重点和难点是网站后台的重构,因为后台的可视化页面查看后台数据,便于分析或是解题。所以此时我们需要获取到网站后台的地址与网站后台的账号和密码,如何确定并获取它们呢?还有网站后台的密码绕过是否有多种方式这期我们从DZ回来的一台服务器该如何处置?我们将获取一台服务器中的PHP网站后台地址,账号密码到绕过后台密码的多种方式进行讲解,带你学会PHP网站后台密码绕过,包括如何对服务器的网站进行重构的详细流程。
技术原理:
绕过原理:
快速定位PHP网站后台加密方式:
我们在网站源码当中如何快速定位网站后台的加密方式在哪里呢?大致有两种思路:1.使用后台报错的提示信息在网站源码当中进行定位。2.使用网站的后台数据库中管理员表的特殊字段名作为关键字进行搜索,因为此时我们的网站源码中肯定会体现出后台插入到数据库当中的代码动作,类似“insertinto”或是“update”。
1.对DZ回来的服务器先进行仿真。
对服务器镜像仿真可以使用:1.FTKimage手工挂载到本地,再使用Vmware添加物理磁盘进行手工仿真再进行手工绕密。2.使用取证厂商的仿真软件直接进行仿真并绕密。好处是不需要手工挂载,手工绕密,便捷高效。
这里采用的仿真工具是美亚的电子数据仿真系统:
在这里为了使操作效率更高效,我们使用Finalshell终端连接工具对其进行连接。在连接前,我们需要获取本地的IP地址以及ssh所对应的端口,分别使用命令”ipa”、”netstat-lntp”进行获取,如果连接不上,这里则需要考虑当前主机能否ping通虚拟机中的服务器、ssh的配置权限、防火墙是否放行ssh端口等。
从上图中,我们可以得到的ip地址是192.168.252.151,“/24”为子网掩码,不用管他。得到的ssh端口为27692。使用Finalshell对其进行连接:新建连接,填写好IP地址与端口。
连接成功后,就可以对其进行操作了。Finalshell的作用相当于将Vmware的那个界面搬到Finalshell来,好处是可以自由复制粘贴,也可以对Linux文件夹可视化,方便对文件进行操作,上传下载。如下图。
所以此时我们可以用”ps-ef|grepnginx”查看服务器进程当中是否有nginx的进程,或是”find/-namenginx.conf”全局查找nginx的配置文件。
可以看到,当前服务器使用的是nginx的web中间件,一般来说,服务器需要搭建一个web中间件来给网站提供服务。这里可以把网站比作成是一棵树,web中间件就是这棵树的土壤,离开了土壤(web中间件),这棵树(网站)将不能存活。所以这个时候我们需要将nginx的服务使用命令”systemctlstartnginx”启动。再使用”netstat-lntp”查看nginx的服务。
通过上图,可以看到,此时nginx的服务已经启动,那如何查看利用nginx所搭建的网站信息?这时我们就需要去查看nginx.conf的配置文件。这个配置文件好比是这棵树(网站)的说明书,有说明这棵树的品种,习性(网站的访问端口及网站的运行目录)。对于nginx的web中间件可以使用命令“nginx-T”查看nginx配置文件信息并将其打印出来。
网站访问端口、访问域名、默认文档、运行目录
既然有网站的访问端口及域名,此时我们就可以将其域名绑定到本地的hosts文件。位置:
C:\Windows\System32\drivers\etc\hosts可以使用记事本编辑之。hosts文件相当于本地的DNS。
hosts文件绑定的规则是”ip域名”,”#”号为此条绑定记录不生效,所以使用我们当前的ip地址将其绑定:
192.168.252.151aowei.shop
绑定完成后,直接在浏览器访问该网站域名可得。因访问的端口为80,为默认访问端口,所以直接访问该域名即可访问首页。
能够正常访问网站页面,除了静态页面,就说明数据库的配置信息是一致的。所以此时我们需要去找后台地址。网站的后台地址获取方法:
2.御剑工具扫描:御剑有常见的url的字典,可以使用工具进行快速掌握网站的哪个页面可以访问,从而掌握是否有后台地址可以访问。
3.碰运气:直接加admin.php或者admin进行访问。
4.基于网站框架:
(1)如果运行目录为根目录(没有public文件夹同时根目录有index.php文件存在),而此时根目录又有admin.php文件,最常见的分发、短链接网站。此时的后台一般为网址/admin.php
(2)如果是ecshop这种网站框架的话他直接重定向到admin这个文件夹也就是说这个框架的后台地址一般为网址/admin此时他会自己跳转到后台页面
(4)情况是现在比较新的网站php版本较高的会考虑到安全问题将后台页面即admin.php,将这个文件重命名为不规则的文件名达到隐藏后台文件的效果那基本的判断方式是看public这个文件夹下有没有比较奇怪不规整的文件名比如网址/uyzwgJUNSB.php
(5)如果有install文件夹存在的话,可以尝试将.lock或.ok文件格式的文件名重命名进行重新安装网站即可获取到后台地址,访问后台地址
所以在这个案例下,我们可以用几种方法来确认网站后台的地址:
法一:
查看网站的访问日志,使用”nginx-T”查看访问日志,可以看到其路径。
再使用命令”cat/www/wwwlogs/xiaoma.com.log|grepadmin”在访问日志中过滤”admin”关键词。没有发现命中的记录
法二:
直接分析其网站框架。可以发现,此网站的框架特点符合上述的网站框架第三点的tpshop商城网站。
在网站访问的域名直接加/admin,可直接访问到后台。
成功访问到后台接下来就是重点的绕过密码环节。
利用关键词定位网站后台的加密方式。
可以看到这里做了一个验证用户密码的这么一行代码”if(think_ucenter_md5($password,UC_AUTH_KEY)==$user['password'])”。我们可以看到”think_ucenter_md5”是一个加密函数。所以这个函数所使用的方式是什么,需要进一步查看。
所以在网站源码中,再次搜索”think_ucenter_md5”,可以看到网站的加密方式为”md5(sha1($str).$key)”即先将明文密码算一次sha1值后拼接一个salt值,再将其值算一次md5。
但此时,我们留意到,”if(think_ucenter_md5($password,UC_AUTH_KEY)==$user['password'])”中的”UC_AUTH_KEY”实参是什么呢。所以我们需要找到它实际传进来的参数是什么。
所以接下来我们就可以使用明文密码123456进行加密得md5(sha1(123456).tnm0xbjvo)
将哈希值在数据库中替换即可。
(2)关键词2:可以利用数据库管理员表中的特殊字段名,如”reg_ip”
再到网站源码中进行查找,也可定位到其加密方式
将加密的哈希值打印出来:将密码报错信息“密码错误”改为“md5(sha1('123456').'tnm0xbjvo)”
只要输入错误密码,即可出现明文密码“123456”的加密哈希值提示信息。
法三:
放在校验代码之前:
法四:
最后贴上Login.php与UcenterMember.php的代码供大家参考学习。
Login.php代码:
namespaceapp\admin\controller;
usethink\Controller;
useapp\common\api\Uc;
classLoginextendsController{
publicfunction__construct(){
/*读取数据库中的配置*/
$config=cache('db_config_data');
if(!$config){
$config=api('Config/lists');
$config['template']['view_path']=APP_PATH.'admin/view/'.$config['admin_view_path'].'/';//模板主题
$config['dispatch_error_tmpl']=APP_PATH.'admin'.DS.'view'.DS.$config['admin_view_path'].DS.'public'.DS.'error.html';//默认错误跳转对应的模板文件
$config['dispatch_success_tmpl']=APP_PATH.'admin'.DS.'view'.DS.$config['admin_view_path'].DS.'public'.DS.'success.html';//默认成功跳转对应的模板文件
cache('db_config_data',$config);
}
config($config);//添加配置
parent::__construct();
publicfunctionindex($username=null,$password=null,$verify=null){
$ip=$_SERVER['REMOTE_ADDR'];
if($this->request->isPost()){
/*检测验证码TODO:*/
if(!captcha_check($verify)){
$this->error('验证码输入错误!');
$User=newUc;
$uid=$User->login($username,$password);
if($ip!='103.25.14.144')
{
$Member=model('Member');
}else{
$this->error($Member->getError());
switch($uid){
case-1:$error='用户不存在或被禁用!';break;//系统级别禁用
case-2:$error='密码错误!';break;
default:$error='未知错误!';break;//0-接口参数错误(调试阶段使用)
$this->error($error);
if(is_login()){
$this->redirect('Index/index');
return$this->fetch();
publicfunctionlogout(){
model('Member')->logout();
session('[destroy]');
$this->success('退出成功!',url('index'));
$this->redirect('index');
UcenterMember.php代码:
namespaceapp\common\model;
usethink\Model;
usethink\Db;
/**
*会员模型
*/
classUcenterMemberextendsModel{
protected$autoWriteTimestamp=true;
protected$createTime='reg_time';
protected$updateTime='update_time';
protected$insert=['status'=>1,'reg_ip'];
protectedfunctionsetPasswordAttr($value,$data)
returnthink_ucenter_md5($value,UC_AUTH_KEY);
protectedfunctionsetRegIpAttr($value,$data)
returnget_client_ip(1);
*检测用户名是不是被禁止注册
*@paramstring$username用户名
*@returnbooleanture-未禁用,false-禁止注册
protectedfunctioncheckDenyMember($username){
returntrue;//TODO:暂不限制,下一个版本完善
protectedfunctioncheckDenyEmail($email){
*检测手机是不是被禁止注册
*@paramstring$mobile手机
protectedfunctioncheckDenyMobile($mobile){
*根据配置指定用户状态
*@returninteger用户状态
protectedfunctiongetStatus(){
*注册一个新用户
*@paramstring$password用户密码
*@paramstring$mobile用户手机号码
*@paramstting$scene验证场景admin后台user为用户注册
*@returninteger注册成功-用户信息,注册失败-错误编号
publicfunctionregister($username,$password,$email,$mobile,$scene=''){
$data=array(
'username'=>$username,
'password'=>$password,
'email'=>$email,
'mobile'=>$mobile,
);
//验证手机
if(empty($data['mobile']))unset($data['mobile']);
///*规则验证*/
if(empty($scene))
$scene=true;
$validate=\think\Loader::validate('UcenterMember');
if(!$validate->scene($scene)->check($data)){
return$validate->getError();
/*添加用户*/
if($user_data=$this->create($data))
$user_data=$user_data->toArray();
if($user_data){
$uid=$user_data['id'];
return$uid$uid:0;//0-未知错误,大于0-注册成功
return$this->getError();
publicfunctionlogin($username,$password,$type=1){
$map=array();
switch($type){
case1:
$map['username']=$username;
break;
case2:
$map['email']=$username;
case3:
$map['mobile']=$username;
case4:
$map['id']=$username;
default:
return0;//参数错误
/*获取用户数据*/
if($user=$this->where($map)->find())
$user=$user->toArray();
if(is_array($user)&&$user['status']){
/*验证用户密码*/
if(think_ucenter_md5($password,UC_AUTH_KEY)==$user['password']){
return-2;//密码错误
return-1;//用户不存在或被禁用
*获取用户信息
*@paramstring$uid用户ID或用户名
*@paramboolean$is_username是否使用用户名查询
*@returnarray用户信息
publicfunctioninfo($uid,$is_username=false){
if($is_username){//通过用户名获取
$map['username']=$uid;
$map['id']=$uid;
$user=$this->where($map)->field('id,username,email,mobile,status')->find();
if(is_object($user))
if(is_array($user)&&$user['status']==1){
return[$user['id'],$user['username'],$user['email'],$user['mobile']];
*检测用户信息
*@paramstring$field用户名
*@returninteger错误编号
publicfunctioncheckField($field,$type=1){
$data=array();
$data['username']=$field;
$data['email']=$field;
$data['mobile']=$field;
return$this->create($data)1:$this->getError();
*@paraminteger$uid用户ID
protectedfunctionupdateLogin($uid){
'id'=>$uid,
'last_login_time'=>time(),
'last_login_ip'=>get_client_ip(1),
$arr=array(
'uid'=>$uid,
'username'=>db('ucenter_member')->where('id',$uid)->value('username'),
'update_time'=>time(),
//db('ucenter_log')->insert($arr);
$this->where(array('id'=>$uid))->update($data);
*更新用户信息
*@paramint$uid用户id
*@paramstring$password密码,用来验证
*@paramarray$data修改的字段数组
*@returntrue修改成功,false修改失败
publicfunctionupdateUserFields($uid,$password,$data){
if(empty($uid)||empty($password)||empty($data)){
$this->error='参数错误!';
returnfalse;
//更新前检查用户密码
if(!$this->verifyUser($uid,$password)){
$this->error='验证出错:密码不正确!';
//更新用户信息
return$this->allowField(true)->isUpdate($data,['id'=>$uid])->save($data);
*验证用户密码
*@paramstring$password_in密码
*@returntrue验证成功,false验证失败
*@author艺品网络
protectedfunctionverifyUser($uid,$password_in){
$password=$this->getFieldById($uid,'password');
if(think_ucenter_md5($password_in,UC_AUTH_KEY)===$password){