如何绕过 apache 拥有上传到 PHP 网络服务器的文件?

发布于 2024-09-12 18:45:22 字数 1963 浏览 8 评论 0原文

我正在 Linux Web 服务器上开发 PHP Web 应用程序,用于为我共同教授的课程提供成绩和文档。我现在正在编写的页面用于提交作业,学生从下拉菜单中选择作业,然后上传作业并提交。提交后,有关提交的所有信息都会进入 MySQL 表,并且文件将移动到文件系统上的永久位置。理想情况下,这将是由作业、学生和版本高度组织的东西,但我现在想要的只是原则上让文件上传工作,所以现在它只是将内容发送到目录 ~/phptest/ (其权限)设置为 755,尽管我只是为了测试而尝试了 777,但这也不起作用)。下面是现在的代码:

($dbh 是我创建的扩展数据库句柄类的实例,目的是使这些特定的数据库事务更清晰)


if(isset($_POST['submit'])) {
    $assignmentID = $_POST['assID'];
    $tmp = "/home/username/phptest/"; 
    $info = pathinfo($_FILES['file']['name']);
    $filename = $info['basename'];
    $ext = $info['extension'];
    if(1) { //strcmpall($ext,array('tar.gz','zip'))) {
        if($_FILES['file']['size'] < 1000000) {
            $path = $tmp . $filename;
            if(move_uploaded_file($_FILES['file']['tmp_name'], $path)) {
                $versionQuery = $dbh->select(array('version'),array('a01_submissions'),array("studentID='$studentID'","assignmentID='$assignmentID'"));
                if(count($versionQuery)) {
                    $versionArray = $dbh->colToArray($versionQuery,'version');
                    $version = max($versionArray)+1;
                }
                else $version = 1;
                echo "Version $version.\n";
                $week = $dbh->getOne('week','a01_assignments','id',$assignmentID);
                $dbh->insert("a01_submissions",array('studentID','assignmentID','version','filePath'),array($studentID,$assignmentID,$version,addslashes($newpath)));
                echo "File $filename sucessfully uploaded and stored at $newpath.\n";
            }
            else echo $moved . "
\n"; } else die("File cannot exceed 1MB"); } else die("Bad file extension."); } else { // HTML to display the submission screen }

但我的问题是 move_uploaded_file 仅适用于具有 777 权限的目录。仔细检查发现,这是因为 PHP 正在以用户“apache”上传内容,因此无法使用 ow 写入我的用户名拥有的目录。我在 PHP 文档中看到用户发布的解决方案建议使用 chown 回收文件,但我没有足够高的权限级别来执行此操作。有没有一个优雅的解决方案来解决这个问题,而不涉及尝试让我的用户名获得更高的权限?

I am working on a PHP web app on a Linux web server for grades and documents for a course that I am co-teaching. The page I am writing at the moment is for submitting assignments, where the student selects an assignment from a drop-down menu and then uploads the assignment and submits. On submit, all the information about the submission goes into a MySQL table, and the file is moved to a permanent location on the file system. Ideally, this would be something highly organized by assignment, student, and version, but all I want right now is to get the file upload working in principle, so for now it just sends stuff to the directory ~/phptest/ (permissions for which are set to 755, though I have tried 777 just for tests, and that didn't work either). Here is the code as it is now:

($dbh is an instance of an expanded DB handle class I created to make these specific DB transactions cleaner)


if(isset($_POST['submit'])) {
    $assignmentID = $_POST['assID'];
    $tmp = "/home/username/phptest/"; 
    $info = pathinfo($_FILES['file']['name']);
    $filename = $info['basename'];
    $ext = $info['extension'];
    if(1) { //strcmpall($ext,array('tar.gz','zip'))) {
        if($_FILES['file']['size'] < 1000000) {
            $path = $tmp . $filename;
            if(move_uploaded_file($_FILES['file']['tmp_name'], $path)) {
                $versionQuery = $dbh->select(array('version'),array('a01_submissions'),array("studentID='$studentID'","assignmentID='$assignmentID'"));
                if(count($versionQuery)) {
                    $versionArray = $dbh->colToArray($versionQuery,'version');
                    $version = max($versionArray)+1;
                }
                else $version = 1;
                echo "Version $version.\n";
                $week = $dbh->getOne('week','a01_assignments','id',$assignmentID);
                $dbh->insert("a01_submissions",array('studentID','assignmentID','version','filePath'),array($studentID,$assignmentID,$version,addslashes($newpath)));
                echo "File $filename sucessfully uploaded and stored at $newpath.\n";
            }
            else echo $moved . "
\n"; } else die("File cannot exceed 1MB"); } else die("Bad file extension."); } else { // HTML to display the submission screen }

My problem, though, is that move_uploaded_file only works for directories with 777 permissions. Closer inspection reveals that this is because PHP is uploading stuff as the user 'apache', and therefore can't write to directories owned by my username with o-w. I saw solutions posted by users in the PHP docs that suggested using chown to reclaim the files, but I don't have a high enough permission level to do this. Is there an elegant solution to this problem that does not involve trying to get my username higher permissions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

逆蝶 2024-09-19 18:45:22

让系统管理员将您置于与 apache 相同的用户组中,或者理想情况下创建一个名为开发人员之类的新组,并将 apache 用户和您自己添加到其中。

否则你可以尝试使用 PHP 的 chmodchown 文件上传后立即运行。如果您运行 chmod($filepath, 0777); ,这应该是一个很好的测试,看看它是否适合您。

Get the sysadmin to put you in the same user group as apache or ideally create a new group called something like developers and add the apache user and yourself to it.

Otherwise you could try using PHP's chmod or chown functions immediately after the file upload. If you run chmod($filepath, 0777); that should be a good test of whether it will work for you or not.

如果没结果 2024-09-19 18:45:22

简短的回答:没有一个优雅的解决方案,因为这在概念上是错误的。该文件首先归 Web 服务器用户所有是有原因的。创建该文件的是 Web 服务器(从操作系统的角度来看),因此他应该拥有该文件。

长答案:
您确实希望该文件归其他用户所有的原因是什么?

  1. 安全性 那么,一旦文件不再属于 Web 服务器,它就无法被 Web 服务器覆盖,因此如果攻击者接管 Web 服务器,他或她就无法更改分配不再有。的确。但是,Web 应用程序不应该做奇怪的事情™,而应该专注于它应该做的事情,并且保护 Web 服务器肯定不是它的任务之一。正确的应用程序架构和一些标准的安全措施应该起到同样的作用,并且本质上比仅仅更改文件的所有者具有更高的安全性。如果您绝对必须移动数据,您可以使用 incroninotincoming 。如果您的安全需求很高,您应该考虑在您的 Web 服务器上实施 SELinux 配置文件。
  2. 底层业务逻辑 独自实现复杂的工作流程是一个坏主意。如果您有关于文档处理的其他业务逻辑,我建议使用 Apache Camel Apache Servicemix,它又使用 Camel,但提供了很多更多功能。 Apache Camel 是一个 Wrouting 和中介引擎”,大致翻译为“它根据 企业集成模式。这反过来意味着它可以转换、分割、丰富、路由或过滤任何给定的有效负载。有一个优秀的文件处理模块,它可以自动化很多工作在实现业务逻辑(处理、恢复中断的处理、创建备份等)时您必须自己处理的事情。 Camel 也支持 php (尽管我不建议使用php 排名第一,但这无疑是完全有偏见的)。您可以将其与 incron 或 inotincoming
  3. Access 链接。您可能想通过 ftp 访问这些文件,但不将 ftp 用户添加到 Web 服务器组。简单的解决方案:使用“其他”权限。并不是说设置对方的权限就可以在互联网上传播文件。确保您拥有“其他”设置的只读权限,然后就可以开始了。另一种解决方案可能是设置具有虚拟用户的 ftp 服务器。

底线:有一个解决方案,而且不会破坏意义,更不用说实施安全措施了。

Short answer: There isn't an elegant solution, as this is conceptually wrong. There is a reason why the file is owned by the web server user in the first place. It is the web server which created the file (from the OS point of view), so he should own it.

Long answer:
What are the reasons behind the fact that you do want the file to be owned by an other user?

  1. Security Well, as soon as the file is not owned by the web server any more, it can not be overwritten by it so if an attacker takes over the web server, he or she can not alter the assignments any more. Granted. But instead of doing Weird Stuff™ a web application should focus on what it is supposed to do and securing the web server surely is not one of it's tasks. A proper application architecture and some standard security measures should do the same trick and inherently hold a lot more security than just changing the owner of the file. If you absolutely have to move the data around, you could either set up a watch folder using a tool like incron or inotincoming. In case your security needs are high, you should think of implementing a SELinux profile on your web server.
  2. Underlying business logic It is a bad idea to implement complex workflows all by yourself. If you have additional business logic regarding the processing of the documents, I'd suggest using either Apache Camel or Apache Servicemix, which in turn uses Camel, but provides a lot more features. Apache camel is a Wrouting and mediation engine", which roughly translates to "it processes messages according to Enterprise Integration Patterns. That in turn means it converts, splits, enriches, routes or filters any given payload. There is an excellent file processing module which automates a lot of stuff you have to take care for yourself when implementing business logic (processing, resuming interrupted processing, creating backups and such). Camel supports php too (though I would not recommend using php the first place, but that is admittedly completely biased). You can chain this with incron or inotincoming
  3. Access It might be that you want to access those files via ftp, but not add the ftp user to the web server group. Easy solution: use the "others" permissions. It is not that setting the other's permission broadcasts the files among the internet. Make sure you have a read only permission for "others" set and you are good to go. Another solution might be to set up a ftp server with virtual users.

Bottom line: there is always a solution without undermining the sense, much less the implementation of security measures.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文