| Author |
Message |
< Advanced Erlang/OTP ~ YAWS-Preventing atom-table attack for action=module:function |
| seancharles |
Posted: Mon Aug 13, 2007 8:06 pm |
|
|
|
User
Joined: 18 Jul 2007
Posts: 57
|
Oh no he's back, and even more code! After taking on board Martins comments about possible attacks to deliberately fill the atom table with junk by calls to list_to_atom, I have devised the following code in my post handler.
I *could* have a static list and simple check against that (final solution!?) but during development I want total freedom i.e. the system must be dynamic and transparent.
The following code is my attempt to verify that the module:function call is viable before
* calling list_to_atom()
* making the Module:Function() call
I would sincerely appreciate any input on my code with regards to:
* Style, Erlang idioms etc etc I have less than a months Erlang experience so far but I love it to bits
* Library calls I may have missed! This seems like a lot of code to do what I want.
I can't 'catch apply()' because that is a gaping hole in my security, I can't use 'keysearch' because it broke trying to compare strings against atoms in the export list.
So, is what I have here ok, drivel, laughable, good enough... ?
Once the code is 'stable' I will add memoization so that a simple lookup will be the first call and the mess of code below only executes on a failed lookup.
Code:
out( A ) ->
[ Action | _ ] = string:tokens( A#arg.appmoddata, "/" ),
[ Module | Function ] = string:tokens( Action, ":" ),
case validate_formhandler( Module, Function) of
{ Mod, Fun } ->
Mod:Fun( A );
false ->
p404:out404( A, undefined, undefined)
end.
validate_formhandler( Module, FList ) ->
case catch hd( FList ) of
{'EXIT', _} -> false;
Function ->
%% MEMOIZATION CHECK HERE...
validate_funcall( Module, Function )
end.
validate_funcall( Module, Function ) ->
case beam_lib:info( Module ) of
{error, beam_lib, _} ->
false;
[ _ , _ , _ ] ->
case beam_lib:chunks( Module, [exports]) of
{ok, {_, [{exports, Exports}]}} ->
case validate_function( Function, Exports ) of
true ->
{list_to_atom( Module ),
list_to_atom( Function )};
false -> false
end;
{error, beam_lib, _} ->
false
end
end.
%% -------------------------------------------------------------------
%% lists:keysearch is no good, strings vs. atoms, so I must convert
%% atom-> strings, avoiding potential pollution of the runtime atom
%% name pool from possible script attacks.
%%
validate_function( Function, Exports) ->
case lists:filter(
fun( EFName ) -> Function == atom_to_list(element(1,EFName)) end,
Exports ) of
[{_, Arity}] -> Arity == 1;
[] -> false
end.
Cheers guys, I have learned something from every response I have made so far.
Sean Charles |
|
|
| Back to top |
|
| Jan Henry Nystrom |
Posted: Mon Aug 13, 2007 8:30 pm |
|
|
|
User
Joined: 09 Oct 2006
Posts: 28
Location: Uppsala, Sweden
|
seancharles wrote: Oh no he's back, and even more code!  After taking on board Martins comments about possible attacks to deliberately fill the atom table with junk by calls to list_to_atom, [Snip, snip]
Sean Charles
There is a function in module erlang(actually a BIF but nominally in erlang) that checks that you have seen a atom before, or as the documetantion formulates it:
Quote:
list_to_existing_atom(String) -> atom()
Types:
String = string()
Returns the atom whose text representation is String, but only if there already exists such atom.
Failure: badarg if there does not already exist an atom whose text representation is String.
/Cheers Henry |
_________________ Jan Henry Nystrom
Training & Research Manager @ Erlang Training and Consulting Ltd
http://www.erlang-consulting.com |
|
| Back to top |
|
| seancharles |
Posted: Mon Aug 13, 2007 9:04 pm |
|
|
|
User
Joined: 18 Jul 2007
Posts: 57
|
Henry,
I knew about that function but it wouldn't help prevent a malicious script from deliberately trying to fill the atom table, in a large loop.
The m.o. of my code is check that the module and function are both present and that the arity is correct before finally committing new atoms to the pool.
list_to_existing atom fails if the atom does not exist, so could you verify then that list_to_atom will always return the *same* atom for the *same* string/list which is what I assumed.
That's why I used it; I just want to call it and have my atom come back, no questions asked but only when I have verified that the atoms won't be 'wasted' in a bad call.
 |
|
|
| Back to top |
|
| Mazen |
Posted: Tue Aug 14, 2007 8:22 am |
|
|
|
User
Joined: 20 Jul 2006
Posts: 164
Location: London
|
Hi again
seancharles wrote:
list_to_existing atom fails if the atom does not exist
This is a good thing. You don't want to handle atoms that do not exist... at all! Which means that it is better to fail completely by doing list_to_existing_atom, then to construct a whole "check" just to make sure that you are creating a "safe" atom.
if you have loaded a module, then the name of that module, which is an atom, also exists in the table, thus you can't fill up any other atoms then those that exist.
A small note on your code:
function validate_formhandler/2 is more or less useless. All it does is to safly retrieve the first element in a potentially non-empty list and return false if it crashes.
If you use patternmatching in the function headers the code become much easier to read. Consider changing the following:
Code:
...
validate_formhandler( Module, FList ) ->
case catch hd( FList ) of
{'EXIT', _} -> false;
Function ->
%% MEMOIZATION CHECK HERE...
validate_funcall( Module, Function )
end.
validate_funcall( Module, Function ) ->
...
to:
Code:
...
validate_funcall( Module, [] ) ->
false;
validate_funcall( Module, [Function|_]) ->
...
and change the call to go straight to this function instead.
In case you want to do your memoization (never heard that word ) in validate_formhandler/2 then keep it and patternmatch on emptylist directly in the header instead.
Hopefully I was careful reading the code this time  |
|
|
| Back to top |
|
| seancharles |
Posted: Tue Aug 14, 2007 8:36 am |
|
|
|
User
Joined: 18 Jul 2007
Posts: 57
|
Mazen,
First of all, memoization is a funny looking word but check out: Memoization for a good explanation.
Secondly, THANKS! I have yet to remember fully that function arguments are indeed patterns, still thinking like a 'conventional' programmer!
Your suggested changes are definitely more Erlang like and *exactly* the kind of input I hoped to get back... I want to get as good an Erlang basher as I can be as quickly as I can and that means learning the idioms ASAP!
I really like the [Function|_] thing, I keep forgetting the list nuances too! That'll save me some calls to hd() elsewhere as well. I am now going to review my code and apply the above patterns as much as I can... I always 'feel good' after deleting code. Less code is better code.
Thanks again Mazen, and yes, you were very careful reading the code, now can I be as careful re-factoring it ?
Excellent!  |
|
|
| Back to top |
|
| wuji |
Posted: Mon Aug 13, 2012 6:31 am |
|
|
|
User
Joined: 10 Aug 2012
Posts: 654
|
every individual has a vote, promising sweeping reforms. "We love love [h3]jordan 6 olympic 2012[/h3] love you, President Shafiq," the crowd chanted in response.Former International
Energy Agency chief and presidential hopeful, Mohamed el-Baradei warned that that cheap replica *beep* that Egypt is entering a dangerous phase."Electing a president without
a constitution or parliament means electing a president with absolute absolute cheap jordans absolute power," el-Baradei said. Still popular with youth leaders, el-Baradei
out of the presidential race in January, saying the democratic democratic [h4]jordan 6s[/h4] democratic electoral process was doomed under SCAF's leadership.After winning 46%
seats in the recent parliament elections, the Muslim Brotherhood stands stands replica designer *beep* stands to lose the most from today's rulings, and many
whether Morsi would still run this weekend.The Council on Foreign Foreign imitation designer *beep* Foreign Relations' Steven Cook described two camps arising out of |
|
|
| Back to top |
|
| wantjersey |
Posted: Fri Aug 17, 2012 6:12 am |
|
|
|
User
Joined: 17 Aug 2012
Posts: 10
|
| Jersey City has one of the best transportation systems in the whole of the US which makes it perfect for travelling in and out of New York's financial cheap nhl jerseys district. A large majority of Jersey City's residents use public transit every day and take advantage of key hubs like the Hudson-Bergen Light Rail, PATH, the Hoboken Terminal-New nba throwback jerseys Transport and the NY Water ferries. If you take office space in Jersey City then you'll be spoilt for choice when it comes to public transport. |
|
|
| Back to top |
|
|
|
All times are GMT
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|
|