Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Z
Zipr Toolchain
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Open Source Software
Zipr Toolchain
Commits
1efc6409
Commit
1efc6409
authored
10 years ago
by
an7s
Browse files
Options
Downloads
Patches
Plain Diff
Added tautology detectory
Former-commit-id: 821dfb3deac5333c7537f7bd8a6d9d7a9155fcc7
parent
bbb70b2c
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
appfw/src/sqlfw.c
+205
-22
205 additions, 22 deletions
appfw/src/sqlfw.c
appfw/src/sqlfw.h
+1
-1
1 addition, 1 deletion
appfw/src/sqlfw.h
with
206 additions
and
23 deletions
appfw/src/sqlfw.c
+
205
−
22
View file @
1efc6409
...
...
@@ -86,7 +86,8 @@ int sqlfw_verify_s(const char *zSql, char *p_critical)
bzero
(
structure
,
len
);
// get all the critical keywords
int
result_flag
=
sqlfw_get_structure
(
zSql
,
markings
,
structure
);
int
is_tautology
=
0
;
int
result_flag
=
sqlfw_get_structure
(
zSql
,
markings
,
structure
,
&
is_tautology
);
strcpy
(
p_critical
,
markings
);
if
(
verbose
)
...
...
@@ -169,13 +170,28 @@ int sqlfw_verify(const char *zSql, char **errMsg)
return
0
;
}
// get all the critical keywords
sqlfw_get_structure
(
zSql
,
tainted
,
structure
);
int
success
=
appfw_establish_taint_fast2
(
zSql
,
tainted
,
FALSE
);
if
(
!
success
&&
verbose
)
appfw_display_taint
(
"SQL Injection detected"
,
zSql
,
tainted
);
int
is_tautology
=
0
;
int
success
=
1
;
// get all the critical keywords / detect tautologies
sqlfw_get_structure
(
zSql
,
tainted
,
structure
,
&
is_tautology
);
if
(
is_tautology
&&
verbose
)
{
appfw_display_taint
(
"SQL Injection detected (tautology)"
,
zSql
,
tainted
);
success
=
0
;
}
if
(
!
is_tautology
)
{
success
=
appfw_establish_taint_fast2
(
zSql
,
tainted
,
FALSE
);
if
(
!
success
&&
verbose
)
appfw_display_taint
(
"SQL Injection detected"
,
zSql
,
tainted
);
}
free
(
tainted
);
free
(
structure
);
return
success
;
}
...
...
@@ -195,6 +211,7 @@ static char *CRITICAL_FUNCTIONS[] = {
"COLLATION"
,
"CONCAT"
,
"CONVERT"
,
"COS"
,
"CRC32"
,
"CURRENT_USER"
,
"DATABASE"
,
...
...
@@ -232,6 +249,7 @@ static char *CRITICAL_FUNCTIONS[] = {
"POSITION"
,
"POW"
,
"QUARTER"
,
"RAND"
,
"REVERSE"
,
"RIGHT"
,
"ROUND"
,
...
...
@@ -239,6 +257,7 @@ static char *CRITICAL_FUNCTIONS[] = {
"SCHEMA"
,
"SESSION_USER"
,
"SHA"
,
"SIN"
,
"SPACE"
,
"STRCMP"
,
"SUBSTR"
,
...
...
@@ -310,13 +329,125 @@ char get_violation_marking(char p_current_marking)
return
APPFW_SECURITY_VIOLATION
;
}
#define TT_NUM_TOKENS 4
#define MAX_TOKEN_SIZE 256
struct
tt_sql_tokens
{
int
type
;
char
data
[
MAX_TOKEN_SIZE
];
};
void
tt_clear
(
struct
tt_sql_tokens
*
tokens
,
int
tt_num_tokens
)
{
memset
(
tokens
,
0
,
sizeof
(
struct
tt_sql_tokens
)
*
tt_num_tokens
);
}
void
tt_save_token
(
struct
tt_sql_tokens
*
tokens
,
int
*
tt_num_tokens
,
int
tokenType
,
const
char
*
zSql
,
int
beg
,
int
end
)
{
int
tokenid
=
*
tt_num_tokens
;
if
(
tokenid
>=
TT_NUM_TOKENS
)
{
fprintf
(
stderr
,
"tt_save_token(): fatal error in tautology detector
\n
"
);
return
;
}
tokens
[
tokenid
].
type
=
tokenType
;
int
len
=
end
-
beg
+
1
;
strncpy
(
tokens
[
tokenid
].
data
,
&
zSql
[
beg
],
len
);
tokens
[
tokenid
].
data
[
len
]
=
0
;
*
tt_num_tokens
=
tokenid
+
1
;
}
// detect tautology
// OR <string> <OP> <string>
// OR <numeric> <OP> <numeric>
// e.g.:
// OR 1 = 1
// OR 1.23 >= 1.2
// OR 'a' = 'a'
// OR 'a' < 'b'
//
int
tt_detect
(
struct
tt_sql_tokens
*
tokens
,
int
tt_num_tokens
)
{
if
(
tt_num_tokens
!=
4
||
tokens
[
0
].
type
!=
TK_OR
||
(
tokens
[
2
].
type
!=
TK_EQ
&&
tokens
[
2
].
type
!=
TK_NE
&&
tokens
[
2
].
type
!=
TK_GT
&&
tokens
[
2
].
type
!=
TK_LT
&&
tokens
[
2
].
type
!=
TK_GE
&&
tokens
[
2
].
type
!=
TK_LE
))
return
0
;
double
val1
,
val3
;
if
(
tokens
[
1
].
type
!=
TK_STRING
)
{
if
((
tokens
[
1
].
type
!=
TK_INTEGER
&&
tokens
[
1
].
type
!=
TK_FLOAT
)
||
(
tokens
[
3
].
type
!=
TK_INTEGER
&&
tokens
[
3
].
type
!=
TK_FLOAT
))
return
0
;
if
(
sscanf
(
tokens
[
1
].
data
,
"%lf"
,
&
val1
)
!=
1
)
return
0
;
if
(
sscanf
(
tokens
[
3
].
data
,
"%lf"
,
&
val3
)
!=
1
)
return
0
;
}
if
(
tokens
[
2
].
type
==
TK_EQ
)
{
if
(
tokens
[
1
].
type
==
TK_STRING
)
return
strcmp
(
tokens
[
1
].
data
,
tokens
[
3
].
data
)
==
0
;
else
return
val1
==
val3
;
}
else
if
(
tokens
[
2
].
type
==
TK_NE
)
{
if
(
tokens
[
1
].
type
==
TK_STRING
)
return
strcmp
(
tokens
[
1
].
data
,
tokens
[
3
].
data
)
!=
0
;
else
return
val1
!=
val3
;
}
else
if
(
tokens
[
2
].
type
==
TK_GT
)
{
if
(
tokens
[
1
].
type
==
TK_STRING
)
return
strcmp
(
tokens
[
1
].
data
,
tokens
[
3
].
data
)
>
0
;
else
return
val1
>
val3
;
}
else
if
(
tokens
[
2
].
type
==
TK_LT
)
{
if
(
tokens
[
1
].
type
==
TK_STRING
)
return
strcmp
(
tokens
[
1
].
data
,
tokens
[
3
].
data
)
<
0
;
else
return
val1
<
val3
;
}
else
if
(
tokens
[
2
].
type
==
TK_GE
)
{
if
(
tokens
[
1
].
type
==
TK_STRING
)
return
strcmp
(
tokens
[
1
].
data
,
tokens
[
3
].
data
)
>
0
||
strcmp
(
tokens
[
1
].
data
,
tokens
[
3
].
data
)
==
0
;
else
return
val1
>=
val3
;
}
else
if
(
tokens
[
2
].
type
==
TK_LE
)
{
if
(
tokens
[
1
].
type
==
TK_STRING
)
return
strcmp
(
tokens
[
1
].
data
,
tokens
[
3
].
data
)
<
0
||
strcmp
(
tokens
[
1
].
data
,
tokens
[
3
].
data
)
==
0
;
else
return
val1
<=
val3
;
}
return
0
;
// by default, return false
}
/*
** Run the original sqlite parser on the given SQL string.
** Identify critical tokens in query
** out:
** Identify critical tokens in query
** Simple tautology detector for OR clause
**
** original code: SQLITE_PRIVATE int sqlite3_sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
*/
int
sqlfw_get_structure
(
const
char
*
zSql
,
char
*
p_annot
,
char
*
p_structure
)
int
sqlfw_get_structure
(
const
char
*
zSql
,
char
*
p_annot
,
char
*
p_structure
,
int
*
is_tautology
)
{
Parse
*
pParse
;
int
nErr
=
0
;
/* Number of errors encountered */
...
...
@@ -333,6 +464,15 @@ int sqlfw_get_structure(const char *zSql, char *p_annot, char *p_structure)
int
comment_2_started
=
0
;
int
result_flag
=
S3_SQL_SAFE
;
int
verbose
=
getenv
(
"APPFW_VERBOSE"
)
?
TRUE
:
FALSE
;
int
very_verbose
=
getenv
(
"APPFW_VERY_VERBOSE"
)
?
TRUE
:
FALSE
;
// for tautology detection
struct
tt_sql_tokens
tt_tokens
[
TT_NUM_TOKENS
];
int
tt_num_tokens
=
0
;
int
tt_do_save_tokens
=
0
;
*
is_tautology
=
0
;
tt_clear
(
tt_tokens
,
TT_NUM_TOKENS
);
// by default mark critial tokens as security violations
// in a subsequent stage, we will attempt to bless them via dna shotgun sequencing
...
...
@@ -359,7 +499,6 @@ int sqlfw_get_structure(const char *zSql, char *p_annot, char *p_structure)
return
S3_SQL_PARSE_ERROR
;
}
while
(
zSql
[
i
]
!=
0
)
{
pParse
->
sLastToken
.
z
=
&
zSql
[
i
];
pParse
->
sLastToken
.
n
=
appfw_sqlite3GetToken
((
unsigned
char
*
)
&
zSql
[
i
],
&
tokenType
);
...
...
@@ -397,7 +536,7 @@ int sqlfw_get_structure(const char *zSql, char *p_annot, char *p_structure)
// here we have a SQL terminator; we need to parse the next statement
// so we recursively call ourself
if
(
end
+
1
<
strlen
(
zSql
))
return
result_flag
|
sqlfw_get_structure
(
&
zSql
[
end
+
1
],
&
p_annot
[
end
+
1
],
p_structure
);
return
result_flag
|
sqlfw_get_structure
(
&
zSql
[
end
+
1
],
&
p_annot
[
end
+
1
],
p_structure
,
is_tautology
);
else
{
return
result_flag
;
// semicolon was the last character in the entire statement return
...
...
@@ -407,13 +546,13 @@ int sqlfw_get_structure(const char *zSql, char *p_annot, char *p_structure)
// show token info
/*
fprintf(stderr, "\n----------------------\n");
fprintf(stderr, "token: [");
for (k = beg; k <= end; ++k)
fprintf(stderr,"%c (%d)", zSql[k], p_annot[k]);
fprintf(stderr, "] type: %d [%d..%d]\n", tokenType, beg, end);
*/
if
(
very_verbose
)
{
fprintf
(
stderr
,
"
\n
----------------------
\n
"
);
fprintf
(
stderr
,
"token: ["
);
for
(
k
=
beg
;
k
<=
end
;
++
k
)
fprintf
(
stderr
,
"%c (%d)"
,
zSql
[
k
],
p_annot
[
k
]);
fprintf
(
stderr
,
"] type: %d [%d..%d]
\n
"
,
tokenType
,
beg
,
end
);
}
appfw_sqlite3Parser
(
pEngine
,
tokenType
,
pParse
->
sLastToken
,
pParse
);
...
...
@@ -423,12 +562,55 @@ int sqlfw_get_structure(const char *zSql, char *p_annot, char *p_structure)
continue
;
}
if
(
tokenType
==
TK_OR
&&
tt_num_tokens
==
0
&&
(
*
is_tautology
==
0
))
tt_do_save_tokens
=
1
;
if
(
tt_do_save_tokens
)
{
switch
(
tt_num_tokens
)
{
case
0
:
// this must be the OR
tt_save_token
(
tt_tokens
,
&
tt_num_tokens
,
tokenType
,
zSql
,
beg
,
end
);
break
;
case
1
:
// this must be a string, an integer or a float
if
(
tokenType
==
TK_STRING
||
tokenType
==
TK_INTEGER
||
tokenType
==
TK_FLOAT
)
{
tt_save_token
(
tt_tokens
,
&
tt_num_tokens
,
tokenType
,
zSql
,
beg
,
end
);
}
else
{
tt_clear
(
tt_tokens
,
TT_NUM_TOKENS
);
tt_do_save_tokens
=
0
;
}
break
;
case
2
:
// this must be an operator: =, >, <, >=, <=
if
(
tokenType
==
TK_EQ
||
tokenType
==
TK_NE
||
tokenType
==
TK_GT
||
tokenType
==
TK_LT
||
tokenType
==
TK_GE
||
tokenType
==
TK_LE
)
{
tt_save_token
(
tt_tokens
,
&
tt_num_tokens
,
tokenType
,
zSql
,
beg
,
end
);
}
else
{
tt_clear
(
tt_tokens
,
TT_NUM_TOKENS
);
tt_do_save_tokens
=
0
;
}
break
;
case
3
:
// this must be a string, an integer or a float
if
(
tokenType
==
TK_STRING
||
tokenType
==
TK_INTEGER
||
tokenType
==
TK_FLOAT
)
{
tt_save_token
(
tt_tokens
,
&
tt_num_tokens
,
tokenType
,
zSql
,
beg
,
end
);
*
is_tautology
=
tt_detect
(
tt_tokens
,
tt_num_tokens
);
// detect tautology here
}
tt_clear
(
tt_tokens
,
TT_NUM_TOKENS
);
tt_do_save_tokens
=
0
;
break
;
}
}
char
temp_identifier
[
4096
];
switch
(
tokenType
)
{
// so here we would need to add all the token types that should not be p_annot
// this would be any SQL keywords
case
TK_STRING
:
strcat
(
p_structure
,
"d "
);
break
;
...
...
@@ -446,16 +628,15 @@ int sqlfw_get_structure(const char *zSql, char *p_annot, char *p_structure)
// if it's one of the identifier we care about, then fallthrough
// list is not exhaustive, need to track all relevant ones
case
TK_EXPLAIN
:
case
TK_ANALYZE
:
case
TK_OR
:
case
TK_AND
:
case
TK_IS
:
case
TK_BETWEEN
:
case
TK_IN
:
case
TK_ISNULL
:
case
TK_NOTNULL
:
case
TK_OR
:
case
TK_NE
:
case
TK_EQ
:
case
TK_GT
:
...
...
@@ -509,10 +690,10 @@ int sqlfw_get_structure(const char *zSql, char *p_annot, char *p_structure)
strcat
(
p_structure
,
" "
);
}
break
;
}
}
// end switch (tokenType) for critical identifiers
break
;
}
}
}
// end switch (tokenType)
// handle comments
if
(
end
+
1
<
strlen
(
zSql
))
...
...
@@ -589,3 +770,5 @@ void sqlfw_save_query_structure_cache(const char *p_file)
{
saveQueryStructureCache
(
p_file
);
}
This diff is collapsed.
Click to expand it.
appfw/src/sqlfw.h
+
1
−
1
View file @
1efc6409
...
...
@@ -17,7 +17,7 @@ extern int sqlfw_isInitialized();
// extern int sqlfw_verify(const char *zSql, char **pzErrMsg);
extern
int
sqlfw_verify
(
const
char
*
zSql
,
char
**
);
extern
int
sqlfw_verify_s
(
const
char
*
zSql
,
char
*
p_annot
);
extern
int
sqlfw_get_structure
(
const
char
*
zSql
,
char
*
p_taint
,
char
*
p_structure
);
extern
int
sqlfw_get_structure
(
const
char
*
zSql
,
char
*
p_taint
,
char
*
p_structure
,
int
*
is_tautology
);
extern
int
sqlfw_is_safe
(
int
);
extern
int
sqlfw_is_error
(
int
);
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment