天道酬勤,学无止境

How to escape sql injection from HANA placeholder

I have some HANA queries which use PLACEHOLDER input and of course I want to prevent an sql injection.

I try to use ? in odbc_prepare()

$query = <<<SQL
SELECT
    col,
    ...
FROM table_name('PLACEHOLDER'=('$$some_key$$', ?))
WHERE col = ?
SQL;
$stmt = \odbc_prepare($conn, $query);

if ($stmt !== false) {
    \odbc_execute($stmt, ['placeholder_value', 'where_value']);
}

but I receive this warning:

Warning: odbc_prepare(): SQL error: [SAP AG][LIBODBCHDB SO][HDBODBC] Syntax error or access violation;257 sql syntax error: incorrect syntax near &quot;?&quot;: line 32 col 40 (at pos 1283), SQL state 37000 in SQLPrepare

and statement wasn't created. So my code now looks like this:

$query = <<<SQL
SELECT
    col,
    ...
FROM table_name('PLACEHOLDER'=('$$some_key$$', 'placeholder_value'))
WHERE col = ?
SQL;
$stmt = \odbc_prepare($conn, $query);

if ($stmt !== false) {
    \odbc_execute($stmt, ['where_value']);
}

As I see here htmlspecialchars() is not enough to prevent an SQL injection.

I can't remove input placeholder, I don't own HANA.

Is there any other way to prevent SQL injection in PLACEHOLDER?

评论

The (old) placeholder syntax ('PLACEHOLDER'=('<varname>', '<var value>')) you're using here does not allow for bind variables.

Instead, the new placeholder syntax (PLACEHOLDER."<varname>"=>?) allows using bind variables.

In your code this would look like this:

$query = <<<SQL
SELECT
    col,
    ...
FROM table_name (PLACEHOLDER."$$some_key$$" => ?)
WHERE col = ?
SQL;
$stmt = \odbc_prepare($conn, $query);

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Escaping single quotes in the PLACEHOLDER clause of a HANA SQL statement
    I noticed an inconsistency in how "HANA SQL" escapes single quotes in the context of the PLACEHOLDER clause. For example, consider the following PLACEHOLDER clause snippet: ('PLACEHOLDER' = ('$$CC_PARAM$$','''foo'',''an escaped single quote \'' ''')) The PLACEHOLDER clause above contains multiple values assigned to the CC_PARAM. parameter. We can see that inside of the second argument we have a single quote that's escaped with a backslash. However, we escape the single quotes outside each argument with another single quote (i.e. we do '' instead of \''. It's possible to use the \'' format for
  • mysqli_real_escape_string 如何无法防止 SQL 注入? [复制](How can mysqli_real_escape_string fail to prevent a SQL injection? [duplicate])
    问题 这个问题在这里已经有了答案: 绕过 mysql_real_escape_string() 的 SQL 注入(4 个回答) 8 年前关闭。 首先,我知道人们想要使用存储过程,以便他们重用查询并处理转义。 但是,我读过很多开发人员说mysqli_real_escape_string不能 100% 防止 SQL 注入。 有人可以提供一个例子吗? 根据我对该主题的有限了解,我会说mysqli_real_escape_string对于字符串总是适用的,但是对于数值,除非您检查数字是 int、float、double 等,否则您可能会被发现。 编辑:我忘了添加一些关键的东西:假设字符集是 UTF8 并且相应地调用了 mysqli_set_charset。 我见过的唯一注入依赖于一些字符集(没有一个是 UTF8)。 回答1 只要您使用mysqli_set_charset()设置客户端编码,并且mysqli_real_escape_string()仅用于格式化字符串,它就非常安全。 但是,如果您的问题暗示在应用程序代码中使用此函数,而不是在基于占位符的查询的幕后处理或至少以 PDO 的quote()类的函数的形式(它同时进行转义和引用) ) 这是直接注射的方法。 这不是函数本身的问题,而是它的使用方式: 由于它只执行所需格式的一部分,因此很容易忘记另一部分并陷入麻烦甚至它也很容易被误用
  • 你需要在 Mysql 参数周围加括号来防止 sql 注入吗?(Do you need brackets around Mysql parameters to prevent sql injection?)
    问题 我正在使用 nodejs 和 mysql npm 包,我正在尝试从 other_text = 的表中进行选择 这是它的样子: var query = connection.query(`SELECT id FROM ${tableName} WHERE other_text = ?`, attributeName.other_text, function (err, rows) { ... 我读过使用 ? 将自动转义用户输入的字符串。 在我看到的大多数执行此操作的示例中,它们在查询函数中的第二个参数周围都有括号,如下所示: var query = connection.query(`SELECT id FROM ${tableName} WHERE other_text = ?`, [attributeName.other_text], function (err, rows) { ... 为了转义传入的字符串,是否需要括号? 当我尝试它时它有效,但我什至不知道如何测试 SQL 注入,所以我真的不知道括号是否必要甚至正确。 谢谢你。 回答1 括号代表一个数组。 如果您有更多要用于查询的值,则可以使用数组。 例如,假设您想从表中选择多个列,并且您想将它们传递给语句,您可以使用以下内容: connection.query(`SELECT ?? FROM ${tableName}`
  • 如何避免SQL注入攻击?(How can I avoid SQL injection attacks?)
    问题 昨天我在与开发人员交谈时,他提到了一些有关限制数据库字段插入的内容,例如-- ( -- minus)之类的字符串。 在同一类型中,我知道这是一种逃避< >等HTML字符的好方法。不是-- 。 这是真的? 我需要担心-- , ++吗? 它更像是神话还是古老的东西? 更新 非常感谢所有答案,因为我对所有这些都是新手,所以很容易理解。 好吧,更具体地说,在这种情况下,我们的讨论与我们正在开发的C#ASP.NET MVC网站有关,因此在其中有一个包含重要信息的复杂的开立帐户表单,因此我不确定MVC是否使用Linq来与数据库的接口是否已经带有这种保护。 因此,如果有人可以提供一些提示,那就太好了。 再次感谢 回答1 避免SQL注入攻击的正确方法不是简单地禁止某些有问题的字符,而是使用参数化的SQL。 简而言之,参数化SQL阻止了数据库作为SQL命令的一部分执行原始用户输入,这阻止了用户输入(例如“删除表”)的执行。 仅转义字符并不能阻止所有形式的SQL注入攻击,并且排除某些单词(例如“ Drop”)在所有情况下均无效。 在某些字段中,“ Drop”是数据条目的完全有效部分。 您可以在此处找到有关参数化SQL的一些不错的文章: https://blog.codinghorror.com/give-me-parameterized-sql-or-give-me-death/ http:/
  • can I place a sql query in a sql hana place holder
    can I place a sql query in a sql hana place holder? the following query works: Select * From table1 ('PLACEHOLDER' = ('$$IP_ShipmentDate$$', '2020-01-01')) I am trying to pass something like the following: Select * From table1 ('PLACEHOLDER' = ('$$IP_ShipmentDate$$', Select TO_VARCHAR(min("some_date"),'YYYY-MM-DD') from Table2) Currently getting a syntex error
  • bind_param完成什么工作?(What does bind_param accomplish?)
    问题 我正在学习避免SQL注入,我有点困惑。 使用bind_param时,我不明白目的。 在手册页上,我找到了以下示例: $stmt = mysqli_prepare($link, "INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)"); mysqli_stmt_bind_param($stmt, 'sssd', $code, $language, $official, $percent); $code = 'DEU'; $language = 'Bavarian'; $official = "F"; $percent = 11.2; 现在,假设这四个变量是用户输入的,我不明白这是如何防止SQL注入的。 据我了解,他们仍然可以在其中输入任何内容。 我也在那里找不到关于'sssd'的解释。 它有什么作用? 那是什么使它更安全? 最后一个问题:我读到另一个问题,即不建议使用mysqli_real_escape_string ,但在手册中并未说明。 如何弃用? 由于某种原因,它不能再转义特殊字符吗? 注意:这个问题解释了bind_param的作用,但是我仍然不明白为什么它更安全或更受保护。 Bind_param说明 回答1 现在,假设这四个变量是用户输入的,我不明白这是如何防止SQL注入的。 据我了解,他们仍然可以在其中输入任何内容。
  • 如何防止用php和mysql进行sql注入(How do I prevent sql injection with php and mysql)
    问题 我有一个访客可以输入数据的表单,我想通过$ _POST变量将此数据存储在mysql数据库中。 我需要什么来防止sql注入? 回答1 使用准备好的语句。 回答2 我在2010年5月的PHP TEK-X会议上作了有关此主题的演讲,并且尝试涵盖多种防止SQL注入的方法。 在所有情况下,没有一种方法是最好的,因此您应该学习多种方法并使用所有这些方法: 在将用户输入或来自外部源的任何其他内容(甚至来自您自己的数据库中的数据)进行验证之前,请先将其插入SQL查询中。 例如,您可以使用PHP的过滤器扩展或正则表达式。 强制外部内容采用正确的格式。 例如, (int) $_POST["userid"]将内容强制转换为纯整数,因此可以安全使用。 当在SQL表达式中包括动态内容而不是文字值时,请使用带参数的预准备查询。 请注意,PHP中的普通mysql扩展不支持查询参数-使用PDO。 我不使用mysqli因为它的API不一致且mysqli 。 使用IN()谓词时,不能将一个参数用于值列表。 串联多个参数占位符,只要列表中有值即可。 这并不难,只需要一行或两行代码即可: $sql = "SELECT ... FROM ... WHERE user_id IN (" . join(",", array_fill(0,count($userid_list),"?")) . ")"; $pdoStmt
  • 这两个功能是否对杀菌消毒过度?(Are these two functions overkill for sanitization?)
    问题 function sanitizeString($var) { $var = stripslashes($var); $var = htmlentities($var); $var = strip_tags($var); return $var; } function sanitizeMySQL($var) { $var = mysql_real_escape_string($var); $var = sanitizeString($var); return $var; } 我从书中获得了这两个函数,作者说,通过使用这两个函数,我可以更加安全地抵御XSS(第一个函数)和sql注入(第二个函子)。 所有这些都是必要的吗? 同样为了进行清理,我使用准备好的语句来防止sql注入。 我会这样使用它: $variable = sanitizeString($_POST['user_input']); $variable = sanitizeMySQL($_POST['user_input']); 编辑:摆脱第1个函数的strip_tags,因为它不执行任何操作。 使用这两个功能是否足以防止大多数攻击并可以在公共站点上使用? 回答1 的确如此,但这种转义级别可能并非在所有情况下都适用。 如果要将HTML存储在数据库中怎么办? 最佳实践表明,在显示它们时,您应该转义它们,而不是逃避接收值。
  • Psycopg2插入到带有占位符的表中(Psycopg2 Insert Into Table with Placeholders)
    问题 这可能是一个很愚蠢的问题,但是我在这里做错了什么? 它创建了表,但是INSERT INTO不起作用,我猜我在占位符上做错了什么? conn = psycopg2.connect("dbname=postgres user=postgres") cur = conn.cursor() escaped_name = "TOUR_2" cur.execute('CREATE TABLE %s(id serial PRIMARY KEY, day date, elapsed_time varchar, net_time varchar, length float, average_speed float, geometry GEOMETRY);' % escaped_name) cur.execute('INSERT INTO %s (day,elapsed_time, net_time, length, average_speed, geometry) VALUES (%s, %s, %s, %s, %s, %s)', (escaped_name, day ,time_length, time_length_net, length_km, avg_speed, myLine_ppy)) conn.commit() cur.close() conn.close() INSERT
  • 使用包含正斜杠“/”的表名将 Sqoop1 与 SAP Hana 结合使用会导致错误(Using Sqoop1 with SAP Hana using a table name that contains forward slash '/' causes error)
    问题 尝试使用包含正斜杠“/”的表从 SAP Hana 导入数据。 不确定转义“/”是否有效。 我的连接尝试: sqoop import –connect jdbc:sap://mysaphost:30015 --driver com.sap.db.jdbc.Driver --username xxxxxx --password xxxx --table xxx./xxx/xxx 产生以下错误: 2016-05-20 13:12:23,098 错误 - [main:] ~ 错误执行语句:com.sap.db.jdbc.exceptions.JDBCDriverException:SAP DBTech JDBC:[257]:sql 语法错误:“/”附近的语法不正确“:第 1 行第 24 行(在 pos 24)(SqlManager:43)com.sap.db.jdbc.exceptions.JDBCDriverException:SAP DBTech JDBC:[257]:sql 语法错误:“/”附近的语法不正确:第 1 行24(在位置 24) 回答1 为了使用带有斜杠(或其他特殊字符)的对象名称,您需要将它们括在双引号 (") 中。 由于您似乎在使用命令行界面并希望将表名作为参数传递,因此您很可能必须转义这些引用。 尝试类似 sqoop import –connect jdbc
  • 用了MyBatis就不会发生SQL注入风险吗?
    用了MyBatis就不会发生SQL注入风险吗? SQL注入问题是很久的事情了,而且现在mybatis,hibernate等框架使用较为成熟了,但是作为一个T新手肯定要对一些本质上的安全问题从新从头梳理一下。 本 文 主 要 说 S Q L 注 入 中 的 S t a t e m e n t 对 象 , P r e p a r e d S t a t e m e n t 对 象 , 和 m y b a t i s 的 注 入 风 险 \color{red}{本文主要说SQL注入中的Statement对象,PreparedStatement对象,和mybatis的注入 风险 ~ } 本文主要说SQL注入中的Statement对象,PreparedStatement对象,和mybatis的注入风险 1.前言 正文开始,首先是环境准备一下,数据库建个表: CREATE TABLE `user` ( `id` bigint(20) NOT NULL auto_increment COMMENT '主键ID', `name` varchar(30) default NULL COMMENT '姓名', `password` varchar(50) default NULL, `age` int(11) default NULL COMMENT '年龄', `email` varchar(50)
  • 如何在Yii框架中使用mysql_escape_string()?(How to use mysql_escape_string() in Yii framework?)
    问题 众所周知,我们不能在诸如Yii之类的框架中使用原始MySQL查询。 我想在Yii框架中运行的项目中使用mysql_escape_string ,以摆脱用户输入中的SQL注入。 我知道mysql_escape_string在PHP 5.5中已弃用,并且我有PDO替代方法。 Yii框架中的替代方法是什么?还有mysql_escape_string()的PDO方法是什么? 回答1 PDO中mysql_escape_string的替代方法是使用准备好的语句。 以Yii为例: $user = Yii::app()->db->createCommand() ->select('username, password') ->from('tbl_user') ->where('id=:id', array(':id'=>$_GET['userId'])) ->queryRow(); (来自Yii参考文档http://www.yiiframework.com/doc/api/1.1/CDbCommand) 在准备好的语句中通过占位符传递参数时,可以防止SQL注入。 回答2 最好使用准备好的语句进行自动参数转义。 但是,这种CDbConnection方法也可以解决问题: Yii::app()->db->quoteValue($your_value); 本质上,这引用了一个字符串值供查询使用
  • Mybatis#号和$的区别,面试时如何不尴尬的回答
    mybatis#号和$的区别是什么,想必大家在面试过程中或多或少都会遇到过这个问题吧! 当面试官问到这个问题的时候,是不是答完:“#号可以防止sql注入,$不可以防止sql注入”。就草草了事了呢? 这么回答正确,没问题!可你有没有想过这么简单的回答有什么意义呢?只能证明你知道答案,对于你个人的能力却毫无展现。 这时对于一个有几年工作经验的你,心中是否在想这么简单的问题还要问吗?是面试官在怀疑你的能力,还是面试官不知道问什么? 为了避免一句话就答完这个问题的尴尬,同时又能展现你的能力,阿灯为大家准备了如下参考。 1、谈发现 在日常开发中,我们难免会根据控制台或日志打印出的sql语句进行验证和调试。但是往往我们在控制台看到的sql语句,并不是完整带参数的语句而是带有?号占位符的。如下: mybatis语句:select id from user where name=#{name} select id from user where name=? 我们复制语句后,想要单独执行sql语句,这时就需要手动的将占位符替换成相应的参数。如果遇到参数过多的情况,那么,我们手动替换时不仅会感到很繁琐,同时也会很浪费时间。这时我们就会想,能不能在控制台打印出不带占位符的完整sql语句,下面阿灯给大家提供点打印完整sql的方式: 可以通过P6Spy跟踪sql的执行情况
  • 在 PHP 中过滤掉 MySQL 查询(Filtering out MySQL query in PHP)
    问题 嘿,我正在对涉及一些用户输入的 MySQL 数据库进行一些查询。我想知道如何防止注入攻击,例如,如果有人要输入 "; a-MySQL query here;" 它将被执行,这将允许人们访问我的系统。 我想知道如何防止这样的事情,可能创建一个函数来过滤掉查找错误语句的查询? 或者可能不允许 ; 特点? 总结一下: 现在防止注入攻击的常见做法是什么? 我该怎么办? 这个解决方案对于那些通过更改我的数据库知道他们在做什么的人来说有多有效。 回答1 唯一的方法是正确转义用户提交的数据。 其他人已经指出了一些这样做的方法。 还有另一种方式:准备好的语句和占位符。 每个现代PHP 数据库接口都支持准备好的语句,包括 mysqli 和 PDO。 让我们使用 PDO 作为演示。 假设我们想更新用户提交的表foo的一些数据。 $sql = 'UPDATE foo SET bar = ? WHERE user_id = ?'; $sh = $db->prepare($sql); $sh->execute(array( $_POST['bar'], $_SESSION['user_id'] )); 传递给execute的数组中的变量替换了查询中的问号占位符。 发生这种情况时,它们会自动转义并引用。 您无需手动对它们进行转义即可将它们安全地放入数据库中! 另一方面,您仍然需要过滤它们以查找意外内容
  • 如何使用占位符/准备好的语句将数据添加到 mysq 中的特定列(How to add data to specific columns in mysq using placeholders/prepared statements)
    问题 我正在学习如何从教科书中编码,它给出了如何使用占位符将数据添加到表中的示例,但它没有显示如何仅将数据添加到特定列。 这是我想出的 if (isset($_POST['title']) && isset($_POST['author']) && isset($_POST['isbn'])) //This checks to see if there is a value inputted into the form at the bottom { $title = get_post('title'); $author = get_post('author'); $isbn = get_post('isbn'); //This retrieves information from the user and assigns it to a variable $q = 'PREPARE statement FROM "INSERT INTO classifieds(title, author, isbn)' . 'VALUES(?,?,?)"'; mysql_query($q); $q = 'SET @title = "$title",' . '@author = "$author",' . '@isbn = "$isbn",'; mysql_query($q); $q =
  • 使用 MySQLi 保护的 PHP TO MySQL 和超链接重定向一旦提交就不起作用(PHP TO MySQL secured with MySQLi and hyperlink redirect not working once submitted)
    问题 我有一个自由职业者在一个网站上为我工作,但无法完成我的项目,这对他来说应该很容易,我需要让这个项目完全运行才能在早上准备好。 这是我必须匆忙创建的 PHP 代码 <?php $con = mysqli_connect('localhost','dbuser','password' if(!$con) { echo 'Not Connected To Server'; } if(!mysqli_select_db($con,'DBName')) { echo 'Database Not Selected'; } $UserN = $_POST['UserN']; $FullN = $_POST['FullN']; $Adrs = $_POST['Adrs']; $Email = $_POST['Email']; $PhoneN = $_POST['PhoneN']; $sql = "INSERT INTO UserIn (UserN, FullN, Adrs, Email, PhoneN) VALUES ('$UserN', '$FullN', '$Adrs', '$Email', '$PhoneN')"; if(!mysqli_query($con,$sql)) { echo 'Not Inserted'; } else { echo 'Inserted'; } header
  • Python SQLite3 SQL注入漏洞代码(Python SQLite3 SQL Injection Vulnerable Code)
    问题 我知道下面的代码段由于.format易受SQL注入攻击,但我不知道为什么。 有谁知道为什么此代码容易受到攻击,我将在哪里开始修复它? 我知道这些代码段使输入字段保持打开状态,从而可以通过SQL Injection执行其他恶意命令,但不知道为什么 cursor.execute("insert into user(username, password)" " values('{0}', '{1}')".format(username, password)) handle[0].execute("insert into auditlog(userid, event)" " values({0}, ‘{1}')".format(handle[2],event)) audit((cursor, connection, 0), "registeration error for {0}”.format(username)) sql="""insert into activitylog(userid, activity, start, stop) values({0}, '{1}', '{2}', '{3}') """.format(handle[2], activity, start, stop) 回答1 使用第一个SQL语句的示例SQL注入: cursor.execute("insert
  • 您是否应该仅将准备好的语句用于转义? [关闭](Should you use prepared statements for their escaping only? [closed])
    问题 从目前的情况来看,这个问题不适合我们的问答形式。 我们希望答案得到事实,参考或专业知识的支持,但是这个问题可能会引起辩论,争论,民意测验或进一步的讨论。 如果您认为此问题可以解决并且可以重新提出,请访问帮助中心以获取指导。 7年前关闭。 我看到很多人说您应该始终对数据库查询使用准备好的语句。 但是,PHP文档说: 每个准备好的语句占用服务器资源。 语句在使用后应立即显式关闭。 如果未明确执行,则当PHP释放语句句柄时,该语句将关闭。 使用准备好的语句并不总是执行语句的最有效方法。 仅执行一次的准备好的语句比未准备好的语句导致更多的客户端-服务器往返。 从http://php.net/manual/en/mysqli.quickstart.prepared-statements.php 鉴于上述情况,如果您仅要使用一次查询,那么不使用准备好的语句是否更好? 回答1 差异可忽略不计。 但是,必须将本地准备语句与准备语句的一般概念区分开。 前者只是大多数DBMS支持的一种运行查询形式,在此进行解释。 其用法可能会受到质疑。 后者是用占位符替换实际数据的总体思路,这意味着要进一步处理替换后的数据。 它在编程中被广泛使用,一个著名的printf()函数就是一个例子。 而且,无论该查询是否由本机准备好的语句支持,都必须始终使用后一种方法对数据库运行查询。 因为:
  • Postgres 查询 ILIKE 和 "%#{}%"(Postgres Querying ILIKE and "%#{}%")
    问题 我可以向我解释一下“?” 防止sql注入? Candy.where("taste ILIKE ?", "%#{term}%") 另外为什么使用“%{term}%”而不是仅仅使用#{term}? 百分比代表什么? 回答1 百分比是与值的任何部分中的字符串匹配的通配符 回答2 你实际上在那里问了两个不同的问题。 它们都与 Rails 没有特别的关系,所以我将笼统地回答它们(也是因为我对 Ruby 不太熟悉!)。 如何使用“?” 防止 SQL 注入 当您直接在 SQL 语句中使用从程序外部提供的值(用户提供的值)时,就会发生 SQL 注入。 例如,假设您有以下伪代码: sql="SELECT foo FROM bar WHERE name='"+name+"'" 也许name是一个包含用户输入数据的变量。 但是,如果name包含单引号 ('),则 SQL 引擎会认为单引号是值的结尾,并继续将变量的其余部分解析为 SQL 文本。 使用占位符(例如“?”)可以避免这种情况,因为占位符内的值不需要被引用——占位符的所有内容都被视为值的一部分,不会被解析为 SQL,无论任何嵌入的引号。 顺便说一下,所使用的占位符的实际形式在某种程度上取决于所使用的实际数据库引擎和/或客户端框架。 本地,Postgresql 使用 $1、$2 等作为占位符。 许多框架对此进行了扩展以允许“?”
  • mysqli_real_escape_string,我应该使用它吗?(mysqli_real_escape_string, should I use it?)
    问题 我想消除SQL注入,应该使用mysqli_real_escape_string()还是在mysqli中清除? 例如 $nick = mysqli_real_escape_string($_POST['nick']) 回答1 您应该使用准备好的语句并将字符串数据作为参数传递,但不要转义它。 此示例摘自文档: /* create a prepared statement */ if ($stmt = $mysqli->prepare("SELECT District FROM City WHERE Name=?")) { /* bind parameters for markers */ $stmt->bind_param("s", $city); /* execute query */ $stmt->execute(); /* bind result variables */ $stmt->bind_result($district); /* fetch value */ $stmt->fetch(); printf("%s is in district %s\n", $city, $district); /* close statement */ $stmt->close(); } 注意,该示例未调用mysqli_real_escape_string 。