表单操作中反映的 XSS - 表单操作最佳实践


Reflected XSS in form action - form action best practice

我刚刚收到一份报告,由于我负责的php/IIS Web应用程序中的反射XSS,PCI合规性扫描失败。

可利用的样本:

GET /login/recover/en?alert('TK00000105') HTTP/1.1

证据:

<form id='recover_form_1' method='post'  action='https://www.somebody.com/login/recover/en?alert('TK00000105')' enctype='multipart/form-data'> 

输出由一个表单类生成,该表单类最近获得了在未提供完整操作时提供完整操作的功能(JavaScript 增强功能和 HTML5 验证)。 此操作是包含查询字符串的完整 URL(或多或少)。 通常,查询字符串实际上是实际加载页面的指示因素(它并不都是友好的!),所以我不能盲目地从URL中删除查询。

我应该如何(你怎么做)清理表单操作的 url,应该过滤的实际危险向量是什么?

剥离 html 标签是否足够,或者唯一真正的方法来修补它以使表单的每次使用都提供特定的操作?

------------------编辑表单创建的详细信息-------------------------

构造和打开表单标签生成如下:

public function __construct( $id = false, $method = 'post', $action = '', $class= '')
    {        
        $this->_method = strtolower($method);
        $this->_action = $action;
        $this->_class =  $class;
        if ($id == false) 
        {
            FormEX::$_numForms++;
            $this->_id = 'form_'.FormEX::$_numForms."";
        } 
        else 
        {
            $this->_id = $id;
        }
        FormEX::Persist($this);
        $this->Controls = new 'Collection(__NAMESPACE__.''HTMLControl');
    }
...
     public function StartForm()
        {
            $action = $this->_action != '' ? $this->_action : $this->GenerateAction();
            $class = $this->_class != '' ? " class ='{$this->_class}'" : '';
            $enc = $this->_formEnctype != '' ? $this->_formEnctype : 'multipart/form-data';
            return "<form id='{$this->getID()}' method='{$this->_method}' $class action='$action' enctype='$enc'>";
        }

您将在控制器(或视图后面的其他位置)中创建窗体,并在视图中使用如下所示的内容:

<?if($this->form != null): ?>
    <?= $this->form->StartForm(); ?>
    <fieldset id="<?= $this->form->getID(); ?>">
        <div class='input'>
            <?= $this->form->_rc('Confirm'); ?>
            <?= $this->form->_rc('Cancel'); ?>
        </div>
    </fieldset>
    <?= $this->form->EndForm(); ?>
<?endif ?>

---------------------编辑 - 感谢马雷克-------------------------------

因此,一项改进是确保 url 被编码,同时在输出点对所有开发人员可写属性进行防御性编码。

_s() 是我们库中htmlentities($value, ENT_QUOTES, 'utf-8')的编码快捷方式。

public function StartForm()
{
    $action = $this->_action != '' ? $this->_action : $this->GenerateAction();
    $class = $this->_class != '' ? " class ='{$this->_class}'" : '';
    $enc = $this->_formEnctype != '' ? $this->_formEnctype : 'multipart/form-data';
    $formTag = "<form id='" . _s($this->getID()) . "' method='" . _s($this->_method) . "' $class action='" . _s($action) . "' enctype='" . _s($enc) . "'>";
    return $formTag;
} 

关于我的问题,还有什么我应该注意的吗?

谢谢。

该库是可利用的,它不能正确转义用于引用属性的单引号。 htmlspecialchars不会转义带有默认参数的单引号(我希望库使用它)。表单标记应为以下之一:

<form id='recover_form_1' method='post'  action='https://www.somebody.com/login/recover/en?alert(&#039;TK00000105&#039;)' enctype='multipart/form-data'>
<form id="recover_form_1" method="post"  action="https://www.somebody.com/login/recover/en?alert('TK00000105')" enctype="multipart/form-data">

第一个将ENT_QUOTES标志添加到htmlspecialchars,第二个使用双引号,并保留单曲。

您现在应该修复库并通知开发人员。