【读者投稿】PHP开源程序中常见的后台绕过方法总结

说明

最近审计了几个开源的PHP源程序,发现都存在后台程序绕过的问题,而且绕过的方式均不相同,写篇总结一下。初步地将绕过方式分为了三个层次: 1. 后台缺乏验证代码 2. 后台验证代码不严谨 3. 变量覆盖漏洞导致后台验证失效

以下就几个我审计过的PHP源程序进行说明。

后台缺乏验证

比如在axublog 1.0.2中后台存在一个验证管理员登录的函数chkadcookie()。但是在后台的ad/art.php中并没有chkadcookie(),因而就造成了越权访问。

这种漏洞的原理也比较简单,一般情况下是经验不足的开发者漏掉了验证函数,这种漏洞目前已经比较少了。

后台验证代码不严谨

这个漏洞的出现情况是最多的,出现的情况也是千奇百怪。

axublog后台验证函数绕过

验证方式

axublog中的后台验证函数是chkadcookie(),代码如下:

function chkadcookie() {
    @$file = "../cache/txtchkad.txt";          //定义文件
    @$fp = fopen($file, "r");                  //以写入方式打开文件
    @$txtchkad = fread($fp, 4096);              //读取文件内容
    $txtchkad2 = str_replace(@$_COOKIE["chkad"], '', $txtchkad);
    if (@$_SESSION["chkad"] == '' && @$_COOKIE["chkad"] == '') {
        header("Content-type:text/html; charset=utf-8");
        echo '<div id=redmsg>请<a href="login.php">登录</a>。。。</div><script>tiao();</script>';
        exit;
    }
    if ($txtchkad == $txtchkad2) {
        header("Content-type:text/html; charset=utf-8");
        echo '<div id=redmsg>请<a href="login.php">登录</a>。。。</div><script>tiao();</script>';
        exit;
    }}// 记录当前登录的用户function loginpass($str) {
    $txtchkad = $_SERVER['HTTP_USER_AGENT'] . '_' . $_SERVER['REMOTE_ADDR'] . '_' . $date;
    $file = "../cache/txtchkad.txt";          //定义文件
    if (file_exists($file)) {
        $txt = file_get_contents($file);
        $txt = $txtchkad . "\r\n" . $txt;
    }
    file_put_contents($file, $txt);}  

分析代码发现非常有趣的问题: 1. txtchkad.txt文件中记录的是客户端的

$_SERVER['HTTP_USER_AGENT'] . '_' . $_SERVER['REMOTE_ADDR'] . '_' . $date

,其中只有$date我们是无法知道,而UA和REMOTE_ADDR都是客户端可控的。 2.

$txtchkad2 = str_replace(@$_COOKIE["chkad"], '', $txtchkad);($txtchkad == $txtchkad2)

的验证逻辑是如果在COOKIE中出现了在txtchkad.txt中的值,那么就认为是登录的。这样的验证逻辑明显存在很大的问题。

问题很明显,既然我们知道了txtchkad.txt中的内容,同时COOKIE也是我们可控的,那么我们就可以绕过了。

绕过验证

只需要将COOKIE中的chkad设置为_就可以绕过后台的登录了。

zzcms的后台验证函数绕过

验证方式

zzcms中的后台验证代码如下:

if (isset($_SESSION["admin"]) && isset($_SESSION["pass"])) {
    $sql = "select * from zzcms_admin where admin='" . $_SESSION["admin"] . "'";
    $rs = query($sql) or showmsg('查寻管理员信息出错');
    $ok = is_array($row = fetch_array($rs));
    if ($ok) {
        if ($_SESSION["pass"] != $row['pass']) {
            showmsg('管理员密码不正确,你无权进入该页面', '/admin/login.php');
        }
    } else {
        showmsg('管理员已不存在,你无权进入该页面', '/admin/login.php');
    }} else {
    session_write_close();
    echo("<script>top.location.href = '/admin/login.php';</script>");}?>

可以发现如果SESSION中不存在adminpass就会跳转到登录代码,跳转代码是

echo("<script>top.location.href = '/admin/login.php';</script>");

。通过前台的JS进行跳转,但是后面没有立即exit(),导致后面的代码仍然是可以执行的,所以这种验证方式也无用的。

绕过方式

绕过方式非常地简单,在浏览器段禁用JS代码就可以了。

变量覆盖漏洞导致后台验证失效

beescms的后台验证函数绕过

验证方式

检查登录的函数is_login()的代码为:

function is_login() {
    if ($_SESSION['login_in'] == 1 && $_SESSION['admin']) {
        if (time() - $_SESSION['login_time'] > 3600) {
            login_out();
        } else {
            $_SESSION['login_time'] = time();
            @session_regenerate_id();
        }
        return 1;
    } else {
        return 0;
    }

正常情况下,如果用户无法控制SESSION中的值,上述代码是没有问题的。

但是后来分析发现,基本所有的文件都会引入includes/init.php文件,其中有代码:

session_start();$_COOKIE = fl_value($_COOKIE);$_GET = fl_value($_GET);@extract($_POST);@extract($_GET);@extract($_COOKIE);function fl_value($str) {
    if (empty($str)) {
        return;
    }
    return preg_replace('/select|insert | update | and | in | on | left | joins | delete |\%|\=|\/\*|\*|\.\.\/|\.\/| union | from | where | group | into |load_file|outfile/i', '', $str);}

上述的代码中并没有对$_POST使用fl_value()函数进行过滤,但又使用了extract()这样的函数,所以就可以通过发送POST参数覆盖掉SEESION中的值,从而绕过验证了。

绕过方式

绕过方式很简单,访问一个页面,发送POST请求如下:

index.php
POST:_SESSION[login_in]=1&_SESSION[admin]=1&_SESSION[login_time]=99999999999

此时就成功地创建了SESION变量,包括$SESSION[loginin]=1$_SESSION[admin]=1SESSION[logintime]=99999999999。 之后访问管理员页面,就可以成功地登录了。

总结

刚开始学习代码审计,发现这些问题都很有趣,于是总结了一下,当然后台绕过的方式估计还有其他的类型,也希望各位师傅们能够多多指教。

原文发布于微信公众号 - 信安之路(xazlsec)

原文发表时间:2017-09-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Timhbw博客

学习提升之HTTP状态码详解

2016-11-1410:23:53 发表评论 315℃热度 1.URL 2.URL中常见的协议 3.TCP/IP协议簇 4.TCP/IP参考模型 ...

36260
来自专栏bboysoul

linux编译安装mysql5.7

wget mirrors.sohu.com/mysql/MySQL-5.7/mysql-boost-5.7.17.tar.gz 因为官方下载地址速度太慢了,所...

21530
来自专栏Jerry的SAP技术分享

记录我开发工作中遇到HTTP跨域和OPTION请求的一个坑

场景是我需要在部署在域名a的Web应用里用JavaScript去消费一个部署在域名b的服务器上的服务。域名b上的服务也是我开发的,因此我将域名a加到了该服务的H...

9820
来自专栏hotqin888的专栏

ONLYOFFICE协作编辑页面中文档下载地址url携带(传输)sessionid测试

onlyoffice协作页面里有个文档下载地址,这个地址是第一个人打开这个文档的时候,服务器会根据这个文档地址,将文档管理服务器里的文档下载到onlyoffic...

21110
来自专栏csxiaoyao

利用NextCloud配置私有云

1.3K60
来自专栏企鹅号快讯

Spring Security源码分析:Spring Security请记住我

有这样一个场景——有个用户初访并登录了你的网站,然而第二天他又来了,却必须再次登录。于是就有了“记住我”这样的功能来方便用户使用,然而有一件不言自明的事情,那就...

272100
来自专栏菩提树下的杨过

Spring Security笔记:Remember Me(下次自动登录)

前一节学习了如何限制登录尝试次数,今天在这个基础上再增加一点新功能:Remember Me. 很多网站,比如博客园,在登录页面就有这个选项,勾选“下次自动登录”...

48960
来自专栏小巫技术博客

Android Library上传到JCenter仓库实践

12440
来自专栏贾鹏辉的技术专栏@CrazyCodeBoy

React Native发布APP之签名打包APK

React Native发布APP之签名打包APK ---- 用React Native开发好APP之后,如何将APP发布以供用户使用呢?一款APP的发布流程...

30350
来自专栏小白安全

Burpsuite插件的使用

Burp插件的使用 使用准备 Burpsuite可以使用三种语言编写的扩展插件,Java、Python和Ruby。除Java外,其它两种需要的扩展...

30940

扫码关注云+社区

领取腾讯云代金券